はじめに
SREチームの須恵です。 SREとしてはDocker/Kubernetesを利用した環境の整備を主に推進するかたわら、ときおりフロントエンド開発にも自由に挑戦させてもらったりしています。
今回は、kube2iamの仕組みと使い方について書いてみようと思います。
これは何?
kube2iamとは、Amazon EKS上のPodごとにIAMロールを使い分けられるようにするためのツールです。
なぜ必要?
Amazon EKSにおいて、クラスターを構成するNodeはEC2インスタンスです。
AWSリソースにアクセスするようなPodを動かしたいとき、Podが持てるAWSリソースへの権限は、EC2インスタンスにアタッチされたインスタンスプロファイルに紐づくIAMロールに準じます。
参考) EC2にIAMRole情報を渡すインスタンスプロファイルを知っていますか? | DevelopersIO
ここで、「異なる種類のAWSリソースを使用する複数のPodを、同じクラスターにデプロイしたい」という状況について考えます。
このとき、クラスターのすべてのNodeに 「各Podが必要とする権限の和集合」を許可することになり、 Podが本来権限を持つべきでないリソースに誤ってアクセスできてしまうリスクが生じます。
そのため、「Node単位」でなく「Pod単位」で権限制御できることにニーズがあります。
どうやって実現?
kube2iamが何を行うのか、おおざっぱに説明すると下記です。
kube2iamなし
AWSに対して何かしたいPod
→コンテナが動作するNodeのEC2メタデータAPI
→インスタンスプロファイルに紐づくロールの一時クレデンシャルをコンテナに返す
kube2iamあり
AWSに対して何かしたいPod
→メタデータAPIへのリクエストをkube2iamコンテナにリダイレクト
→kube2iamが「何かしたいコンテナ」のアノテーションに記述されたロールを引き受け(Assume)
→当該ロールの一時クレデンシャルをコンテナに返す
kube2iamに使用させるIAMロールの作成
ここから実際にkube2iamを利用するための準備を進めます。
まず下記のポリシーを作成します。
{ "Version": "2012-10-17", "Statement": [ { "Action": [ "sts:AssumeRole" ], "Effect": "Allow", "Resource": "*" } ] }
次に、「使用サービス:EC2」のロールを作成し、このポリシーをアタッチします。 ロールを作成したら、信頼関係の編集を行います。
{ "Version": "2012-10-17", "Statement": [ { "Sid": "", "Effect": "Allow", "Principal": { "Service": "ec2.amazonaws.com" }, "Action": "sts:AssumeRole" }, { "Sid": "", "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::123456789012:role/kubernetes-worker-role" ←ここは各自の値 }, "Action": "sts:AssumeRole" } ] }
"arn:aws:iam::123456789012:role/kubernetes-worker-role"
この部分には、ワーカーノード(にアタッチされたインスタンスプロファイル)のIAMロールを記載します。
ここまでの作業で、ワーカーノードに対して、AssumeRoleができる権限だけを与えました。
RBAC用リソース作成
ここからはKubernetesリソースを作成していきます。 まず作成するのはServiceAccount, ClusterRole, ClusterRoleBindingです。
このServiceAccountはkube2iamのPodがKubernetesのAPIサーバーにアクセスする際に利用します。
--- apiVersion: v1 kind: ServiceAccount metadata: name: kube2iam namespace: kube-system --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: kube2iam rules: - apiGroups: [""] resources: ["namespaces","pods"] verbs: ["get","watch","list"] --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: kube2iam subjects: - kind: ServiceAccount name: kube2iam namespace: kube-system roleRef: kind: ClusterRole name: kube2iam apiGroup: rbac.authorization.k8s.io
DaemonSet作成
ここからは、kube2iamのPodを稼働させるための作業です。
「EC2メタデータAPIへのリクエストを奪取する」という役割を遂行するためには、どのノードでリクエストが発生してもよい=すべてのワーカーノードでkube2iamが動作している必要があるので、DaemonSetリソースを作成します。
apiVersion: apps/v1 kind: DaemonSet metadata: name: kube2iam namespace: kube-system labels: app: kube2iam spec: selector: matchLabels: name: kube2iam template: metadata: labels: name: kube2iam spec: serviceAccountName: kube2iam hostNetwork: true containers: - image: jtblin/kube2iam:latest imagePullPolicy: Always name: kube2iam args: - "--app-port=8181" - "--auto-discover-base-arn" - "--iptables=true" - "--host-ip=$(HOST_IP)" - "--host-interface=eni+" - "--verbose" env: - name: HOST_IP valueFrom: fieldRef: fieldPath: status.podIP ports: - containerPort: 8181 hostPort: 8181 name: http securityContext: privileged: true
https://hub.docker.com/r/jtblin/kube2iam/
このイメージから起動したコンテナを持つPodが各ノードに配置されます。
privilegedが要る理由
--iptables=true
かつprivileged: true
とすることで、EC2メタデータAPIへのアクセスがkube2iamにプロキシされ、直接EC2メタデータAPIにアクセスしないようにすることができます。
kube2iamを利用してPodでロールを使用する
DaemonSetが作成できたら、任意のロールをPodで使用する準備は完了です。
Podのアノテーションにiam.amazonaws.com/role
を追加すると、任意のロールをPodで利用できます。
# Sample apiVersion: v1 kind: Pod metadata: name: aws-cli labels: name: aws-cli annotations: iam.amazonaws.com/role: role-arn ←ここです spec: containers: - image: fstab/aws-cli command: - "/home/aws/aws/env/bin/aws" - "s3" - "ls" - "some-bucket" name: aws-cli
最後に
続編として、今回セットアップしたkube2iamともう一つのツールを組み合わせ、EKS上のアプリケーションへALBを使ってルーティングを行う方法について書こうと思います。
SREチームも人が少しずつ増えてきました。
オクトではエンジニアを積極採用中です。ぜひ気軽に採用サイトを見てみてください。