Skip to content

Commit 3a16188

Browse files
svelangoElango Sundararajanbryantbiggs
authored
feat: Add support for AppMesh controller addon with AppMesh mTLS example (#539)
Co-authored-by: Elango Sundararajan <[email protected]> Co-authored-by: Bryant Biggs <[email protected]>
1 parent 0529549 commit 3a16188

File tree

15 files changed

+611
-1
lines changed

15 files changed

+611
-1
lines changed

.github/workflows/plan-examples.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ def get_examples():
99
returning a string formatted json array of the example directories minus those that are excluded
1010
"""
1111
exclude = {
12+
'examples/appmesh-mtls', # excluded until Rout53 is setup
1213
'examples/eks-cluster-with-external-dns', # excluded until Rout53 is setup
1314
'examples/ci-cd/gitlab-ci-cd', # excluded since GitLab auth, backend, etc. required
1415
'examples/fully-private-eks-cluster/vpc', # skipping until issue #711 is addressed

examples/appmesh-mtls/README.md

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
# EKS Cluster w/ AppMesh mTLS
2+
3+
This example shows how to provision an EKS cluster with AppMesh mTLS enabled.
4+
5+
## Prerequisites:
6+
7+
Ensure that you have the following tools installed locally:
8+
9+
1. [aws cli](https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2.html)
10+
2. [kubectl](https://Kubernetes.io/docs/tasks/tools/)
11+
3. [terraform](https://learn.hashicorp.com/tutorials/terraform/install-cli)
12+
13+
## Deploy
14+
15+
To provision this example:
16+
17+
```sh
18+
terraform init
19+
terraform apply
20+
```
21+
22+
Enter `yes` at command prompt to apply
23+
24+
25+
## Validate
26+
27+
The following command will update the `kubeconfig` on your local machine and allow you to interact with your EKS Cluster using `kubectl` to validate the deployment.
28+
29+
1. Run `update-kubeconfig` command:
30+
31+
```sh
32+
aws eks --region <REGION> update-kubeconfig --name <CLUSTER_NAME>
33+
```
34+
35+
2. List the nodes running currently
36+
37+
```sh
38+
kubectl get nodes
39+
40+
# Output should look like below
41+
NAME STATUS ROLES AGE VERSION
42+
ip-10-0-30-125.us-west-2.compute.internal Ready <none> 2m19s v1.22.9-eks-810597c
43+
```
44+
45+
3. List out the pods running currently:
46+
47+
```sh
48+
kubectl get pods -A
49+
50+
# TODO
51+
```
52+
53+
## Destroy
54+
55+
To teardown and remove the resources created in this example:
56+
57+
```sh
58+
terraform destroy -target="module.eks_blueprints_kubernetes_addons" -auto-approve
59+
terraform destroy -target="module.eks_blueprints" -auto-approve
60+
terraform destroy -auto-approve
61+
```

examples/appmesh-mtls/main.tf

Lines changed: 231 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,231 @@
1+
provider "aws" {
2+
region = local.region
3+
}
4+
5+
provider "kubernetes" {
6+
host = module.eks_blueprints.eks_cluster_endpoint
7+
cluster_ca_certificate = base64decode(module.eks_blueprints.eks_cluster_certificate_authority_data)
8+
token = data.aws_eks_cluster_auth.this.token
9+
}
10+
11+
provider "helm" {
12+
kubernetes {
13+
host = module.eks_blueprints.eks_cluster_endpoint
14+
cluster_ca_certificate = base64decode(module.eks_blueprints.eks_cluster_certificate_authority_data)
15+
token = data.aws_eks_cluster_auth.this.token
16+
}
17+
}
18+
19+
provider "kubectl" {
20+
apply_retry_count = 10
21+
host = module.eks_blueprints.eks_cluster_endpoint
22+
cluster_ca_certificate = base64decode(module.eks_blueprints.eks_cluster_certificate_authority_data)
23+
load_config_file = false
24+
token = data.aws_eks_cluster_auth.this.token
25+
}
26+
27+
data "aws_eks_cluster_auth" "this" {
28+
name = module.eks_blueprints.eks_cluster_id
29+
}
30+
31+
data "aws_availability_zones" "available" {}
32+
33+
locals {
34+
name = basename(path.cwd)
35+
region = "us-west-2"
36+
37+
vpc_cidr = "10.0.0.0/16"
38+
azs = slice(data.aws_availability_zones.available.names, 0, 3)
39+
40+
41+
tags = {
42+
Blueprint = local.name
43+
GithubRepo = "github.com/aws-ia/terraform-aws-eks-blueprints"
44+
}
45+
}
46+
47+
#---------------------------------------------------------------
48+
# EKS Blueprints
49+
#---------------------------------------------------------------
50+
51+
module "eks_blueprints" {
52+
source = "../.."
53+
54+
cluster_name = local.name
55+
cluster_version = "1.23"
56+
57+
vpc_id = module.vpc.vpc_id
58+
private_subnet_ids = module.vpc.private_subnets
59+
60+
managed_node_groups = {
61+
this = {
62+
node_group_name = local.name
63+
instance_types = ["m5.large"]
64+
subnet_ids = module.vpc.private_subnets
65+
66+
min_size = 1
67+
max_size = 2
68+
desired_size = 1
69+
70+
update_config = [{
71+
max_unavailable_percentage = 30
72+
}]
73+
}
74+
}
75+
76+
tags = local.tags
77+
}
78+
79+
module "eks_blueprints_kubernetes_addons" {
80+
source = "../../modules/kubernetes-addons"
81+
82+
eks_cluster_id = module.eks_blueprints.eks_cluster_id
83+
eks_cluster_endpoint = module.eks_blueprints.eks_cluster_endpoint
84+
eks_oidc_provider = module.eks_blueprints.oidc_provider
85+
eks_cluster_version = module.eks_blueprints.eks_cluster_version
86+
eks_cluster_domain = var.eks_cluster_domain
87+
88+
enable_amazon_eks_vpc_cni = true
89+
enable_amazon_eks_coredns = true
90+
enable_amazon_eks_kube_proxy = true
91+
92+
aws_privateca_acmca_arn = aws_acmpca_certificate_authority.example.arn
93+
enable_appmesh_controller = true
94+
enable_cert_manager = true
95+
enable_aws_privateca_issuer = true
96+
97+
tags = local.tags
98+
}
99+
100+
#---------------------------------------------------------------
101+
# Certificate Resources
102+
#---------------------------------------------------------------
103+
104+
resource "aws_acmpca_certificate_authority" "example" {
105+
type = "ROOT"
106+
107+
certificate_authority_configuration {
108+
key_algorithm = "RSA_4096"
109+
signing_algorithm = "SHA512WITHRSA"
110+
111+
subject {
112+
common_name = "example.com"
113+
}
114+
}
115+
}
116+
117+
resource "aws_acmpca_certificate" "example" {
118+
certificate_authority_arn = aws_acmpca_certificate_authority.example.arn
119+
certificate_signing_request = aws_acmpca_certificate_authority.example.certificate_signing_request
120+
signing_algorithm = "SHA512WITHRSA"
121+
122+
template_arn = "arn:aws:acm-pca:::template/RootCACertificate/V1"
123+
124+
validity {
125+
type = "YEARS"
126+
value = 10
127+
}
128+
}
129+
130+
resource "aws_acmpca_certificate_authority_certificate" "example" {
131+
certificate_authority_arn = aws_acmpca_certificate_authority.example.arn
132+
133+
certificate = aws_acmpca_certificate.example.certificate
134+
certificate_chain = aws_acmpca_certificate.example.certificate_chain
135+
}
136+
137+
# This resource creates a CRD of AWSPCAClusterIssuer Kind, which then represents the ACM PCA in K8
138+
resource "kubectl_manifest" "cluster_pca_issuer" {
139+
yaml_body = yamlencode({
140+
apiVersion = "awspca.cert-manager.io/v1beta1"
141+
kind = "AWSPCAClusterIssuer"
142+
143+
metadata = {
144+
name = module.eks_blueprints.eks_cluster_id
145+
}
146+
147+
spec = {
148+
arn = aws_acmpca_certificate_authority.example.arn
149+
region : local.region
150+
}
151+
})
152+
}
153+
154+
# This resource creates a CRD of Certificate Kind, which then represents certificate issued from ACM PCA,
155+
# mounted as K8 secret
156+
resource "kubectl_manifest" "example_pca_certificate" {
157+
yaml_body = yamlencode({
158+
apiVersion = "cert-manager.io/v1"
159+
kind = "Certificate"
160+
161+
metadata = {
162+
name = var.certificate_name
163+
namespace = "default"
164+
}
165+
166+
spec = {
167+
commonName = var.certificate_dns
168+
duration = "2160h0m0s"
169+
issuerRef = {
170+
group = "awspca.cert-manager.io"
171+
kind = "AWSPCAClusterIssuer"
172+
name : module.eks_blueprints.eks_cluster_id
173+
}
174+
renewBefore = "360h0m0s"
175+
# This is the name with which the K8 Secret will be available
176+
secretName = "${var.certificate_name}-clusterissuer"
177+
usages = [
178+
"server auth",
179+
"client auth"
180+
]
181+
privateKey = {
182+
algorithm : "RSA"
183+
size : 2048
184+
}
185+
}
186+
})
187+
188+
depends_on = [
189+
kubectl_manifest.cluster_pca_issuer,
190+
]
191+
}
192+
193+
#---------------------------------------------------------------
194+
# Supporting Resources
195+
#---------------------------------------------------------------
196+
197+
module "vpc" {
198+
source = "terraform-aws-modules/vpc/aws"
199+
version = "~> 3.0"
200+
201+
name = local.name
202+
cidr = local.vpc_cidr
203+
204+
azs = local.azs
205+
public_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 8, k)]
206+
private_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 8, k + 10)]
207+
208+
enable_nat_gateway = true
209+
single_nat_gateway = true
210+
enable_dns_hostnames = true
211+
212+
# Manage so we can name
213+
manage_default_network_acl = true
214+
default_network_acl_tags = { Name = "${local.name}-default" }
215+
manage_default_route_table = true
216+
default_route_table_tags = { Name = "${local.name}-default" }
217+
manage_default_security_group = true
218+
default_security_group_tags = { Name = "${local.name}-default" }
219+
220+
public_subnet_tags = {
221+
"kubernetes.io/cluster/${local.name}" = "shared"
222+
"kubernetes.io/role/elb" = 1
223+
}
224+
225+
private_subnet_tags = {
226+
"kubernetes.io/cluster/${local.name}" = "shared"
227+
"kubernetes.io/role/internal-elb" = 1
228+
}
229+
230+
tags = local.tags
231+
}

examples/appmesh-mtls/outputs.tf

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
output "configure_kubectl" {
2+
description = "Configure kubectl: make sure you're logged in with the correct AWS profile and run the following command to update your kubeconfig"
3+
value = module.eks_blueprints.configure_kubectl
4+
}

examples/appmesh-mtls/variables.tf

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
variable "eks_cluster_domain" {
2+
description = "Route53 domain for the cluster"
3+
type = string
4+
default = "example.com"
5+
}
6+
7+
variable "certificate_name" {
8+
description = "name for the certificate"
9+
type = string
10+
default = "example"
11+
}
12+
13+
variable "certificate_dns" {
14+
description = "CommonName used in the Certificate, usually DNS"
15+
type = string
16+
default = "example.com"
17+
}

examples/appmesh-mtls/versions.tf

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
terraform {
2+
required_version = ">= 1.0.0"
3+
4+
required_providers {
5+
aws = {
6+
source = "hashicorp/aws"
7+
version = ">= 3.72"
8+
}
9+
kubernetes = {
10+
source = "hashicorp/kubernetes"
11+
version = ">= 2.10"
12+
}
13+
helm = {
14+
source = "hashicorp/helm"
15+
version = ">= 2.4.1"
16+
}
17+
kubectl = {
18+
source = "gavinbunney/kubectl"
19+
version = ">= 1.14"
20+
}
21+
}
22+
23+
# ## Used for end-to-end testing on project; update to suit your needs
24+
# backend "s3" {
25+
# bucket = "terraform-ssp-github-actions-state"
26+
# region = "us-west-2"
27+
# key = "e2e/appmesh-mtls/terraform.tfstate"
28+
# }
29+
}

examples/karpenter/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ After few times you should see 2 new nodes (one created by each provisioner)
111111
# Output should look like below
112112
NAME STATUS ROLES AGE VERSION PROVISIONER-NAME
113113
ip-10-0-10-14.us-west-2.compute.internal Ready <none> 11m v1.22.9-eks-810597c default
114-
ip-10-0-11-16.us-west-2.compute.internal Ready <none> 70m v1.22.9-eks-810597c
114+
ip-10-0-11-16.us-west-2.compute.internal Ready <none> 70m v1.22.9-eks-810597c
115115
ip-10-0-12-138.us-west-2.compute.internal Ready <none> 4m57s v1.22.9-eks-810597c default-lt
116116

117117
We now have :

modules/kubernetes-addons/README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
| <a name="module_agones"></a> [agones](#module\_agones) | ./agones | n/a |
2828
| <a name="module_airflow"></a> [airflow](#module\_airflow) | ./airflow | n/a |
2929
| <a name="module_app_2048"></a> [app\_2048](#module\_app\_2048) | ./app-2048 | n/a |
30+
| <a name="module_appmesh_controller"></a> [appmesh\_controller](#module\_appmesh\_controller) | ./appmesh-controller | n/a |
3031
| <a name="module_argo_rollouts"></a> [argo\_rollouts](#module\_argo\_rollouts) | ./argo-rollouts | n/a |
3132
| <a name="module_argocd"></a> [argocd](#module\_argocd) | ./argocd | n/a |
3233
| <a name="module_aws_cloudwatch_metrics"></a> [aws\_cloudwatch\_metrics](#module\_aws\_cloudwatch\_metrics) | ./aws-cloudwatch-metrics | n/a |
@@ -111,6 +112,8 @@
111112
| <a name="input_amazon_eks_vpc_cni_config"></a> [amazon\_eks\_vpc\_cni\_config](#input\_amazon\_eks\_vpc\_cni\_config) | ConfigMap of Amazon EKS VPC CNI add-on | `any` | `{}` | no |
112113
| <a name="input_amazon_prometheus_workspace_endpoint"></a> [amazon\_prometheus\_workspace\_endpoint](#input\_amazon\_prometheus\_workspace\_endpoint) | AWS Managed Prometheus WorkSpace Endpoint | `string` | `null` | no |
113114
| <a name="input_amazon_prometheus_workspace_region"></a> [amazon\_prometheus\_workspace\_region](#input\_amazon\_prometheus\_workspace\_region) | AWS Managed Prometheus WorkSpace Region | `string` | `null` | no |
115+
| <a name="input_appmesh_helm_config"></a> [appmesh\_helm\_config](#input\_appmesh\_helm\_config) | AppMesh Helm Chart config | `any` | `{}` | no |
116+
| <a name="input_appmesh_irsa_policies"></a> [appmesh\_irsa\_policies](#input\_appmesh\_irsa\_policies) | Additional IAM policies for a IAM role for service accounts | `list(string)` | `[]` | no |
114117
| <a name="input_argo_rollouts_helm_config"></a> [argo\_rollouts\_helm\_config](#input\_argo\_rollouts\_helm\_config) | Argo Rollouts Helm Chart config | `any` | `null` | no |
115118
| <a name="input_argocd_applications"></a> [argocd\_applications](#input\_argocd\_applications) | Argo CD Applications config to bootstrap the cluster | `any` | `{}` | no |
116119
| <a name="input_argocd_helm_config"></a> [argocd\_helm\_config](#input\_argocd\_helm\_config) | Argo CD Kubernetes add-on config | `any` | `{}` | no |
@@ -173,6 +176,7 @@
173176
| <a name="input_enable_amazon_eks_vpc_cni"></a> [enable\_amazon\_eks\_vpc\_cni](#input\_enable\_amazon\_eks\_vpc\_cni) | Enable VPC CNI add-on | `bool` | `false` | no |
174177
| <a name="input_enable_amazon_prometheus"></a> [enable\_amazon\_prometheus](#input\_enable\_amazon\_prometheus) | Enable AWS Managed Prometheus service | `bool` | `false` | no |
175178
| <a name="input_enable_app_2048"></a> [enable\_app\_2048](#input\_enable\_app\_2048) | Enable sample app 2048 | `bool` | `false` | no |
179+
| <a name="input_enable_appmesh_controller"></a> [enable\_appmesh\_controller](#input\_enable\_appmesh\_controller) | Enable AppMesh add-on | `bool` | `false` | no |
176180
| <a name="input_enable_argo_rollouts"></a> [enable\_argo\_rollouts](#input\_enable\_argo\_rollouts) | Enable Argo Rollouts add-on | `bool` | `false` | no |
177181
| <a name="input_enable_argocd"></a> [enable\_argocd](#input\_enable\_argocd) | Enable Argo CD Kubernetes add-on | `bool` | `false` | no |
178182
| <a name="input_enable_aws_cloudwatch_metrics"></a> [enable\_aws\_cloudwatch\_metrics](#input\_enable\_aws\_cloudwatch\_metrics) | Enable AWS CloudWatch Metrics add-on for Container Insights | `bool` | `false` | no |

0 commit comments

Comments
 (0)