はじめに
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 暗号化(マルチテナント構成)を実際に構築・検証しました。
この記事で学べること
- 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 でクラスタを作成します。ポイントは addons に eks-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
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
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}
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
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"
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 では防げません。これを完全に制限するには Kyverno や OPA 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 とは異なる認証方式 |
わかったこと・学び
-
Pod Identity は IRSA より運用が楽: OIDC プロバイダーの管理が不要で、信頼ポリシーがクラスタに依存しないため、同一ロールを複数クラスタで再利用できます。
-
EKS アドオンとの統合が強力:
create-addonの--pod-identity-associationsで IAM ロールの紐付けまで完結するため、IRSA のように ServiceAccount のアノテーションを別途管理する必要がありません。 -
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 が必要です。次回はこの部分を深掘りしたいと思います。





