Skip to content

Commit 35ee2fb

Browse files
authored
Update EKS basic components (cloudposse/terraform-aws-components#509)
1 parent 6394e9e commit 35ee2fb

File tree

7 files changed

+141
-48
lines changed

7 files changed

+141
-48
lines changed

src/README.md

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1-
# Component: `alb-controller`
1+
# Component: `eks/alb-controller`
22

33
This component creates a Helm release for [alb-controller](https://github.com/kubernetes-sigs/aws-load-balancer-controller) on an EKS cluster.
44

5-
[alb-controller](https://github.com/kubernetes-sigs/aws-load-balancer-controller) is a Kubernetes addon that, in the context of AWS, provisions and manages ALBs and NLBs based on Service and Ingress annotations.
5+
[alb-controller](https://github.com/kubernetes-sigs/aws-load-balancer-controller) is a Kubernetes addon that,
6+
in the context of AWS, provisions and manages ALBs and NLBs based on Service and Ingress annotations.
7+
This module also can (and is recommended to) provision a default IngressClass.
68

79
## Usage
810

@@ -21,9 +23,21 @@ The default catalog values `e.g. stacks/catalog/eks/alb-controller.yaml`
2123
```yaml
2224
components:
2325
terraform:
24-
alb-controller:
26+
eks/alb-controller:
2527
vars:
26-
enabled: true
28+
chart: aws-load-balancer-controller
29+
chart_repository: https://aws.github.io/eks-charts
30+
chart_version: "1.4.5"
31+
create_namespace: true
32+
kubernetes_namespace: alb-controller
33+
# this feature causes inconsistent final plans
34+
# see https://github.com/hashicorp/terraform-provider-helm/issues/711#issuecomment-836192991
35+
helm_manifest_experiment_enabled: false
36+
37+
default_ingress_class_name: default
38+
default_ingress_group: common
39+
default_ingress_ip_address_type: ipv4
40+
default_ingress_scheme: internet-facing
2741
# You can use `chart_values` to set any other chart options. Treat `chart_values` as the root of the doc.
2842
#
2943
# # For example
@@ -39,30 +53,29 @@ components:
3953
| Name | Version |
4054
|------|---------|
4155
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.0.0 |
42-
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | ~> 4.0 |
56+
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 4.9.0 |
4357
| <a name="requirement_helm"></a> [helm](#requirement\_helm) | >= 2.0 |
58+
| <a name="requirement_kubernetes"></a> [kubernetes](#requirement\_kubernetes) | >= 2.14.0 |
4459
4560
## Providers
4661
4762
| Name | Version |
4863
|------|---------|
49-
| <a name="provider_aws"></a> [aws](#provider\_aws) | ~> 4.0 |
50-
| <a name="provider_kubernetes"></a> [kubernetes](#provider\_kubernetes) | n/a |
64+
| <a name="provider_aws"></a> [aws](#provider\_aws) | >= 4.9.0 |
5165
5266
## Modules
5367
5468
| Name | Source | Version |
5569
|------|--------|---------|
56-
| <a name="module_alb_controller"></a> [alb\_controller](#module\_alb\_controller) | cloudposse/helm-release/aws | 0.5.0 |
57-
| <a name="module_eks"></a> [eks](#module\_eks) | cloudposse/stack-config/yaml//modules/remote-state | 0.22.4 |
70+
| <a name="module_alb_controller"></a> [alb\_controller](#module\_alb\_controller) | cloudposse/helm-release/aws | 0.7.0 |
71+
| <a name="module_eks"></a> [eks](#module\_eks) | cloudposse/stack-config/yaml//modules/remote-state | 1.3.1 |
5872
| <a name="module_iam_roles"></a> [iam\_roles](#module\_iam\_roles) | ../../account-map/modules/iam-roles | n/a |
5973
| <a name="module_this"></a> [this](#module\_this) | cloudposse/label/null | 0.25.0 |
6074
6175
## Resources
6276
6377
| Name | Type |
6478
|------|------|
65-
| [kubernetes_namespace.default](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/namespace) | resource |
6679
| [aws_eks_cluster_auth.eks](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/eks_cluster_auth) | data source |
6780
6881
## Inputs
@@ -80,6 +93,13 @@ components:
8093
| <a name="input_cleanup_on_fail"></a> [cleanup\_on\_fail](#input\_cleanup\_on\_fail) | Allow deletion of new resources created in this upgrade when upgrade fails. | `bool` | `true` | no |
8194
| <a name="input_context"></a> [context](#input\_context) | Single object for setting entire context at once.<br>See description of individual variables for details.<br>Leave string and numeric variables as `null` to use default value.<br>Individual variable settings (non-null) override settings in context object,<br>except for attributes, tags, and additional\_tag\_map, which are merged. | `any` | <pre>{<br> "additional_tag_map": {},<br> "attributes": [],<br> "delimiter": null,<br> "descriptor_formats": {},<br> "enabled": true,<br> "environment": null,<br> "id_length_limit": null,<br> "label_key_case": null,<br> "label_order": [],<br> "label_value_case": null,<br> "labels_as_tags": [<br> "unset"<br> ],<br> "name": null,<br> "namespace": null,<br> "regex_replace_chars": null,<br> "stage": null,<br> "tags": {},<br> "tenant": null<br>}</pre> | no |
8295
| <a name="input_create_namespace"></a> [create\_namespace](#input\_create\_namespace) | Create the namespace if it does not yet exist. Defaults to `false`. | `bool` | `null` | no |
96+
| <a name="input_default_ingress_additional_tags"></a> [default\_ingress\_additional\_tags](#input\_default\_ingress\_additional\_tags) | Additional tags to apply to the ingress load balancer. | `map(string)` | `{}` | no |
97+
| <a name="input_default_ingress_class_name"></a> [default\_ingress\_class\_name](#input\_default\_ingress\_class\_name) | Class name for default ingress | `string` | `"default"` | no |
98+
| <a name="input_default_ingress_enabled"></a> [default\_ingress\_enabled](#input\_default\_ingress\_enabled) | Set `true` to deploy a default IngressClass. There should only be one default per cluster. | `bool` | `true` | no |
99+
| <a name="input_default_ingress_group"></a> [default\_ingress\_group](#input\_default\_ingress\_group) | Group name for default ingress | `string` | `"common"` | no |
100+
| <a name="input_default_ingress_ip_address_type"></a> [default\_ingress\_ip\_address\_type](#input\_default\_ingress\_ip\_address\_type) | IP address type for default ingress, one of `ipv4` or `dualstack`. | `string` | `"dualstack"` | no |
101+
| <a name="input_default_ingress_load_balancer_attributes"></a> [default\_ingress\_load\_balancer\_attributes](#input\_default\_ingress\_load\_balancer\_attributes) | A list of load balancer attributes to apply to the default ingress load balancer.<br>See [Load Balancer Attributes](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/application-load-balancers.html#load-balancer-attributes). | `list(object({ key = string, value = string }))` | `[]` | no |
102+
| <a name="input_default_ingress_scheme"></a> [default\_ingress\_scheme](#input\_default\_ingress\_scheme) | Scheme for default ingress, one of `internet-facing` or `internal`. | `string` | `"internet-facing"` | no |
83103
| <a name="input_delimiter"></a> [delimiter](#input\_delimiter) | Delimiter to be used between ID elements.<br>Defaults to `-` (hyphen). Set to `""` to use no delimiter at all. | `string` | `null` | no |
84104
| <a name="input_descriptor_formats"></a> [descriptor\_formats](#input\_descriptor\_formats) | Describe additional descriptors to be output in the `descriptors` output map.<br>Map of maps. Keys are names of descriptors. Values are maps of the form<br>`{<br> format = string<br> labels = list(string)<br>}`<br>(Type is `any` so the map values can later be enhanced to provide additional options.)<br>`format` is a Terraform format string to be passed to the `format()` function.<br>`labels` is a list of labels, in order, to pass to `format()` function.<br>Label values will be normalized before being passed to `format()` so they will be<br>identical to how they appear in `id`.<br>Default is `{}` (`descriptors` output will be empty). | `any` | `{}` | no |
85105
| <a name="input_eks_component_name"></a> [eks\_component\_name](#input\_eks\_component\_name) | The name of the eks component | `string` | `"eks/cluster"` | no |

src/default.auto.tfvars

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

src/main.tf

Lines changed: 32 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2,33 +2,23 @@ locals {
22
enabled = module.this.enabled
33
}
44

5-
resource "kubernetes_namespace" "default" {
6-
count = local.enabled && var.create_namespace ? 1 : 0
7-
8-
metadata {
9-
name = var.kubernetes_namespace
10-
11-
annotations = {}
12-
13-
labels = module.this.tags
14-
}
15-
}
16-
175
module "alb_controller" {
186
source = "cloudposse/helm-release/aws"
19-
version = "0.5.0"
7+
version = "0.7.0"
8+
9+
name = "" # avoids hitting length restrictions on IAM Role names
10+
chart = var.chart
11+
repository = var.chart_repository
12+
description = var.chart_description
13+
chart_version = var.chart_version
14+
wait = true # required for installing IngressClassParams
15+
atomic = var.atomic
16+
cleanup_on_fail = var.cleanup_on_fail
17+
timeout = var.timeout
2018

21-
name = "" # avoids hitting length restrictions on IAM Role names
22-
chart = var.chart
23-
repository = var.chart_repository
24-
description = var.chart_description
25-
chart_version = var.chart_version
26-
kubernetes_namespace = join("", kubernetes_namespace.default.*.id)
27-
create_namespace = false
28-
wait = var.wait
29-
atomic = var.atomic
30-
cleanup_on_fail = var.cleanup_on_fail
31-
timeout = var.timeout
19+
create_namespace_with_kubernetes = var.create_namespace
20+
kubernetes_namespace = var.kubernetes_namespace
21+
kubernetes_namespace_labels = merge(module.this.tags, { name = var.kubernetes_namespace })
3222

3323
eks_cluster_oidc_issuer_url = replace(module.eks.outputs.eks_cluster_identity_oidc_issuer, "https://", "")
3424

@@ -311,7 +301,24 @@ module "alb_controller" {
311301
aws = {
312302
region = var.region
313303
}
314-
clusterName = module.eks.outputs.eks_cluster_id
304+
clusterName = module.eks.outputs.eks_cluster_id
305+
createIngressClassResource = var.default_ingress_enabled
306+
ingressClass = var.default_ingress_class_name
307+
ingressClassParams = {
308+
name = var.default_ingress_class_name
309+
create = var.default_ingress_enabled
310+
default = true
311+
spec = {
312+
group = {
313+
name = var.default_ingress_group
314+
}
315+
scheme = var.default_ingress_scheme
316+
ipAddressType = var.default_ingress_ip_address_type
317+
tags = [for k, v in merge(module.this.tags, var.default_ingress_additional_tags) : { key = k, value = v }]
318+
loadBalancerAttributes = var.default_ingress_load_balancer_attributes
319+
}
320+
}
321+
defaultTags = module.this.tags
315322
}),
316323
# additional values
317324
yamlencode(var.chart_values)

src/provider-helm.tf

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@
22
#
33
# This file is a drop-in to provide a helm provider.
44
#
5+
# It depends on 2 standard Cloud Posse data source modules to be already
6+
# defined in the same component:
7+
#
8+
# 1. module.iam_roles to provide the AWS profile or Role ARN to use to access the cluster
9+
# 2. module.eks to provide the EKS cluster information
10+
#
511
# All the following variables are just about configuring the Kubernetes provider
612
# to be able to modify EKS cluster. The reason there are so many options is
713
# because at various times, each one of them has had problems, so we give you a choice.
@@ -100,9 +106,11 @@ locals {
100106
"--role-arn", local.kube_exec_auth_role_arn
101107
] : []
102108

103-
certificate_authority_data = module.eks.outputs.eks_cluster_certificate_authority_data
104-
eks_cluster_id = module.eks.outputs.eks_cluster_id
105-
eks_cluster_endpoint = module.eks.outputs.eks_cluster_endpoint
109+
# Provide dummy configuration for the case where the EKS cluster is not available.
110+
certificate_authority_data = try(module.eks.outputs.eks_cluster_certificate_authority_data, "")
111+
# Use coalesce+try to handle both the case where the output is missing and the case where it is empty.
112+
eks_cluster_id = coalesce(try(module.eks.outputs.eks_cluster_id, ""), "missing")
113+
eks_cluster_endpoint = try(module.eks.outputs.eks_cluster_endpoint, "")
106114
}
107115

108116
data "aws_eks_cluster_auth" "eks" {
@@ -114,14 +122,14 @@ provider "helm" {
114122
kubernetes {
115123
host = local.eks_cluster_endpoint
116124
cluster_ca_certificate = base64decode(local.certificate_authority_data)
117-
token = local.kube_data_auth_enabled ? data.aws_eks_cluster_auth.eks[0].token : null
125+
token = local.kube_data_auth_enabled ? one(data.aws_eks_cluster_auth.eks[*].token) : null
118126
# The Kubernetes provider will use information from KUBECONFIG if it exists, but if the default cluster
119127
# in KUBECONFIG is some other cluster, this will cause problems, so we override it always.
120128
config_path = local.kubeconfig_file_enabled ? var.kubeconfig_file : ""
121129
config_context = var.kubeconfig_context
122130

123131
dynamic "exec" {
124-
for_each = local.kube_exec_auth_enabled ? ["exec"] : []
132+
for_each = local.kube_exec_auth_enabled && length(local.certificate_authority_data) > 0 ? ["exec"] : []
125133
content {
126134
api_version = local.kubeconfig_exec_auth_api_version
127135
command = "aws"
@@ -132,21 +140,21 @@ provider "helm" {
132140
}
133141
}
134142
experiments {
135-
manifest = var.helm_manifest_experiment_enabled
143+
manifest = var.helm_manifest_experiment_enabled && module.this.enabled
136144
}
137145
}
138146

139147
provider "kubernetes" {
140148
host = local.eks_cluster_endpoint
141149
cluster_ca_certificate = base64decode(local.certificate_authority_data)
142-
token = local.kube_data_auth_enabled ? data.aws_eks_cluster_auth.eks[0].token : null
150+
token = local.kube_data_auth_enabled ? one(data.aws_eks_cluster_auth.eks[*].token) : null
143151
# The Kubernetes provider will use information from KUBECONFIG if it exists, but if the default cluster
144152
# in KUBECONFIG is some other cluster, this will cause problems, so we override it always.
145153
config_path = local.kubeconfig_file_enabled ? var.kubeconfig_file : ""
146154
config_context = var.kubeconfig_context
147155

148156
dynamic "exec" {
149-
for_each = local.kube_exec_auth_enabled ? ["exec"] : []
157+
for_each = local.kube_exec_auth_enabled && length(local.certificate_authority_data) > 0 ? ["exec"] : []
150158
content {
151159
api_version = local.kubeconfig_exec_auth_api_version
152160
command = "aws"

src/remote-state.tf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
module "eks" {
22
source = "cloudposse/stack-config/yaml//modules/remote-state"
3-
version = "0.22.4"
3+
version = "1.3.1"
44

55
component = var.eks_component_name
66

src/variables.tf

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,3 +91,60 @@ variable "eks_component_name" {
9191
description = "The name of the eks component"
9292
default = "eks/cluster"
9393
}
94+
95+
####### Configure default Ingress Class #######
96+
97+
variable "default_ingress_enabled" {
98+
type = bool
99+
description = "Set `true` to deploy a default IngressClass. There should only be one default per cluster."
100+
default = true
101+
}
102+
103+
variable "default_ingress_class_name" {
104+
type = string
105+
description = "Class name for default ingress"
106+
default = "default"
107+
}
108+
109+
variable "default_ingress_group" {
110+
type = string
111+
description = "Group name for default ingress"
112+
default = "common"
113+
}
114+
115+
variable "default_ingress_scheme" {
116+
type = string
117+
description = "Scheme for default ingress, one of `internet-facing` or `internal`."
118+
default = "internet-facing"
119+
120+
validation {
121+
condition = contains(["internet-facing", "internal"], var.default_ingress_scheme)
122+
error_message = "The default ingress scheme must be one of `internet-facing` or `internal`."
123+
}
124+
}
125+
126+
variable "default_ingress_ip_address_type" {
127+
type = string
128+
description = "IP address type for default ingress, one of `ipv4` or `dualstack`."
129+
default = "dualstack"
130+
131+
validation {
132+
condition = contains(["ipv4", "dualstack"], var.default_ingress_ip_address_type)
133+
error_message = "The default ingress IP address type must be one of `ipv4` or `dualstack`."
134+
}
135+
}
136+
137+
variable "default_ingress_load_balancer_attributes" {
138+
type = list(object({ key = string, value = string }))
139+
description = <<-EOT
140+
A list of load balancer attributes to apply to the default ingress load balancer.
141+
See [Load Balancer Attributes](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/application-load-balancers.html#load-balancer-attributes).
142+
EOT
143+
default = []
144+
}
145+
146+
variable "default_ingress_additional_tags" {
147+
type = map(string)
148+
description = "Additional tags to apply to the ingress load balancer."
149+
default = {}
150+
}

src/versions.tf

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,15 @@ terraform {
44
required_providers {
55
aws = {
66
source = "hashicorp/aws"
7-
version = "~> 4.0"
7+
version = ">= 4.9.0"
88
}
99
helm = {
1010
source = "hashicorp/helm"
1111
version = ">= 2.0"
1212
}
13+
kubernetes = {
14+
source = "hashicorp/kubernetes"
15+
version = ">= 2.14.0"
16+
}
1317
}
1418
}

0 commit comments

Comments
 (0)