APC 技術ブログ

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

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

EKS Pod Identityの仕組みを深堀りしてみた

はじめに

こんにちは!クラウド事業部の中根です。
半年ほど前から、Kubernetesを学びEKSを使うようになりました。
その中で特に苦戦した、EKS Pod Identityの仕組みについて紹介します!

本記事について

想定読者

 EKS Pod Identityを使い始めたばかりの方、仕組みに興味がある方

書くこと

 EKS Pod Identityの仕組みを初心者目線で解説します。

書かないこと

 EKS Pod Identityの使い方。
 使い方を知りたい方は、こちらをご覧ください。
 EKS Pod IdentityでPodにIAM権限を付与する - APC 技術ブログ

その他

 EKS Pod Identityを全く使ったことのない方は、1度実装してみてから読むことをおすすめします!

EKS Pod Identityとは?

一言で言うと、PodにIAMアクセス許可を付与する機能です。

なぜ必要なのか?

前提として、KubernetesではPodにアクセス許可を与える時、サービスアカウントを介しています。

しかし、IAMロールをサービスアカウントに直接関連付ける機能がKubernetesにはありません。

この関連付けを行うために、EKS Pod IdentityまたはIRSAが必要になります。

IRSA(IAM Roles for Service Accounts)について

EKS Pod Identityと同様に、PodにIAMアクセス許可を付与する方法に、IRSAがあります。
もともとこちらが最初にあったのですが、別の方法としてEKS Pod Identityが昨年登場しました。
基本的にはEKS Pod Identityを使用し、EKS Pod Identityが使用できない場面ではIRSAを使うことが推奨されています。(以下リンク参考)

Unless you have specific usecases for IRSA, we recommend you use EKS Pod Identities when using EKS.

Identity and Access Management - Amazon EKS

積極的にEKS Pod Identityを利用しましょう!

なぜ仕組みを知る必要があるのか?

一言で言うと、EKSクラスタの構築をスムーズにするためです。
EKS Pod Identityは、設定が比較的簡単という点も魅力の一つです。
確かに簡単ではあるのですが、設定したけどうまく動いてくれない、といった場面によく出会うことになると思います。
特に、IaCなどのドキュメントと異なる手順で設定する場面で出会うことでしょう。

私の経験談(余談)

私は、このトラブルシューティングに結構時間を使わされてきました。
振り返った時に、先に仕組みを知っておけば、もっと早く簡単に解決できたな、と後悔しています。

具体的な事例だと、
  AWSサービスへのアクセス部分で認証エラーになる
  → 設定を確認し修正する
  → 設定は正しく修正したのにエラーのまま
  → その日は解決できず諦め
  → 次の日になったら突然エラーが解消されていた
ということがありました。
なんかわからんけど動いた、というのが一番恐ろしいですよね。
仕組みを学んでから、原因は「Podに環境変数が追加されてないままだったから」で、たまたま「Podが再起動」されたから正しく動作した、と理解しました。

仕組み解説

全体像

大まかな流れを図にしました。
①~⑤の詳細は後述します。

登場人物

図の登場人物について、補足します。

  • EKS Pod Identity API
    EKS Pod Identityで使うAPI一式です。
    Pod Identityの関連付けを作成したり、関連付け情報の取得を行うなどのAPIが含まれます。
    (AWS全般に言えることですが、マネジメントコンソール上で作成しても、裏側でAPIが呼ばれています。)

  • EKS Pod Identity Webhookサーバー
    EKSマネージドで作成される、Mutating Webhookです。
    Mutating Webhookは、簡単に言うと、「Kubernetesのリソースを作成・変更した時に、その設定を変更する機能」です。
    EKS Pod Identity Webhookサーバーの場合は、「Podを作る時に、AWSの認証情報を取得するためにPodの設定変更」をします。
    コントロールプレーン側にいるので普段は見えませんが、EKS Pod IdentityやIRSAを利用する上で欠かせない存在です。

  • SDK
    プログラミングで AWSサービスを利用するためのツールです。
    上図の場合だと、Pod(アプリケーション)で次のようなコードが実行された、というイメージです。

      cloudwatch = boto3.client('cloudwatch')
    
      # メトリクスデータをCloudWatchに送信
      response = cloudwatch.put_metric_data(
          Namespace='MyApp/Metrics', 
          MetricData=[
              {
                  'MetricName': 'PageViewCount',  
                  'Dimensions': [
                      {
                          'Name': 'PageType',
                          'Value': 'HomePage'
                      },
                  ],
                  'Timestamp': datetime.utcnow(), 
                  'Value': 1.0, 
                  'Unit': 'Count' 
              },
          ]
      )
    
  • EKS Pod Identity エージェント
    EKS Pod Identityを使用するためのエージェント(Pod)です。
    DaemonSetなので、クラスタ上の各ノードに1つ存在します。
    AWSサービスにアクセスする時に、このエージェントにリクエストして、エージェントに認証情報を取ってきてもらいます。

  • EKS Auth API
    EKS上の認証で使うAPI一式です。
    サービスアカウントトークンなどの情報を渡すと、それを検証してAWSサービスにアクセスするための一時的な認証情報を返してくれます。
    EKS Pod Identityでは、AssumeRoleForPodIdentity APIを使用します。

