Skip to content

Commit 0d77e30

Browse files
barryibitssimondpiddockcmp
authored
feat: Add EKS Fargate support (#1067)
Co-authored-by: Simon Gurcke <[email protected]> Co-authored-by: Daniel Piddock <[email protected]>
1 parent 571da60 commit 0d77e30

File tree

14 files changed

+460
-2
lines changed

14 files changed

+460
-2
lines changed

README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,8 +187,11 @@ MIT Licensed. See [LICENSE](https://github.com/terraform-aws-modules/terraform-a
187187
| cluster\_version | Kubernetes version to use for the EKS cluster. | `string` | n/a | yes |
188188
| config\_output\_path | Where to save the Kubectl config file (if `write_kubeconfig = true`). Assumed to be a directory if the value ends with a forward slash `/`. | `string` | `"./"` | no |
189189
| create\_eks | Controls if EKS resources should be created (it affects almost all resources) | `bool` | `true` | no |
190+
| create\_fargate\_pod\_execution\_role | Controls if the EKS Fargate pod execution IAM role should be created. | `bool` | `true` | no |
190191
| eks\_oidc\_root\_ca\_thumbprint | Thumbprint of Root CA for EKS OIDC, Valid until 2037 | `string` | `"9e99a48a9960b14926bb7f3b02e22da2b0ab7280"` | no |
191192
| enable\_irsa | Whether to create OpenID Connect Provider for EKS to enable IRSA | `bool` | `false` | no |
193+
| fargate\_pod\_execution\_role\_name | The IAM Role that provides permissions for the EKS Fargate Profile. | `string` | `null` | no |
194+
| fargate\_profiles | Fargate profiles to create. See `fargate_profile` keys section in fargate submodule's README.md for more details | `any` | `{}` | no |
192195
| iam\_path | If provided, all IAM roles will be created on this path. | `string` | `"/"` | no |
193196
| kubeconfig\_aws\_authenticator\_additional\_args | Any additional arguments to pass to the authenticator such as the role to assume. e.g. ["-r", "MyEksRole"]. | `list(string)` | `[]` | no |
194197
| kubeconfig\_aws\_authenticator\_command | Command to use to fetch AWS EKS credentials. | `string` | `"aws-iam-authenticator"` | no |
@@ -243,6 +246,10 @@ MIT Licensed. See [LICENSE](https://github.com/terraform-aws-modules/terraform-a
243246
| cluster\_security\_group\_id | Security group ID attached to the EKS cluster. On 1.14 or later, this is the 'Additional security groups' in the EKS console. |
244247
| cluster\_version | The Kubernetes server version for the EKS cluster. |
245248
| config\_map\_aws\_auth | A kubernetes configuration to authenticate to this EKS cluster. |
249+
| fargate\_iam\_role\_arn | IAM role ARN for EKS Fargate pods |
250+
| fargate\_iam\_role\_name | IAM role name for EKS Fargate pods |
251+
| fargate\_profile\_arns | Amazon Resource Name (ARN) of the EKS Fargate Profiles. |
252+
| fargate\_profile\_ids | EKS Cluster name and EKS Fargate Profile names separated by a colon (:). |
246253
| kubeconfig | kubectl config file contents for this EKS cluster. |
247254
| kubeconfig\_filename | The filename of the generated kubectl config. |
248255
| node\_groups | Outputs from EKS node groups. Map of maps, keyed by var.node\_groups keys |

aws_auth.tf

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,18 +43,20 @@ locals {
4343
local.auth_launch_template_worker_roles,
4444
local.auth_worker_roles,
4545
module.node_groups.aws_auth_roles,
46+
module.fargate.aws_auth_roles,
4647
) :
4748
{
4849
# Work around https://github.com/kubernetes-sigs/aws-iam-authenticator/issues/153
4950
# Strip the leading slash off so that Terraform doesn't think it's a regex
5051
rolearn = replace(role["worker_role_arn"], replace(var.iam_path, "/^//", ""), "")
51-
username = "system:node:{{EC2PrivateDNSName}}"
52+
username = role["platform"] == "fargate" ? "system:node:{{SessionName}}" : "system:node:{{EC2PrivateDNSName}}"
5253
groups = tolist(concat(
5354
[
5455
"system:bootstrappers",
5556
"system:nodes",
5657
],
57-
role["platform"] == "windows" ? ["eks:kube-proxy-windows"] : []
58+
role["platform"] == "windows" ? ["eks:kube-proxy-windows"] : [],
59+
role["platform"] == "fargate" ? ["system:node-proxier"] : [],
5860
))
5961
}
6062
]

examples/fargate/main.tf

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
terraform {
2+
required_version = ">= 0.12.6"
3+
}
4+
5+
provider "aws" {
6+
version = ">= 2.28.1"
7+
region = var.region
8+
}
9+
10+
provider "random" {
11+
version = "~> 2.1"
12+
}
13+
14+
provider "local" {
15+
version = "~> 1.2"
16+
}
17+
18+
provider "null" {
19+
version = "~> 2.1"
20+
}
21+
22+
provider "template" {
23+
version = "~> 2.1"
24+
}
25+
26+
data "aws_eks_cluster" "cluster" {
27+
name = module.eks.cluster_id
28+
}
29+
30+
data "aws_eks_cluster_auth" "cluster" {
31+
name = module.eks.cluster_id
32+
}
33+
34+
provider "kubernetes" {
35+
host = data.aws_eks_cluster.cluster.endpoint
36+
cluster_ca_certificate = base64decode(data.aws_eks_cluster.cluster.certificate_authority.0.data)
37+
token = data.aws_eks_cluster_auth.cluster.token
38+
load_config_file = false
39+
version = "~> 1.11"
40+
}
41+
42+
data "aws_availability_zones" "available" {
43+
}
44+
45+
locals {
46+
cluster_name = "test-eks-${random_string.suffix.result}"
47+
}
48+
49+
resource "random_string" "suffix" {
50+
length = 8
51+
special = false
52+
}
53+
54+
module "vpc" {
55+
source = "terraform-aws-modules/vpc/aws"
56+
version = "2.47.0"
57+
58+
name = "test-vpc"
59+
cidr = "172.16.0.0/16"
60+
azs = data.aws_availability_zones.available.names
61+
private_subnets = ["172.16.1.0/24", "172.16.2.0/24", "172.16.3.0/24"]
62+
public_subnets = ["172.16.4.0/24", "172.16.5.0/24", "172.16.6.0/24"]
63+
enable_nat_gateway = true
64+
single_nat_gateway = true
65+
enable_dns_hostnames = true
66+
67+
public_subnet_tags = {
68+
"kubernetes.io/cluster/${local.cluster_name}" = "shared"
69+
"kubernetes.io/role/elb" = "1"
70+
}
71+
72+
private_subnet_tags = {
73+
"kubernetes.io/cluster/${local.cluster_name}" = "shared"
74+
"kubernetes.io/role/internal-elb" = "1"
75+
}
76+
}
77+
78+
module "eks" {
79+
source = "../.."
80+
cluster_name = local.cluster_name
81+
cluster_version = "1.17"
82+
subnets = module.vpc.private_subnets
83+
84+
tags = {
85+
Environment = "test"
86+
GithubRepo = "terraform-aws-eks"
87+
GithubOrg = "terraform-aws-modules"
88+
}
89+
90+
vpc_id = module.vpc.vpc_id
91+
92+
fargate_profiles = {
93+
example = {
94+
namespace = "default"
95+
96+
# Kubernetes labels for selection
97+
# labels = {
98+
# Environment = "test"
99+
# GithubRepo = "terraform-aws-eks"
100+
# GithubOrg = "terraform-aws-modules"
101+
# }
102+
103+
tags = {
104+
Owner = "test"
105+
}
106+
}
107+
}
108+
109+
map_roles = var.map_roles
110+
map_users = var.map_users
111+
map_accounts = var.map_accounts
112+
}

examples/fargate/outputs.tf

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
output "cluster_endpoint" {
2+
description = "Endpoint for EKS control plane."
3+
value = module.eks.cluster_endpoint
4+
}
5+
6+
output "cluster_security_group_id" {
7+
description = "Security group ids attached to the cluster control plane."
8+
value = module.eks.cluster_security_group_id
9+
}
10+
11+
output "kubectl_config" {
12+
description = "kubectl config as generated by the module."
13+
value = module.eks.kubeconfig
14+
}
15+
16+
output "config_map_aws_auth" {
17+
description = "A kubernetes configuration to authenticate to this EKS cluster."
18+
value = module.eks.config_map_aws_auth
19+
}
20+
21+
output "region" {
22+
description = "AWS region."
23+
value = var.region
24+
}
25+
26+
output "fargate_profile_arns" {
27+
description = "Outputs from node groups"
28+
value = module.eks.fargate_profile_arns
29+
}

examples/fargate/variables.tf

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
variable "region" {
2+
default = "us-west-2"
3+
}
4+
5+
variable "map_accounts" {
6+
description = "Additional AWS account numbers to add to the aws-auth configmap."
7+
type = list(string)
8+
9+
default = [
10+
"777777777777",
11+
"888888888888",
12+
]
13+
}
14+
15+
variable "map_roles" {
16+
description = "Additional IAM roles to add to the aws-auth configmap."
17+
type = list(object({
18+
rolearn = string
19+
username = string
20+
groups = list(string)
21+
}))
22+
23+
default = [
24+
{
25+
rolearn = "arn:aws:iam::66666666666:role/role1"
26+
username = "role1"
27+
groups = ["system:masters"]
28+
},
29+
]
30+
}
31+
32+
variable "map_users" {
33+
description = "Additional IAM users to add to the aws-auth configmap."
34+
type = list(object({
35+
userarn = string
36+
username = string
37+
groups = list(string)
38+
}))
39+
40+
default = [
41+
{
42+
userarn = "arn:aws:iam::66666666666:user/user1"
43+
username = "user1"
44+
groups = ["system:masters"]
45+
},
46+
{
47+
userarn = "arn:aws:iam::66666666666:user/user2"
48+
username = "user2"
49+
groups = ["system:masters"]
50+
},
51+
]
52+
}

fargate.tf

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
module "fargate" {
2+
source = "./modules/fargate"
3+
cluster_name = coalescelist(aws_eks_cluster.this[*].name, [""])[0]
4+
create_eks = var.create_eks
5+
create_fargate_pod_execution_role = var.create_fargate_pod_execution_role
6+
fargate_pod_execution_role_name = var.fargate_pod_execution_role_name
7+
fargate_profiles = var.fargate_profiles
8+
iam_path = var.iam_path
9+
iam_policy_arn_prefix = local.policy_arn_prefix
10+
subnets = var.subnets
11+
tags = var.tags
12+
13+
# Hack to ensure ordering of resource creation.
14+
# This is a homemade `depends_on` https://discuss.hashicorp.com/t/tips-howto-implement-module-depends-on-emulation/2305/2
15+
# Do not create node_groups before other resources are ready and removes race conditions
16+
# Ensure these resources are created before "unlocking" the data source.
17+
# Will be removed in Terraform 0.13
18+
eks_depends_on = [
19+
aws_eks_cluster.this,
20+
kubernetes_config_map.aws_auth,
21+
]
22+
}

modules/fargate/README.md

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# eks `fargate` submodule
2+
3+
Helper submodule to create and manage resources related to `aws_eks_fargate_profile`.
4+
5+
## Assumptions
6+
* Designed for use by the parent module and not directly by end users
7+
8+
## `fargate_profile` keys
9+
`fargate_profile` is a map of maps. Key of first level will be used as unique value for `for_each` resources and in the `aws_eks_fargate_profile` name. Inner map can take the below values.
10+
11+
| Name | Description | Type | Default | Required |
12+
|------|-------------|------|---------|:--------:|
13+
| name | Fargate profile name | `string` | Auto generated in the following format `[cluster_name]-fargate-[fargate_profile_map_key]`| no |
14+
| namespace | Kubernetes namespace for selection | `string` | n/a | yes |
15+
| labels | Key-value map of Kubernetes labels for selection | `map(string)` | `{}` | no |
16+
| tags | Key-value map of resource tags. Will be merged with root module tags. | `map(string)` | `var.tags` | no |
17+
18+
<!-- BEGINNING OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
19+
## Requirements
20+
21+
No requirements.
22+
23+
## Providers
24+
25+
| Name | Version |
26+
|------|---------|
27+
| aws | n/a |
28+
29+
## Inputs
30+
31+
| Name | Description | Type | Default | Required |
32+
|------|-------------|------|---------|:--------:|
33+
| cluster\_name | Name of the EKS cluster. | `string` | n/a | yes |
34+
| create\_eks | Controls if EKS resources should be created (it affects almost all resources) | `bool` | `true` | no |
35+
| create\_fargate\_pod\_execution\_role | Controls if the the IAM Role that provides permissions for the EKS Fargate Profile should be created. | `bool` | `true` | no |
36+
| eks\_depends\_on | List of references to other resources this submodule depends on. | `any` | `null` | no |
37+
| fargate\_pod\_execution\_role\_name | The IAM Role that provides permissions for the EKS Fargate Profile. | `string` | `null` | no |
38+
| fargate\_profiles | Fargate profiles to create. See `fargate_profile` keys section in README.md for more details | `any` | `{}` | no |
39+
| iam\_path | IAM roles will be created on this path. | `string` | `"/"` | no |
40+
| iam\_policy\_arn\_prefix | IAM policy prefix with the correct AWS partition. | `string` | n/a | yes |
41+
| subnets | A list of subnets for the EKS Fargate profiles. | `list(string)` | `[]` | no |
42+
| tags | A map of tags to add to all resources. | `map(string)` | `{}` | no |
43+
44+
## Outputs
45+
46+
| Name | Description |
47+
|------|-------------|
48+
| aws\_auth\_roles | Roles for use in aws-auth ConfigMap |
49+
| fargate\_profile\_arns | Amazon Resource Name (ARN) of the EKS Fargate Profiles. |
50+
| fargate\_profile\_ids | EKS Cluster name and EKS Fargate Profile names separated by a colon (:). |
51+
| iam\_role\_arn | IAM role ARN for EKS Fargate pods |
52+
| iam\_role\_name | IAM role name for EKS Fargate pods |
53+
54+
<!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK -->

modules/fargate/data.tf

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
data "aws_iam_policy_document" "eks_fargate_pod_assume_role" {
2+
count = local.create_eks && var.create_fargate_pod_execution_role ? 1 : 0
3+
statement {
4+
effect = "Allow"
5+
actions = ["sts:AssumeRole"]
6+
7+
principals {
8+
type = "Service"
9+
identifiers = ["eks-fargate-pods.amazonaws.com"]
10+
}
11+
}
12+
}
13+
14+
data "aws_iam_role" "custom_fargate_iam_role" {
15+
count = local.create_eks && ! var.create_fargate_pod_execution_role ? 1 : 0
16+
name = var.fargate_pod_execution_role_name
17+
}

modules/fargate/fargate.tf

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
resource "aws_iam_role" "eks_fargate_pod" {
2+
count = local.create_eks && var.create_fargate_pod_execution_role ? 1 : 0
3+
name_prefix = format("%s-fargate", var.cluster_name)
4+
assume_role_policy = data.aws_iam_policy_document.eks_fargate_pod_assume_role[0].json
5+
tags = var.tags
6+
path = var.iam_path
7+
}
8+
9+
resource "aws_iam_role_policy_attachment" "eks_fargate_pod" {
10+
count = local.create_eks && var.create_fargate_pod_execution_role ? 1 : 0
11+
policy_arn = "${var.iam_policy_arn_prefix}/AmazonEKSFargatePodExecutionRolePolicy"
12+
role = aws_iam_role.eks_fargate_pod[0].name
13+
}
14+
15+
resource "aws_eks_fargate_profile" "this" {
16+
for_each = local.create_eks ? local.fargate_profiles_expanded : {}
17+
cluster_name = var.cluster_name
18+
fargate_profile_name = lookup(each.value, "name", format("%s-fargate-%s", var.cluster_name, replace(each.key, "_", "-")))
19+
pod_execution_role_arn = local.pod_execution_role_arn
20+
subnet_ids = var.subnets
21+
tags = each.value.tags
22+
23+
selector {
24+
namespace = each.value.namespace
25+
labels = lookup(each.value, "labels", null)
26+
}
27+
28+
depends_on = [var.eks_depends_on]
29+
}

modules/fargate/locals.tf

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
locals {
2+
create_eks = var.create_eks && length(var.fargate_profiles) > 0
3+
pod_execution_role_arn = var.create_fargate_pod_execution_role ? element(concat(aws_iam_role.eks_fargate_pod.*.arn, list("")), 0) : element(concat(data.aws_iam_role.custom_fargate_iam_role.*.arn, list("")), 0)
4+
pod_execution_role_name = var.create_fargate_pod_execution_role ? element(concat(aws_iam_role.eks_fargate_pod.*.name, list("")), 0) : element(concat(data.aws_iam_role.custom_fargate_iam_role.*.name, list("")), 0)
5+
6+
fargate_profiles_expanded = { for k, v in var.fargate_profiles : k => merge(
7+
{ tags = var.tags },
8+
v,
9+
) if var.create_eks }
10+
}

0 commit comments

Comments
 (0)