EKS の Amazon CloudWatch Observability アドオンを EKS Pod Identity を利用して設定してみた

EKS の Amazon CloudWatch Observability アドオンを EKS Pod Identity を利用して設定してみた

少し前の話題ですが、Amazon CloudWatch Observability アドオン(以降 Observability アドオン)は v3.1.0 から EKS Pod Identity(以降 Pod Identity) に対応しています。

https://github.com/aws-observability/helm-charts/releases/tag/amazon-cloudwatch-observability-3.1.0

Pod Identity は 2023 年末に出た機能ですが、Observability アドオンは長らく対応していませんでした。
背景として Observability アドオンが CloudWatch エージェントと Fluent Bit を含んでおり、Fluent Bit が Pod Identity に長らく対応していなかったというものがあります。
aws-for-fluent-bit のバージョンで言えば v2.32.5 になったタイミングで Fluent Bit 側が対応したので、Observability アドオンも Pod Identity を利用できるようになったと考えられます。

https://github.com/aws/aws-for-fluent-bit/releases/tag/v2.32.5

構築してみる

実際に環境を作成して動作確認してみます。
各種リソースは 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 のダッシュボードを確認します。
クラスターレベルのメトリクスも良い感じに見れています。

container1.png

Pod レベルのメトリクスも良い感じに見れていました。

container2.png

ログ出力についても確認します。
まず、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 を使っていくと、特に複数クラスターが存在する環境で設定がシンプルになって嬉しい気がします!

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.