Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add EKS Fargate support #1067

Merged
merged 38 commits into from
Nov 7, 2020
Merged
Show file tree
Hide file tree
Changes from 35 commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
7f4a239
Add EKS Fargate support
itssimon May 5, 2020
2d57db8
Add new inputs for EKS Fargate
itssimon May 6, 2020
0a4343a
Add new outputs for EKS Fargate
itssimon May 6, 2020
7fc3248
Formatting
itssimon May 6, 2020
4ff3b8a
Fix lint issues
itssimon May 6, 2020
622908c
Remove cluster security group from workers again
itssimon May 6, 2020
94be39e
Add security group rule
itssimon May 6, 2020
0079356
Move Fargate resources to submodule
itssimon May 12, 2020
5f0fa6a
Requested changes in review
itssimon May 20, 2020
b5b0444
Update according to review changes
itssimon May 20, 2020
082b7a3
Fix
itssimon May 20, 2020
cc1571c
Clean up
itssimon May 20, 2020
cc981aa
Use splat syntax for cluster name
itssimon May 20, 2020
fa3b602
Requested changes
itssimon May 23, 2020
1986954
Fix
itssimon May 23, 2020
cb8f425
Remove security groups here (adding to main module)
itssimon May 26, 2020
9370d54
Update modules/fargate/fargate.tf
itssimon May 27, 2020
403f7a7
Update modules/fargate/fargate.tf
itssimon May 27, 2020
a73cbf1
Update modules/fargate/fargate.tf
itssimon May 27, 2020
b8af582
Remove unnecessary variables
itssimon May 27, 2020
3d348be
Simplify aws_auth_roles output
itssimon May 27, 2020
1303406
Fix formatting
itssimon May 27, 2020
feaa071
Add create_fargate_pod_execution_role input
itssimon May 28, 2020
fd89023
Remove race conditions
itssimon Jun 4, 2020
b57ec9f
Undo adding depedency on aws-auth
itssimon Jun 4, 2020
6869ab2
rework #866 and add suggested reviews
Oct 25, 2020
579b92a
Add iam_path variables for fargate IAM role
Oct 25, 2020
39fe86f
add docs
Oct 26, 2020
b903f65
defaut create_fargate_pod_execution_role to true
Oct 26, 2020
e07310d
fix cycle
Oct 26, 2020
a8625de
fixup: fix docs
Oct 26, 2020
2890606
move locals into a separete file
Nov 2, 2020
7406d1e
add example
Nov 2, 2020
cde1ea8
update doc
Nov 4, 2020
6070174
apply reviewer suggestions
Nov 5, 2020
403a5fc
update docs
Nov 5, 2020
bf494a5
create ressources only if fargate profiles are defined
Nov 5, 2020
d394a53
Merge branch 'master' into tba/fargate
barryib Nov 7, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -187,8 +187,11 @@ MIT Licensed. See [LICENSE](https://github.com/terraform-aws-modules/terraform-a
| cluster\_version | Kubernetes version to use for the EKS cluster. | `string` | n/a | yes |
| 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 |
| create\_eks | Controls if EKS resources should be created (it affects almost all resources) | `bool` | `true` | no |
| create\_fargate\_pod\_execution\_role | Controls if the EKS Fargate pod execution IAM role should be created. | `bool` | `true` | no |
| eks\_oidc\_root\_ca\_thumbprint | Thumbprint of Root CA for EKS OIDC, Valid until 2037 | `string` | `"9e99a48a9960b14926bb7f3b02e22da2b0ab7280"` | no |
| enable\_irsa | Whether to create OpenID Connect Provider for EKS to enable IRSA | `bool` | `false` | no |
| fargate\_pod\_execution\_role\_name | The IAM Role that provides permissions for the EKS Fargate Profile. | `string` | `null` | no |
| fargate\_profiles | Fargate profiles to create. See `fargate_profile` keys section in fargate submodule's README.md for more details | `any` | `{}` | no |
| iam\_path | If provided, all IAM roles will be created on this path. | `string` | `"/"` | no |
| 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 |
| kubeconfig\_aws\_authenticator\_command | Command to use to fetch AWS EKS credentials. | `string` | `"aws-iam-authenticator"` | no |
Expand Down Expand Up @@ -243,6 +246,10 @@ MIT Licensed. See [LICENSE](https://github.com/terraform-aws-modules/terraform-a
| 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. |
| cluster\_version | The Kubernetes server version for the EKS cluster. |
| config\_map\_aws\_auth | A kubernetes configuration to authenticate to this EKS cluster. |
| fargate\_iam\_role\_arn | IAM role ARN for EKS Fargate pods |
| fargate\_iam\_role\_name | IAM role name for EKS Fargate pods |
| fargate\_profile\_arns | Amazon Resource Name (ARN) of the EKS Fargate Profiles. |
| fargate\_profile\_ids | EKS Cluster name and EKS Fargate Profile names separated by a colon (:). |
| kubeconfig | kubectl config file contents for this EKS cluster. |
| kubeconfig\_filename | The filename of the generated kubectl config. |
| node\_groups | Outputs from EKS node groups. Map of maps, keyed by var.node\_groups keys |
Expand Down
6 changes: 4 additions & 2 deletions aws_auth.tf
Original file line number Diff line number Diff line change
Expand Up @@ -43,18 +43,20 @@ locals {
local.auth_launch_template_worker_roles,
local.auth_worker_roles,
module.node_groups.aws_auth_roles,
module.fargate.aws_auth_roles,
) :
{
# Work around https://github.com/kubernetes-sigs/aws-iam-authenticator/issues/153
# Strip the leading slash off so that Terraform doesn't think it's a regex
rolearn = replace(role["worker_role_arn"], replace(var.iam_path, "/^//", ""), "")
username = "system:node:{{EC2PrivateDNSName}}"
username = role["platform"] == "fargate" ? "system:node:{{SessionName}}" : "system:node:{{EC2PrivateDNSName}}"
groups = tolist(concat(
[
"system:bootstrappers",
"system:nodes",
],
role["platform"] == "windows" ? ["eks:kube-proxy-windows"] : []
role["platform"] == "windows" ? ["eks:kube-proxy-windows"] : [],
role["platform"] == "fargate" ? ["system:node-proxier"] : [],
))
}
]
Expand Down
112 changes: 112 additions & 0 deletions examples/fargate/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
terraform {
required_version = ">= 0.12.6"
}

provider "aws" {
version = ">= 2.28.1"
region = var.region
}

provider "random" {
version = "~> 2.1"
}

provider "local" {
version = "~> 1.2"
}

provider "null" {
version = "~> 2.1"
}

provider "template" {
version = "~> 2.1"
}

data "aws_eks_cluster" "cluster" {
name = module.eks.cluster_id
}

data "aws_eks_cluster_auth" "cluster" {
name = module.eks.cluster_id
}

provider "kubernetes" {
host = data.aws_eks_cluster.cluster.endpoint
cluster_ca_certificate = base64decode(data.aws_eks_cluster.cluster.certificate_authority.0.data)
token = data.aws_eks_cluster_auth.cluster.token
load_config_file = false
version = "~> 1.11"
}

data "aws_availability_zones" "available" {
}

locals {
cluster_name = "test-eks-${random_string.suffix.result}"
}

resource "random_string" "suffix" {
length = 8
special = false
}

module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = "2.47.0"

name = "test-vpc"
cidr = "172.16.0.0/16"
azs = data.aws_availability_zones.available.names
private_subnets = ["172.16.1.0/24", "172.16.2.0/24", "172.16.3.0/24"]
public_subnets = ["172.16.4.0/24", "172.16.5.0/24", "172.16.6.0/24"]
enable_nat_gateway = true
single_nat_gateway = true
enable_dns_hostnames = true

public_subnet_tags = {
"kubernetes.io/cluster/${local.cluster_name}" = "shared"
"kubernetes.io/role/elb" = "1"
}

private_subnet_tags = {
"kubernetes.io/cluster/${local.cluster_name}" = "shared"
"kubernetes.io/role/internal-elb" = "1"
}
}

