1
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なしIRSAへの道 ― 第3回:Mutating WebhookでPodを自動書き換えしてIRSAを簡単にする

1
Last updated at Posted at 2026-02-21

この記事は、「EKSを使わずにIRSAを使う」試みの3回目の記事です。

これまでの記事の内容と課題

以下の2つの記事で、kubeadmで構築したKubernetesクラスターにおいて、ServiceAccountを使ってIAMロールを引き受けられる(AssumeRoleできる)状態、つまりIRSAが使える状態になっています。

しかしながら、Podのマニフェストに以下を毎回書く必要があります。

  • AWS_ROLE_ARN / AWS_WEB_IDENTITY_TOKEN_FILEenv
  • projectedserviceAccountToken ボリューム定義と volumeMount

これは動作確認としては分かりやすいのですが、「Podのマニフェストが冗長」「コピペが増える」「書き間違いが起きる」などのつらさが出ます。

そこで今回は、EKSでも使われている amazon-eks-pod-identity-webhook をインストールし、Mutating WebhookによってPod作成時に必要な定義を自動注入させます。結果として、PodマニフェストからRoleArnやprojected volumeの記述を消し、シンプルに書けることを目標にします。

この記事でやること

  • Mutating Webhook(Admission Webhook)が何を解決するかを整理する
  • amazon-eks-pod-identity-webhook をHelm(Helmfile)でインストールする
  • ServiceAccountにロールを紐付け、Pod側は最小限のマニフェストでIRSAを使えることを確認する

参考情報

本記事の記載内容を実現するための環境は、以下の k8s-irsa-without-eks で構築可能です。

Mutating Webhook とは(今回の文脈)

Kubernetesでは、リソースの作成・更新などのリクエストがkube-apiserverに到達した時点でAdmission Controllerが介入し、リクエストの許可/拒否や、リソース内容の書き換え(ミューテーション)を行えます。例えば、ポリシーに違反するPodを拒否したり、運用ルールに沿うようにPodの定義を自動で補正できます。

このうちMutating Webhookは、kube-apiserverが受け取ったPodの作成リクエストに対してフィールドを追加・変更するパッチを適用し、その結果を「実体として作られるPod」の定義に反映できます。

今回インストールする amazon-eks-pod-identity-webhook は、ざっくり以下を行います。

  • Podが参照しているServiceAccountに、IRSA用の注釈(例: eks.amazonaws.com/role-arn)が付いているかを見る
  • 条件に合えば、Podに以下を注入する
    • AWS_ROLE_ARN などの env
    • Web Identityトークンのファイルを置くための projected ボリュームと volumeMount

つまり、前回記事でPodマニフェストに手書きしていた部分を、Webhookが自動で差し込んでくれるイメージです。

amazon-eks-pod-identity-webhook のインストール

以下のHelmfileを使ってインストールします。

amazon-eks-pod-identity-webhook.yaml
repositories:
  - name: jkroepke
    url: https://jkroepke.github.io/helm-charts/

releases:
  - chart: jkroepke/amazon-eks-pod-identity-webhook
    version: 2.6.0
    createNamespace: false
    name: amazon-eks-pod-identity-webhook
    namespace: kube-system
    values: # 環境に応じて適宜変更ください
      - config:
          defaultAwsRegion: ap-northeast-1

以下はインストールコマンドです。

helmfile apply -f amazon-eks-pod-identity-webhook.yaml

各リソースがデプロイされているのを確認します。

$ kubectl -n kube-system get svc,deploy,po -l app.kubernetes.io/name=amazon-eks-pod-identity-webhook
NAME                                      TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)             AGE
service/amazon-eks-pod-identity-webhook   ClusterIP   10.106.84.229   <none>        8443/TCP,9999/TCP   94s

NAME                                              READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/amazon-eks-pod-identity-webhook   1/1     1            1           94s

NAME                                                   READY   STATUS    RESTARTS   AGE
pod/amazon-eks-pod-identity-webhook-5d584bc69d-92jp4   1/1     Running   0          93s

以下のように、MutatingWebhookConfigurationリソースもデプロイされていることを確認できます。

$ kubectl -n kube-system get mutatingwebhookconfigurations | rg -i 'pod-identity'
amazon-eks-pod-identity-webhook                        1          3m38s

IAMロールに紐付けるServiceAccountの作成

前回記事と同様に、IAMロールを引き受けるServiceAccountを作成します。

基本は、対象Podが使うServiceAccountにRoleArnのannotationを付与します。

例(前回と同じ default/my-app を使う想定):

AWS_ACCOUNT_ID=012345678901
ROLE_NAME='default/my-app'

kubectl -n default create sa my-app
kubectl -n default annotate sa my-app "eks.amazonaws.com/role-arn=arn:aws:iam::${AWS_ACCOUNT_ID}:role/${ROLE_NAME}"

以下は、上記コマンドをマニフェストで表現したものです。RoleArnのannotationが追加されている点がポイントです。

apiVersion: v1
kind: ServiceAccount
metadata:
  name: my-app
  namespace: default
  annotations: # ポイント
    eks.amazonaws.com/role-arn: "arn:aws:iam::012345678901:role/default/my-app"

ここで紐付けるIAMロールの信頼ポリシー(sts:AssumeRoleWithWebIdentity)は、前回記事の内容と同様に sub=system:serviceaccount:default:my-appaud=sts.amazonaws.com を満たすようにしておく必要があります。

ServiceAccountを使うPodの作成

