APC 技術ブログ

株式会社エーピーコミュニケーションズの技術ブログです。

株式会社 エーピーコミュニケーションズの技術ブログです。

EKS Pod IdentityでPodにIAM権限を付与する

こんにちは、クラウド事業部の山路です。

今回は昨年11月にリリースされたEKS Pod Identityの紹介です。

aws.amazon.com

EKS Pod Identityとは

EKS Pod Identityは、IAM Role for Service Account (IRSA) と同様、Podに対してAWS IAM権限を付与し、Pod内のコンテナがAWSリソースにアクセスする権限を付与する機能です。

IRSAと比較したとき、Pod Identityには以下のような特徴があります。

  • AWSに閉じた権限管理: IRSAを利用するには、OIDC ID プロバイダーの作成が必要で、これはKubernetes クラスターの管理とは別のチームの責任になることもあります。一方でEKS Pod Identityの設定はすべてEKSで行われ、IAM権限の設定もすべてIAMで行われます。
  • 1つのIAMロールを複数のEKSクラスターで共有できる: IRSAではEKSクラスターごとに個別のプリンシパルが必要となるので、クラスター専用のIAMロールが必要です。一方でEKS Pod Identityは単一の IAM プリンシパルを使用し、複数のクラスターでIAMロールを共用できます。
  • スケーラビリティの向上: EKS Pod IdentityはEKS Pod Identity AgentというDaemonSetを利用します。これにより認証上の発行といった処理はNodeごとに1回で済むようになったようです。

なおEKS Pod Identityの仕組みは以下のように図示されています。

https://d2908q01vomqb2.cloudfront.net/fe2ef495a1152561572949784c16bf23abb28057/2023/12/20/Pod-Identity-Worklow.jpg

AWS公式ブログより

検証

ここではPod Identityの利用方法を簡単にさらっていきます。

前提条件

Pod Identityを利用するにはいくつかの条件があります。

  • EKS ver 1.24以上、かつ一定のPlatform version以上であること
  • データプレーンはEC2 (Linux) を使っている
  • EKS Add-onとして、IAM認証情報を利用する以下のアドオンではPod Identityを利用できません。
    • Amazon VPC CNI plugin for Kubernetes
    • AWS Load Balancer Controller
    • CSI ストレージドライバー
  • クラスター内の各Service Accountには、1つのIAM ロールを関連付けることができます。
  • EKS Pod Identity Agentは hostNetwork を使用し、Node上のリンクローカルアドレス上の 169.254.170.23 (IPv4アドレス) 、 80 / 2703 ポートを使用します。

docs.aws.amazon.com

IAMロールの作成

Pod中のコンテナが使用するIAMロールを用意します。今回はS3へのアクセス権限を付与するため、以下のファイルを使いました。

iam-for-pod-identity.yaml

AWSTemplateFormatVersion: '2010-09-09'
Resources:
  IAMRoleForPodIdentityTest:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - pods.eks.amazonaws.com
            Action:
              - sts:AssumeRole
              - sts:TagSession
      Path: /
      Policies:
        - PolicyName: iam-policy-for-pod-identity-test
          PolicyDocument:
            Version: '2012-10-17'
            Statement:
              - Effect: Allow
                Action: s3:ListAllMyBuckets
                Resource: '*'
      RoleName: iam-role-for-pod-identity-test

Pod Identity Agentのインストール

次にPod Identity AgentをEKSクラスターにインストールします。AgentのインストールはAWSマネジメントコンソールからも可能ですが、今回は以下のCloudFormationファイルを使いました。

addon.yaml

AWSTemplateFormatVersion: "2010-09-09"
Resources:
  AddonForPodIdentity:
    Type: AWS::EKS::Addon
    Properties:
      AddonName: "eks-pod-identity-agent"
      AddonVersion: "v1.0.0-eksbuild.1"
      ClusterName: "eks-cluster"

docs.aws.amazon.com

Agentインストール後はEKS上でPodとして確認できます。

[cloudshell-user@ip-10-132-76-136 ~]$ kubectl get pods -A
NAMESPACE     NAME                           READY   STATUS    RESTARTS   AGE
kube-system   aws-node-4xg2n                 2/2     Running   0          13m
kube-system   aws-node-sqr4t                 2/2     Running   0          13m
kube-system   coredns-58c6c4f5db-75878       1/1     Running   0          17m
kube-system   coredns-58c6c4f5db-v7xpt       1/1     Running   0          17m
kube-system   eks-pod-identity-agent-5g9rq   1/1     Running   0          6m35s
kube-system   eks-pod-identity-agent-jkgfs   1/1     Running   0          6m35s
kube-system   kube-proxy-df7dg               1/1     Running   0          13m
kube-system   kube-proxy-zqxpq               1/1     Running   0          13m

Service Account / Pod Identity Agentとの連携

Pod Identity Agentをインストールしたので、Podへの権限付与に利用するService Accountの作成、及びPod Identity Associationを設定します。なお少し試したところ、この2つのリソースはどちらを先に作成しても良いようですが、前段で作成したIAMロールが存在しない場合はエラーとなりました。

Service Account / Pod Identity Associationはそれぞれ以下のファイルで作成しました。

serviceaccount.yaml

apiVersion: v1
kind: ServiceAccount
metadata:
  name: pod-identity-test
  namespace: default

podidentityassociation.yaml

AWSTemplateFormatVersion: "2010-09-09"
Resources:
  PodIdentityAssociation:
    Type: AWS::EKS::PodIdentityAssociation
    Properties:
      ClusterName: "eks-cluster"
      Namespace: "default"
      RoleArn: "arn:aws:iam::<AWS Account ID>:role/iam-role-for-pod-identity-test"
      ServiceAccount: "pod-identity-test"

