Introduction to Amazon EKS Workshopの記録
AWS Workshop StudioのIntroduction to Amazon EKSの手順を実行しました。
Workshopのコンテンツが消えた後でも見返せるようにやったことを記録しておきます。
リージョンはバージニア北部(us-east-1)で実行しました
目次
作業環境作成
Cloud9の準備
- Cloud9をt2.microでデフォルト値で作成しました。
- Cloud9のAWS managed temporary credentialsは無効化。
- Cloud9で使用するEC2向けのIAMロールはAWS管理ポリシーAdministratorAccessをアタッチしました。
アイデンティティの確認
1 2 |
aws sts get-caller-identity |
ロールを引き受けていることを確認
デフォルトリージョンの設定
1 2 3 4 |
AWS_REGION="us-east-1" aws configure set region ${AWS_REGION} aws configure get region |
us-east-1を確認
ページャーの無効化
手順に従って
1 2 3 4 5 6 |
export AWS_PAGER="" cat <<"EOT" >> ${HOME}/.bashrc export AWS_PAGER="" EOT |
eksctlコマンドのインストール
1 2 3 4 |
curl -L "https://github.com/weaveworks/eksctl/releases/latest/download/eksctl_$(uname -s)_amd64.tar.gz" | tar xz -C /tmp sudo mv /tmp/eksctl /usr/local/bin eksctl version |
バージョン 0.165.0を確認
kubectlコマンドのインストール
1 2 3 4 |
sudo curl -L -o /usr/local/bin/kubectl https://s3.us-west-2.amazonaws.com/amazon-eks/1.28.1/2023-09-14/bin/linux/amd64/kubectl sudo chmod +x /usr/local/bin/kubectl kubectl version --client |
インストール結果を確認
Client Version: v1.28.1-eks-43840fb
Kustomize Version: v5.0.4-0.20230601165947-6ce0bf390ce3
クラスターの作成
1 2 3 4 5 6 7 |
AWS_REGION=$(aws configure get region) eksctl create cluster \ --name=ekshandson \ --version 1.28 \ --nodes=3 --managed \ --region ${AWS_REGION} --zones ${AWS_REGION}a,${AWS_REGION}c |
EKS cluster “ekshandson” in “us-east-1” region is readyとなるまでだいたい15分でした。
マネジメントコンソールを見ると、ekshandsonクラスターができていて、ノードグループは3つのEC2インスタンスが指定したアベイラビリティゾーンで起動させるオートスケーリンググループで起動していました。
Control Planeはマネージドで見えなくて、Data PlaneはEC2を使用しているので、3つのノードとしてのインスタンスが見えています。
Control Planeが実行されたkubectlコマンドを受けて、ノード上でpodとしてコンテナを実行します。
デフォルトの名前空間とpod
デフォルトで4つの名前空間ができています。
* default
* kube-node-lease
* kube-public
* kube-system
kube-systemには3つのノードを使ってpodがいくつかできています。
ツール導入とコマンド補完設定
- jq(jsonデータ処理)、bas-completion(コマンド補完)のインストール
1 2 |
sudo yum -y install jq bash-completion tree gettext moreutils |
- docker composeの導入
1 2 3 4 5 6 7 8 9 |
COMPOSE_VERSION=$(curl -s "https://api.github.com/repos/docker/compose/releases/latest" | grep '"tag_name":' | sed -E 's/.*"v([^"]+)".*/\1/' ) DOCKER_CONFIG=${DOCKER_CONFIG:-$HOME/.docker} mkdir -p $DOCKER_CONFIG/cli-plugins curl -SL https://github.com/docker/compose/releases/download/v${COMPOSE_VERSION}/docker-compose-linux-x86_64 -o $DOCKER_CONFIG/cli-plugins/docker-compose chmod +x $DOCKER_CONFIG/cli-plugins/docker-compose |
- kubectlのコマンド補完
1 2 3 |
kubectl completion bash > kubectl_completion sudo mv kubectl_completion /etc/bash_completion.d/kubectl |
- eksctlのコマンド補完
1 2 3 |
eksctl completion bash > eksctl_completion sudo mv eksctl_completion /etc/bash_completion.d/eksctl |
- dockerコマンド補完
1 2 |
sudo curl -L -o /etc/bash_completion.d/docker https://raw.githubusercontent.com/docker/cli/master/contrib/completion/bash/docker |
- k=kubectlのエイリアス設定
1 2 3 4 5 6 |
cat <<"EOT" >> ${HOME}/.bashrc alias k="kubectl" complete -o default -F __start_kubectl k EOT |
- kube-ps1の導入
1 2 3 4 5 6 7 8 9 10 11 12 |
git clone https://github.com/jonmosco/kube-ps1.git ~/.kube-ps1 cat <<"EOT" >> ~/.bashrc source ~/.kube-ps1/kube-ps1.sh function get_cluster_short() { echo "$1" | cut -d . -f1 } KUBE_PS1_CLUSTER_FUNCTION=get_cluster_short KUBE_PS1_SUFFIX=') ' PS1='$(kube_ps1)'$PS1 EOT |
- kubectxとkubensの導入
1 2 3 4 5 6 7 8 |
git clone https://github.com/ahmetb/kubectx.git ~/.kubectx sudo ln -sf ~/.kubectx/completion/kubens.bash /etc/bash_completion.d/kubens sudo ln -sf ~/.kubectx/completion/kubectx.bash /etc/bash_completion.d/kubectx cat <<"EOT" >> ~/.bashrc export PATH=~/.kubectx:$PATH EOT |
- sternの導入
1 2 3 4 5 6 7 |
STERN_VERSION=$(curl -s "https://api.github.com/repos/stern/stern/releases/latest" | grep '"tag_name":' | sed -E 's/.*"v([^"]+)".*/\1/' ) curl -L "https://github.com/stern/stern/releases/download/v${STERN_VERSION}/stern_${STERN_VERSION}_linux_amd64.tar.gz" | tar xz -C /tmp sudo mv /tmp/stern /usr/local/bin |
- 設定の読み込み直し
1 2 3 4 5 6 |
. ~/.bashrc . /etc/profile.d/bash_completion.sh . /etc/bash_completion.d/kubectl . /etc/bash_completion.d/eksctl . /etc/bash_completion.d/docker |
サンプルアプリのデプロイ
3層のアプリケーションがサンプルで用意されていたのでデプロイしてみました。
DynamoDBテーブルの作成
マネジメントコンソールで作成しました。
テーブル名: messages
パーティションキー: uuid 文字列
オンデマンドモード
Dockerイメージの作成
1 2 3 4 5 6 |
cd ~/environment/ wget https://static.us-east-1.prod.workshops.aws/public/51075a38-e4dc-4703-93f1-5d4bda1e2508/static/sample-app.zip unzip sample-app.zip cd sample-app docker compose build |
sample-app.zipにはbackendとfrontendディレクトリがあり、それぞれにDpckerfile、app.py、requirements.txt、frontendのみtemplats/home.htmlがありました。
それぞれのDockerfileです。
frontend
1 2 3 4 5 6 7 8 9 10 11 12 13 |
FROM python:3-alpine WORKDIR /usr/src/app COPY requirements.txt ./ RUN pip install --no-cache-dir -r requirements.txt COPY templates/ ./templates/ COPY app.py ./ ENV PYTHONUNBUFFERED 1 ENTRYPOINT [ "python", "./app.py" ] |
backend
1 2 3 4 5 6 7 8 9 10 11 12 |
FROM python:3-alpine WORKDIR /usr/src/app COPY requirements.txt ./ RUN pip install --no-cache-dir -r requirements.txt COPY app.py ./ ENV PYTHONUNBUFFERED 1 ENTRYPOINT [ "python", "./app.py" ] |
docker imagesコマンドで2つのイメージが作成されていることを確認しました。
1 2 3 4 |
REPOSITORY TAG IMAGE ID CREATED SIZE backend latest 0e15b96fdc1b 3 minutes ago 86.7MB frontend latest 64fa653bf8d1 3 minutes ago 69.1MB |
ECRリポジトリの作成とイメージの登録
1 2 3 4 5 |
aws ecr create-repository --repository-name frontend aws ecr create-repository --repository-name backend frontend_repo=$(aws ecr describe-repositories --repository-names frontend --query 'repositories[0].repositoryUri' --output text) backend_repo=$(aws ecr describe-repositories --repository-names backend --query 'repositories[0].repositoryUri' --output text) |
frontend用backend用それぞれのECRリポジトリを作成して、URIを変数にセットしました。
1 2 3 4 5 6 7 8 |
docker tag frontend:latest ${frontend_repo}:latest docker tag backend:latest ${backend_repo}:latest AWS_ACCOUNT_ID=$(aws sts get-caller-identity --output text --query Account) AWS_REGION=$(aws configure get region) aws ecr get-login-password | docker login --username AWS --password-stdin https://${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com docker push ${frontend_repo}:latest docker push ${backend_repo}:latest |
docker tagコマンドでリポジトリURIの別名を設定して、ECRにログインして、イメージをプッシュしました。
frontendアプリのデプロイ
作業用ディレクトリの準備
1 2 3 |
mkdir -p ~/environment/manifests/ cd ~/environment/manifests/ |
frontendアプリ用の名前空間を作成して切り替え
1 2 3 |
kubectl create namespace frontend kubens frontend |
Deploymentマニフェストの作成
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
frontend_repo=$(aws ecr describe-repositories --repository-names frontend --query 'repositories[0].repositoryUri' --output text) cat <<EOF > frontend-deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: frontend namespace: frontend spec: selector: matchLabels: app: frontend replicas: 2 template: metadata: labels: app: frontend spec: containers: - name: frontend image: ${frontend_repo}:latest imagePullPolicy: Always ports: - containerPort: 5000 env: - name: BACKEND_URL value: http://backend.backend:5000/messages EOF |
環境変数BACKEND_URLは、frontendのapp.pyから使用しています。
Deploymentの作成
1 2 |
kubectl apply -f frontend-deployment.yaml -n frontend |
Deploymentリソースを作成したことで、ReplicaSetが作成されて、ReplicaSetリソースによってPodが作成されました。
Serviceマニフェストの作成
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
cat <<EOF > frontend-service-lb.yaml apiVersion: v1 kind: Service metadata: name: frontend namespace: frontend spec: type: LoadBalancer selector: app: frontend ports: - protocol: TCP port: 80 targetPort: 5000 EOF |
type: LoadBalancerとすることで、デフォルトでClassic Load Balancerがデプロイされます。
Serviceの作成
1 2 |
kubectl apply -f frontend-service-lb.yaml -n frontend |
Classic Load BalancerのDNSにブラウザからアクセスすると、frontendアプリにアクセスできます。
まだbackendアプリがないので、アプリが画面にエラーを出力してくれています。
backendアプリのデプロイ
frontend同様に、名前空間を作成、Deploymentマニフェストを作成、Deploymentを作成、Serviceマニフェストを作成、Serviceを作成しました。
backend名前空間を作成して切り替え
1 2 3 |
kubectl create namespace backend kubens backend |
Deploymentマニフェストを作成
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
AWS_REGION=$(aws configure get region) backend_repo=$(aws ecr describe-repositories --repository-names backend --query 'repositories[0].repositoryUri' --output text) cat <<EOF > backend-deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: backend namespace: backend spec: selector: matchLabels: app: backend replicas: 2 template: metadata: labels: app: backend spec: containers: - name: backend image: ${backend_repo}:latest imagePullPolicy: Always ports: - containerPort: 5000 env: - name: AWS_DEFAULT_REGION value: ${AWS_REGION} - name: DYNAMODB_TABLE_NAME value: messages EOF |
Deploymentを作成
1 2 |
kubectl apply -f backend-deployment.yaml -n backend |
Serviceマニフェストを作成
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
cat <<EOF > backend-service.yaml apiVersion: v1 kind: Service metadata: name: backend namespace: backend spec: type: ClusterIP selector: app: backend ports: - protocol: TCP port: 5000 targetPort: 5000 EOF |
Serviceを作成
1 2 |
kubectl apply -f backend-service.yaml -n backend |
backendアプリができたので、ブラウザから確認するとメッセージが変わりました。
backendアプリのログを確認します。
1 2 |
stern backend --since 3m -n backend |
botocore.exceptions.ClientError: An error occurred (AccessDeniedException) when calling the Scan operation: User: arn:aws:sts::123456789012:assumed-role/eksctl-ekshandson-nodegroup-ng-a21-NodeInstanceRole-Fkpspxkl2U2G/i-0aa365d55cd4db129 is not authorized to perform: dynamodb:Scan on resource: arn:aws:dynamodb:us-east-1:123456789012:table/messages because no identity-based policy allows the dynamodb:Scan action
DynamoDBテーブルに対してscanの権限がないというエラーです。
IAM Roles for Service Accountsを使用してアプリケーションにIAMロールを付与する。
OIDCプロバイダーの作成
1 2 3 4 |
eksctl utils associate-iam-oidc-provider \ --cluster ekshandson \ --approve |
IAMにOpenID Connectプロバイダが作成されました。
IAMポリシーの作成
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
cat <<EOF > backend-dynamodb-access.json { "Version": "2012-10-17", "Statement": [ { "Sid": "", "Effect": "Allow", "Action": [ "dynamodb:Scan", "dynamodb:GetItem", "dynamodb:PutItem", "dynamodb:DeleteItem" ], "Resource": "arn:aws:dynamodb:*:*:table/messages" } ] } EOF |
1 2 3 4 |
aws iam create-policy \ --policy-name backend-dynamodb-access \ --policy-document file://backend-dynamodb-access.json |
IAMロールとServiceAccountの作成
1 2 3 4 5 6 7 8 |
AWS_ACCOUNT_ID=$(aws sts get-caller-identity --output text --query Account) eksctl create iamserviceaccount \ --name backend-dynamodb-access \ --namespace backend \ --cluster ekshandson \ --attach-policy-arn arn:aws:iam::${AWS_ACCOUNT_ID}:policy/backend-dynamodb-access \ --approve |
CloudFromationスタックによってIAMロールとServiceAccountが作成されました。
名前空間backendに作成されたbackend-dynamodb-accessというServiceAccountに関連づいているIAMロールはOpenID ConnectプロバイダをからAssumeRoleが実行されています。
IAMロールの信頼ポリシー
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Federated": "arn:aws:iam::123456789012:oidc-provider/oidc.eks.us-east-1.amazonaws.com/id/8803A2FEDF072F514EF5A3F9595E9455" }, "Action": "sts:AssumeRoleWithWebIdentity", "Condition": { "StringEquals": { "oidc.eks.us-east-1.amazonaws.com/id/8803A2FEDF072F514EF5A3F9595E9455:aud": "sts.amazonaws.com", "oidc.eks.us-east-1.amazonaws.com/id/8803A2FEDF072F514EF5A3F9595E9455:sub": "system:serviceaccount:backend:backend-dynamodb-access" } } } ] } |
Deploymentの修正
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
apiVersion: apps/v1 kind: Deployment metadata: name: backend namespace: backend spec: selector: matchLabels: app: backend replicas: 2 template: metadata: labels: app: backend spec: serviceAccountName: backend-dynamodb-access containers: - name: backend image: 079700436326.dkr.ecr.us-east-1.amazonaws.com/backend:latest imagePullPolicy: Always ports: - containerPort: 5000 env: - name: AWS_DEFAULT_REGION value: us-east-1 - name: DYNAMODB_TABLE_NAME value: messages |
specにserviceAccountName: backend-dynamodb-accessの行を追加しました。
修正を適用しました。
1 2 |
kubectl apply -f backend-deployment.yaml -n backend |
ポッドが起動し直されます。
できました!!!
クリーンアップ
IAMロール、ServiceAccount、frontend、bakend名前空間、IAMポリシーを個別に削除して、クラスターをまとめて削除。
ECRリポジトリは私はまた使うのでとりあえず置いておきました。
1 2 3 4 5 6 7 |
eksctl delete iamserviceaccount --cluster ekshandson --namespace backend --name backend-dynamodb-access kubectl delete namespace frontend backend aws dynamodb delete-table --table-name 'messages' AWS_ACCOUNT_ID=$(aws sts get-caller-identity --output text --query Account) aws iam delete-policy --policy-arn arn:aws:iam::${AWS_ACCOUNT_ID}:policy/backend-dynamodb-access eksctl delete cluster --name ekshandson |
アプリなどを削除するときに名前空間でまとめて削除できるのは便利ですね。
最後までお読みいただきましてありがとうございました!
「AWS認定資格試験テキスト&問題集 AWS認定ソリューションアーキテクト - プロフェッショナル 改訂第2版」という本を書きました。
「AWS認定資格試験テキスト AWS認定クラウドプラクティショナー 改訂第3版」という本を書きました。
「ポケットスタディ AWS認定 デベロッパーアソシエイト [DVA-C02対応] 」という本を書きました。
「要点整理から攻略するAWS認定ソリューションアーキテクト-アソシエイト」という本を書きました。
「AWSではじめるLinux入門ガイド」という本を書きました。
開発ベンダー5年、ユーザ企業システム部門通算9年、ITインストラクター5年目でプロトタイプビルダーもやりだしたSoftware Engineerです。
質問はコメントかSNSなどからお気軽にどうぞ。
出来る限りなるべく答えます。
このブログの内容/発言の一切は個人の見解であり、所属する組織とは関係ありません。
このブログは経験したことなどの共有を目的としており、手順や結果などを保証するものではありません。
ご参考にされる際は、読者様自身のご判断にてご対応をお願いいたします。
また、勉強会やイベントのレポートは自分が気になったことをメモしたり、聞いて思ったことを書いていますので、登壇者の意見や発表内容ではありません。
ad
ad
関連記事
-
API GatewayからLambdaを介さずにSNSトピックへ送信
やりたいこと APIリクエストをまずLambdaで受けて、SNSトピックへ送信す …
-
CloudFormationドリフト検出
CloudFormationスタックのドリフト検出を確認しました。 CloudF …
-
ヤマムギvol.23 Amazon RDS for MySQLとAmazon Aurora Serverlessの起動のデモをしました
ゴールデンウィーク毎朝デモ勉強会は終わったのですが、土曜日にやれるときがあれば、 …
-
AWS Summit 2016 Tokyoに参加してきました (Day3)
飛天3日目です。 JAWS-UGブースのすぐ前にあったこのお水がめちゃめちゃおい …
-
Well-Architected Tool レンズヴァージョンアップ
当ブログのWell-Architectedレビューを久しぶりにやろうと思い、We …
-
リザーブドインスタンスはじめました
このブログも2014年9月にはじめたので、もうすぐ3年。 1件~17件とばらつき …
-
「Fin-JAWS 第14回 Fin人類育成計画」で話させていただきました!
「Fin-JAWS 第14回 Fin人類育成計画」で話させていただきました。 久 …
-
EC2ハードウェア専有インスタンス(Dedicated Instances)を起動して請求書を確認してみました
EC2ハードウェア専有インスタンスのサイトには、次の料金と表記されています。 * …
-
AWS Cost Anomaly Detectionでコストモニターを作成しました
[ご利用開始にあたって]を押下しました。 このあと画面を説明してくれるツアーがあ …
-
Lambda関数からAWS Systems Managerパラメータストアの値を取得して更新する
Lambda関数で自分自身の環境変数を更新する だと、Lambdaのエイリアスと …