🧢

EKSのサービスアカウント作成時に複数のポリシーを割り当てる

2023/09/18に公開

目的

EKSにおいてPodごとにアクセスできるAWSサービスを限定したい際に利用するIRSAですが、
複数のポリシーを1つのRoleおよびサービスアカウントに紐づける方法があるか検証してみます。
https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/iam-roles-for-service-accounts.html

結論

eksctl create iamserviceaccountで事前に定義済みのRoleを紐づけることで、
複数のポリシーを1つのRoleおよびサービスアカウントに紐づけることができました。

最終的な構成は以下の通りです。

手順

0. サービスアカウントの動作確認用画面疎通

最終的に作成したサービスアカウントが正しく機能するかどうか、動作確認するためにサービスアカウントなしの状態でエラーが発生することを確認します。
今回の環境はIntroduction to Amazon EKSで作成した環境を利用しています。
上記ハンズオンにおいてIRSAが設定されていない(backendアプリにDynamoDB周りのポリシーが割り当たっていない)状態だと、以下の画面に遷移します。


1. 任意のポリシーを作成する。

今回はマネコン上から任意のポリシーを3つ作成しました。

ここで作成するポリシーはIntroduction to Amazon EKSのIAM Roles for Service Accountsで利用するDynamoDBのポリシーを3つに分解したものです。
バックエンドサービスにこのポリシーを付与することで、0.で確認したエラーを回避できます。


2. OIDCプロバイダーの作成

eksctlでOICDプロバイダーを作成します。

OIDCプロバイダの作成
$ eksctl utils associate-iam-oidc-provider \
    --cluster ekshandson \
    --approve
出力サンプル
2022-12-23 10:28:19 []  will create IAM Open ID Connect provider for cluster "ekshandson" in "us-east-1"
2022-12-23 10:28:19 []  created IAM Open ID Connect provider for cluster "ekshandson" in "us-east-1"


3. 任意のRoleを作成する。

eksctl create iamserviceaccountでサービスアカウントに紐づけるRoleを作成します。
ここではRoleに対して1.で作成したポリシーを関連付けるとともに、信頼ポリシーも編集します。
信頼ポリシーの編集は作成するRoleを紐づけ先のサービスアカウントから利用できるようにするために行います。

信頼ポリシー
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Federated": "[2.で作成したOIDCプロバイダーのArn]"
            },
            "Action": "sts:AssumeRoleWithWebIdentity",
            "Condition": {
                "StringEquals": {
                    "[プロバイダ]:aud": "sts.amazonaws.com",
                    "[プロバイダ]:sub": "system:serviceaccount:backend:[サービスアカウント名]"
                }
            }
        }
    ]
}

4. サービスアカウントの作成

いよいよeksctlでサービスアカウントを作成します。
通常、--atache-policy-arnを使用することによって、--atache-policy-arnで割り当てたポリシーが設定されたIAM Roleが作成され、eksctlコマンドで作成されたサービスアカウントと関連付けられます。
3.で信頼ポリシーを設定しましたが、eksctlコマンドでRoleごと作成してしまう場合は、自動的に信頼ポリシーを設定してくれるためユーザ自身で定義する必要はありません。

今回は事前定義済みのRoleとサービスアカウントを関連付けるため、--atache-role-arnで関連付けるRoleを直接指定します。

attach-role-arnを指定してサービスアカウントを作成
$ eksctl create iamserviceaccount --name my-service-account --namespace backend --cluster ekshandson --attach-role-arn arn:aws:iam::[アカウントID]:role/Role --approve                                                        
2023-09-18 02:35:20 []  1 existing iamserviceaccount(s) (backend/dynamodb-messages-access) will be excluded
2023-09-18 02:35:20 []  1 iamserviceaccount (backend/my-service-account) was included (based on the include/exclude rules)
2023-09-18 02:35:20 [!]  serviceaccounts that exist in Kubernetes will be excluded, use --override-existing-serviceaccounts to override
2023-09-18 02:35:20 []  1 task: { create serviceaccount "backend/my-service-account" }
2023-09-18 02:35:20 []  created serviceaccount "backend/my-service-account"

以下のコマンドで作成されたサービスアカウントが確認できます。
Annotationsでattach-role-arnに指定した、RoleのArnが記載されていることが確認できます。

作成されたサービスアカウントの確認
$ kubectl describe serviceaccount my-service-account -n backend
Name:                my-service-account
Namespace:           backend
Labels:              app.kubernetes.io/managed-by=eksctl
Annotations:         eks.amazonaws.com/role-arn: arn:aws:iam::[アカウントID]:role/Role
Image pull secrets:  <none>
Mountable secrets:   <none>
Tokens:              <none>
Events:              <none>

5. deployment.yamlの修正

podsにサービスアカウントを関連付けるため、deployment.yamlにserviceAccountNameを追記します。

deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: backend
spec:
  selector:
    matchLabels:
      app: backend
  replicas: 2
  template:
    metadata:
      labels:
        app: backend
    spec:
+     serviceAccountName: my-service-account
      containers:
      - name: backend
        image: 123456789012.dkr.ecr.us-east-1.amazonaws.com/backend:latest
        imagePullPolicy: Always
        ports:
        - containerPort: 5000
        env:
        - name: AWS_DEFAULT_REGION
          value: us-east-1
        - name: DYNAMODB_TABLE_NAME
          value: messages

6. デプロイ

deployment.yamlの変更を環境に反映します。

変更のデプロイ
$ kubectl apply -f backend-deployment.yaml -n backend
deployment.apps/backend configured

無事デプロイに成功し、0.で確認した画面に再度アクセスしたところ、期待する画面が表示されました!

うまくいかなかったときはこちら

再作成コマンドはこちら

$ kubectl rollout restart deploy backend

IRSAのトラブルシューティングには以下のページを利用しました。
https://repost.aws/ja/knowledge-center/eks-troubleshoot-oidc-and-irsa

まとめ

事前定義済みのRoleをサービスアカウントに関連付けることで、複数のポリシーをサービスアカウントに紐づけることができました。
ただし、eksctl create iamserviceacountでRoleを作ってしまったほうが、信頼ポリシーを編集する手間がないのでお手軽に感じました。

https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/associate-service-account-role.html

Discussion