以下のように、作成したServiceAccountを使うPodのマニフェストを用意します。

irsa-test.pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: irsa-test
  namespace: default
spec:
  serviceAccountName: my-app
  containers:
  - name: app
    image: public.ecr.aws/aws-cli/aws-cli:latest
    command: ["sh","-c"]
    args:
      - |
        tail -f /dev/null

マニフェストをもとに、Podをデプロイします。

kubectl apply -f irsa-test.pod.yaml

Podがデプロイされたことを確認します。

$ kubectl get po -n default irsa-test
NAME        READY   STATUS    RESTARTS   AGE
irsa-test   1/1     Running   0          25s

前回記事と同様に、PodがIAMロールを引き受けられている(AssumeRoleできている)のを確認できます。

$ kubectl exec -n default -it irsa-test -- aws sts get-caller-identity
{
    "UserId": "AROAXK6M****:botocore-session-012345678901",
    "Account": "012345678901",
    "Arn": "arn:aws:sts::012345678901:assumed-role/my-app/botocore-session-012345678901"
}
$ kubectl exec -n default -it irsa-test -- aws configure list
NAME       : VALUE                    : TYPE             : LOCATION
profile    : <not set>                : None             : None
access_key : ****************4HRP     : assume-role-with-web-identity :
secret_key : ****************pBSf     : assume-role-with-web-identity :
region     : ap-northeast-1           : env              : ['AWS_REGION', 'AWS_DEFAULT_REGION']

Podのマニフェストがどれだけ簡単になったかの確認

前回記事のPodのマニフェストではAWS_ROLE_ARNなどの環境変数やprojected volumeの設定が必要でしたが、今回はserviceAccountNameの指定だけで済み、非常にシンプルになっています。

前回記事のPodのマニフェストとの差分は以下です。

apiVersion: v1
kind: Pod
metadata:
  name: irsa-test
  namespace: default
spec:
  serviceAccountName: my-app
  containers:
   - name: app
     image: public.ecr.aws/aws-cli/aws-cli:latest
-    env:
-    - name: AWS_ROLE_ARN
-      value: arn:aws:iam::012345678901:role/default/my-app
-    - name: AWS_WEB_IDENTITY_TOKEN_FILE
-      value: /var/run/secrets/tokens/aws-token
     command: ["sh","-c"]
     args:
       - |
         tail -f /dev/null
-    volumeMounts:
-    - name: aws-token
-      mountPath: /var/run/secrets/tokens
-      readOnly: true
-  volumes:
-  - name: aws-token
-    projected:
-      sources:
-      - serviceAccountToken:
-          path: aws-token
-          audience: sts.amazonaws.com
-          expirationSeconds: 3600

amazon-eks-pod-identity-webhookによって変更された箇所の確認

作成されたPodのマニフェストを、以下のコマンドで確認してみましょう。

kubectl get po irsa-test -oyaml

上記の出力とPodのデプロイに使ったマニフェストを比較すると、次のような差分があることがわかりました。

※ 実際のマニフェストでは他の差分もありますが、ここでは関係する差分だけを出力しています。

 apiVersion: v1
 kind: Pod
 metadata:
   name: irsa-test
   namespace: default
 spec:
   serviceAccountName: my-app
   containers:
   - name: app
     args:
     - |
       tail -f /dev/null
     command:
     - sh
     - -c
+    env:
+    - name: AWS_STS_REGIONAL_ENDPOINTS
+      value: regional
+    - name: AWS_DEFAULT_REGION
+      value: ap-northeast-1
+    - name: AWS_REGION
+      value: ap-northeast-1
+    - name: AWS_ROLE_ARN
+      value: arn:aws:iam::012345678901:role/default/my-app
+    - name: AWS_WEB_IDENTITY_TOKEN_FILE
+      value: /var/run/secrets/eks.amazonaws.com/serviceaccount/token
     image: public.ecr.aws/aws-cli/aws-cli
+    volumeMounts:
+    - mountPath: /var/run/secrets/eks.amazonaws.com/serviceaccount
+      name: aws-iam-token
+      readOnly: true
+  volumes:
+  - name: aws-iam-token
+    projected:
+      defaultMode: 420
+      sources:
+      - serviceAccountToken:
+          audience: sts.amazonaws.com
+          expirationSeconds: 86400
+          path: token

AWS CLIに関する環境変数とprojected volumeの設定が追加されていますね。これは、amazon-eks-pod-identity-webhookがPod作成時にMutating Webhookによって自動注入したものです。

トリガーは my-app のServiceAccountリソース作成時に追加した以下のannotationです。

  annotations:
    eks.amazonaws.com/role-arn: "arn:aws:iam::012345678901:role/default/my-app"

ServiceAccountを作成する際に、うっかりこのannotationが抜ける(または内容が間違っている)とAWSに認証できないので、使用時はお気をつけください。

おわりに

PodからIRSAでAWSのリソースにアクセスする際に、前回記事ではAWSにアクセスするための設定を書く必要がありましたが、amazon-eks-pod-identity-webhookを使うことで、それらを書かずに済むことを確認できました。Mutating WebhookによってPodの内容が書き換えられる様子も確認できたので、私自身もKubernetesに関する理解が一つ進んだ気がします。

IRSAの使い勝手を改善したKubernetesクラスターに、次回記事ではaws-ebs-csi-driverをインストールした後に、PVCリソースを作成してAWS EBSのボリュームが調達できることを確認する予定です。

1
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
1
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?