Amazon EKS のリファレンス環境を、VPC と EKS クラスタ別々に CLI から作成するための手順と実践
背景
EKS の勉強をしようと思うと、いまだと鉄板は eksctl を使うことだと思うんですが、その他にも AWS が提供しているリファレンス環境を使う方法もあるかと思います(個人差があります)1。
こちらからは、既存の VPC にデプロイするか、それとも新規に VPC を作成してそこにデプロイするか、のふたつから選択できます。
当然勉強用なので、既存の環境とは別に新しい VPC を作りたくなります。ですが勉強用なので EKS クラスタは何度も消したり作ったりしたいのですが、そのたびに VPC から作り直すのはなんだか無駄です。また個人的な趣味として、リージョンはオレゴン(us-east-2
)ではなく東京(ap-northeast-1
)を使いたいものですし。
実はリファレンス環境を作成する CloudFormation(CFn)テンプレートは、VPC 作成部分を別の CFn テンプレート(aws-vpc.template
)に切り出して、必要であればそれを呼び出す(Nest する)という構成になっています。
ということはこの aws-vpc.template
を手動で呼び出せば、リファレンスに則ったかたちで VPC を作れると言うことになります。
さっそくやってみました!
リファレンスのテンプレートは随時変更される可能性があり、以下の内容そのままが必ずしも将来にわたって有効である保証はないので、その旨ご了承ください。
なお eksctl について、ならびに EKS について本気で勉強したいというひとについては、弊社ハマコーが書いたこちら記事を読んで頂ければと思います!
とはいえ VPC を作る部分については、eksctl を使う場合においても流用が可能なので無駄ではないと思ってます 2。
構成
このクイックスタートで構築される環境は、こちらの図の通りです。
※quickstart-amazon-eks/README.md at master · aws-quickstart/quickstart-amazon-eks より
詳細は、こちらのリポジトリをご覧になるのがはやいと思います。CFnテンプレートもこちらにあります。
用意
まずは aws-vpc.template
がどのように呼び出されているかを確認するため、リファレンスである CFn テンプレートを入手しましょう。
上記ページは現在、「新規の VPC にデプロイする」という文字列のリンク先が下記の URL になっています。
こちらは短縮 URL なので、HTTP レスポンスヘッダの location:
からリダイレクト先を得て、そこから CFn テンプレートの URL を抽出します。
(下は適宜改行をいれています)
1 2 3 4 5 | % curl -sI https: //fwd .aws /6dEQ7 | grep -i '^location:' location: https: //console .aws.amazon.com /cloudformation/home ?\ region=us-east-2 #/stacks/new?\ stackName=Amazon-EKS&\ templateURL=https: //s3 .amazonaws.com /aws-quickstart/quickstart-amazon-eks/templates/amazon-eks-master .template.yaml |
これで、実際に呼び出される CFn テンプレートの入手先(templateURL
)が分かりました。
実際にダウンロードして内容を確認すると、どうやら下記の部分が該当しているようです。
1 2 3 4 5 6 | : Resources: VPCStack: : TemplateURL: !Sub 'https://${QSS3BucketName}.s3.amazonaws.com/${QSS3KeyPrefix} submodules/quickstart-aws-vpc/templates/aws-vpc.template' : |
このうち変数 ${QSS3BucketName}
と ${QSS3KeyPrefix}
は、クイックスタートの URL からするとデフォルト値が使われることになっているので、最終的には下記の URL からテンプレート (JSON) がダウンロードされることになります。
- aws-vpc.template (リンク先 JSON ファイル)
これらのテンプレートのParameters
フィールドを比較し、指定すべきパラメータを特定します。
呼び出し元(amazon-eks-master.template.yaml
)が決め打ちで値を指定しているものはそれを踏襲し、aws-vpc.template
のデフォルト値を利用できるものはそのまま利用するとした場合、そもそも CFn 起動のために必要なものとあわせ、起動時に指定すべきパラメータはこれらになります。
- 指定が必要なもの
- 起動するリージョン
- AZ 名のリスト (
AvailabilityZones
) 3 つ
- 決め打ちして指定
- Stack 名 :
Amazon-EKS-VPCStack
- ノード数 (
NumberOfAZs
) : 3 PrivateSubnetATag2
:"kubernetes.io/role/internal-elb="
PublicSubnetTag2
:"kubernetes.io/role/elb="
- Stack 名 :
起動するリージョンを東京(ap-northeast-1
)とすると、ぼくの環境では 1a, 1c, 1d の 3AZ が使用可能なので、それら全てを指定することにします。
起動 - VPC 作成
すると、AWS CLI としては以下のコマンドで構築が可能ということになりました。
1 2 3 4 5 6 7 8 9 10 11 12 13 | ( Region= 'ap-northeast-1' AvailabilityZones= 'ap-northeast-1a,ap-northeast-1c,ap-northeast-1d' aws cloudformation create-stack \ --stack-name Amazon-EKS-VPCStack \ --region ${Region} \ --parameters \ ParameterKey=AvailabilityZones,ParameterValue= '"' ${AvailabilityZones} '"' \ ParameterKey=NumberOfAZs,ParameterValue=3 \ ParameterKey=PrivateSubnetATag2,ParameterValue= "kubernetes.io/role/internal-elb=" \ ParameterKey=PublicSubnetTag2,ParameterValue= "kubernetes.io/role/elb=" \ --template-url https: //aws-quickstart .s3.amazonaws.com /quickstart-amazon-eks/submodules/quickstart-aws-vpc/templates/aws-vpc .template ) |
8 行目の環境変数 ${AvailabilityZones}
のところは、カンマ区切りの内容を文字列のまま CloudFormation API に渡す必要があったのでこう(エスケープ)しています。
実際に動かしてみると、構築に 5 分程度でしょうか。
削除する場合は、作成した CFn スタック Amazon-EKS-VPCStack
を削除すればよいです。問題なければ数分できれいになるでしょう。
1 2 | aws cloudformation delete-stack \ --stack-name Amazon-EKS-VPCStack |
EKS を起動する
それでは、作った VPC の上に EKS のクイックスタート環境を起動してみます。
この場合は「既存の VPC にデプロイする」リンクからでいいかな、と思ったんですが、以下の問題がありました。
- VPC ID や Subnet ID を指定しなくてはならない
- 接続試験や SSH 接続のために、アクセスを許可する IP アドレスを指定する必要がある
- 踏み台 (bastion) ホストの EC2 インスタンスタイプを選択できない
他にも EKS ノードの EC2 インスタンスタイプなど、毎回指定するのがだるいですよね。
これらはある程度値を決め打ちしたり、自動的に取得したりして起動できると楽です。ちょっとやってみましょう。
先ほどの aws-vpc.template
と同じく CFn テンプレートを内容確認します。すると、クイックスタートから呼び出される CFn テンプレート、ならびに EKS クラスタを作成している CFn テンプレートは以下であることがわかりました。
というわけで、このふたつのテンプレートの「Parameters:
」セクションを見比べます。デフォルト値などを勘案すると、以下のパラメータを用意すればいいことが分かりました。
パラメータ名 | 説明 | デフォルト値 |
---|---|---|
KeyPairName |
ノードおよび踏み台ホストに設定するキーペア名 | |
NodeInstanceType |
ノード EC2 のインスタンスタイプ | t3.medium |
BastionInstanceType |
踏み台 EC2 のインスタンスタイプ | t2.micro |
RemoteAccessCIDR |
踏み台への SSH 接続を許可する IP アドレス |
また以下のパラメータは、作成したスタックから describe-stacks
すれば入手できます。
- VPC ID
VPCID
- サブネット ID
PublicSubnet1ID
,PublicSubnet2ID
,PublicSubnet3ID
PrivateSubnet1ID
,PrivateSubnet2ID
,PrivateSubnet3ID
というわけで、下記のようなシェルスクリプトを作成しました。JSON の加工のためにjq
コマンドを使っていますので、まだの方はこの機会にインストールしてみてください。
また、どうせならということでRemoteAccessCIDR
に「今現在つかっているグローバル IP アドレス」を自動的にセットするために、curl
コマンドで下記 URL へアクセスしています。あわせてご確認下さい。
- https://checkip.amazonaws.com/
#!/bin/bash | |
# usage: $0 | |
# $0 DELETE | |
# 環境変数の設定 | |
Region="ap-northeast-1" | |
StackName="Amazon-EKS-EKSStack" | |
TemplateUrl=https://aws-quickstart.s3.amazonaws.com/quickstart-amazon-eks/templates/amazon-eks.template.yaml | |
VPCStackName="Amazon-EKS-VPCStack" | |
KeyPairName="id_rsa_aws-common" | |
NodeInstanceType="t3.small" | |
BastionInstanceType="t3.micro" | |
# 第一引数に DELETE と指定されたらスタックを削除する | |
if [ "$1" = "DELETE" ]; then | |
read -p "${StackName} を削除しますか? (y/N): " yn | |
case $yn in | |
y|Y) | |
echo "DELETING stack ${StackName}..." | |
aws cloudformation delete-stack \ | |
--stack-name ${StackName} && echo "done." | |
exit | |
;; | |
*) | |
echo "abort." | |
exit | |
;; | |
esac | |
fi | |
# VPC情報をスタックから取得、環境変数に格納 | |
printf "VPC情報取得 (${Amazon-EKS-VPCStack})..." | |
eval $( | |
aws cloudformation describe-stacks --stack-name ${VPCStackName} | \ | |
jq -r '.Stacks[].Outputs[] | | |
"VPCID=" + select(.OutputKey == "VPCID").OutputValue, | |
"PublicSubnet1ID=" + select(.OutputKey == "PublicSubnet1ID").OutputValue, | |
"PublicSubnet2ID=" + select(.OutputKey == "PublicSubnet2ID").OutputValue, | |
"PublicSubnet3ID=" + select(.OutputKey == "PublicSubnet3ID").OutputValue, | |
"PrivateSubnet1ID=" + select(.OutputKey == "PrivateSubnet1AID").OutputValue, | |
"PrivateSubnet2ID=" + select(.OutputKey == "PrivateSubnet2AID").OutputValue, | |
"PrivateSubnet3ID=" + select(.OutputKey == "PrivateSubnet3AID").OutputValue | |
' | |
) && echo " done." | |
# アクセス許可IPアドレスを、使用中の端末のグローバルIPアドレスにする | |
printf "グローバルIPアドレス取得..." | |
RemoteAccessCIDR="$(curl -s https://checkip.amazonaws.com/)/32" && echo " done." | |
# CFn起動 | |
echo "CFnスタック ${StackName} 作成中..." | |
aws cloudformation create-stack \ | |
--stack-name ${StackName} \ | |
--region ${Region} \ | |
--parameters \ | |
ParameterKey=KeyPairName,ParameterValue="${KeyPairName}" \ | |
ParameterKey=NodeInstanceType,ParameterValue="${NodeInstanceType}" \ | |
ParameterKey=BastionInstanceType,ParameterValue="${BastionInstanceType}" \ | |
ParameterKey=VPCID,ParameterValue="${VPCID}" \ | |
ParameterKey=PublicSubnet1ID,ParameterValue="${PublicSubnet1ID}" \ | |
ParameterKey=PublicSubnet2ID,ParameterValue="${PublicSubnet2ID}" \ | |
ParameterKey=PublicSubnet3ID,ParameterValue="${PublicSubnet3ID}" \ | |
ParameterKey=PrivateSubnet1ID,ParameterValue="${PrivateSubnet1ID}" \ | |
ParameterKey=PrivateSubnet2ID,ParameterValue="${PrivateSubnet2ID}" \ | |
ParameterKey=PrivateSubnet3ID,ParameterValue="${PrivateSubnet3ID}" \ | |
ParameterKey=RemoteAccessCIDR,ParameterValue="${RemoteAccessCIDR}" \ | |
--capabilities CAPABILITY_IAM \ | |
--template-url ${TemplateUrl} && echo "done." | |
printf "作成完了 (CREATE_COMPLETE) まで待機 (およそ20分+)..." | |
aws cloudformation wait stack-create-complete \ | |
--stack-name ${StackName} && echo " done." |
実際にクイックスタートを動かされた方だとお分かりと思いますが、ここからさらにネストして複数の CFn スタックが起動され、さらには作成された Lambda や AutoScalingGroup から別の CFn スタックや EC2 が起動したりします。これらが完全に立ち上がるまで 20 分〜25 分前後かかりますので、気長に待ってみて下さい。
実行時には、下記のようなログが表示されるかと思います。
1 2 3 4 5 6 7 8 9 10 | $ . /launch-amazon-eks-master-existing-vpc .sh VPC 情報取得 (EKS-VPCStack)... done . グローバル IP アドレス取得... done . CFn スタック Amazon-EKS-EKSStack 作成中... { "StackId" : "arn:aws:cloudformation:ap-northeast-1: ... } done . 作成完了 (CREATE_COMPLETE) まで待機 (およそ 20 分+)... done . |
なお、第 1 引数に DELETE
と指定した場合は、既存のスタック Amazon-EKS-EKSStack
を削除します。
EKS クラスタを作り直したりするときにお使い下さい。
1 2 3 | $ . /launch-amazon-eks-master-existing-vpc .sh DELETE Amazon-EKS-EKSStack を削除しますか? (y /N ): y DELETING stack Amazon-EKS-EKSStack... done . |
起動した EKS クラスタで何か動かしてみる
取りあえず何か動かしてみたいと思います。踏み台サーバ (LinuxBastion
) に SSH ログインして、kubectl
コマンドを叩いてみます。
1 2 3 4 5 | $ kubectl get nodes NAME STATUS ROLES AGE VERSION ip-10-0-31-98.ap-northeast-1.compute.internal Ready <none> 22m v1.14.8-eks-b8860f ip-10-0-34-245.ap-northeast-1.compute.internal Ready <none> 22m v1.14.8-eks-b8860f ip-10-0-90-254.ap-northeast-1.compute.internal Ready <none> 22m v1.14.8-eks-b8860f |
3AZ ぶん Node も見えているし大丈夫そうですね。
試しに Sock Shop マイクロサービスデモアプリケーションを動かしてみることにします。
Sock Shop を EKS で動作させる手順については、@Mr-K 氏の公開されている Qiita の記事を参考にさせて頂きました。
こちらの記事が書かれた当時と違い、いまのクイックスタートで起動する踏み台ホストには最初から Git が入っているようです。
1 2 3 4 5 6 | $ git clone https: //github .com /microservices-demo/microservices-demo $ cd microservices-demo /deploy/kubernetes/ $ sed -i 's/NodePort/LoadBalancer/g' complete-demo.yaml $ kubectl create namespace sock-shop $ kubectl apply -f complete-demo.yaml |
確認がとれたら削除しましょう。EKSクラスタごと消してもいいですが、Sock Shopのみ削除する場合は下記のように実行します。
1 | $ kubectl delete -f complete-demo.yaml |
まとめ
EKS利用を前提としたVPCの構築と、その上で動くEKSクラスタの構築について、AWSが公開しているクイックスタートをベースに少しだけカスタマイズできる状態で進めてみました。
明日から eksctl を使ってみたいと思います。