module "eks" {
source = "../.."
cluster_name = local.cluster_name
cluster_version = "1.17"
subnets = module.vpc.private_subnets

tags = {
Environment = "test"
GithubRepo = "terraform-aws-eks"
GithubOrg = "terraform-aws-modules"
}

vpc_id = module.vpc.vpc_id

fargate_profiles = {
example = {
namespace = "default"

# Kubernetes labels for selection
# labels = {
# Environment = "test"
# GithubRepo = "terraform-aws-eks"
# GithubOrg = "terraform-aws-modules"
# }

tags = {
Owner = "test"
}
}
}

map_roles = var.map_roles
map_users = var.map_users
map_accounts = var.map_accounts
}
29 changes: 29 additions & 0 deletions examples/fargate/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
output "cluster_endpoint" {
description = "Endpoint for EKS control plane."
value = module.eks.cluster_endpoint
}

output "cluster_security_group_id" {
description = "Security group ids attached to the cluster control plane."
value = module.eks.cluster_security_group_id
}

output "kubectl_config" {
description = "kubectl config as generated by the module."
value = module.eks.kubeconfig
}

output "config_map_aws_auth" {
description = "A kubernetes configuration to authenticate to this EKS cluster."
value = module.eks.config_map_aws_auth
}

output "region" {
description = "AWS region."
value = var.region
}

