EKS Pod Identity を活用するメリット

この記事は はてなエンジニア Advent Calendar 2023 の 26 日目の記事です。 本日からはてなエンジニア Advent Calendar 2023 はオーバーランに突入します。昨日は id:d-haru さん明日は id:chaya2z さんとなっています。

私が所属するチームでは EKS を利用してサービスを運用しています。

developer.hatenastaff.com

今年の AWS re:Invent 2023 内でも EKS 関連のアップデートがありましたが、特に EKS Pod Identity という便利な機能に注目したので利用してみました。

EKS Pod Identity とは

EKS を利用者にとって嬉しい機能が発表されました。これまで Pod への IAM 権限の割り振りは IRSA ( IAM Roles for Service Accounts ) を利用するのが一般的でした。Pod に権限を与えるという結果は両者変わらないのですがリソースの管理方法が異なります。

IRSA を利用した場合は以下のような manifest を書くことで kubernetes の ServiceAccount と IAM Role を紐づけていました。

 apiVersion: v1
 kind: ServiceAccount
 metadata:
   name: sample
   annotations:
     eks.amazonaws.com/role-arn: arn:aws:iam::XXXXXXXXXXXX:role/sample-role-arn

ServiceAccount リソースの annotation に IAM Role の Arn を記述しています。manifest に Arn を埋め込むのって面倒ですよね。特に IaC などしている場合、IaC で作成したリソースの Arn をなんとかして埋め込みたくなると思います。

今回、発表された EKS Pod Identity は IAM Role と ServiceAccount の紐づけを kubernetes 側ではなく EKS 側の設定で行うことができるため、IaC との親和性も高く権限管理が簡素化されます。

使い方と解説

アドオンのインストール

コンソールを使った方法は以下のリンクを参照するのが良いと思います。

aws.amazon.com

今回は Terraform を利用した方法で試してみます。

まず、EKS Pod Identity を利用するには eks-auth:AssumeRoleForPodIdentity のポリシーが必要です。事前に Node の Role に AmazonEKSWorkerNodePolicy を利用するかカスタムポリシーでを作成してアタッチしておく必要があります。

EKS Pod Identity は EKS アドオンで追加できるようになっています。 EKS の Terraform module を利用した場合、以下のようにしてアドオンを追加することができます。

module "eks" {
  source  = "terraform-aws-modules/eks/aws"


  cluster_name    = var.cluster_name
  cluster_version = var.cluster_version


  ...
  
  cluster_addons = {
    kube-proxy             = {}
    eks-pod-identity-agent = {}
  } 
}

余談ですが上記に記述しているアドオンの name は以下のコマンドを叩くことで確認することができます。

  • aws eks describe-addon-versions | grep addonName

さらにアドオンのバージョンやconfigのオプションについても以下のコマンドで確認することができます。

  • aws eks describe-addon-versions --addon-name eks-pod-identity-agent

  • aws eks describe-addon-configuration --addon-name eks-pod-identity-agent --addon-version v1.0.0-eksbuild.1

EKS Pod Identity のアドオンを有効にすると kuberntes クラスターの kube-system Namespace に eks-pod-identity-agent が Daemonset としてインストールされエージェントの Pod が起動します。

$ kubectl get daemonset -n kube-system eks-pod-identity-agent
NAME                     DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE
eks-pod-identity-agent   1         1         1       1            1           <none>          3d1h

このエージェントは Node に付与した AssumeRoleForPodIdentity のアクションを利用して、一時的な認証情報を取得し、コンテナ内の SDK がその認証情報を利用できるようにします。 Node 側でまとめて認証してくれるので各 Pod 毎に認証をすることがなくなっています。

docs.aws.amazon.com

IAM Role の信頼ポリシー

IRSA ではクラスター毎に OIDC プロバイダーを作成する必要があり、OIDC プロバイダーが EKS と IAM の信頼関係を確率していました。 そのためIAM Role に以下のような信頼ポリシーを設定する必要がありました。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Federated": "arn:aws:iam::ACCOUNT_ID:oidc-provider/oidc.eks.AWS_REGION.amazonaws.com/id/EXAMPLED539D4633E53DE1B716D3041E"
      },
      "Action": "sts:AssumeRoleWithWebIdentity",
      "Condition": {
        "StringEquals": {
          "oidc.eks.AWS_REGION.amazonaws.com/id/EXAMPLED539D4633E53DE1B716D3041E:sub": "system:serviceaccount:SERVICE_ACCOUNT_NAMESPACE:SERVICE_ACCOUNT_NAME",
          "oidc.eks.AWS_REGION.amazonaws.com/id/EXAMPLED539D4633E53DE1B716D3041E:aud": "sts.amazonaws.com"
        }
      }
    }
  ]
}

クラスター固有の情報が含まれているため、クラスターが増える度に全ての IAM Role の信頼ポリシーを更新する手間が発生していました。

EKS Pod Identity を利用するとその手間は無くなり、OIDC プロバイダーも作成する必要もありません。 IAM Roleの信頼ポリシーは以下を追加すればよくて、固有のクラスター情報を含まないシンプルなものになりました。

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

クラスターの BlueGreen アップグレード時の IAM Role の更新の手間が減り作業もシンプルになります。

ServiceAccount と IAM Roleの関連付け

kubernetes の ServiceAccount と IAM Role の関連付けについてですが、マネコンから紐づけることもできますが以下の Terraform リソースを利用することで IaC 管理できます。

registry.terraform.io

resource "aws_eks_pod_identity_association" "example" {
  cluster_name    = aws_eks_cluster.example.name
  namespace       = "example"
  service_account = "example-sa"
  role_arn        = aws_iam_role.example.arn
}

Terraform で IAM Role を作成していれば Arn の Attribute を参照することができるので ServiceAccount と IAM Role の関連付けが Terraform 内だけで完結します。もう manifest に Arn を記述する必要はありません。

まとめ

まとめると以下のような設定が必要です。

  • Node の IAM Role に eks-auth:AssumeRoleForPodIdentity を付与する
  • EKS Pod Identity アドオンをインストール
  • IAM Role の信頼ポリシーを EKS Pod Identity に対応したものに設定する
  • IAM Role と ServiceAccount を関連付ける

上記4点を全て IaC で管理できるので EKS と kubernetes のリソースを独立して管理できます。必要なリソースと内部的な処理も簡略化されているため導入・運用の観点からもこれまでよりも良くなっていると感じました。

2024/01/05 追記

利用しているサービスによっては SDK のバージョンが古く利用できない場合があるため注意が必要でした。secrets-store-csi-driver-provider-aws で利用している SDK のバージョンが v1.47.10 と古いため直近での EKS Pod Identity の利用は見送るつもりです。今後、利用できることを楽しみにしています。

github.com

docs.aws.amazon.com

参考