血と汗となみだを流す

個人の思ったこと、やったことの吐き出し口です。

Karpenter で Pod Identity で割り当てた IAM ロールが使われずに Worker Node の IAM ロールが使われてしまった件

現象

Karpenter をインストールする際に Pod Identity を使うように設定したが、何故か Karpenter Controller が Worker Node の IAM ロールを使って、EC2NodeClass で Failed to resolve AMIs エラーが発生していた。

原因

  • terraform-aws-modules を使って Karpenter の設定をしていたが、namespace が未指定だったので Service Account などは namespace kube-system に作成されていた。
  • helm_release モジュールを使って Karpenter のインストールをしたが、そのときは namespace karpenter を指定していた。
  • Pod Identity に紐づく Service Account が見つからないため、Worker Node の IAM ロールが使われていた。

経緯

使った terraform module はこれです。

registry.terraform.io

terraform-aws-modules で Pod Identity を使うように指定した (が、namespace が未指定のままだった)。

module "karpenter" {
  source = "terraform-aws-modules/eks/aws//modules/karpenter"

  cluster_name = module.eks.cluster_name
 
  enable_pod_identity             = true
  create_pod_identity_association = true
  node_iam_role_additional_policies = {
    AmazonSSMManagedInstanceCore = "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore"
  }
}

Karpenter のインストールを helm_release モジュールで実施してみる。

registry.terraform.io

resource "helm_release" "karpenter" {
  namespace        = "karpenter"
  create_namespace = true

  name                = "karpenter"
  repository          = "oci://public.ecr.aws/karpenter"
  repository_username = data.aws_ecrpublic_authorization_token.token.user_name
  repository_password = data.aws_ecrpublic_authorization_token.token.password
  chart               = "karpenter"
  version             = var.karpenter_version

  values = [
    <<-EOT
    serviceAccount:
      name: ${module.karpenter.service_account}
    settings:
      clusterName: ${module.eks.cluster_name}
      clusterEndpoint: ${module.eks.cluster_endpoint}
    EOT
  ]

  # https://github.com/hashicorp/terraform-provider-helm/issues/593 
  depends_on = [
    module.eks
  ]
}

Karpenter Controller で発生したエラー。

{
    "level": "ERROR",
    "time": "2024-07-15T14:51:23.650Z",
    "logger": "controller",
    "message": "Reconciler error",
    "commit": "490ef94",
    "controller": "nodeclass.status",
    "controllerGroup": "karpenter.k8s.aws",
    "controllerKind": "EC2NodeClass",
    "EC2NodeClass": {
        "name": "default"
    },
    "namespace": "",
    "name": "default",
    "reconcileID": "3d9e21ea-5b21-441f-886b-9aa94562b1c8",
    "error": "creating instance profile, getting instance profile \"karpenter_xxxxxxxxxx\", AccessDenied: User: arn:aws:sts::999999999999:assumed-role/default-eks-node-group-xxxxxxxxxxx/i-9999999999is not authorized to perform: iam:GetInstanceProfile on resource: instance profile karpenter_xxxxxxxxxx because no identity-based policy allows the iam:GetInstanceProfile action\n\tstatus code: 403, request id: 825b11e9-54b3-4631-88ff-885fb83357b8"
}

EC2NodeClass も見てみるとエラーになっている。

$ kubectl describe EC2NodeClass default
〜略〜
Message: Failed to resolve AMIs

ただし、EC2NodeClass には Karpenter Controller を動かすのに必要なロールが 付与されていた。

Role: Karpenter-multi-arch-inference-xxxxxxxxxx

AMI 系のエラーを調査すべく CloudTrail を見ると、ec2:DescribeImages で失敗しているログがでているが、ユーザーは何故か Worker Node の IAM ロールだった。

You are not authorized to perform this operation. 
User: arn:aws:sts::999999999999:assumed-role/default-eks-node-group-xxxxxxxxxxx/i-002aefdbea1442380 is not authorized to perform: ec2:DescribeImages because no identity-based policy allows the ec2:DescribeImages action"

Karpenter module の namespace を "karpenter" に合わせたところエラーは解消した。

module "karpenter" {
  source = "terraform-aws-modules/eks/aws//modules/karpenter"

  cluster_name = module.eks.cluster_name
  namespace = "karpenter"

  enable_pod_identity             = true
  create_pod_identity_association = true
  node_iam_role_additional_policies = {
    AmazonSSMManagedInstanceCore = "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore"
  }
}

関連ドキュメント

おそらくこれか?Service Account が見つからず、Worker Node の IAM ロールが使われた。しかし Worker Node の IAM には必要な権限が付与されていなかった。

Pod がサービスアカウントに関連付けられた IAM ロールの AWS 認証情報を使用する場合、AWS CLI またはその Pod のコンテナ内の他の SDK は、そのロールによって提供される認証情報を使用します。
Amazon EKS ノード IAM ロール に提供された認証情報へのアクセスを制限しない場合、Pod は引き続きこれらの認証情報にアクセスできます。
詳細については、「ワーカーノードに割り当てられたインスタンスプロファイルへのアクセスを制限する」を参照してください。

docs.aws.amazon.com

プライバシーポリシー