0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

EKS Pod Identityで EBS CSI Driverの権限管理とKMSテナント別暗号化を検証してみた

0
Last updated at Posted at 2026-04-06

はじめに

EKS でステートフルワークロードを運用する際、EBS CSI Driver の IAM 権限管理と EBS ボリュームの暗号化は避けて通れないテーマです。

2023年にリリースされた EKS Pod Identity は、従来の IRSA(IAM Roles for Service Accounts)を置き換える新しい認証方式です。本記事では、Pod Identity を使って EBS CSI Driver に最小権限の IAM ロールを付与し、さらに KMS カスタマーマネージドキーによる Namespace 別の EBS 暗号化(マルチテナント構成)を実際に構築・検証しました。

52747.jpg

この記事で学べること

  • EKS Pod Identity で EBS CSI Driver に IAM ロールを付与する方法
  • KMS カスタマーマネージドキーを使った EBS ボリューム暗号化の設定
  • Namespace ごとに異なる KMS キーを使い分ける StorageClass 設計
  • Pod Identity と IRSA の具体的な違い(環境変数・信頼ポリシー)
  • 検証中にハマったポイントと解決策

想定読者

  • EKS でマルチテナント環境のストレージセキュリティを設計したい方
  • IRSA から Pod Identity への移行を検討している方
  • EBS CSI Driver の暗号化設定を実践的に理解したい方

背景・課題

EKS 上のワークロードが AWS サービスにアクセスする際、IAM 権限の付与方法として長らく IRSA が使われてきました。しかし IRSA にはいくつかの課題があります。

  • OIDC プロバイダーの管理が必要: クラスタごとに OIDC プロバイダーを作成し、IAM ロールの信頼ポリシーに記載する必要がある
  • 信頼ポリシーの文字数上限: IAM ロールの信頼ポリシーは 4096 文字が上限で、約 12 クラスタまでしか共有できない
  • クラスタ固有の設定: ロールを別クラスタで再利用するたびに信頼ポリシーの更新が必要

Pod Identity はこれらの課題を解決し、さらに EKS アドオンとの統合も強化されています。

一方、マルチテナント環境では「テナントごとに異なる暗号化キーで EBS ボリュームを暗号化したい」という要件がよくあります。StorageClass の kmsKeyId パラメータと Namespace の組み合わせでこれを実現できるか、実際に検証しました。

検証環境

項目 内容
EKS バージョン 1.34
EBS CSI Driver アドオン版(Pod Identity 連携)
ノード t3.medium × 2(Managed Node Group)
リージョン ap-northeast-1
KMS キー カスタマーマネージドキー × 2(テナント別)
認証方式 EKS Pod Identity

検証内容

1. EKS クラスタと Pod Identity Agent の構築

eksctl でクラスタを作成します。ポイントは addonseks-pod-identity-agent を指定することです。

apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig

metadata:
  name: ebs-pod-identity-test
  region: ap-northeast-1
  version: "1.34"

managedNodeGroups:
  - name: ng-1
    instanceType: t3.medium
    desiredCapacity: 2

addons:
  - name: eks-pod-identity-agent
eksctl create cluster -f cluster-config.yaml

Pod Identity Agent が各ノードで DaemonSet として起動していることを確認します。

$ kubectl get pods -n kube-system -l app.kubernetes.io/name=eks-pod-identity-agent
NAME                           READY   STATUS    RESTARTS   AGE
eks-pod-identity-agent-bpp4m   1/1     Running   0          2m44s
eks-pod-identity-agent-k59zs   1/1     Running   0          2m45s

52742_0.jpg

2. Pod Identity 用 IAM ロールの作成

Pod Identity の信頼ポリシーは IRSA と大きく異なります。OIDC プロバイダーの ARN ではなく、pods.eks.amazonaws.com というサービスプリンシパルを指定します。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "pods.eks.amazonaws.com"
      },
      "Action": [
        "sts:AssumeRole",
        "sts:TagSession"
      ]
    }
  ]
}

sts:TagSession は Pod Identity がセッションタグ(クラスタ名、Namespace、ServiceAccount 名など)を付与するために必要です。

ロールを作成し、AWS マネージドポリシーをアタッチします。

aws iam create-role \
  --role-name EBSCSIDriverPodIdentityRole \
  --assume-role-policy-document file://trust-policy.json

aws iam attach-role-policy \
  --role-name EBSCSIDriverPodIdentityRole \
  --policy-arn arn:aws:iam::aws:policy/service-role/AmazonEBSCSIDriverPolicy

