EKS Pod Identityを利用してセキュアにkubernetesリソースからAWSリソースにアクセスする
はじめに
AWS EKS (Elastic Kubernetes Service) を利用している場合、Kubernetes上のリソースだけで完結させることはほぼなく、多くの場合、kubernetesの世界にないAWSリソースにアクセスする必要があります。例えば、S3バケットへのファイルのアップロード、DynamoDBのテーブルへのデータの読み書き、SQSキューへのメッセージの送受信など、様々なユースケースが考えられます。その際に使用するのがPod Identityです。
Pod Identityとは
Pod Identityは、Kubernetes上のPodがAWSリソースにアクセスするための認証情報を安全に取得するための仕組みです。これにより、PodはIAMロールを使用してAWSリソースにアクセスできるようになります。
Pod Identityは名前に反して、Pod単位でのアクセス制御をするわけではありません。Pod IdentityはEKSクラスタ上の Kubernetes Service Accountに対してIAMロールを関連付けます。 PodはService Accountを通じてIAMロールを取得し、そのIAMロールを使用してAWSリソースにアクセスします。
似たような仕組みとして、IRSA (IAM Roles for Service Accounts) がありますが、Pod Identityはより簡単に設定できるように設計されています。Pod Identityは、AWS EKSの公式アドオンとして提供されており、AWS CLIやAWS Management Consoleを使用して簡単にインストールできます。
IRSAに関してはこの記事では詳しく触れません。より詳細な情報はAWSの公式ドキュメントを参照してください。
Pod Identityの仕組み
Pod Identityは、EKSクラスター上でPodがAWSリソースに安全にアクセスするための仕組みです。以下の手順で動作します。
- Pod Identity AgentをEKSクラスターにインストール
- 必要な権限を持つIAMロールを作成
- Service AccountとIAMロールを関連付け
- PodがService Accountを介してAWSリソースにアクセス
このプロセスでは、次のような認証フローが実行されます。
- Pod Identity AgentがService Accountトークンを監視
- PodがAWSリソースにアクセスを試みると、Agentがトークンを使用してAWS STSから一時的な認証情報を取得
- 取得した認証情報を用いてPodがAWSリソースにアクセス
この仕組みにより、認証情報の自動ローテーションやPod単位での細かいアクセス制御が可能になり、認証情報がPod内に保存されるリスクを回避できます。
Pod Identityの設定方法
Pod Identity Agentアドオンのインストール
Pod Identity Agentは、EKSクラスターにアドオンとしてインストールします。
インストールはAWS CLI、GUI、そしてterraform eks moduleを使用してインストールすることができます。
Pod Identity Agentをインストールするとeks-pod-identity-agent
というpodが作成されていることが確認できます。
❯ kubectl get -n kube-system pod | grep identity
eks-pod-identity-agent-v8x4n 1/1 Running 0 6m2s
IAMロールの作成
Pod IdentityでAWSリソースにアクセスするためには、以下のような信頼ポリシーを持つIAMロールを作成する必要があります。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowEksAuthToAssumeRoleForPodIdentity",
"Effect": "Allow",
"Principal": {
"Service": "pods.eks.amazonaws.com"
},
"Action": [
"sts:AssumeRole",
"sts:TagSession"
]
}
]
}
このとき、AssumeRole
はKubernetes Service AccountがIAMロールを引き受ける際に必要になります。
また、Pod IdentityはAWS STS へのリクエストにセッションタグを含めるために TagSession を使用します。
この信頼ポリシーをアタッチしたIAMロールに、podに付与したい権限を設定することで、PodがAWSリソースにアクセスできるようになります。
IAMロールとService Accountの関連付け
EKS上のService AccountとIAMロールを関連付けます。GUI上から設定することが可能です。
クラスター > アクセス > Pod Identity の関連付け > 作成
から、権限を与えたいpodに割り当てられているService Accountとnamespaceを選択します。
設定が完了すると、以下の画像のような状態になるはずです。
これにてPod Identityの設定は終了です。
terraform moduleの紹介
ここまでおこなってきた、必要なポリシー、権限をもったIAMロールの作成およびKubernetes Service Accountの作成をすべて担ってくれるterraform moduleが公開されています。
例えば、AWS EBS CSI Driver用のPod Identityはこのモジュールを使って以下のように設定することができます。
module "aws_ebs_csi_pod_identity" {
source = "terraform-aws-modules/eks-pod-identity/aws"
version = "1.11.0"
name = "ebs-csi-controller"
attach_aws_ebs_csi_policy = true
# Pod Identity Associations
associations = {
"ebs-csi-controller" = {
cluster_name = "my-cluster"
namespace = "kube-system"
service_account = "ebs-csi-controller-sa"
}
}
}
EBS CSI Driverについては公式ドキュメントを見てください。ドキュメントでは煩雑になりがちな設定を、このモジュールを使うことで非常に簡潔に、宣言的に書くことができます。
EBS CSI Driverは、通常kube-system
namespaceにデプロイされ、ebs-csi-controller-sa
というService Accountを使用します。このモジュールを使うことで、IAMロールとService Accountの関連付けが簡単に行えます。
必要となる権限セットもモジュール側で用意がされており、IAMロールのことをほぼ考えずに、直にKubernetes Service Accoutnに権限を付与しているような感覚で使うことができます。
モジュールには、現在以下の権限セットが用意されており、フラグで簡単に権限を付与できます。
input | description |
---|---|
attach_amazon_managed_service_prometheus_policy | Amazon Managed Service for Prometheus用のポリシーをアタッチします。 |
attach_aws_appmesh_controller_policy | AWS App Mesh用のポリシーをアタッチします。 |
attach_aws_appmesh_envoy_proxy_policy | AWS App Mesh Envoy Proxy用のポリシーをアタッチします。 |
attach_aws_cloudwatch_observability_policy | AWS CloudWatch Observability用のポリシーをアタッチします。 |
attach_aws_ebs_csi_policy | AWS EBS CSI Driver用のポリシーをアタッチします。 |
attach_aws_efs_csi_policy | AWS EFS CSI Driver用のポリシーをアタッチします。 |
attach_aws_fsx_lustre_csi_policy | AWS FSx for Lustre CSI Driver用のポリシーをアタッチします。 |
attach_aws_gateway_controller_policy | AWS Gateway Load Balancer用のポリシーをアタッチします。 |
attach_aws_lb_controller_policy | AWS Load Balancer Controller用のポリシーをアタッチします。 |
attach_aws_lb_controller_targetgroup_binding_only_policy | AWS Load Balancer Controller TargetGroup Binding用のポリシーをアタッチします。 |
attach_aws_node_termination_handler_policy | AWS Node Termination Handler用のポリシーをアタッチします。 |
attach_aws_privateca_issuer_policy | AWS Private CA Issuer用のポリシーをアタッチします。 |
attach_aws_vpc_cni_policy | AWS VPC CNI用のポリシーをアタッチします。 |
attach_cert_manager_policy | AWS Certificate Manager用のポリシーをアタッチします。 |
attach_cluster_autoscaler_policy | AWS Cluster Autoscaler用のポリシーをアタッチします。 |
attach_custom_policy | カスタムポリシーをアタッチします。 |
attach_external_dns_policy | AWS External DNS用のポリシーをアタッチします。 |
attach_external_secrets_policy | AWS External Secrets(Secret Managerm )用のポリシーをアタッチします。 |
attach_mountpoint_s3_csi_policy | AWS S3 Mountpoint CSI Driver用のポリシーをアタッチします。 |
attach_velero_policy | AWS Velero用のポリシーをアタッチします。 |
このように、用意されている権限セットは豊富ですが、必要に応じてカスタムポリシーを作成することも可能です。以下は、カスタムポリシーを作成してPod Identityを設定する例です。
module "custom_pod_identity" {
source = "terraform-aws-modules/eks-pod-identity/aws"
version = "1.11.0"
name = "custom-pod-identity"
attach_custom_policy = true
policy_statements = [
{
sid = "AllowReadingMetricsFromCloudWatch"
actions = [
"cloudwatch:DescribeAlarmsForMetric",
"cloudwatch:DescribeAlarmHistory",
"cloudwatch:DescribeAlarms",
"cloudwatch:ListMetrics",
"cloudwatch:GetMetricData",
"cloudwatch:GetInsightRuleReport"
]
resources = ["*"]
},
]
# Pod Identity Associations
associations = {
"grafana-eks" = {
cluster_name = "my-cluster"
namespace = "my-namespace"
service_account = "my-service-account"
}
}
}
このように、それぞれのリソースで定義すると散らばりがちなIAMロールの設定を、モジュールを使うことで一元管理することができます。これにより、IAMロールの設定ミスや権限の過剰付与を防ぐことができ、セキュリティを向上させることができます。
まとめ
Pod Identityを使用することで、Kubernetes上のPodから安全にAWSリソースにアクセスすることができます。主なメリットは以下の通りです:
- セキュアな認証情報の管理
- きめ細かいアクセス制御
- 簡単な設定と管理
適切に設定を行い、定期的に動作確認とセキュリティ監査を行うことで、安全なアプリケーション運用が可能になります。セキュリティのベストプラクティスに従うことで、より堅牢なシステムを構築することができます。
また、terraform moduleを使用することで、Pod Identityの設定を簡素化することが可能になります。
Discussion