EKS の Amazon CloudWatch Observability アドオンを EKS Pod Identity を利用して設定してみた
少し前の話題ですが、Amazon CloudWatch Observability アドオン(以降 Observability アドオン)は v3.1.0 から EKS Pod Identity(以降 Pod Identity) に対応しています。
Pod Identity は 2023 年末に出た機能ですが、Observability アドオンは長らく対応していませんでした。
背景として Observability アドオンが CloudWatch エージェントと Fluent Bit を含んでおり、Fluent Bit が Pod Identity に長らく対応していなかったというものがあります。
aws-for-fluent-bit のバージョンで言えば v2.32.5 になったタイミングで Fluent Bit 側が対応したので、Observability アドオンも Pod Identity を利用できるようになったと考えられます。
構築してみる
実際に環境を作成して動作確認してみます。
各種リソースは Terraform の AWS EKS Terraform module で作ってみました。
VPC 周り
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = "~> 5.17.0"
name = "eks-vpc"
cidr = "10.0.0.0/16"
azs = ["ap-northeast-1a", "ap-northeast-1c", "ap-northeast-1d"]
public_subnets = ["10.0.0.0/24", "10.0.1.0/24", "10.0.2.0/24"]
private_subnets = ["10.0.100.0/24", "10.0.101.0/24", "10.0.102.0/24"]
enable_nat_gateway = true
single_nat_gateway = true
public_subnet_tags = {
"kubernetes.io/role/elb" = 1
}
private_subnet_tags = {
"kubernetes.io/role/internal-elb" = 1
}
}
EKS 周り
locals {
cluster_name = "test-cluster"
k8s_service_account_namespace = "amazon-cloudwatch"
k8s_service_account_name = "cloudwatch-agent"
}
module "eks" {
source = "terraform-aws-modules/eks/aws"
version = "~> 20.36.0"
cluster_name = local.cluster_name
cluster_version = "1.32"
cluster_endpoint_public_access = true
cluster_endpoint_private_access = true
vpc_id = module.vpc.vpc_id
subnet_ids = module.vpc.private_subnets
enable_cluster_creator_admin_permissions = true
cluster_compute_config = {
enabled = true
node_pools = ["general-purpose"]
}
bootstrap_self_managed_addons = false
cluster_addons = {
"observability" = {
name = "amazon-cloudwatch-observability"
version = "v4.0.0"
pod_identity_role_arn = {
role_arn = aws_iam_role.observability_addon.arn
service_account = local.k8s_service_account_name
}
}
}
}
data "aws_iam_policy_document" "allow_pod_identity" {
statement {
effect = "Allow"
principals {
type = "Service"
identifiers = ["pods.eks.amazonaws.com"]
}
actions = [
"sts:AssumeRole",
"sts:TagSession"
]
}
}
resource "aws_iam_role" "observability_addon" {
name = "AmazonCloudWatchObservabilityAddonRole"
assume_role_policy = data.aws_iam_policy_document.allow_pod_identity.json
}
resource "aws_iam_role_policy_attachment" "observability_addon" {
role = aws_iam_role.observability_addon.name
policy_arn = "arn:aws:iam::aws:policy/CloudWatchAgentServerPolicy"
}
resource "aws_eks_pod_identity_association" "observability_addon" {
cluster_name = module.eks.cluster_name
namespace = local.k8s_service_account_namespace
service_account = local.k8s_service_account_name
role_arn = aws_iam_role.observability_addon.arn
}
EKS Auto Mode の場合、Pod Identity エージェントが最初から入っているのも嬉しいポイントです。
下記のような信頼ポリシーの IAM ロールを作成して、サービスアカウントと IAM ロールを関連付けるだけで、Pod の権限管理を行うことができます。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "pods.eks.amazonaws.com"
},
"Action": ["sts:TagSession", "sts:AssumeRole"]
}
]
}
構築完了後、必要な Pod は全て Running 状態になっていました。
% kubectl get pod -n amazon-cloudwatch
NAME READY STATUS RESTARTS AGE
amazon-cloudwatch-observability-controller-manager-7c886665kc2v 1/1 Running 0 18m
cloudwatch-agent-hg6lf 1/1 Running 0 17m
fluent-bit-fcm4r 1/1 Running 0 18m
動作確認用に Nginx の Pod も起動しておきます。
apiVersion: apps/v1
kind: Deployment
metadata:
namespace: default
name: nginx
spec:
selector:
matchLabels:
app.kubernetes.io/name: nginx
replicas: 2
template:
metadata:
labels:
app.kubernetes.io/name: nginx
spec:
containers:
- image: nginx
imagePullPolicy: Always
name: nginx
ports:
- containerPort: 80
resources:
requests:
cpu: "0.5"
リクエストを送りたいので、ついでに Service も作成します。
apiVersion: v1
kind: Service
metadata:
namespace: default
name: nginx
spec:
ports:
- port: 80
targetPort: 80
protocol: TCP
type: NodePort
selector:
app.kubernetes.io/name: nginx
動作確認
では動作確認に移ります。
まずは CloudWatch Container Insights のダッシュボードを確認します。
クラスターレベルのメトリクスも良い感じに見れています。
Pod レベルのメトリクスも良い感じに見れていました。
ログ出力についても確認します。
まず、Nginx の Service に対してリクエストを送ります。
# curl -I http://nginx.default.svc.cluster.local
HTTP/1.1 200 OK
Server: nginx/1.27.5
Date: Thu, 22 May 2025 11:46:42 GMT
Content-Type: text/html
Content-Length: 615
Last-Modified: Wed, 16 Apr 2025 12:01:11 GMT
Connection: keep-alive
ETag: "67ff9c07-267"
Accept-Ranges: bytes
CloudWatch のロググループを確認すると、/aws/containerinsights/test-cluster/application
に Nginx Pod のログが出力されていました。
{
"time": "2025-05-22T11:46:12.421510971Z",
"stream": "stdout",
"_p": "F",
"log": "10.0.100.112 - - [22/May/2025:11:46:12 +0000] \"GET / HTTP/1.1\" 200 615 \"-\" \"curl/7.88.1\" \"-\"",
"kubernetes": {
"pod_name": "nginx-7c64dfbfdc-bqbxd",
"namespace_name": "default",
"pod_id": "cf681c20-827c-42eb-9476-d75bf93542c9",
"host": "i-00ce998d7d80ce788",
"container_name": "nginx",
"docker_id": "f842e5d8eb5948c45dfaf646429787629d5d19def8a19c47b48b9a4f40757be1",
"container_hash": "docker.io/library/nginx@sha256:fb39280b7b9eba5727c884a3c7810002e69e8f961cc373b89c92f14961d903a0",
"container_image": "docker.io/library/nginx:latest"
}
}
良い感じですね!
最後に
主要なアドオンは一通り Pod Identity に対応したように思います。
新規作成時はもちろん、今まで IRSA(IAM Roles for Service Accounts) で使っていた場合でも積極的に Pod Identity を使っていくと、特に複数クラスターが存在する環境で設定がシンプルになって嬉しい気がします!