52744_0.jpg

3. KMS カスタマーマネージドキーの作成とポリシー設定

テナントごとに KMS キーを作成します。

TENANT_A_KEY_ID=$(aws kms create-key \
  --description "EBS encryption key for tenant-a" \
  --query KeyMetadata.KeyId --output text)

aws kms create-alias --alias-name alias/ebs-tenant-a --target-key-id ${TENANT_A_KEY_ID}

52743_0.jpg

EBS CSI Driver のロールに KMS アクセス権限を付与するインラインポリシーを追加します。

cat > kms-policy.json << EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "kms:Encrypt",
        "kms:Decrypt",
        "kms:ReEncrypt*",
        "kms:GenerateDataKey*",
        "kms:CreateGrant",
        "kms:DescribeKey"
      ],
      "Resource": [
        "arn:aws:kms:ap-northeast-1:<ACCOUNT_ID>:key/<TENANT_A_KEY_ID>",
        "arn:aws:kms:ap-northeast-1:<ACCOUNT_ID>:key/<TENANT_B_KEY_ID>"
      ]
    }
  ]
}
EOF

52745_0.jpg

4. EBS CSI Driver のインストール(Pod Identity 連携)

EBS CSI Driver アドオンを --pod-identity-associations 付きでインストールします。これが Pod Identity の最大の利点で、アドオンのインストールと IAM ロールの紐付けを 1 コマンドで完了できます。

aws eks create-addon \
  --cluster-name ebs-pod-identity-test \
  --addon-name aws-ebs-csi-driver \
  --pod-identity-associations \
    "serviceAccount=ebs-csi-controller-sa,roleArn=arn:aws:iam::<ACCOUNT_ID>:role/EBSCSIDriverPodIdentityRole"

52746_0.jpg

Pod Identity Association が作成されたことを確認します。

$ aws eks list-pod-identity-associations --cluster-name ebs-pod-identity-test
{
    "associations": [
        {
            "clusterName": "ebs-pod-identity-test",
            "namespace": "kube-system",
            "serviceAccount": "ebs-csi-controller-sa",
            "associationArn": "arn:aws:eks:ap-northeast-1:<ACCOUNT_ID>:podidentityassociation/...",
            "associationId": "a-xxxxxxxxxxxxx",
            "ownerArn": "arn:aws:eks:ap-northeast-1:<ACCOUNT_ID>:addon/..."
        }
    ]
}

IRSA では ServiceAccount にアノテーション(eks.amazonaws.com/role-arn)を付与する方式でしたが、Pod Identity では EKS API 側で Association を管理するため、Kubernetes マニフェストの変更が不要です。

5. テナント別 StorageClass の作成

Namespace ごとに異なる KMS キーで暗号化するため、テナント別の StorageClass を作成します。

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: ebs-encrypted-tenant-a
provisioner: ebs.csi.aws.com
volumeBindingMode: WaitForFirstConsumer
parameters:
  type: gp3
  encrypted: "true"
  kmsKeyId: arn:aws:kms:ap-northeast-1:<ACCOUNT_ID>:key/<TENANT_A_KEY_ID>

テナント B 用も同様に、異なる kmsKeyId を指定して作成します。

$ kubectl get storageclass
NAME                     PROVISIONER             RECLAIMPOLICY   VOLUMEBINDINGMODE      AGE
ebs-encrypted-tenant-a   ebs.csi.aws.com         Delete          WaitForFirstConsumer   14s
ebs-encrypted-tenant-b   ebs.csi.aws.com         Delete          WaitForFirstConsumer   10s
gp2                      kubernetes.io/aws-ebs   Delete          WaitForFirstConsumer   19m

6. テナント別 EBS 暗号化の検証

各テナントの Namespace に PVC と Pod をデプロイし、EBS ボリュームが対応する KMS キーで暗号化されているか確認します。

$ aws ec2 describe-volumes --volume-ids ${VOL_A} ${VOL_B} \
    --query 'Volumes[*].{VolumeId:VolumeId,Encrypted:Encrypted,KmsKeyId:KmsKeyId}' \
    --output table

実行結果:

----------------------------------------------------------------------------------------------------------------------------
|                                                      DescribeVolumes                                                     |
+-----------+------------------------------------------------------------------------------------+-------------------------+
| Encrypted |                                     KmsKeyId                                       |        VolumeId         |
+-----------+------------------------------------------------------------------------------------+-------------------------+
|  True     |  arn:aws:kms:ap-northeast-1:<ACCOUNT_ID>:key/<TENANT_A_KEY_ID>                     |  vol-xxxxxxxxxxxxxxxxx  |
|  True     |  arn:aws:kms:ap-northeast-1:<ACCOUNT_ID>:key/<TENANT_B_KEY_ID>                     |  vol-yyyyyyyyyyyyyyyyy  |
+-----------+------------------------------------------------------------------------------------+-------------------------+

テナント A とテナント B で異なる KMS キーが使われていることが確認できました。

7. RBAC によるテナント間分離の確認

StorageClass はクラスタスコープのリソースなので、RBAC だけでは「どの StorageClass を使えるか」を制限できません。ただし、Namespace レベルの RBAC で PVC の作成先を制限することは可能です。

$ kubectl auth can-i create pvc --as=system:serviceaccount:tenant-a:tenant-a-user -n tenant-a
yes

$ kubectl auth can-i create pvc --as=system:serviceaccount:tenant-a:tenant-a-user -n tenant-b
no

テナント A のユーザーはテナント B の Namespace に PVC を作成できないため、結果的にテナント B 用の StorageClass を使ったボリュームを自分の Namespace に作成されることを防げます。ただし、テナント A のユーザーが自分の Namespace でテナント B 用の StorageClass を指定して PVC を作成することは RBAC では防げません。これを完全に制限するには KyvernoOPA Gatekeeper などの Admission Webhook が必要です。

8. Pod Identity と IRSA の比較

CSI Controller の Pod 内に注入される環境変数を確認しました。

Pod Identity の場合:

AWS_CONTAINER_CREDENTIALS_FULL_URI=http://169.254.170.23/v1/credentials
AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE=/var/run/secrets/pods.eks.amazonaws.com/serviceaccount/eks-pod-identity-token

IRSA の場合(参考):

AWS_ROLE_ARN=arn:aws:iam::<ACCOUNT_ID>:role/...
AWS_WEB_IDENTITY_TOKEN_FILE=/var/run/secrets/eks.amazonaws.com/serviceaccount/token

認証の仕組みが根本的に異なることがわかります。Pod Identity は Pod Identity Agent(169.254.170.23)を経由してクレデンシャルを取得するのに対し、IRSA は OIDC トークンを使って STS に直接 AssumeRoleWithWebIdentity を呼び出します。

検証結果のまとめ

検証項目 結果 備考
Pod Identity で EBS CSI Driver に IAM ロール付与 ✅ 成功 --pod-identity-associations で 1 コマンド
KMS カスタマーマネージドキーによる暗号化 ✅ 成功 StorageClass の kmsKeyId で指定
テナント別 KMS キーの使い分け ✅ 成功 StorageClass を分けることで実現
RBAC による Namespace 分離 ✅ 成功 PVC 作成先の Namespace は制限可能
Pod Identity の環境変数注入 ✅ 確認 IRSA とは異なる認証方式

わかったこと・学び

  1. Pod Identity は IRSA より運用が楽: OIDC プロバイダーの管理が不要で、信頼ポリシーがクラスタに依存しないため、同一ロールを複数クラスタで再利用できます。

  2. EKS アドオンとの統合が強力: create-addon--pod-identity-associations で IAM ロールの紐付けまで完結するため、IRSA のように ServiceAccount のアノテーションを別途管理する必要がありません。

  3. StorageClass × KMS でテナント別暗号化は実現可能: ただし StorageClass はクラスタスコープなので、テナントが「間違った」StorageClass を使うことを RBAC だけでは防げません。本番環境では Kyverno 等の Policy Engine を併用すべきです。

まとめ

EKS Pod Identity を使った EBS CSI Driver の IAM 権限管理と、KMS カスタマーマネージドキーによるテナント別 EBS 暗号化を検証しました。

Pod Identity は IRSA と比べて設定がシンプルで、特に EKS アドオンとの統合では --pod-identity-associations パラメータ一つで IAM ロールの紐付けが完了します。マルチクラスタ環境では信頼ポリシーの管理負荷が大幅に軽減されるため、新規構築では Pod Identity を第一選択にすることをおすすめします。

テナント別の EBS 暗号化は StorageClass の kmsKeyId で実現できますが、テナントが誤った StorageClass を使うことを防ぐには Kyverno や OPA Gatekeeper 等の Policy Engine が必要です。次回はこの部分を深掘りしたいと思います。

参考リンク

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?