仕組みの詳細

EKS Pod IdentityでAWSサービスにアクセスするまでの流れ①~⑤について説明します。
EKS Pod Identityアドオンが有効な、EKSクラスタを作成し終わった時点からの説明になります。

①IAMロールの作成

Podに与えたい権限を持つIAMロールを作成します。
IAMロールの信頼ポリシーは指定されたものが必要なので、設定を忘れないようにしましょう。
ポリシーは以下リンクを参照してください。

IAM ロールを Kubernetes サービスアカウントに割り当てる - Amazon EKS

②Pod Identityの関連付け作成

作成したIAMロールと、Podに関連付けるサービスアカウントの組み合わせを登録します。
各クラスタ単位で設定する必要があります。
作成方法の例は以下リンクを参照してください。

IAM ロールを Kubernetes サービスアカウントに割り当てる - Amazon EKS

ざっくりまとめると、「このサービスアカウントは、このIAMロールを使いますよ」ということをクラスタに登録しています。

③Pod作成(kubectl apply)

Podを作成します。
ここでは、kubectl applyを実行した時の動きについて解説します。

  1. APIサーバーは、Pod作成のリクエストを受け取ります。
  2. Podを実際に作成する前に、MutatingWebhookConfigurationに従って、EKS Pod Identity Webhookサーバーにリクエストが送られます。
    こちらは、MutatingWebhookConfigurationの定義です。
    ここから、Podが作成されるとPod Identity Webhookサーバーの/mutateエンドポイントにリクエストが送られることが読み取れます。

  3. EKS Pod Identity Webhookサーバーは、Podに環境変数を追加します。
    いくつか追加されますが特筆すべき2つについて紹介します。
    AWS_CONTAINER_CREDENTIALS_FULL_URIは、認証情報を取得する時のリクエスト先(エンドポイント)です。
    AWS_CONTAINER_AUTHORIZATION_TOKEN_FILEは、認証の際に使うトークンの格納場所です。

  4. 同じタイミングで、サービスアカウントトークンの設定も行われます。
    serviceAccountTokenタイプの投影ボリューム(Projected Volume)が使われます。

  5. 変更が行われたPodが作成されます。
    この時点で、EKS Pod Identityによる認証情報取得の準備が整った状態になっています。

ざっくりまとめると、「Webhookサーバーが、Pod作成に割り込んで、AWSの認証する準備をしてくれる」ということです。

④一時的な認証情報取得

Podが起動し、やがてAWSサービス(例だとCloudWatch)にアクセスするコードが実行されます。
ここでは、コードが実行された時の動きについて解説します。

  1. 環境変数AWS_CONTAINER_CREDENTIALS_FULL_URIに対して、環境変数AWS_CONTAINER_AUTHORIZATION_TOKEN_FILEのトークンとともにリクエストを送ります。
    認証したい → 環境変数に認証用URIがある → リクエストしよう! という流れです。
    なお、認証方法には優先順位があります。
    そのため、コードの内容によってはこの環境変数が使用されず、別の認証方法を使う場合があります。
    ここでは、コードで明示的に指定しておらず、この環境変数が使われるものとします。
    SDKの認証設定の優先順位についてはこちらを参照してください。

  2. AWS_CONTAINER_CREDENTIALS_FULL_URIは、デフォルトでEKS Pod Identity エージェントを指します。
    つまり、EKS Pod Identity エージェントがリクエストを受け取ります。
    それぞれのソースも置いておきます。

  3. EKS Pod Identity エージェントは、リクエストを受け、AssumeRoleForPodIdentity を実行します。
    すると、サービスアカウントトークンを元に、Pod Identityの関連付けが検証され、一時的な認証情報が取得できます。
    具体的なAPIの中身まではわからないので、ここからは、以下の図やリファレンスからの推測になります。
    まず、AssumeRoleForPodIdentity のリクエストには、クラスタ名とサービスアカウントの情報が入っています。
    そこからEKS Pod Identity APIを使って、Pod Identityの関連付けを検索し、使用するIAMロールを特定していると思われます。

    AWS公式ブログより引用

ざっくりまとめると、「IAMサービスを使う時に、EKS Pod Identityエージェントにお願いして、認証情報の取得をしてもらう」ということです。

⑤アクセス

取得した認証情報を使って、AWSサービスにアクセスすることができるようになります!

終わりに

今回はEKS Pod Identityの仕組みについて解説しました!
仕組みを知っておくと障害切り分けが捗り、結果的にEKSクラスタの構築がスムーズになります!
皆様の参考になれば幸いです!

参考リンク集

EKS Pod Identity の詳細を理解する - Amazon EKS

Amazon EKS Pod Identity simplifies IAM permissions for applications on Amazon EKS clusters | AWS News Blog

Amazon EKS Pod Identity: a new way for applications on EKS to obtain IAM credentials | Containers