はじめに
昨年の12月、みなさんが待ちに待ったEKS on Fargateが正式発表されました。
これによりノード管理から解放され、Fargateを利用するようになる人も増えるのではないかと思います。
ただ、そこで問題になるのが EKS on Fargate におけるいくつかの制限です。
- 各ポッドが使用できるのは最大 4 vCPU と 30Gb のメモリです。
- パーシステントボリュームやファイルシステムで必要とされるステートフルなワークロードのサポートは、現時点ではありません。
- Daemonsets、Privileged ポッド、または HostNetwork または HostPort を使用するポッドは実行できません。
- 利用できるロードバランサーは、Application Load Balancer だけです。
公式ブログ参考: AWS Fargate 上の Amazon EKS を一般公開
このうち、個人的にまず困ったのは「ロードバランサーで使用できるものがApplication Load Balancerだけ」ということです。
一見すると問題ないように感じますが、EKS on Fargate においてALBを使うということは、ALB Ingress Controllerを導入するということと同義なので、Terraformで別管理などができません。
回避するには従来の方法とのハイブリッド型を選択する必要がありますが、どうせならそこも楽にしたく、本記事では潔くALB Ingress Controllerに乗っかることにするとして、これを導入するための手順がまたちょい手間です。
手順通りに構築したつもりでも何か抜け落ちている可能性があったり、毎回構築するたびに同じ手順を繰り返すのはあれなので、せめてスクリプト化したいと考えていました。
今回は、その際に作成したシェルスクリプトを紹介していければと思います。
環境
使用 | バージョン |
---|---|
Kubernetes | 1.14 |
ALB Ingress Controller | 1.1.4 |
eksctl | 0.13.0 |
helm | 3.0.1 |
シェルスクリプト
前置きが長かったため、早速本題のシェルスクリプトを貼ります。
基本的には、AWSのドキュメントに沿った流れとなります。
ので、EKS on Fargateがもとで生まれた本スクリプトですが、従来通りのパターンでも活用できるかと思います。
#!/bin/bash -e
# Step1: 情報の取得
if [ ! -e $CLUSTER_YAML_PATH ]; then
echo "yamlファイルが存在しません: ${CLUSTER_YAML_PATH}"
exit 1
fi
cluster_name=$(yq r $CLUSTER_YAML_PATH metadata.name)
region=$(yq r $CLUSTER_YAML_PATH metadata.region)
# Step2: クラスタの作成
eksctl create cluster -f $CLUSTER_YAML_PATH
# Step3: 権限の割り当て
eksctl utils associate-iam-oidc-provider \
--region $region \
--cluster $cluster_name \
--approve
policy_name='ALBIngressControllerIAMPolicy'
policy_arn=$(aws iam list-policies --output json | jq -r ".Policies[] | select(.PolicyName == \"${policy_name}\").Arn")
if [ -z "$policy_arn" ]; then
policy_arn=$(aws iam create-policy \
--policy-name $policy_name \
--policy-document https://raw.githubusercontent.com/kubernetes-sigs/aws-alb-ingress-controller/v1.1.4/docs/examples/iam-policy.json \
--output json | jq -r .Policy.Arn)
fi
kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/aws-alb-ingress-controller/v1.1.4/docs/examples/rbac-role.yaml
eksctl create iamserviceaccount \
--region $region \
--name alb-ingress-controller \
--namespace kube-system \
--cluster $cluster_name \
--attach-policy-arn $policy_arn \
--override-existing-serviceaccounts \
--approve
# Step4: ALB Ingress Controllerのインストール
vpc_id=$(eksctl get cluster \
--name $cluster_name \
--output json | jq -r .[].ResourcesVpcConfig.VpcId)
helm repo add incubator http://storage.googleapis.com/kubernetes-charts-incubator
helm install incubator/aws-alb-ingress-controller \
--set clusterName=$cluster_name \
--set awsRegion=$region \
--set awsVpcID=$vpc_id \
--set rbac.create=false \
--set rbac.serviceAccountName=alb-ingress-controller \
--generate-name \
--namespace kube-system \
--version 0.1.12
元: https://gist.github.com/yukiarrr/df476d0928c358ea01052f8226231e2f
EKS on Fargateの構築には、eksctlを使用しています。
冪等性がないとはいえ、1コマンドで環境が構築できてしまうのはやはり強力ですね。
Step1: 情報の取得
# Step1: 情報の取得
if [ ! -e $CLUSTER_YAML_PATH ]; then
echo "yamlファイルが存在しません: ${CLUSTER_YAML_PATH}"
exit 1
fi
cluster_name=$(yq r $CLUSTER_YAML_PATH metadata.name)
region=$(yq r $CLUSTER_YAML_PATH metadata.region)
eksctlを使用する場合、基本的には設定をyamlで記述するかと思いますので、ここでは環境変数$CLUSTER_YAML_PATH
として、yamlのパスを受け取ることを想定してます。
そして、そのyamlからyqを使いクラスタ名とリージョンを取得します。
これらはクラスタを作成後にALB Ingress Controllerをインストールするために必要となります。
Step2: クラスタの作成
# Step2: クラスタの作成
eksctl create cluster -f $CLUSTER_YAML_PATH
yamlの情報をもとに、クラスタを生成します。
(結構時間かかります)
この後AWSのドキュメントでは、サブネットに対するタグ付けを必要としていますが、eksctlを使った場合は勝手にやってくれるので、無視で大丈夫です。
Step3: 権限の割り当て
# Step3: 権限の割り当て
eksctl utils associate-iam-oidc-provider \
--region $region \
--cluster $cluster_name \
--approve
policy_name='ALBIngressControllerIAMPolicy'
policy_arn=$(aws iam list-policies --output json | jq -r ".Policies[] | select(.PolicyName == \"${policy_name}\").Arn")
if [ -z "$policy_arn" ]; then
policy_arn=$(aws iam create-policy \
--policy-name $policy_name \
--policy-document https://raw.githubusercontent.com/kubernetes-sigs/aws-alb-ingress-controller/v1.1.4/docs/examples/iam-policy.json \
--output json | jq -r .Policy.Arn)
fi
kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/aws-alb-ingress-controller/v1.1.4/docs/examples/rbac-role.yaml
eksctl create iamserviceaccount \
--region $region \
--name alb-ingress-controller \
--namespace kube-system \
--cluster $cluster_name \
--attach-policy-arn $policy_arn \
--override-existing-serviceaccounts \
--approve
ALB Ingress Controllerでは名前の通りAWSのALBを制御するため、制御するPod側には専用の権限が必要となります。
ここでは、AWS上のIAMポリシー一覧から、以前同じ名前のポリシーを作成していないか確認し、存在しなければeksctlより提供されているサンプルをもとに作成します。
そして、そのポリシーと紐付いたServiceAccountを作成し、以後はこれを用いてALBを制御するようにします。
Step4: ALB Ingress Controllerのインストール
# Step4: ALB Ingress Controllerのインストール
vpc_id=$(eksctl get cluster \
--name $cluster_name \
--output json | jq -r .[].ResourcesVpcConfig.VpcId)
helm repo add incubator http://storage.googleapis.com/kubernetes-charts-incubator
helm install incubator/aws-alb-ingress-controller \
--set clusterName=$cluster_name \
--set awsRegion=$region \
--set awsVpcID=$vpc_id \
--set rbac.create=false \
--set rbac.serviceAccountName=alb-ingress-controller \
--generate-name \
--namespace kube-system \
--version 0.1.12
最後に、ALB Ingress Controller自体のインストールです。
ここでは、面倒なVPC IDなどの挿入を避けるため、helmを使用しています。
これで一通りの環境構築は完了します。
その他マニフェストファイルについてなどはドキュメントを参考にしてください。
マニフェストファイルでの注意
FargateでALB Ingress Controllerを使用する場合、IP Modeを使用する必要があります。
IP Modeとは、Fargateで起動したPodにIPアドレスを使い直接ルーティングする方法で、annotationsで使用を宣言する必要があります。
具体的に、実際に使用したIngressのannotationsを抜粋します。
annotations:
kubernetes.io/ingress.class: alb # AWSドキュメントより必須項目
alb.ingress.kubernetes.io/scheme: internet-facing # インターネット接続する際に必要
alb.ingress.kubernetes.io/target-type: ip # IP Mode
まとめ
これで、スクリプト1つ実行すれば簡単に環境構築することができるようになりました。
若干環境に依存してしまっているところはありますが、手で毎回やるよりはマシになったかなと思います。
今後もできる限り、楽にしていきたいと思います。
GitHub: @yukiarrr
Twitter: @yukiarrr