docs.aws.amazon.com

Podの作成

Pod Identityを利用する準備は整ったので、試しにAWS CLIイメージを使ってS3にアクセスできるかをチェックします。

以下のようにService Accountを指定してPodを作成すると、 aws s3 ls コマンドを使ってS3の一覧を取得できることを確認できます。

[cloudshell-user@ip-10-132-76-136 ~]$ kubectl run -n default --rm -it pod-identity-test --image=public.ecr.aws/aws-cli/aws-cli:2.15.3 --overrides='{ "spec": { "serviceAccount": "pod-identity-test" }  }' -- s3 ls
If you don't see a command prompt, try pressing enter.
2023-03-26 01:36:30 alb-unit-test-handler-20230326
2023-10-14 06:37:18 athena-output-20231014

<割愛>

2023-04-26 06:41:16 test-202304261541

Service Accountを指定しない、あるいは s3:ListAllMyBuckets 以外の操作をするとエラーが発生することも確認できます。

[cloudshell-user@ip-10-132-76-136 ~]$ kubectl run -n default --rm -it pod-identity-test --image=public.ecr.aws/aws-cli/aws-cli:2.15.3 --overrides='{ "spec": { "serviceAccount": "pod-identity-test" }  }' -- s3 ls test-202304261541
If you don't see a command prompt, try pressing enter.

An error occurred (AccessDenied) when calling the ListObjectsV2 operation: Access Denied
Session ended, resume using 'kubectl attach pod-identity-test -c pod-identity-test -i -t' command when the pod is running

なお、Pod Identityで使用するService Accountを指定したPodの状態を見ると、以下のように変数の設定やトークンのマウントを確認できます。

kubectl describe pod コマンドの実行結果

[cloudshell-user@ip-10-132-76-136 ~]$ kubectl get pods
NAME                                       READY   STATUS    RESTARTS   AGE
nginx-deployment-65947784f7-nwwhl          1/1     Running   0          3m55s


[cloudshell-user@ip-10-132-76-136 ~]$ kubectl describe pod nginx-deployment-65947784f7-nwwhl
Name:             nginx-deployment-65947784f7-nwwhl
Namespace:        default
Priority:         0
Service Account:  pod-identity-test
Node:             ip-192-168-121-100.ap-northeast-1.compute.internal/192.168.121.100
Start Time:       Wed, 03 Apr 2024 11:56:14 +0000
Labels:           app=nginx
                  pod-template-hash=65947784f7
Annotations:      <none>
Status:           Running
IP:               192.168.114.13
IPs:
  IP:           192.168.114.13
Controlled By:  ReplicaSet/nginx-deployment-65947784f7
Containers:
  nginx:
    Container ID:   containerd://72ec9c48f4e7ca4ea7e7cf2d0fbf971af7e183f991a535fe3591d2202611801d
    Image:          nginx:latest
    Image ID:       docker.io/library/nginx@sha256:6db391d1c0cfb30588ba0bf72ea999404f2764febf0f1f196acd5867ac7efa7e
    Port:           80/TCP
    Host Port:      0/TCP
    State:          Running
      Started:      Wed, 03 Apr 2024 11:56:21 +0000
    Ready:          True
    Restart Count:  0
    Environment: # Pod Identity Agentによって追加される
      AWS_STS_REGIONAL_ENDPOINTS:              regional
      AWS_DEFAULT_REGION:                      ap-northeast-1
      AWS_REGION:                              ap-northeast-1
      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
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-b27c2 (ro)
      /var/run/secrets/pods.eks.amazonaws.com/serviceaccount from eks-pod-identity-token (ro) # Pod Identity Agentによって追加される
Conditions:
  Type              Status
  Initialized       True 
  Ready             True 
  ContainersReady   True 
  PodScheduled      True 
Volumes:
  eks-pod-identity-token: # Pod Identity Agentによって追加される
    Type:                    Projected (a volume that contains injected data from multiple sources)
    TokenExpirationSeconds:  86400
  kube-api-access-b27c2:
    Type:                    Projected (a volume that contains injected data from multiple sources)
    TokenExpirationSeconds:  3607
    ConfigMapName:           kube-root-ca.crt
    ConfigMapOptional:       <nil>
    DownwardAPI:             true
QoS Class:                   BestEffort
Node-Selectors:              <none>
Tolerations:                 node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
                             node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
  Type    Reason     Age    From               Message
  ----    ------     ----   ----               -------
  Normal  Scheduled  3m36s  default-scheduler  Successfully assigned default/nginx-deployment-65947784f7-nwwhl to ip-192-168-121-100.ap-northeast-1.compute.internal
  Normal  Pulling    3m35s  kubelet            Pulling image "nginx:latest"
  Normal  Pulled     3m29s  kubelet            Successfully pulled image "nginx:latest" in 6.588s (6.588s including waiting)
  Normal  Created    3m29s  kubelet            Created container nginx
  Normal  Started    3m29s  kubelet            Started container nginx
[cloudshell-user@ip-10-132-76-136 ~]$ 

さいごに

今回はEKS Pod Identityの紹介でした。EKS Pod Identityはいくつかの条件があるものの、設定や管理のしやすさはIRSAよりも優れているため、条件を満たす場合は積極的に乗り換えを検討してもよさそうです。またeksctlはIRSAからPod Identityへの移行をコマンドで実行できるので、こういった機能を試すことも検討してみてはいかがでしょうか。

最後に、弊社はAWSアドバンスドティアサービスパートナー認定を受けております。また以下のようにAWSの活用を支援するサービスも行っているので、何かご相談したいことがあればお気軽にご連絡ください。

www.ap-com.co.jp