Skip to content

Commit aec2bab

Browse files
feat: Add Karpenter v1beta1 compatibility (#2800)
* feat: Add Karpenter v1beta1 compatibility * fix: Update to make changes opt-in * fix: Update resource schemas to align with latest Karpenter version - validated and working as intended --------- Co-authored-by: Bryant Biggs <[email protected]>
1 parent 69eb456 commit aec2bab

File tree

6 files changed

+86
-59
lines changed

6 files changed

+86
-59
lines changed

.pre-commit-config.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
repos:
22
- repo: https://github.com/antonbabenko/pre-commit-terraform
3-
rev: v1.83.4
3+
rev: v1.83.5
44
hooks:
55
- id: terraform_fmt
66
- id: terraform_validate

examples/karpenter/README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,16 +73,16 @@ Note that this example may create resources which cost money. Run `terraform des
7373
|------|--------|---------|
7474
| <a name="module_eks"></a> [eks](#module\_eks) | ../.. | n/a |
7575
| <a name="module_karpenter"></a> [karpenter](#module\_karpenter) | ../../modules/karpenter | n/a |
76-
| <a name="module_vpc"></a> [vpc](#module\_vpc) | terraform-aws-modules/vpc/aws | ~> 4.0 |
76+
| <a name="module_vpc"></a> [vpc](#module\_vpc) | terraform-aws-modules/vpc/aws | ~> 5.0 |
7777

7878
## Resources
7979

8080
| Name | Type |
8181
|------|------|
8282
| [helm_release.karpenter](https://registry.terraform.io/providers/hashicorp/helm/latest/docs/resources/release) | resource |
8383
| [kubectl_manifest.karpenter_example_deployment](https://registry.terraform.io/providers/gavinbunney/kubectl/latest/docs/resources/manifest) | resource |
84-
| [kubectl_manifest.karpenter_node_template](https://registry.terraform.io/providers/gavinbunney/kubectl/latest/docs/resources/manifest) | resource |
85-
| [kubectl_manifest.karpenter_provisioner](https://registry.terraform.io/providers/gavinbunney/kubectl/latest/docs/resources/manifest) | resource |
84+
| [kubectl_manifest.karpenter_node_class](https://registry.terraform.io/providers/gavinbunney/kubectl/latest/docs/resources/manifest) | resource |
85+
| [kubectl_manifest.karpenter_node_pool](https://registry.terraform.io/providers/gavinbunney/kubectl/latest/docs/resources/manifest) | resource |
8686
| [aws_availability_zones.available](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/availability_zones) | data source |
8787
| [aws_ecrpublic_authorization_token.token](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ecrpublic_authorization_token) | data source |
8888

examples/karpenter/main.tf

Lines changed: 56 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -160,10 +160,9 @@ module "karpenter" {
160160
cluster_name = module.eks.cluster_name
161161
irsa_oidc_provider_arn = module.eks.oidc_provider_arn
162162

163-
# Used to attach additional IAM policies to the Karpenter controller IRSA role
164-
# policies = {
165-
# "xxx" = "yyy"
166-
# }
163+
# In v0.32.0/v1beta1, Karpenter now creates the IAM instance profile
164+
# so we disable the Terraform creation and add the necessary permissions for Karpenter IRSA
165+
enable_karpenter_instance_profile_creation = true
167166

168167
# Used to attach additional IAM policies to the Karpenter node IAM role
169168
iam_role_additional_policies = {
@@ -182,75 +181,78 @@ resource "helm_release" "karpenter" {
182181
repository_username = data.aws_ecrpublic_authorization_token.token.user_name
183182
repository_password = data.aws_ecrpublic_authorization_token.token.password
184183
chart = "karpenter"
185-
version = "v0.29.0"
186-
187-
set {
188-
name = "settings.aws.clusterName"
189-
value = module.eks.cluster_name
190-
}
191-
192-
set {
193-
name = "settings.aws.clusterEndpoint"
194-
value = module.eks.cluster_endpoint
195-
}
196-
197-
set {
198-
name = "serviceAccount.annotations.eks\\.amazonaws\\.com/role-arn"
199-
value = module.karpenter.irsa_arn
200-
}
201-
202-
set {
203-
name = "settings.aws.defaultInstanceProfile"
204-
value = module.karpenter.instance_profile_name
205-
}
206-
207-
set {
208-
name = "settings.aws.interruptionQueueName"
209-
value = module.karpenter.queue_name
210-
}
184+
version = "v0.32.1"
185+
186+
values = [
187+
<<-EOT
188+
settings:
189+
clusterName: ${module.eks.cluster_name}
190+
clusterEndpoint: ${module.eks.cluster_endpoint}
191+
interruptionQueueName: ${module.karpenter.queue_name}
192+
serviceAccount:
193+
annotations:
194+
eks.amazonaws.com/role-arn: ${module.karpenter.irsa_arn}
195+
EOT
196+
]
211197
}
212198

213-
resource "kubectl_manifest" "karpenter_provisioner" {
199+
resource "kubectl_manifest" "karpenter_node_class" {
214200
yaml_body = <<-YAML
215-
apiVersion: karpenter.sh/v1alpha5
216-
kind: Provisioner
201+
apiVersion: karpenter.k8s.aws/v1beta1
202+
kind: EC2NodeClass
217203
metadata:
218204
name: default
219205
spec:
220-
requirements:
221-
- key: karpenter.sh/capacity-type
222-
operator: In
223-
values: ["spot"]
224-
limits:
225-
resources:
226-
cpu: 1000
227-
providerRef:
228-
name: default
229-
ttlSecondsAfterEmpty: 30
206+
amiFamily: AL2
207+
role: ${module.karpenter.role_name}
208+
subnetSelectorTerms:
209+
- tags:
210+
karpenter.sh/discovery: ${module.eks.cluster_name}
211+
securityGroupSelectorTerms:
212+
- tags:
213+
karpenter.sh/discovery: ${module.eks.cluster_name}
214+
tags:
215+
karpenter.sh/discovery: ${module.eks.cluster_name}
230216
YAML
231217

232218
depends_on = [
233219
helm_release.karpenter
234220
]
235221
}
236222

237-
resource "kubectl_manifest" "karpenter_node_template" {
223+
resource "kubectl_manifest" "karpenter_node_pool" {
238224
yaml_body = <<-YAML
239-
apiVersion: karpenter.k8s.aws/v1alpha1
240-
kind: AWSNodeTemplate
225+
apiVersion: karpenter.sh/v1beta1
226+
kind: NodePool
241227
metadata:
242228
name: default
243229
spec:
244-
subnetSelector:
245-
karpenter.sh/discovery: ${module.eks.cluster_name}
246-
securityGroupSelector:
247-
karpenter.sh/discovery: ${module.eks.cluster_name}
248-
tags:
249-
karpenter.sh/discovery: ${module.eks.cluster_name}
230+
template:
231+
spec:
232+
nodeClassRef:
233+
name: default
234+
requirements:
235+
- key: "karpenter.k8s.aws/instance-category"
236+
operator: In
237+
values: ["c", "m", "r"]
238+
- key: "karpenter.k8s.aws/instance-cpu"
239+
operator: In
240+
values: ["4", "8", "16", "32"]
241+
- key: "karpenter.k8s.aws/instance-hypervisor"
242+
operator: In
243+
values: ["nitro"]
244+
- key: "karpenter.k8s.aws/instance-generation"
245+
operator: Gt
246+
values: ["2"]
247+
limits:
248+
cpu: 1000
249+
disruption:
250+
consolidationPolicy: WhenEmpty
251+
consolidateAfter: 30s
250252
YAML
251253

252254
depends_on = [
253-
helm_release.karpenter
255+
kubectl_manifest.karpenter_node_class
254256
]
255257
}
256258

@@ -292,7 +294,7 @@ resource "kubectl_manifest" "karpenter_example_deployment" {
292294

293295
module "vpc" {
294296
source = "terraform-aws-modules/vpc/aws"
295-
version = "~> 4.0"
297+
version = "~> 5.0"
296298

297299
name = local.name
298300
cidr = local.vpc_cidr

modules/karpenter/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@ No modules.
150150
| <a name="input_create_iam_role"></a> [create\_iam\_role](#input\_create\_iam\_role) | Determines whether an IAM role is created or to use an existing IAM role | `bool` | `true` | no |
151151
| <a name="input_create_instance_profile"></a> [create\_instance\_profile](#input\_create\_instance\_profile) | Whether to create an IAM instance profile | `bool` | `true` | no |
152152
| <a name="input_create_irsa"></a> [create\_irsa](#input\_create\_irsa) | Determines whether an IAM role for service accounts is created | `bool` | `true` | no |
153+
| <a name="input_enable_karpenter_instance_profile_creation"></a> [enable\_karpenter\_instance\_profile\_creation](#input\_enable\_karpenter\_instance\_profile\_creation) | Determines whether Karpenter will be allowed to create the IAM instance profile (v1beta1) or if Terraform will (v1alpha1) | `bool` | `false` | no |
153154
| <a name="input_enable_spot_termination"></a> [enable\_spot\_termination](#input\_enable\_spot\_termination) | Determines whether to enable native spot termination handling | `bool` | `true` | no |
154155
| <a name="input_iam_role_additional_policies"></a> [iam\_role\_additional\_policies](#input\_iam\_role\_additional\_policies) | Additional policies to be added to the IAM role | `map(string)` | `{}` | no |
155156
| <a name="input_iam_role_arn"></a> [iam\_role\_arn](#input\_iam\_role\_arn) | Existing IAM role ARN for the IAM instance profile. Required if `create_iam_role` is set to `false` | `string` | `null` | no |

modules/karpenter/main.tf

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,24 @@ data "aws_iam_policy_document" "irsa" {
160160
resources = [aws_sqs_queue.this[0].arn]
161161
}
162162
}
163+
164+
# TODO - this will be replaced in v20.0 with the scoped policy provided by Karpenter
165+
# https://github.com/aws/karpenter/blob/main/website/content/en/docs/upgrading/v1beta1-controller-policy.json
166+
dynamic "statement" {
167+
for_each = var.enable_karpenter_instance_profile_creation ? [1] : []
168+
169+
content {
170+
actions = [
171+
"iam:AddRoleToInstanceProfile",
172+
"iam:CreateInstanceProfile",
173+
"iam:DeleteInstanceProfile",
174+
"iam:GetInstanceProfile",
175+
"iam:RemoveRoleFromInstanceProfile",
176+
"iam:TagInstanceProfile",
177+
]
178+
resources = ["*"]
179+
}
180+
}
163181
}
164182

165183
resource "aws_iam_policy" "irsa" {
@@ -368,7 +386,7 @@ locals {
368386
}
369387

370388
resource "aws_iam_instance_profile" "this" {
371-
count = var.create && var.create_instance_profile ? 1 : 0
389+
count = var.create && var.create_instance_profile && !var.enable_karpenter_instance_profile_creation ? 1 : 0
372390

373391
name = var.iam_role_use_name_prefix ? null : local.iam_role_name
374392
name_prefix = var.iam_role_use_name_prefix ? "${local.iam_role_name}-" : null

modules/karpenter/variables.tf

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,12 @@ variable "irsa_assume_role_condition_test" {
123123
default = "StringEquals"
124124
}
125125

126+
variable "enable_karpenter_instance_profile_creation" {
127+
description = "Determines whether Karpenter will be allowed to create the IAM instance profile (v1beta1) or if Terraform will (v1alpha1)"
128+
type = bool
129+
default = false
130+
}
131+
126132
################################################################################
127133
# Node Termination Queue
128134
################################################################################

0 commit comments

Comments
 (0)