1.CLOUD9 環境の作成#
1-1.CLOUD9 環境の作成##
本ハンズオンは、全て、「バージニア北部」で実行していきます。
「Cloud9」を開き、次の要件で作成していきます。
Step 1 Name environment
Name:任意の名前を指定。
Step 2 Configure settings
基本は次の通り、全てデフォルトです。
Environment type:Create a new EC2 instance for environment (direct access)
Instance type:t2.micro (1 GiB RAM + 1 vCPU)
Platform:Amazon Linux
Network (VPC):任意の VPC を指定して、Publicサブネットを指定してください。
Step 3 Review
「Create environment」ボタンをクリック。
1-2.IAM ロールの作成とEC2への割り当て##
以下のIAMポリシーを付与したIAMロールを作成し、EC2にアタッチします。
AdministratorAccess
1-3.一時的なクレデンシャルの無効化##
Cloud9では、IAMユーザーの一時的なクレデンシャルを自動的に設定する機能がありますが、
この一時的なクレデンシャルは IAMなどの一部のアクションに制限があるため、
この一時的なクレデンシャルは無効化して EC2インスタンスに割り当てたIAMロールが使用されるようにします。
右上の歯車の形のアイコンを開き、「AWS Settings」メニューを開き、「AWS managed temporary credentials」を無効化します。
1-4.AWS CLI の初期設定##
leomaro7:~/environment $ rm -vf ${HOME}/.aws/credentials
leomaro7:~/environment $ aws --version
aws-cli/1.18.162 Python/3.6.12 Linux/4.14.193-113.317.amzn1.x86_64 botocore/1.19.2
leomaro7:~/environment $ AWS_REGION="us-east-1"
leomaro7:~/environment $ aws configure set default.region ${AWS_REGION}
leomaro7:~/environment $ aws configure get default.region
us-east-1
leomaro7:~/environment $ aws sts get-caller-identity
{
"UserId": "",
"Account": "",
"Arn": ""
}
2.クラスターの作成#
2-1.eksctlのインストール##
eksctl:Kubernetes クラスター自体の作成に使用するコマンド
leomaro7:~/environment $ curl -L "https://github.com/weaveworks/eksctl/releases/latest/download/eksctl_$(uname -s)_amd64.tar.gz" | tar xz -C /tmp
leomaro7:~/environment $ sudo mv /tmp/eksctl /usr/local/bin
leomaro7:~/environment $ eksctl version
0.30.0
eksctl - The official CLI for Amazon EKS
2-2.kubectlのインストール##
kubectl:作成した Kubernetes クラスターの操作に使用するコマンド
leomaro7:~/environment $ sudo curl -L -o /usr/local/bin/kubectl https://amazon-eks.s3.us-west-2.amazonaws.com/1.17.7/2020-07-08/bin/linux/amd64/kubectl
leomaro7:~/environment $ sudo chmod +x /usr/local/bin/kubectl
leomaro7:~/environment $ kubectl version --short --client
Client Version: v1.17.7-eks-bffbac
2-3.クラスターの作成##
AWS_REGION=$(aws configure get default.region)
eksctl create cluster \
--name=ekshandson \
--version 1.17 \
--nodes=3 --managed \
--region ${AWS_REGION} --zones ${AWS_REGION}a,${AWS_REGION}c
- 設定オプションを引数で渡す方法以外にも、設定を YAML に記述し、引数でその YAML 指定することも可能。
- 既存の VPC を指定してクラスターを作成することも可能。今回は 新規に VPC が作成される。
- eksctl は CloudFormation を使って コントロールプレーンのVPC や EKS クラスター、ワーカーノードの Auto Scaling Group などの AWS リソースが作成される。(実際にCloudFormationを開き、作成されたリソースを確認してみるのがよいと思われる。)
※クラスターに失敗する場合のトラブルシュート
- Availability Zone のリソース不足
- AWS CLI のバージョンが古い
- IAMロールが割り当てられていない
2-4.便利なツールの導入と、コマンド補完の設定##
jq と bash-completion###
jq:json データを処理する便利なコマンド
bash-completion:bash シェル上でコマンドの補完をしてくれる
sudo yum -y install jq bash-completion
docker、docker-compose と コマンド補完###
sudo curl -L -o /etc/bash_completion.d/docker https://raw.githubusercontent.com/docker/cli/master/contrib/completion/bash/docker
sudo curl -L -o /usr/local/bin/docker-compose "https://github.com/docker/compose/releases/download/1.26.2/docker-compose-$(uname -s)-$(uname -m)"
sudo chmod +x /usr/local/bin/docker-compose
sudo curl -L -o /etc/bash_completion.d/docker-compose https://raw.githubusercontent.com/docker/compose/1.26.2/contrib/completion/bash/docker-compose
kubectl のコマンド補完###
kubectl completion bash > kubectl_completion
sudo mv kubectl_completion /etc/bash_completion.d/kubectl
eksctl のコマンド補完###
eksctl completion bash > eksctl_completion
sudo mv eksctl_completion /etc/bash_completion.d/eksctl
k(エイリアス)###
cat <<"EOT" >> ${HOME}/.bash_profile
alias k="kubectl"
complete -o default -F __start_kubectl k
EOT
kube-ps1###
kube-ps1:現在の kubectl のコンテキストや Namespace をプロンプトに表示してくれる。
git clone https://github.com/jonmosco/kube-ps1.git ~/.kube-ps1
cat <<"EOT" >> ~/.bash_profile
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###
kubectx と kubens:kubectx と kubens kubectl のコンテキストや Namespace の切替を容易にしてくれる
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" >> ~/.bash_profile
export PATH=~/.kubectx:$PATH
EOT
stern###
stern:コンテナのログを確認する
sudo curl -L -o /usr/local/bin/stern https://github.com/wercker/stern/releases/download/1.11.0/stern_linux_amd64
sudo chmod +x /usr/local/bin/stern
~/.bash_profile に追記した設定を有効化するために、現在のターミナルのタブを閉じて新しいターミナルのタブを開く。
3.クラスターの確認#
3-1.クラスターの確認##
現在存在するクラスターとクラスターの基本情報を表示。
leomaro7:~/environment $ eksctl get cluster
NAME REGION
ekshandson us-east-1
leomaro7:~/environment $ kubectl cluster-info
Kubernetes master is running at https://25FF2316ECD9ED0E8D621ED7DCFD6263.gr7.us-east-1.eks.amazonaws.com
CoreDNS is running at https://25FF2316ECD9ED0E8D621ED7DCFD6263.gr7.us-east-1.eks.amazonaws.com/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.
3-2.ノードの確認##
クラスターに所属しているノードとノードのキャパシティや稼働しているPodを確認。
leomaro7:~/environment $ kubectl get node
NAME STATUS ROLES AGE VERSION
ip-192-168-4-184.ec2.internal Ready <none> 13m v1.17.11-eks-cfdc40
ip-192-168-56-48.ec2.internal Ready <none> 13m v1.17.11-eks-cfdc40
ip-192-168-6-63.ec2.internal Ready <none> 13m v1.17.11-eks-cfdc40
leomaro7:~/environment $ kubectl describe node ip-192-168-4-184.ec2.internal
3-3.NAMESPACEの確認##
Namespace:Pod や Service といった Kubernetes リソースをグルーピングするもの。
Namespace を確認
leomaro7:~/environment $ kubectl get namespace
NAME STATUS AGE
default Active 24m
kube-node-lease Active 24m
kube-public Active 24m
kube-system Active 24m
Pod:Kubernetes におけるデプロイの最小単位で、Pod の中では 1 つ以上のコンテナが稼働する。
↓はnamespace:defaultの中身をのPod(勿論まだない。)
leomaro7:~/environment $ kubectl get pod -n default
No resources found in default namespace.
kubensを利用して、デフォルトのNamespaceをkube-system に変更。
leomaro7:~/environment $ kubens kube-system
Context "i-0fa58438b91ce5f53@ekshandson.us-east-1.eksctl.io" modified.
Active namespace is "kube-system".
kube-systemでは、↓のようなPodが動作している。
leomaro7:~/environment $ kubectl get pod -n kube-system
NAME READY STATUS RESTARTS AGE
aws-node-2p7s2 1/1 Running 0 26m
aws-node-cmmkc 1/1 Running 0 26m
aws-node-vbp6f 1/1 Running 0 26m
coredns-75b44cb5b4-cktx9 1/1 Running 0 31m
coredns-75b44cb5b4-lq58q 1/1 Running 0 31m
kube-proxy-c6td9 1/1 Running 0 26m
kube-proxy-jxwc6 1/1 Running 0 26m
全ての Namespace を対象として情報を取得する場青は -Aオプション を使う。
leomaro7:~/environment $ kubectl get pod -A
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system aws-node-2p7s2 1/1 Running 0 27m
kube-system aws-node-cmmkc 1/1 Running 0 27m
kube-system aws-node-vbp6f 1/1 Running 0 27m
kube-system coredns-75b44cb5b4-cktx9 1/1 Running 0 32m
kube-system coredns-75b44cb5b4-lq58q 1/1 Running 0 32m
kube-system kube-proxy-c6td9 1/1 Running 0 27m
kube-system kube-proxy-jxwc6 1/1 Running 0 27m
kube-system kube-proxy-z454c 1/1 Running 0 27m
4.サンプルアプリケーションのデプロイ#
4-1.DynamoDB テーブルの作成##
aws dynamodb create-table --table-name 'messages' \
--attribute-definitions '[{"AttributeName":"uuid","AttributeType": "S"}]' \
--key-schema '[{"AttributeName":"uuid","KeyType": "HASH"}]' \
--provisioned-throughput '{"ReadCapacityUnits": 1,"WriteCapacityUnits": 1}'
4-2.Dockerイメージの作成##
ディレクトリを移動している場合は、~/environment/ ディレクトリに戻っておく。
cd ~/environment/
サンプルアプリケーションをDLし、解凍。
wget https://eks-for-aws-summit-online.workshop.aws/sample-app.zip
unzip sample-app.zip
docker-compose で ビルド。
cd sample-app
docker-compose build
ビルドされたことを確認する。
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
backend latest 412ec271d5e7 11 seconds ago 107MB
frontend latest fa4eba7cd29c 20 seconds ago 57.7MB
python 3-alpine dc68588b1801 6 days ago 44.3MB
4-3.ECR へのイメージの登録##
ECRリポジトリを作成。
aws ecr create-repository --repository-name frontend
aws ecr create-repository --repository-name backend
リポジトリの URL を取得して変数に格納しておく。
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)
先ほどビルドしたイメージに、ECR のリポジトリの URL 名で別名をつけます。
docker tag frontend:latest ${frontend_repo}:latest
docker tag backend:latest ${backend_repo}:latest
別名をつけたイメージを確認。
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
4.dkr.ecr.us-east-1.amazonaws.com/backend latest 412ec271d5e7 2 minutes ago 107MB
4.dkr.ecr.us-east-1.amazonaws.com/frontend latest fa4eba7cd29c 2 minutes ago 57.7MB
ECR にログイン。
ACCOUNT_ID=$(aws sts get-caller-identity --output text --query Account)
AWS_REGION=$(aws configure get default.region)
aws ecr get-login-password | docker login --username AWS --password-stdin https://${ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com
イメージを ECR に push。
docker push ${frontend_repo}:latest
docker push ${backend_repo}:latest
4.アプリのデプロイ##
作業用ディレクトリの作成。
mkdir -p ~/environment/manifests/
cd ~/environment/manifests/
アプリケーション1用の Namespace を作成。デフォルトの Namespace も変更。
kubectl create namespace frontend
kubens frontend
Deployment の作成
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
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
kubectl apply -f frontend-deployment.yaml -n frontend
作成されたデプロイメントを確認。
※Deployment リソースを作成したことで、Deployment リソースの定義内容にしたがって、自動的に Pod が作成される。
(正確には、Deployment リソースによって ReplicaSet リソースが作成され、ReplicaSet リソースによって Pod が作成される。)
kubectl get deployment -n frontend
NAME READY UP-TO-DATE AVAILABLE AGE
frontend 2/2 2 2 13s
Podを確認。
kubectl get pod -n frontend
NAME READY STATUS RESTARTS AGE
frontend-84ccd456fb-l6kjl 1/1 Running 0 53s
frontend-84ccd456fb-wdhwr 1/1 Running 0 53s
Service の作成。
Service:Deployment によって起動された Pod 群にアクセスするために、名前解決と負荷分散の機能を提供する。
cat <<EOF > frontend-service-lb.yaml
apiVersion: v1
kind: Service
metadata:
name: frontend
spec:
type: LoadBalancer
selector:
app: frontend
ports:
- protocol: TCP
port: 80
targetPort: 5000
EOF
kubectl apply -f frontend-service-lb.yaml -n frontend
作成した Service を確認。
kubectl get service -n frontend
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
frontend LoadBalancer 10.100.219.241 dd7c90ab25e44a939b065e566aa5432-1872056256.us-east-1.elb.amazonaws.com 80:30374/TCP 10s
EXTERNAL-IP にアクセスして表示されるか確認する。(名前解決ができるまで数分かかる)
アプリケーション2用の Namespace を作成。デフォルトの Namespace も変更。
kubectl create namespace backend
kubens backend
Deployment の作成。
AWS_REGION=$(aws configure get default.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
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
kubectl apply -f backend-deployment.yaml -n backend
Podを確認。
kubectl get pod -n backend
NAME READY STATUS RESTARTS AGE
backend-7544ddcd98-7lxcx 1/1 Running 0 12s
backend-7544ddcd98-bn5jq 1/1 Running 0 12s
Service の作成。
cat <<EOF > backend-service.yaml
apiVersion: v1
kind: Service
metadata:
name: backend
spec:
type: ClusterIP
selector:
app: backend
ports:
- protocol: TCP
port: 5000
targetPort: 5000
EOF
kubectl apply -f backend-service.yaml -n backend
作成した Service を確認。
kubectl get service -n backend
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
backend ClusterIP 10.100.60.141 <none> 5000/TCP 13s
EXTERNAL-IP にもう一度アクセスしてみる。
5.IAM ROLES FOR SERVICE ACCOUNTS#
IAM Roles for Service Accounts と呼ばれる EKS の機能を使用して アプリケーション2の Pod に IAM ロールを付与し、DynamoDB へのアクセスを許可させる。
OIDC ID プロバイダーを作成し、クラスターに関連付けます。
eksctl utils associate-iam-oidc-provider \
--cluster ekshandson \
--approve
DynamoDB の messages テーブルへのフルアクセスを許可する IAM ポリシーを作成。
cat <<EOF > dynamodb-messages-fullaccess-policy.json
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "ListAndDescribe",
"Effect": "Allow",
"Action": [
"dynamodb:List*",
"dynamodb:DescribeReservedCapacity*",
"dynamodb:DescribeLimits",
"dynamodb:DescribeTimeToLive"
],
"Resource": "*"
},
{
"Sid": "SpecificTable",
"Effect": "Allow",
"Action": [
"dynamodb:BatchGet*",
"dynamodb:DescribeStream",
"dynamodb:DescribeTable",
"dynamodb:Get*",
"dynamodb:Query",
"dynamodb:Scan",
"dynamodb:BatchWrite*",
"dynamodb:CreateTable",
"dynamodb:Delete*",
"dynamodb:Update*",
"dynamodb:PutItem"
],
"Resource": "arn:aws:dynamodb:*:*:table/messages"
}
]
}
EOF
aws iam create-policy \
--policy-name dynamodb-messages-fullaccess \
--policy-document file://dynamodb-messages-fullaccess-policy.json
アプリケーション2の実行に使用するための ServiceAccount と IAM ロールを作成し、関連付ける。
ACCOUNT_ID=$(aws sts get-caller-identity --output text --query Account)
eksctl create iamserviceaccount \
--name dynamodb-messages-fullaccess \
--namespace backend \
--cluster ekshandson \
--attach-policy-arn arn:aws:iam::${ACCOUNT_ID}:policy/dynamodb-messages-fullaccess \
--override-existing-serviceaccounts \
--approve
作成された ServiceAccount を確認。
kubectl get serviceaccount -n backend
default 1 24m
dynamodb-messages-fullaccess 1 35s
アプリケーション2の Deployment の定義を修正し、作成した ServiceAccount で Pod を実行させる。
Cloud9 で backend-deployment.yaml をダブルクリックで開き、serviceAccountName の指定を次のとおり追加して保存。
spec:
+ serviceAccountName: dynamodb-messages-fullaccess
containers:
kubectl apply -f backend-deployment.yaml -n backend
自動的に新しい Pod が起動されるので、確認。
kubectl get pod -n backend
NAME READY STATUS RESTARTS AGE
backend-647595dd78-jjmml 1/1 Running 0 70s
backend-647595dd78-w7f6t 1/1 Running 0 72s
EXTERNAL-IP にもう一度アクセスしてみると正しく表示される、はず。