skip to Main Content

Using an terraform-created eks cluster. I am using the aws-eks-terraform module. When specifying the aws-ebs-csi-driver as a cluster add-addon, I get

  cluster_addons = {
    coredns = {
      addon_version = "v1.8.7-eksbuild.3"
      resolve_conflicts = "OVERWRITE"
    }
    kube-proxy = {
      addon_version = "v1.24.7-eksbuild.2"
      resolve_conflicts = "OVERWRITE"
    }
    vpc-cni = {
      addon_version = "v1.12.0-eksbuild.1"
      resolve_conflicts = "OVERWRITE"
    }
    aws-ebs-csi-driver = {
      addon_version = "v1.13.0-eksbuild.2"
      resolve_conflicts="PRESERVE"
    }
  }
aws_eks_addon.this["aws-ebs-csi-driver"]: Modifying... [id=it-tooling-eks-8fmuw5:aws-ebs-csi-driver]
╷
│ Error: error updating EKS Add-On (it-tooling-eks-8fmuw5:aws-ebs-csi-driver): InvalidParameter: 1 validation error(s) found.
│ - minimum field size of 1, UpdateAddonInput.ServiceAccountRoleArn.

5

Answers


  1. Chosen as BEST ANSWER

    Short answer is use this:

      cluster_addons = {
        aws-ebs-csi-driver = {
          service_account_role_arn = "arn:aws:iam::123456789012:role/amazon-eks-ebs-csi-driver-role-8fmuw5"
          addon_version = "v1.13.0-eksbuild.2"
          resolve_conflicts="PRESERVE"
        }
      }
    

    You need the role, and associated policy for things to work properly. I am including terragrunt scripts (terragrunt=terraform wrapper that uses terraform modules), in the hope that this helps someone.

    ROLE

    terraform {
      source = "${format("%s%s", dirname(get_parent_terragrunt_dir()), "/..//modules/terraform-aws-iam/modules/iam-assumable-role-with-oidc")}"
    }
    
    include {
      path = find_in_parent_folders()
    }
    
    dependencies {
      paths = [
        "../../../../once-per-account/policies/ebs-csi-driver-policy",
        "../../../../once-per-account/policies/ebs-csi-kms-encryption-policy",
        "../../random-string-env",
        "../../eks"
      ]
    }
    
    dependency "ebs-csi-driver-policy" {
      config_path = "../../../../once-per-account/policies/ebs-csi-driver-policy"
    }
    
    dependency "ebs-csi-kms-encryption-policy" {
      config_path = "../../../../once-per-account/policies/ebs-csi-kms-encryption-policy"
    }
    
    dependency "random-string" {
      config_path = "../../random-string-env"
    }
    
    dependency "eks" {
      config_path = "../../eks"
    }
    
    inputs = {
      create_role       = true
      role_requires_mfa = false
      role_name         = "amazon-eks-ebs-csi-driver-role-${dependency.random-string.outputs.random_suffix}"
    
      tags = {
        Role = "amazon-eks-ebs-csi-driver-role-${dependency.random-string.outputs.random_suffix}"
      }
    
      provider_url                   = dependency.eks.outputs.cluster_oidc_issuer_url
      role_policy_arns               = [dependency.ebs-csi-driver-policy.outputs.arn,dependency.ebs-csi-kms-encryption-policy.outputs.arn]
      oidc_fully_qualified_audiences = [ "sts.amazonaws.com" ]
      oidc_fully_qualified_subjects  = ["system:serviceaccount:kube-system:ebs-csi-controller-sa"]
    }
    

    Policy

    terraform {
      source = "${format("%s%s", dirname(get_parent_terragrunt_dir()), "/..//modules/terraform-aws-iam/modules/iam-policy")}"
    }
    
    include {
      path = find_in_parent_folders()
    }
    
    inputs = {
      name   = "AmazonEBSCSIDriverPolicyNew"
      policy = <<EOF
    {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Effect": "Allow",
                "Action": [
                    "ec2:CreateSnapshot",
                    "ec2:AttachVolume",
                    "ec2:DetachVolume",
                    "ec2:ModifyVolume",
                    "ec2:DescribeAvailabilityZones",
                    "ec2:DescribeInstances",
                    "ec2:DescribeSnapshots",
                    "ec2:DescribeTags",
                    "ec2:DescribeVolumes",
                    "ec2:DescribeVolumesModifications"
                ],
                "Resource": "*"
            },
            {
                "Effect": "Allow",
                "Action": [
                    "ec2:CreateTags"
                ],
                "Resource": [
                    "arn:aws:ec2:*:*:volume/*",
                    "arn:aws:ec2:*:*:snapshot/*"
                ],
                "Condition": {
                    "StringEquals": {
                        "ec2:CreateAction": [
                            "CreateVolume",
                            "CreateSnapshot"
                        ]
                    }
                }
            },
            {
                "Effect": "Allow",
                "Action": [
                    "ec2:DeleteTags"
                ],
                "Resource": [
                    "arn:aws:ec2:*:*:volume/*",
                    "arn:aws:ec2:*:*:snapshot/*"
                ]
            },
            {
                "Effect": "Allow",
                "Action": [
                    "ec2:CreateVolume"
                ],
                "Resource": "*",
                "Condition": {
                    "StringLike": {
                        "aws:RequestTag/ebs.csi.aws.com/cluster": "true"
                    }
                }
            },
            {
                "Effect": "Allow",
                "Action": [
                    "ec2:CreateVolume"
                ],
                "Resource": "*",
                "Condition": {
                    "StringLike": {
                        "aws:RequestTag/CSIVolumeName": "*"
                    }
                }
            },
            {
                "Effect": "Allow",
                "Action": [
                    "ec2:CreateVolume"
                ],
                "Resource": "*",
                "Condition": {
                    "StringLike": {
                        "aws:RequestTag/kubernetes.io/cluster/*": "owned"
                    }
                }
            },
            {
                "Effect": "Allow",
                "Action": [
                    "ec2:DeleteVolume"
                ],
                "Resource": "*",
                "Condition": {
                    "StringLike": {
                        "ec2:ResourceTag/ebs.csi.aws.com/cluster": "true"
                    }
                }
            },
            {
                "Effect": "Allow",
                "Action": [
                    "ec2:DeleteVolume"
                ],
                "Resource": "*",
                "Condition": {
                    "StringLike": {
                        "ec2:ResourceTag/CSIVolumeName": "*"
                    }
                }
            },
            {
                "Effect": "Allow",
                "Action": [
                    "ec2:DeleteVolume"
                ],
                "Resource": "*",
                "Condition": {
                    "StringLike": {
                        "ec2:ResourceTag/kubernetes.io/cluster/*": "owned"
                    }
                }
            },
            {
                "Effect": "Allow",
                "Action": [
                    "ec2:DeleteSnapshot"
                ],
                "Resource": "*",
                "Condition": {
                    "StringLike": {
                        "ec2:ResourceTag/CSIVolumeSnapshotName": "*"
                    }
                }
            },
            {
                "Effect": "Allow",
                "Action": [
                    "ec2:DeleteSnapshot"
                ],
                "Resource": "*",
                "Condition": {
                    "StringLike": {
                        "ec2:ResourceTag/ebs.csi.aws.com/cluster": "true"
                    }
                }
            }
        ]
    }
    EOF
    }
    

  2. Friedrich’s answer is correct. Here’s mine but without terragrunt:

    
    locals {
      ebs_csi_service_account_namespace = "kube-system"
      ebs_csi_service_account_name = "ebs-csi-controller-sa"
    }
    
    module "ebs_csi_controller_role" {
      source                        = "terraform-aws-modules/iam/aws//modules/iam-assumable-role-with-oidc"
      version                       = "5.11.1"
      create_role                   = true
      role_name                     = "${var.cluster_name}-ebs-csi-controller"
      provider_url                  = replace(module.eks.cluster_oidc_issuer_url, "https://", "")
      role_policy_arns              = [aws_iam_policy.ebs_csi_controller.arn]
      oidc_fully_qualified_subjects = ["system:serviceaccount:${local.ebs_csi_service_account_namespace}:${local.ebs_csi_service_account_name}"]
    }
    
    resource "aws_iam_policy" "ebs_csi_controller" {
      name_prefix = "ebs-csi-controller"
      description = "EKS ebs-csi-controller policy for cluster ${var.cluster_name}"
      policy      = file("${path.module}/policies/ebs_csi_controller_iam_policy.json")
    }
    

    And for the EKS module:

    module "eks" {
      source  = "terraform-aws-modules/eks/aws"
      version = "19.0.4"
    
      cluster_name    = var.cluster_name
      cluster_version = "1.24"
    
      vpc_id                   = var.vpc_id
      subnet_ids               = var.private_subnets
      control_plane_subnet_ids = var.intra_subnets
    
      cluster_endpoint_public_access  = false
      cluster_endpoint_private_access = true
    
      enable_irsa = true
    
      cluster_addons = {
        kube-proxy = {
          addon_version = "v1.24.7-eksbuild.2"
          resolve_conflicts="PRESERVE"
        }
        vpc-cni    = {
          addon_version = "v1.11.4-eksbuild.1"
          resolve_conflicts="PRESERVE"
        }
        coredns = {
          addon_version = "v1.8.7-eksbuild.3"
          configuration_values = jsonencode({
            computeType = "Fargate"
          })
          resolve_conflicts="PRESERVE"
        }
        aws-ebs-csi-driver = {
          service_account_role_arn = "arn:aws:iam::${data.aws_caller_identity.current.account_id}:role/${var.cluster_name}-ebs-csi-controller"
        }
      }
    }
    
    Login or Signup to reply.
  3. Adrian’s answer is almost complete except that it’s still needed explicitly declare aws_caller_identity somewhere before using service_account_role_arn passing.

    data "aws_caller_identity" "current" {}
    
    Login or Signup to reply.
  4. }
    aws-ebs-csi-driver = {
      service_account_role_arn = "arn:aws:iam::${data.aws_caller_identity.current.account_id}:role/${var.cluster_name}-ebs-csi-controller"
    }
    

    here as answer given by Adrian’s, my doubt is here the :role/${var.cluster_name}-ebs-csi-controller do we need to create this role fisrt

    Login or Signup to reply.
  5. There’s two pieces you need to get the EBS CSI driver working:

    • An IAM Role with the correct permissions as defined by AWS.
    • An install of the CSI driver on the cluster.

    For the driver install, there’s a helm chart and an add-on. The add-on is much easier to set up.

    The terraform-aws-modules organization has terraform modules available that make it very easy to set up.

    The iam-role-for-service-accounts-eks module will configure the IAM Role exactly as you need in a very clean way.

    With the role set up, you just need to pass the ARN to the add-on.

    module "ebs_csi_irsa_role" {
      source = "terraform-aws-modules/iam/aws//modules/iam-role-for-service-accounts-eks"
    
      role_name             = "${var.cluster_name}-ebs-csi"
      attach_ebs_csi_policy = true
    
      oidc_providers = {
        ex = {
          provider_arn               = module.eks.oidc_provider_arn
          namespace_service_accounts = ["kube-system:ebs-csi-controller-sa"]
        }
      }
    }
    
    module "eks" {
      source  = "terraform-aws-modules/eks/aws"
      version = "v19.10.0"
    
      cluster_name    = var.cluster_name
    
      ...
    
      cluster_addons = {
        aws-ebs-csi-driver = {
          service_account_role_arn = module.ebs_csi_irsa_role.iam_role_arn
          most_recent = true
        }
      }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search