output "fargate_profile_arns" {
description = "Outputs from node groups"
value = module.eks.fargate_profile_arns
}
52 changes: 52 additions & 0 deletions examples/fargate/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
variable "region" {
default = "us-west-2"
}

variable "map_accounts" {
description = "Additional AWS account numbers to add to the aws-auth configmap."
type = list(string)

default = [
"777777777777",
"888888888888",
]
}

variable "map_roles" {
description = "Additional IAM roles to add to the aws-auth configmap."
type = list(object({
rolearn = string
username = string
groups = list(string)
}))

default = [
{
rolearn = "arn:aws:iam::66666666666:role/role1"
username = "role1"
groups = ["system:masters"]
},
]
}

variable "map_users" {
description = "Additional IAM users to add to the aws-auth configmap."
type = list(object({
userarn = string
username = string
groups = list(string)
}))

default = [
{
userarn = "arn:aws:iam::66666666666:user/user1"
username = "user1"
groups = ["system:masters"]
},
{
userarn = "arn:aws:iam::66666666666:user/user2"
username = "user2"
groups = ["system:masters"]
},
]
}
22 changes: 22 additions & 0 deletions fargate.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
module "fargate" {
source = "./modules/fargate"
cluster_name = coalescelist(aws_eks_cluster.this[*].name, [""])[0]
create_eks = var.create_eks
create_fargate_pod_execution_role = var.create_fargate_pod_execution_role
fargate_pod_execution_role_name = var.fargate_pod_execution_role_name
fargate_profiles = var.fargate_profiles
iam_path = var.iam_path
iam_policy_arn_prefix = local.policy_arn_prefix
subnets = var.subnets
tags = var.tags

# Hack to ensure ordering of resource creation.
# This is a homemade `depends_on` https://discuss.hashicorp.com/t/tips-howto-implement-module-depends-on-emulation/2305/2
# Do not create node_groups before other resources are ready and removes race conditions
# Ensure these resources are created before "unlocking" the data source.
# Will be removed in Terraform 0.13
eks_depends_on = [
aws_eks_cluster.this,
kubernetes_config_map.aws_auth,
]
}
54 changes: 54 additions & 0 deletions modules/fargate/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# eks `fargate` submodule

Helper submodule to create and manage resources related to `aws_eks_fargate_profile`.

## Assumptions
* Designed for use by the parent module and not directly by end users

