https://aws.amazon.com/jp/blogs/news/introducing-fine-grained-iam-roles-service-accounts/
最近EKSにServiceAccountに紐付いたrole arnでIAM権限を付与する仕組みが実装されました
非の打ち所のないような公式ドキュメントで、eksctlを使う場合は上のドキュメントを読んでいただければ完璧に理解できると思います、この記事ではeksctlではなくterraformを使って IAM Roles for Service Accounts
を使用する手順を記載します
- 東京リージョンで作成することを想定しています
source code: https://github.com/keiSunagawa/qiita/tree/master/eks-sa-2-iam
そもそも何ができるようになったの?
従来のEKSではWorkerNodeのIAM roleがPod内に引き継がれる仕様でした
つまり、Pod内のアプリケーションからAWSリソースへアクセスするための権限を、対象のPodがデプロイされる可能性のある全てのWorkerNode自身につける必要がありました
これを回避するためにPod自身に(正確にはServiceAccountに)IAM roleを付与する方法が今回追加されました
- ちなみに以前から kiam などを使えば同様のことができたそうですが、僕はよく知らないので説明しません
OpenID Connect
今回追加された IAM Roles for Service Accounts
を構成する要素の一つ
OAuth2.0の仕様を拡張し、IDトークン
と呼ばれる情報を取得できるようにした認可/認証のための仕様
IAM Roles for Service Accounts
ではこれに則って認可/認証を実装しているため
OpenID Connect
という用語がドキュメントやコンソールにちらほら出てきます
ただし、今回の機能を使う上でほとんどEKSとIAM(及びSTS)の間で完結している話なのでユーザはあまり気にしなくても良かったりします
環境構築
冒頭で貼った source code
に沿って説明します
- VPC ~ EKS ~ EC2
この辺は通常通りなので特に説明をしません - IAM
worker & master用のロールとServiceAccount用のロールを付与します - worker & master用のロール
通常通り、EKSに必要なポリシー以外は付与しません - ServiceAccount用のロール
assume_role_policy
がworkerの付与するロールと違っているので注意
あとで付与するPodのためにCloudWatchLogsのFullAccessを付与します
resource "aws_iam_role" "eks_log_role" {
name = "${local.prefix}_eks_log_role"
assume_role_policy = <<EOS
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "${aws_iam_openid_connect_provider.for_eks.arn}"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"${aws_iam_openid_connect_provider.for_eks.url}:aud": "sts.amazonaws.com"
}
}
}
]
}
EOS
resource "aws_iam_role_policy_attachment" "eks_log_role_policy" {
policy_arn = "arn:aws:iam::aws:policy/CloudWatchFullAccess"
role = "${aws_iam_role.eks_log_role.name}"
}
- IAM OpenID Connect Provider
EKSをidP(OpenID Connectで言う認証を行うためのサーバ)とするための設定を作成します
thumbprintはidPのドメインの証明書から生成しますが、リージョンがap-northeast-1
の場合はソースそのままで問題ありません(もちろん証明書が差し替わった場合は変更になります)
自分で作成したい場合は以下の手順が参照できます
https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/id_roles_providers_create_oidc_verify-thumbprint.html
resource "aws_iam_openid_connect_provider" "for_eks" {
url = "${aws_eks_cluster.main_eks.identity.0.oidc.0.issuer}"
client_id_list = [
"sts.amazonaws.com"
]
thumbprint_list = ["9e99a48a9960b14926bb7f3b02e22da2b0ab7280"]
}
マニフェストファイル
- ServiceAccount
annotations
に環境構築で作ったarnを記載します、このアノテーションをみてEKSは認証方式を判断します(厳密に言うとSTS認証方式向けの環境変数と値のファイルを作成します)
apiVersion: v1
kind: ServiceAccount
metadata:
annotations:
eks.amazonaws.com/role-arn: <your role arn>
name: fluentd
namespace: kube-system
- DaemonSet
特に特筆することはない、通常のDaemonSetです、上記で作ったServiceAccountを紐付けます
今回はCloudWatchにfluentdでログを転送するアプリケーションをデプロイすることにします
Let's Deploy
$ cd play-ground/eks-sa-2-iam/terraform
$ terraform init && terraform apply
$ vim ~/.kube/config # 接続先情報の編集
$ terraform output eks_configmap | kubectl apply -f -
$ cd ../k8s
$ vim service-account.yml # metadata.annotations.eks.amazonaws.com/role-arnを作成したServiceAccount用roleのarnで書き換え
$ kubectl apply -f .
fluentdよりCloudWatchにログが流れていれば成功です
確認
$ kube get pods fluentd-k8sd5 -n kube-system -o yaml
podの情報を取得すると、マニフェストファイルに記載しておらず、EKSによって自動で付与された環境変数 AWS_ROLE_ARN
AWS_WEB_IDENTITY_TOKEN_FILE
やvolumeの aws-iam-token
などを確認することができます
aws client(およびsdk)はこれらの情報を使い、STS経由で認証/認可を行うことができます