Skip to content

Commit

Permalink
Support karpenter 0.32+ (#368)
Browse files Browse the repository at this point in the history
Karpenter 0.32 introduces new v1beta apis and depricates the
existing v1alpha apis.

These APIs require a different IAM policy for the controler
to work.

This PR adds 2 new variables to the karpenter module.

`v1alpha` and `v1beta` which will allow one or both policies
to be used (useful during the migration process)

We will enable both policies by default in the 1.28 release,
then drop support for the `v1alpha` policy in 1.30
(as karpenter 1.31 doesn't work properly with k8s 1.30).
  • Loading branch information
errm authored Jul 18, 2024
1 parent 5b09110 commit b41410d
Show file tree
Hide file tree
Showing 5 changed files with 432 additions and 39 deletions.
371 changes: 367 additions & 4 deletions modules/karpenter/controller_iam.tf
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,19 @@ data "aws_iam_policy_document" "karpenter_controller_assume_role_policy" {
}
}

resource "aws_iam_role_policy" "karpenter_controller" {
name = "KarpenterController"
resource "aws_iam_role_policy" "karpenter_controller_v1_alpha" {
count = var.v1alpha ? 1 : 0
name = "KarpenterController-v1alpha"
role = aws_iam_role.karpenter_controller.id
policy = data.aws_iam_policy_document.karpenter_controller.json
policy = data.aws_iam_policy_document.karpenter_controller_v1_alpha.json
}

data "aws_iam_policy_document" "karpenter_controller" {
moved {
from = aws_iam_role_policy.karpenter_controller
to = aws_iam_role_policy.karpenter_controller_v1_alpha
}

data "aws_iam_policy_document" "karpenter_controller_v1_alpha" {
statement {
sid = "AllowScopedEC2InstanceActions"
effect = "Allow"
Expand Down Expand Up @@ -282,3 +288,360 @@ data "aws_iam_policy_document" "karpenter_controller" {
actions = ["eks:DescribeCluster"]
}
}

resource "aws_iam_role_policy" "karpenter_controller_v1_beta" {
count = var.v1beta ? 1 : 0
name = "KarpenterController-v1beta"
role = aws_iam_role.karpenter_controller.id
policy = data.aws_iam_policy_document.karpenter_controller_v1_beta.json
}

data "aws_iam_policy_document" "karpenter_controller_v1_beta" {
statement {
sid = "AllowScopedEC2InstanceAccessActions"
effect = "Allow"

# tfsec:ignore:aws-iam-no-policy-wildcards
resources = [
"arn:${data.aws_partition.current.partition}:ec2:${data.aws_region.current.name}::image/*",
"arn:${data.aws_partition.current.partition}:ec2:${data.aws_region.current.name}::snapshot/*",
"arn:${data.aws_partition.current.partition}:ec2:${data.aws_region.current.name}:*:security-group/*",
"arn:${data.aws_partition.current.partition}:ec2:${data.aws_region.current.name}:*:subnet/*",
]

actions = [
"ec2:RunInstances",
"ec2:CreateFleet",
]
}

statement {
sid = "AllowScopedEC2LaunchTemplateAccessActions"
effect = "Allow"

# tfsec:ignore:aws-iam-no-policy-wildcards
resources = [
"arn:${data.aws_partition.current.partition}:ec2:${data.aws_region.current.name}:*:launch-template/*",
]

actions = [
"ec2:RunInstances",
"ec2:CreateFleet",
]

condition {
test = "StringEquals"
variable = "aws:ResourceTag/kubernetes.io/cluster/${var.cluster_config.name}"
values = ["owned"]
}

condition {
test = "StringLike"
variable = "aws:ResourceTag/karpenter.sh/nodepool"
values = ["*"]
}
}

statement {
sid = "AllowScopedEC2InstanceActionsWithTags"
effect = "Allow"

# tfsec:ignore:aws-iam-no-policy-wildcards
resources = [
"arn:${data.aws_partition.current.partition}:ec2:${data.aws_region.current.name}:*:fleet/*",
"arn:${data.aws_partition.current.partition}:ec2:${data.aws_region.current.name}:*:instance/*",
"arn:${data.aws_partition.current.partition}:ec2:${data.aws_region.current.name}:*:volume/*",
"arn:${data.aws_partition.current.partition}:ec2:${data.aws_region.current.name}:*:network-interface/*",
"arn:${data.aws_partition.current.partition}:ec2:${data.aws_region.current.name}:*:launch-template/*",
"arn:${data.aws_partition.current.partition}:ec2:${data.aws_region.current.name}:*:spot-instances-request/*",
]

actions = [
"ec2:RunInstances",
"ec2:CreateFleet",
"ec2:CreateLaunchTemplate",
]

condition {
test = "StringEquals"
variable = "aws:RequestTag/kubernetes.io/cluster/${var.cluster_config.name}"
values = ["owned"]
}

condition {
test = "StringLike"
variable = "aws:RequestTag/karpenter.sh/nodepool"
values = ["*"]
}
}

statement {
sid = "AllowScopedResourceCreationTagging"
effect = "Allow"

# tfsec:ignore:aws-iam-no-policy-wildcards
resources = [
"arn:${data.aws_partition.current.partition}:ec2:${data.aws_region.current.name}:*:fleet/*",
"arn:${data.aws_partition.current.partition}:ec2:${data.aws_region.current.name}:*:instance/*",
"arn:${data.aws_partition.current.partition}:ec2:${data.aws_region.current.name}:*:volume/*",
"arn:${data.aws_partition.current.partition}:ec2:${data.aws_region.current.name}:*:network-interface/*",
"arn:${data.aws_partition.current.partition}:ec2:${data.aws_region.current.name}:*:launch-template/*",
"arn:${data.aws_partition.current.partition}:ec2:${data.aws_region.current.name}:*:spot-instances-request/*",
]

actions = ["ec2:CreateTags"]

condition {
test = "StringEquals"
variable = "aws:RequestTag/kubernetes.io/cluster/${var.cluster_config.name}"
values = ["owned"]
}

condition {
test = "StringEquals"
variable = "ec2:CreateAction"

values = [
"RunInstances",
"CreateFleet",
"CreateLaunchTemplate",
]
}

condition {
test = "StringLike"
variable = "aws:RequestTag/karpenter.sh/nodepool"
values = ["*"]
}
}

statement {
sid = "AllowScopedResourceTagging"
effect = "Allow"

# tfsec:ignore:aws-iam-no-policy-wildcards
resources = ["arn:${data.aws_partition.current.partition}:ec2:${data.aws_region.current.name}:*:instance/*"]
actions = ["ec2:CreateTags"]

condition {
test = "StringEquals"
variable = "aws:ResourceTag/kubernetes.io/cluster/${var.cluster_config.name}"
values = ["owned"]
}

condition {
test = "StringLike"
variable = "aws:ResourceTag/karpenter.sh/nodepool"
values = ["*"]
}

condition {
test = "ForAllValues:StringEquals"
variable = "aws:TagKeys"
values = ["karpenter.sh/nodeclaim", "Name"]
}
}


statement {
sid = "AllowScopedDeletion"
effect = "Allow"

# tfsec:ignore:aws-iam-no-policy-wildcards
resources = [
"arn:${data.aws_partition.current.partition}:ec2:${data.aws_region.current.name}:*:instance/*",
"arn:${data.aws_partition.current.partition}:ec2:${data.aws_region.current.name}:*:launch-template/*",
]

actions = [
"ec2:TerminateInstances",
"ec2:DeleteLaunchTemplate",
]

condition {
test = "StringEquals"
variable = "aws:ResourceTag/kubernetes.io/cluster/${var.cluster_config.name}"
values = ["owned"]
}

condition {
test = "StringLike"
variable = "aws:ResourceTag/karpenter.sh/nodepool"
values = ["*"]
}
}

statement {
sid = "AllowRegionalReadActions"
effect = "Allow"
resources = ["*"]

actions = [
"ec2:DescribeAvailabilityZones",
"ec2:DescribeImages",
"ec2:DescribeInstances",
"ec2:DescribeInstanceTypeOfferings",
"ec2:DescribeInstanceTypes",
"ec2:DescribeLaunchTemplates",
"ec2:DescribeSecurityGroups",
"ec2:DescribeSpotPriceHistory",
"ec2:DescribeSubnets",
]

condition {
test = "StringEquals"
variable = "aws:RequestedRegion"
values = [data.aws_region.current.name]
}
}

statement {
sid = "AllowSSMReadActions"
effect = "Allow"
resources = ["arn:${data.aws_partition.current.partition}:ssm:${data.aws_region.current.name}::parameter/aws/service/*"]
actions = ["ssm:GetParameter"]
}

statement {
sid = "AllowPricingReadActions"
effect = "Allow"
resources = ["*"]
actions = ["pricing:GetProducts"]
}

statement {
sid = "AllowInterruptionQueueActions"
effect = "Allow"
resources = [aws_sqs_queue.karpenter_interruption.arn]

actions = [
"sqs:DeleteMessage",
"sqs:GetQueueUrl",
"sqs:ReceiveMessage",
]
}

statement {
sid = "AllowPassingInstanceRole"
effect = "Allow"
resources = concat([aws_iam_role.karpenter_node.arn], var.additional_node_role_arns)
actions = ["iam:PassRole"]

condition {
test = "StringEquals"
variable = "iam:PassedToService"
values = ["ec2.amazonaws.com"]
}
}

statement {
sid = "AllowScopedInstanceProfileCreationActions"
effect = "Allow"
resources = ["*"]
actions = ["iam:CreateInstanceProfile"]

condition {
test = "StringEquals"
variable = "aws:RequestTag/kubernetes.io/cluster/${var.cluster_config.name}"
values = ["owned"]
}

condition {
test = "StringEquals"
variable = "aws:RequestTag/topology.kubernetes.io/region"
values = [data.aws_region.current.name]
}

condition {
test = "StringLike"
variable = "aws:RequestTag/karpenter.k8s.aws/ec2nodeclass"
values = ["*"]
}
}

statement {
sid = "AllowScopedInstanceProfileTagActions"
effect = "Allow"
resources = ["*"]
actions = ["iam:TagInstanceProfile"]

condition {
test = "StringEquals"
variable = "aws:ResourceTag/kubernetes.io/cluster/${var.cluster_config.name}"
values = ["owned"]
}

condition {
test = "StringEquals"
variable = "aws:ResourceTag/topology.kubernetes.io/region"
values = [data.aws_region.current.name]
}

condition {
test = "StringEquals"
variable = "aws:RequestTag/kubernetes.io/cluster/${var.cluster_config.name}"
values = ["owned"]
}

condition {
test = "StringEquals"
variable = "aws:RequestTag/topology.kubernetes.io/region"
values = [data.aws_region.current.name]
}

condition {
test = "StringLike"
variable = "aws:ResourceTag/karpenter.k8s.aws/ec2nodeclass"
values = ["*"]
}

condition {
test = "StringLike"
variable = "aws:RequestTag/karpenter.k8s.aws/ec2nodeclass"
values = ["*"]
}
}

statement {
sid = "AllowScopedInstanceProfileActions"
effect = "Allow"
resources = ["*"]
actions = [
"iam:AddRoleToInstanceProfile",
"iam:RemoveRoleFromInstanceProfile",
"iam:DeleteInstanceProfile",
]

condition {
test = "StringEquals"
variable = "aws:ResourceTag/kubernetes.io/cluster/${var.cluster_config.name}"
values = ["owned"]
}

condition {
test = "StringEquals"
variable = "aws:ResourceTag/topology.kubernetes.io/region"
values = [data.aws_region.current.name]
}

condition {
test = "StringLike"
variable = "aws:ResourceTag/karpenter.k8s.aws/ec2nodeclass"
values = ["*"]
}
}

statement {
sid = "AllowInstanceProfileReadActions"
effect = "Allow"
resources = ["*"]
actions = ["iam:GetInstanceProfile"]
}

statement {
sid = "AllowAPIServerEndpointDiscovery"
effect = "Allow"
resources = [var.cluster_config.arn]
actions = ["eks:DescribeCluster"]
}
}
Loading

0 comments on commit b41410d

Please sign in to comment.