## `fargate_profile` keys
`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.

| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| name | Fargate profile name | `string` | Auto generated in the following format `[cluster_name]-fargate-[fargate_profile_map_key]`| no |
| namespace | Kubernetes namespace for selection | `string` | n/a | yes |
| labels | Key-value map of Kubernetes labels for selection | `map(string)` | `{}` | no |
| tags | Key-value map of resource tags. Will be merged with root module tags. | `map(string)` | `var.tags` | no |

<!-- BEGINNING OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
## Requirements

No requirements.

## Providers

| Name | Version |
|------|---------|
| aws | n/a |

## Inputs

| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| cluster\_name | Name of the EKS cluster. | `string` | n/a | yes |
| create\_eks | Controls if EKS resources should be created (it affects almost all resources) | `bool` | `true` | no |
| 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 |
| eks\_depends\_on | List of references to other resources this submodule depends on. | `any` | `null` | no |
| fargate\_pod\_execution\_role\_name | The IAM Role that provides permissions for the EKS Fargate Profile. | `string` | `null` | no |
| fargate\_profiles | Fargate profiles to create. See `fargate_profile` keys section in README.md for more details | `any` | `{}` | no |
| iam\_path | IAM roles will be created on this path. | `string` | n/a | yes |
| iam\_policy\_arn\_prefix | IAM policy prefix with the correct AWS partition. | `string` | n/a | yes |
| subnets | A list of subnets for the EKS Fargate profiles. | `list(string)` | n/a | yes |
| tags | A map of tags to add to all resources. | `map(string)` | n/a | yes |

## Outputs

| Name | Description |
|------|-------------|
| aws\_auth\_roles | Roles for use in aws-auth ConfigMap |
| fargate\_profile\_arns | Amazon Resource Name (ARN) of the EKS Fargate Profiles. |
| fargate\_profile\_ids | EKS Cluster name and EKS Fargate Profile names separated by a colon (:). |
| iam\_role\_arn | IAM role ARN for EKS Fargate pods |
| iam\_role\_name | IAM role name for EKS Fargate pods |

<!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
17 changes: 17 additions & 0 deletions modules/fargate/data.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
data "aws_iam_policy_document" "eks_fargate_pod_assume_role" {
count = var.create_eks && var.create_fargate_pod_execution_role ? 1 : 0
statement {
effect = "Allow"
actions = ["sts:AssumeRole"]

principals {
type = "Service"
identifiers = ["eks-fargate-pods.amazonaws.com"]
}
}
}

data "aws_iam_role" "custom_fargate_iam_role" {
count = var.create_eks && ! var.create_fargate_pod_execution_role ? 1 : 0
name = var.fargate_pod_execution_role_name
}
29 changes: 29 additions & 0 deletions modules/fargate/fargate.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
resource "aws_iam_role" "eks_fargate_pod" {
count = var.create_eks && var.create_fargate_pod_execution_role ? 1 : 0
name_prefix = format("%s-fargate", var.cluster_name)
assume_role_policy = data.aws_iam_policy_document.eks_fargate_pod_assume_role[0].json
tags = var.tags
path = var.iam_path
}

resource "aws_iam_role_policy_attachment" "eks_fargate_pod" {
count = var.create_eks && var.create_fargate_pod_execution_role ? 1 : 0
policy_arn = "${var.iam_policy_arn_prefix}/AmazonEKSFargatePodExecutionRolePolicy"
role = aws_iam_role.eks_fargate_pod[0].name
}

resource "aws_eks_fargate_profile" "this" {
for_each = var.create_eks ? local.fargate_profiles_expanded : {}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This for_each will fail if local.fargate_profiles_expanded contains not-yet-known values (as you've just replaced for local.create_eks). I am not sure what is the best solution for this here.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

var.fargate_profiles and local.fargate_profiles_expanded are maps and to work with for_each, their keys must be known during plan. If keys are known, I think the Terraform will wait correctly for aws_eks_fargate_profile creation if there is a not yet known values inside local.fargate_profiles_expanded.

So length(var.fargate_profiles) will be known because keys must be known.

cluster_name = var.cluster_name
fargate_profile_name = lookup(each.value, "name", format("%s-fargate-%s", var.cluster_name, replace(each.key, "_", "-")))
pod_execution_role_arn = local.pod_execution_role_arn
subnet_ids = var.subnets
tags = each.value.tags

selector {
namespace = each.value.namespace
labels = lookup(each.value, "labels", null)
}

depends_on = [var.eks_depends_on]
}
9 changes: 9 additions & 0 deletions modules/fargate/locals.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
locals {
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)
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)

fargate_profiles_expanded = { for k, v in var.fargate_profiles : k => merge(
{ tags = var.tags },
v,
) if var.create_eks }
}
Loading