Skip to content

Commit 67f29e1

Browse files
authored
Update EKS basic components (cloudposse/terraform-aws-components#509)
1 parent dae5eda commit 67f29e1

File tree

6 files changed

+104
-101
lines changed

6 files changed

+104
-101
lines changed

src/README.md

Lines changed: 36 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
1-
# Component: `karpenter`
1+
# Component: `eks/karpenter`
22

33
This component provisions [Karpenter](https://karpenter.sh) on an EKS cluster.
44

55
## Usage
66

77
**Stack Level**: Regional
88

9+
These instructions assume you are provisioning 2 EKS clusters in the same account
10+
and region, named "blue" and "green", and alternating between them.
11+
If you are only using a single cluster, you can ignore the "blue" and "green"
12+
references and remove the `metadata` block from the `karpenter` module.
13+
914
```yaml
1015
components:
1116
terraform:
@@ -27,7 +32,7 @@ components:
2732
name: "karpenter"
2833
chart: "karpenter"
2934
chart_repository: "https://charts.karpenter.sh"
30-
chart_version: "v0.10.1"
35+
chart_version: "v0.16.3"
3136
create_namespace: true
3237
kubernetes_namespace: "karpenter"
3338
resources:
@@ -59,51 +64,29 @@ We will be using the `plat-ue2-dev` stack as an example.
5964

6065
### Provision Service-Linked Roles for EC2 Spot and EC2 Spot Fleet
6166

62-
__Note:__ If you want to use EC2 Spot or Spot Fleet for the instances launched by Karpenter,
63-
you will need to provision the following Service-Linked Roles for EC2 Spot and Spot Fleet before provisioning Karpenter:
67+
__Note:__ If you want to use EC2 Spot for the instances launched by Karpenter,
68+
you may need to provision the following Service-Linked Role for EC2 Spot:
6469

6570
- Service-Linked Role for EC2 Spot
66-
- Service-Linked Role for EC2 Spot Fleet
67-
68-
This is only necessary if this is the first time you're using EC2 Spot and Spot Fleet in the account.
6971

70-
```yaml
71-
components:
72-
terraform:
73-
iam-service-linked-roles:
74-
settings:
75-
spacelift:
76-
workspace_enabled: true
77-
vars:
78-
enabled: true
79-
root_account_tenant_name: core
80-
service_linked_roles:
81-
spot_amazonaws_com:
82-
aws_service_name: "spot.amazonaws.com"
83-
description: "AWSServiceRoleForEC2Spot Service-Linked Role for EC2 Spot"
84-
spotfleet_amazonaws_com:
85-
aws_service_name: "spotfleet.amazonaws.com"
86-
description: "AWSServiceRoleForEC2SpotFleet Service-Linked Role for EC2 Spot Fleet"
87-
```
72+
This is only necessary if this is the first time you're using EC2 Spot in the account.
73+
Since this is a one-time operation, we recommend you do this manually via
74+
the AWS CLI:
8875

8976
```bash
90-
atmos terraform plan iam-service-linked-roles -s plat-gbl-dev
91-
atmos terraform apply iam-service-linked-roles -s plat-gbl-dev
77+
aws --profile <namespace>-<tenamt>-gbl-<stage>-admin iam create-service-linked-role --aws-service-name spot.amazonaws.com
9278
```
9379

94-
Note that if the Service-Linked Roles already exist in the AWS account (if you used EC2 Spot or Spot Fleet before),
80+
Note that if the Service-Linked Roles already exist in the AWS account (if you used EC2 Spot or Spot Fleet before),
9581
and you try to provision them again, you will see the following errors:
9682

9783
```text
9884
An error occurred (InvalidInput) when calling the CreateServiceLinkedRole operation:
9985
Service role name AWSServiceRoleForEC2Spot has been taken in this account, please try a different suffix
100-
101-
An error occurred (InvalidInput) when calling the CreateServiceLinkedRole operation:
102-
Service role name AWSServiceRoleForEC2SpotFleet has been taken in this account, please try a different suffix
10386
```
10487

10588
For more details, see:
106-
- https://karpenter.sh/v0.10.1/getting-started/getting-started-with-terraform/
89+
- https://karpenter.sh/v0.18.0/getting-started/getting-started-with-terraform/
10790
- https://docs.aws.amazon.com/batch/latest/userguide/spot_fleet_IAM_role.html
10891
- https://docs.aws.amazon.com/IAM/latest/UserGuide/using-service-linked-roles.html
10992

@@ -145,26 +128,26 @@ __Notes__:
145128
We use EKS Fargate Profile for Karpenter because It is recommended to run Karpenter on an EKS Fargate Profile.
146129

147130
```text
148-
Karpenter is installed using a Helm chart. The Helm chart installs the Karpenter controller and
149-
a webhook pod as a Deployment that needs to run before the controller can be used for scaling your cluster.
150-
We recommend a minimum of one small node group with at least one worker node.
131+
Karpenter is installed using a Helm chart. The Helm chart installs the Karpenter controller and
132+
a webhook pod as a Deployment that needs to run before the controller can be used for scaling your cluster.
133+
We recommend a minimum of one small node group with at least one worker node.
151134
152135
As an alternative, you can run these pods on EKS Fargate by creating a Fargate profile for the
153-
karpenter namespace. Doing so will cause all pods deployed into this namespace to run on EKS Fargate.
136+
karpenter namespace. Doing so will cause all pods deployed into this namespace to run on EKS Fargate.
154137
Do not run Karpenter on a node that is managed by Karpenter.
155138
```
156139

157140
See [Run Karpenter Controller on EKS Fargate](https://aws.github.io/aws-eks-best-practices/karpenter/#run-the-karpenter-controller-on-eks-fargate-or-on-a-worker-node-that-belongs-to-a-node-group)
158141
for more details.
159142

160-
We provision IAM Role for Nodes launched by Karpenter because they must run with an Instance Profile that grants
143+
We provision IAM Role for Nodes launched by Karpenter because they must run with an Instance Profile that grants
161144
permissions necessary to run containers and configure networking.
162145

163146
We define the IAM role for the Instance Profile in `components/terraform/eks/cluster/karpenter.tf`.
164147

165148
Note that we provision the EC2 Instance Profile for the Karpenter IAM role in the `components/terraform/eks/karpenter` component (see the next step).
166149

167-
Run the following commands to provision the EKS Fargate Profile for Karpenter and the IAM role for instances launched by Karpenter
150+
Run the following commands to provision the EKS Fargate Profile for Karpenter and the IAM role for instances launched by Karpenter
168151
on the blue EKS cluster and add the role ARNs to the `aws-auth` ConfigMap:
169152

170153
```bash
@@ -174,8 +157,8 @@ atmos terraform apply eks/cluster-blue -s plat-ue2-dev
174157

175158
For more details, refer to:
176159

177-
- https://karpenter.sh/v0.10.1/getting-started/getting-started-with-terraform
178-
- https://karpenter.sh/v0.10.1/getting-started/getting-started-with-eksctl
160+
- https://karpenter.sh/v0.18.0/getting-started/getting-started-with-terraform
161+
- https://karpenter.sh/v0.18.0/getting-started/getting-started-with-eksctl
179162

180163

181164
### 2. Provision `karpenter` component
@@ -207,10 +190,10 @@ Note that the stack config for the blue Karpenter component is defined in `stack
207190

208191
### 3. Provision `karpenter-provisioner` component
209192

210-
In this step, we provision the `components/terraform/eks/karpenter-provisioner` component, which deploys Karpenter [Provisioners](https://karpenter.sh/v0.10.1/aws/provisioning)
193+
In this step, we provision the `components/terraform/eks/karpenter-provisioner` component, which deploys Karpenter [Provisioners](https://karpenter.sh/v0.18.0/aws/provisioning)
211194
using the `kubernetes_manifest` resource.
212195

213-
__NOTE:__ We deploy the provisioners in a separate step as a separate component since it uses `kind: Provisioner` CRD which itself is created by
196+
__NOTE:__ We deploy the provisioners in a separate step as a separate component since it uses `kind: Provisioner` CRD which itself is created by
214197
the `karpenter` component in the previous step.
215198

216199
Run the following commands to deploy the Karpenter provisioners on the blue EKS cluster:
@@ -238,7 +221,7 @@ You can override the default values from the `eks/karpenter-provisioner` base co
238221

239222
For your cluster, you will need to review the following configurations for the Karpenter provisioners and update it according to your requirements:
240223

241-
- [requirements](https://karpenter.sh/v0.10.1/provisioner/#specrequirements):
224+
- [requirements](https://karpenter.sh/v0.18.0/provisioner/#specrequirements):
242225

243226
```yaml
244227
requirements:
@@ -297,8 +280,8 @@ For your cluster, you will need to review the following configurations for the K
297280

298281
For more details, refer to:
299282

300-
- https://karpenter.sh/v0.10.1/provisioner/#specrequirements
301-
- https://karpenter.sh/v0.10.1/aws/provisioning
283+
- https://karpenter.sh/v0.18.0/provisioner/#specrequirements
284+
- https://karpenter.sh/v0.18.0/aws/provisioning
302285
- https://aws.github.io/aws-eks-best-practices/karpenter/#creating-provisioners
303286
- https://aws.github.io/aws-eks-best-practices/karpenter
304287
- https://docs.aws.amazon.com/batch/latest/userguide/spot_fleet_IAM_role.html
@@ -310,31 +293,30 @@ For more details, refer to:
310293
| Name | Version |
311294
|------|---------|
312295
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.0.0 |
313-
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | ~> 4.0 |
296+
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 4.9.0 |
314297
| <a name="requirement_helm"></a> [helm](#requirement\_helm) | >= 2.0 |
298+
| <a name="requirement_kubernetes"></a> [kubernetes](#requirement\_kubernetes) | >= 2.7.1 |
315299

316300
## Providers
317301

318302
| Name | Version |
319303
|------|---------|
320-
| <a name="provider_aws"></a> [aws](#provider\_aws) | ~> 4.0 |
321-
| <a name="provider_kubernetes"></a> [kubernetes](#provider\_kubernetes) | n/a |
304+
| <a name="provider_aws"></a> [aws](#provider\_aws) | >= 4.9.0 |
322305

323306
## Modules
324307

325308
| Name | Source | Version |
326309
|------|--------|---------|
327-
| <a name="module_eks"></a> [eks](#module\_eks) | cloudposse/stack-config/yaml//modules/remote-state | 0.22.4 |
310+
| <a name="module_eks"></a> [eks](#module\_eks) | cloudposse/stack-config/yaml//modules/remote-state | 1.3.1 |
328311
| <a name="module_iam_roles"></a> [iam\_roles](#module\_iam\_roles) | ../../account-map/modules/iam-roles | n/a |
329-
| <a name="module_karpenter"></a> [karpenter](#module\_karpenter) | cloudposse/helm-release/aws | 0.5.0 |
312+
| <a name="module_karpenter"></a> [karpenter](#module\_karpenter) | cloudposse/helm-release/aws | 0.7.0 |
330313
| <a name="module_this"></a> [this](#module\_this) | cloudposse/label/null | 0.25.0 |
331314

332315
## Resources
333316

334317
| Name | Type |
335318
|------|------|
336319
| [aws_iam_instance_profile.default](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_instance_profile) | resource |
337-
| [kubernetes_namespace.default](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/namespace) | resource |
338320
| [aws_eks_cluster_auth.eks](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/eks_cluster_auth) | data source |
339321

340322
## Inputs
@@ -400,14 +382,14 @@ For more details, refer to:
400382

401383
- https://karpenter.sh
402384
- https://aws.github.io/aws-eks-best-practices/karpenter
403-
- https://karpenter.sh/v0.10.1/getting-started/getting-started-with-terraform
385+
- https://karpenter.sh/v0.18.0/getting-started/getting-started-with-terraform
404386
- https://aws.amazon.com/blogs/aws/introducing-karpenter-an-open-source-high-performance-kubernetes-cluster-autoscaler
405387
- https://github.com/aws/karpenter
406388
- https://www.eksworkshop.com/beginner/085_scaling_karpenter
407389
- https://ec2spotworkshops.com/karpenter.html
408390
- https://www.eksworkshop.com/beginner/085_scaling_karpenter/install_karpenter
409-
- https://karpenter.sh/v0.10.1/development-guide
410-
- https://karpenter.sh/v0.10.1/aws/provisioning
391+
- https://karpenter.sh/v0.18.0/development-guide
392+
- https://karpenter.sh/v0.18.0/aws/provisioning
411393
- https://docs.aws.amazon.com/eks/latest/userguide/pod-execution-role.html
412394
- https://aws.amazon.com/premiumsupport/knowledge-center/fargate-troubleshoot-profile-creation
413395
- https://learn.hashicorp.com/tutorials/terraform/kubernetes-crd-faas

src/default.auto.tfvars

Lines changed: 0 additions & 3 deletions
This file was deleted.

src/main.tf

Lines changed: 46 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -9,79 +9,89 @@
99
# https://catalog.us-east-1.prod.workshops.aws/workshops/76a5dd80-3249-4101-8726-9be3eeee09b2/en-US/autoscaling/karpenter
1010

1111
locals {
12-
enabled = module.this.enabled
13-
create_namespace = local.enabled && var.create_namespace
14-
eks_cluster_identity_oidc_issuer = module.eks.outputs.eks_cluster_identity_oidc_issuer
15-
karpenter_iam_role_name = module.eks.outputs.karpenter_iam_role_name
12+
enabled = module.this.enabled
13+
14+
eks_cluster_identity_oidc_issuer = try(module.eks.outputs.eks_cluster_identity_oidc_issuer, "")
15+
karpenter_iam_role_name = try(module.eks.outputs.karpenter_iam_role_name, "")
16+
karpenter_role_enabled = local.enabled && length(local.karpenter_iam_role_name) > 0
1617
}
1718

1819
resource "aws_iam_instance_profile" "default" {
19-
count = local.enabled ? 1 : 0
20+
count = local.karpenter_role_enabled ? 1 : 0
2021

2122
name = local.karpenter_iam_role_name
2223
role = local.karpenter_iam_role_name
2324
tags = module.this.tags
2425
}
2526

26-
# Create Karpenter Kubernetes namespace
27-
resource "kubernetes_namespace" "default" {
28-
count = local.create_namespace ? 1 : 0
29-
30-
metadata {
31-
name = var.kubernetes_namespace
32-
annotations = {}
33-
labels = module.this.tags
34-
}
35-
}
36-
3727
# Deploy Karpenter helm chart
3828
module "karpenter" {
3929
source = "cloudposse/helm-release/aws"
40-
version = "0.5.0"
30+
version = "0.7.0"
4131

42-
chart = var.chart
43-
repository = var.chart_repository
44-
description = var.chart_description
45-
chart_version = var.chart_version
46-
kubernetes_namespace = local.create_namespace ? one(kubernetes_namespace.default[*].id) : var.kubernetes_namespace
47-
create_namespace = false
48-
wait = var.wait
49-
atomic = var.atomic
50-
cleanup_on_fail = var.cleanup_on_fail
51-
timeout = var.timeout
32+
chart = var.chart
33+
repository = var.chart_repository
34+
description = var.chart_description
35+
chart_version = var.chart_version
36+
wait = var.wait
37+
atomic = var.atomic
38+
cleanup_on_fail = var.cleanup_on_fail
39+
timeout = var.timeout
5240

53-
eks_cluster_oidc_issuer_url = replace(local.eks_cluster_identity_oidc_issuer, "https://", "")
41+
create_namespace_with_kubernetes = var.create_namespace
42+
kubernetes_namespace = var.kubernetes_namespace
43+
kubernetes_namespace_labels = merge(module.this.tags, { name = var.kubernetes_namespace })
44+
45+
eks_cluster_oidc_issuer_url = coalesce(replace(local.eks_cluster_identity_oidc_issuer, "https://", ""), "deleted")
5446

5547
service_account_name = module.this.name
5648
service_account_namespace = var.kubernetes_namespace
5749

58-
iam_role_enabled = true
50+
iam_role_enabled = local.karpenter_role_enabled
5951

6052
# https://karpenter.sh/v0.6.1/getting-started/cloudformation.yaml
6153
# https://karpenter.sh/v0.10.1/getting-started/getting-started-with-terraform
54+
# https://github.com/aws/karpenter/issues/2649
55+
# Apparently the source of truth for the best IAM policy is the `data.aws_iam_policy_document.karpenter_controller` in
56+
# https://github.com/terraform-aws-modules/terraform-aws-iam/blob/master/modules/iam-role-for-service-accounts-eks/policies.tf
6257
iam_policy_statements = [
6358
{
6459
sid = "KarpenterController"
6560
effect = "Allow"
6661
resources = ["*"]
6762

6863
actions = [
64+
# https://github.com/terraform-aws-modules/terraform-aws-iam/blob/99c69ad54d985f67acf211885aa214a3a6cc931c/modules/iam-role-for-service-accounts-eks/policies.tf#L511-L581
65+
# The reference policy is broken up into multiple statements with different resource restrictions based on tags.
66+
# This list has breaks where statements are separated in the reference policy for easier comparison and maintenance.
6967
"ec2:CreateLaunchTemplate",
7068
"ec2:CreateFleet",
71-
"ec2:RunInstances",
7269
"ec2:CreateTags",
73-
"ec2:TerminateInstances",
74-
"ec2:DeleteLaunchTemplate",
7570
"ec2:DescribeLaunchTemplates",
71+
"ec2:DescribeImages",
7672
"ec2:DescribeInstances",
7773
"ec2:DescribeSecurityGroups",
7874
"ec2:DescribeSubnets",
7975
"ec2:DescribeInstanceTypes",
8076
"ec2:DescribeInstanceTypeOfferings",
8177
"ec2:DescribeAvailabilityZones",
82-
"ssm:GetParameter",
83-
"iam:PassRole"
78+
"ec2:DescribeSpotPriceHistory",
79+
"pricing:GetProducts",
80+
81+
"ec2:TerminateInstances",
82+
"ec2:DeleteLaunchTemplate",
83+
84+
"ec2:RunInstances",
85+
86+
"iam:PassRole",
8487
]
88+
},
89+
{
90+
sid = "KarpenterControllerSSM"
91+
effect = "Allow"
92+
# Allow Karpenter to read AMI IDs from SSM
93+
actions = ["ssm:GetParameter"]
94+
resources = ["arn:aws:ssm:*:*:parameter/aws/service/*"]
8595
}
8696
]
8797

@@ -110,4 +120,6 @@ module "karpenter" {
110120
])
111121

112122
context = module.this.context
123+
124+
depends_on = [aws_iam_instance_profile.default]
113125
}

0 commit comments

Comments
 (0)