この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
こんにちは、かたいなかです。
EKSをチームで運用する際に、EKSクラスタにアクセスする必要があるIAMユーザ/ロールが増えるたび、すでにアクセスできる状態になっている人に依頼してaws-auth
ConfigMapをeditしてもらうというのは大変ですよね。
そこで今回は以下の図のように、Codeシリーズを使用してaws-auth
ConfigMapのYAMLの変更が、Kubernetesのクラスタに自動で反映されるようにする方法をご紹介します。
おさらい:aws-auth
ConfigMapとは
aws-auth
ConfigMapはIAMのユーザ/ロールをKubernetes内のユーザやロールに紐付けを定義します。EKSクラスタ作成者以外のIAMのユーザ/ロールは、このConfigMapに紐づけが定義されていないと、Kubernetesクラスタ内のリソースにアクセスすることができません。
具体的には以下のようなConfigMapとなります。
apiVersion: v1
kind: ConfigMap
data:
mapRoles: |
- rolearn: arn:aws:iam::XXXXXXXXXXXX:role/devel-worker-nodes-NodeInstanceRole-74RF4UBDUKL6
username: system:node:{{EC2PrivateDNSName}}
groups:
- system:bootstrappers
- system:nodes
mapUsers: |
- userarn: arn:aws:iam::XXXXXXXXXXXX:user/admin
username: admin
groups:
- system:masters
- userarn: arn:aws:iam::XXXXXXXXXXXX:user/ops-user
username: ops-user
groups:
- system:masters
実際に構築してみる
流れ
以下の流れで進めます。
- CodeBuild用サービスロールの準備
- ロールの作成
- Kubernetesクラスタ内の
aws-auth
に手動で設定
- CodeBuildのビルド環境用 Dockerイメージの準備
- ECRのリポジトリを作成
- イメージのビルド・プッシュ
- CodeCommitのリポジトリの準備
aws-auth
ConfigMapのYAML作成buildspec.yml
作成
- CodePipeline/CodeBuild作成
前提条件
以下の前提条件を満たした状態であることを前提に進めていきます。
- EKSのクラスタが作成されていること
docker
,kubectl
,aws-iam-authenticator
等のツールが作業を行うPCにインストールされていることkubectl
でEKSのクラスタにアクセスできるようになっていること
CodeBuild用サービスロールの準備
まずは、CodeBuildのサービスロールを定義します。
CodeBuildのサービスロールには、以下のようなポリシードキュメントをもつIAM Policyを作成し、アタッチします。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "EKSPolicy",
"Effect": "Allow",
"Action": "eks:DescribeCluster",
"Resource": "*"
},
{
"Sid": "CloudWatchLogsPolicy",
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": [
"*"
]
},
{
"Sid": "CodeCommitPolicy",
"Effect": "Allow",
"Action": [
"codecommit:GitPull"
],
"Resource": [
"*"
]
},
{
"Sid": "S3GetObjectPolicy",
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:GetObjectVersion"
],
"Resource": [
"*"
]
},
{
"Sid": "S3PutObjectPolicy",
"Effect": "Allow",
"Action": [
"s3:PutObject"
],
"Resource": [
"*"
]
}
]
}
EKSのクラスタをdescribeする権限とCodeBuildのサービスロールとして一般的に必要な権限を与えています。
信頼ポリシー
また、CodeBuildがAssume Roleできるようにするため、CodeBuildのサービスロールは以下のような信頼ポリシーを持つようにします。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"Service": [
"codebuild.amazonaws.com"
]
},
"Action": "sts:AssumeRole"
}
]
}
EKSクラスタ内のaws-auth
ConfigMapにCodeBuildのサービスロールを追加
CodeBuildのサービスロールをaws-auth
ConfigMapに予め手動で追加しておきます。先に追加を済ませておかないとCodeBuildがConfigMapの編集を行えないためです。
以下のようなYAMLを作成します。EKSのクラスタにワーカーノードが追加された時点でワーカーノードのインスタンスのロールに関する設定はされているはずなので、新たにハイライトされた部分のCodeBuildのサービスロールの設定を追加します。
aws-auth.yml
apiVersion: v1
kind: ConfigMap
metadata:
name: aws-auth
namespace: kube-system
data:
mapRoles: |
- username: system:node:{{EC2PrivateDNSName}}
rolearn: <EKSのワーカーノードのインスタンスのロールのARN>
groups:
- system:bootstrappers
- system:nodes
- username: codebuild
rolearn: <CodeBuildのサービスロールのARN>
groups:
- system:masters
そして、クラスタに対してこのYAMLをkubectl apply
します。
$ kubectl apply -f aws-auth.yml
CodeBuildのビルド環境用 Dockerイメージの準備
ECRのリポジトリを作成
ECRのリポジトリを作成します。
CodeBuildがイメージをpullできるようにするため、以下のようなリポジトリポリシーを付与しておきます。
リポジトリポリシー
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "CodeBuildAccess",
"Effect": "Allow",
"Principal": {
"Service": "codebuild.amazonaws.com"
},
"Action": [
"ecr:BatchCheckLayerAvailability",
"ecr:BatchGetImage",
"ecr:GetDownloadUrlForLayer"
]
}
]
}
Dockerイメージをビルド・ECRにプッシュ
まず、以下のようなDockerfileを用意します。
FROM alpine:3.8
# install AWS CLI
ENV AWS_CLI_VERSION 1.16.26
RUN apk --update --no-cache add \
python \
py-pip \
&& \
pip install --upgrade awscli==${AWS_CLI_VERSION} && \
apk -v --purge del py-pip
# install kubectl
ENV KUBECTL_VERSION 1.11.3
RUN wget -O /usr/local/bin/kubectl https://storage.googleapis.com/kubernetes-release/release/v${KUBECTL_VERSION}/bin/linux/amd64/kubectl && \
chmod +x /usr/local/bin/kubectl
# install AWS IAM Authenticator
ENV AWS_IAM_AUTHENTICATOR_RELEASE_DATE 2018-07-26
ENV AWS_IAM_AUTHENTICATOR_VERSION 1.10.3
RUN wget -O /usr/local/bin/aws-iam-authenticator https://amazon-eks.s3-us-west-2.amazonaws.com/${AWS_IAM_AUTHENTICATOR_VERSION}/${AWS_IAM_AUTHENTICATOR_RELEASE_DATE}/bin/linux/amd64/aws-iam-authenticator && \
chmod +x /usr/local/bin/aws-iam-authenticator
そして、以下のようなコマンドでDockerイメージをビルドし、ECRにプッシュします。
$ $(aws ecr get-login --no-include-email --region ap-northeast-1)
$ docker build -t <ECRのリポジトリのURI>:latest .
$ docker push <ECRのリポジトリのURI>:latest
YAMLを管理するCodeCommitリポジトリの準備
CodeCommitのリポジトリを作成し、以下に示すような2つのファイルがプッシュされた状態にします。
まずは先程、EKSのクラスタにapplyしたaws-auth
ConfigMapのYAMLです。
aws-auth.yml
apiVersion: v1
kind: ConfigMap
metadata:
name: aws-auth
namespace: kube-system
data:
mapRoles: |
- username: system:node:{{EC2PrivateDNSName}}
rolearn: <EKSのインスタンスのロールのARN>
groups:
- system:bootstrappers
- system:nodes
- username: codebuild
rolearn: <CodeBuildのサービスロールのARN>
groups:
- system:masters
そして、CodeBuildでYAMLの適用をおこなうためのbuildspec.yml
です
buildspec.yml
version: 0.2
phases:
pre_build:
commands:
- aws eks update-kubeconfig --name ${EKS_CLUSTER_NAME}
build:
commands:
- kubectl apply -f aws-auth.yml
CodePipeline/CodeBuildの設定
最後に、CodePipelineのパイプラインをは今まで作ったものをつなげて作成していきます。
- CodePipelineのソースに作成したCodeCommitリポジトリのmasterブランチを選択します。
- CodeBuildのプロジェクトを以下のような設定で作成し、CodePipelineに関連付けます。
- サービスロールとして予め準備しておいたCodeBuildのロールを使用するようにします。
- CodeBuildの環境として、ECRに予めプッシュしておいたイメージを使用するようにします。
- ビルド定義ファイルはCodeCommitのリポジトリの
buildspec.yml
を指定します。
パイプライン作成が完了したら、処理が自動で開始されます。
正常に処理が完了すれば、構築が正しく行えています。
ここまででCodeCommit上でのaws-auth.yaml
の変更が自動でEKSのクラスタに反映されるようになりました。
自動で適用されることを確認してみる
では、実際に反映が正しく行われるか確認してみましょう。
aws-auth.yml
に以下のハイライトの部分を追加してコミットし、CodeCommitにプッシュします。
aws-auth.yml
apiVersion: v1
kind: ConfigMap
metadata:
name: aws-auth
namespace: kube-system
data:
mapRoles: |
- username: system:node:{{EC2PrivateDNSName}}
rolearn: <EKSのインスタンスのロールのARN>
groups:
- system:bootstrappers
- system:nodes
- username: codebuild
rolearn: <CodeBuildのサービスロールのARN>
groups:
- system:masters
mapUsers: |
- userarn: <追加するIAMユーザのARN>
username: admin
groups:
- system:masters
そして、CodePipelineの処理が成功したのを確認したら、aws-auth.yml
に追加したIAMユーザを使用してkubectl
でアクセスできることを確認してましょう。
$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.100.0.1 <none> 443/TCP 16h
正しくアクセスが行えました。
まとめ
今回は、EKSのクラスタに対してaws-auth
ConfigMapが自動で適用されるようにする方法の例をご紹介しました。今回はCodeシリーズを使用していますが、GitHub等の他のGitホスティングサービスやCircle CI等他のCIツールを使用しても同様の処理を行うことももちろん可能です。
ソースコードリポジトリで管理されたYAMLの変更から aws-auth
ConfigMapの適用を自動で行うしくみが作れると、すでにアクセス権を持っている人に依頼してConfigMapをeditしてもらうようなトイルになりがちな作業を削除できます。
実は今回使用した方法は、Kuberenetesの特定のリソースに限った方法ではなく、CodeBuildで実行されるコマンドさえ修正すれば他のKubernetesのリソースの自動デプロイにも応用できるものです。そのため、EKSクラスタを立てたらまずはこのような仕組みを作っておくことで、自動デプロイの仕組みを整えていくのに良いスタートになるのではないかなと思います。
EKSのクラスタを立てた際には試していただけますと幸いです。
参考資料
- クラスターのユーザーまたは IAM ロールの管理:EKSのドキュメントのIAMユーザ/ロールとEKSのユーザの関連付けのページです。
- actions/example-aws:GitHub ActionsでEKSへのCDの実装例のリポジトリです。
- CRD implementation:現在は
aws-auth
ConfigMapで内のmapRoles
,mapUsers
というプロパティの属性としてYAMLの文字列を埋め込む形で設定していますが、将来的には、IAMロールとKubernetesのRBACのロールのヒモ付をCustomResourceDefinitionとして設定できるようにすることが検討されているようです。