以前こういう記事を書いた.
このときから更に便利になり,kOps 1.23で,ついにeks-pod-identity-webhookさえも自動インストールできるようになったので紹介する.
PodIdentityWebhookをインストールする
cluster_specに
spec: certManager: enabled: true podIdentityWebhook: enabled: true
と書くだけで良い.ちなみに,webhookなので証明書が必要になるのだが,これを管理するためにcertManagerは必須となっている.なので certManager.enabled: true
はお忘れなく.
この状態でクラスタを作ると,
$ kubectl get pods -n kube-system NAME READY STATUS RESTARTS AGE cert-manager-84955789dd-g2djl 1/1 Running 0 3m54s cert-manager-cainjector-6475d566f7-jtx99 1/1 Running 0 3m54s cert-manager-webhook-7b7b64cc86-t64dk 1/1 Running 0 3m54s # 中略 pod-identity-webhook-565f794b7c-gffkd 1/1 Running 0 3m54s pod-identity-webhook-565f794b7c-scrf8 1/1 Running 0 3m54s
このようにpod-identity-webhookが自動的にデプロイされる.
IRSAの使い方まとめ
セットアップ
最終的にどういう手順になったのかを書いておく.
- publicなS3 bucketを作る
spec.serviceAccountIssuerDiscovery
をcluster_specに指定- (Optional)
spec.iam.serviceAccountExternalPermission
をcluster_specに指定 spec.podIdentityWebhook
をcluster_specに指定- kopsコマンドでクラスタを作るだけ
spec: serviceAccountIssuerDiscovery: discoveryStore: s3://public-readable-s3-bucket-name enableAWSOIDCProvider: true iam: serviceAccountExternalPermissions: - name: my-sa namespace: my-ns aws: inlinePolicy: |- [ { "Effect": "Allow", "Action": "ec2:Describe*", "Resource": "*" } ] podIdentityWebhook: enabled: true certManager: enabled: true
これだけ.
使い方
ServiceAccountを作成
クラスタができたらServiceAccountを作っておく.
apiVersion: v1 kind: ServiceAccount metadata: annotations: eks.amazonaws.com/role-arn: arn:aws:iam::00000000:role/my-sa.my-ns.sa.cluster-name name: my-sa namespace: my-ns
spec.iam.serviceAccountExternalPermissions
を指定している場合 eks.amazonaws.com/role-arn
は自動的に作成されるわけだが,これは以下のようなコマンドで探してくる.
$ aws iam get-role --role-name my-sa.my-ns.sa.cluster-name { "Role": { "Path": "/", "RoleName": "my-sa.my-ns.sa.cluster-name", "RoleId": "***********", "Arn": "arn:aws:iam::00000000:role/my-sa.my-ns.sa.cluster-name", "CreateDate": "2022-03-17T12:25:46+00:00", "AssumeRolePolicyDocument": { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Federated": "arn:aws:iam::00000000:oidc-provider/public-readable-s3-bucket-name.s3.us-east-1.amazonaws.com" }, "Action": "sts:AssumeRoleWithWebIdentity", "Condition": { "StringEquals": { "public-readable-s3-bucket-name.s3.us-east-1.amazonaws.com:sub": "system:serviceaccount:my-ns:my-sa" } } } ] }, } }
注意: spec.iam.serviceAccountExternalPermission
を指定しない場合,これに相当するIAM Roleは自分で作る必要がある.
terraformで作る場合は以下のようなものになる.
resource "aws_iam_role" "my-sa" { name = "my-sa.my-ns.sa" path = "/" inline_policy { name = "my_inline_policy" policy = jsonencode({ Version = "2012-10-17" Statement = [ { Action = ["ec2:Describe*"] Effect = "Allow" Resource = "*" }, ] }) } assume_role_policy = <<EOF { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Federated": "arn:aws:iam::00000000:oidc-provider/public-readable-s3-bucket-name.s3.us-east-1.amazonaws.com" }, "Action": "sts:AssumeRoleWithWebIdentity", "Condition": { "StringEquals": { "public-readable-s3-bucket-name.s3.us-east-1.amazonaws.com:sub": "system:serviceaccount:my-ns:my-sa" } } } ] } EOF }
このとき,Federated
に指定する値は
$ aws iam list-open-id-connect-providers { "OpenIDConnectProviderList": [ { "Arn": "arn:aws:iam::00000000:oidc-provider/public-readable-s3-bucket-name.s3.us-east-1.amazonaws.com" } ] }
のようにして探してくる.
動作確認
こんなJobを作ってみる.
apiVersion: batch/v1 kind: Job metadata: name: awscli namespace: my-ns spec: template: spec: restartPolicy: Never serviceAccountName: my-sa containers: - name: awscli image: amazon/aws-cli:latest args: ["ec2", "describe-instances", "--region", "ap-northeast-1"] backoffLimit: 0
これをapplyすると
spec: containers: - args: - ec2 - describe-instances - --region - ap-northeast-1 env: - name: AWS_ROLE_ARN value: arn:aws:iam::564677439943:role/my-sa.my-ns.sa.playground.k8s.h3poteto.dev - name: AWS_WEB_IDENTITY_TOKEN_FILE value: /var/run/secrets/eks.amazonaws.com/serviceaccount/token image: amazon/aws-cli:latest imagePullPolicy: Always name: awscli # Omission volumes: - name: aws-iam-token projected: defaultMode: 420 sources: - serviceAccountToken: audience: amazonaws.com expirationSeconds: 86400 path: token
このように AWS_ROLE_ARN
とAWS_WEB_IDENTITY_TOKEN_FILE
がenvに設定される.
また,projected volumeがマウントされている.
というわけでログをみると
$ kubectl logs -f awscli-xbksl -n my-ns { "Reservations": [ { "Groups": [], "Instances": [ { "AmiLaunchIndex": 0, "ImageId": "ami-********", "InstanceId": "i-0f4e3e20cf27d652c", "InstanceType": "t3.medium", "KeyName": "******", "LaunchTime": "2022-03-11T15:25:05+00:00", "Monitoring": { "State": "disabled" }, "Placement": { "AvailabilityZone": "ap-northeast-1c", "GroupName": "", "Tenancy": "default" },
無事awsコマンドが成功している.
まとめ
ようやくkOpsでもEKSと大差ないくらいの手順でIRSAが利用できるようになった. あと,eks-pod-identity-webhook側がcert-manager対応してくれたおかげで,ここまで来ることができた.長らくeks-pod-identity-webhookは独自で証明書管理をしていたのだが,これが分離されたことにより単体でインストールする場合もかなり楽になったんではないだろうか.