Skip to content

Commit

Permalink
Merge pull request #63 from hashicorp/webdog/hcp-eks-standard-deployment
Browse files Browse the repository at this point in the history
Create HCP Consul and Amazon EKS terraform deployment
  • Loading branch information
webdog authored May 13, 2022
2 parents 17f512d + fa9d2af commit 1bcae7f
Show file tree
Hide file tree
Showing 6 changed files with 415 additions and 0 deletions.
69 changes: 69 additions & 0 deletions hcp-consul-eks/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
## Requirements

| Name | Version |
|------|---------|
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.1.5 |
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | 3.74.0 |
| <a name="requirement_hcp"></a> [hcp](#requirement\_hcp) | 0.22.0 |

## Providers

| Name | Version |
|------|---------|
| <a name="provider_aws"></a> [aws](#provider\_aws) | 3.74.0 |
| <a name="provider_local"></a> [local](#provider\_local) | 2.1.0 |
| <a name="provider_null"></a> [null](#provider\_null) | 3.1.0 |

## Modules

| Name | Source | Version |
|------|--------|---------|
| <a name="module_aws"></a> [aws](#module\_aws) | ./modules/aws | n/a |
| <a name="module_aws_vpc"></a> [aws\_vpc](#module\_aws\_vpc) | registry.terraform.io/terraform-aws-modules/vpc/aws | 3.11.5 |
| <a name="module_cleanup"></a> [cleanup](#module\_cleanup) | ./modules/cleanup | n/a |
| <a name="module_eks"></a> [eks](#module\_eks) | registry.terraform.io/terraform-aws-modules/eks/aws | 18.9.0 |
| <a name="module_eks_iam"></a> [eks\_iam](#module\_eks\_iam) | ./modules/iam | n/a |
| <a name="module_hcp_applications"></a> [hcp\_applications](#module\_hcp\_applications) | ./modules/hcp_applications | n/a |
| <a name="module_hcp_networking"></a> [hcp\_networking](#module\_hcp\_networking) | ./modules/hcp_networking | n/a |
| <a name="module_hcp_networking_primitives"></a> [hcp\_networking\_primitives](#module\_hcp\_networking\_primitives) | ./modules/hcp_networking_primitives | n/a |
| <a name="module_iam_role_for_service_accounts"></a> [iam\_role\_for\_service\_accounts](#module\_iam\_role\_for\_service\_accounts) | registry.terraform.io/terraform-aws-modules/iam/aws//modules/iam-role-for-service-accounts-eks | 4.14.0 |

## Resources

| Name | Type |
|------|------|
| [local_file.kubernetes_tfvars](https://registry.terraform.io/providers/hashicorp/local/latest/docs/resources/file) | resource |
| [null_resource.update_kubeconfig](https://registry.terraform.io/providers/hashicorp/null/latest/docs/resources/resource) | resource |
| [aws_caller_identity.current](https://registry.terraform.io/providers/hashicorp/aws/3.74.0/docs/data-sources/caller_identity) | data source |

## Inputs

| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| <a name="input_availability_zones"></a> [availability\_zones](#input\_availability\_zones) | Availability Zones for the EKS Cluster deployed in main.tf | `list(string)` | <pre>[<br> "us-east-1a",<br> "us-east-1b",<br> "us-east-1c"<br>]</pre> | no |
| <a name="input_aws_cidr_block"></a> [aws\_cidr\_block](#input\_aws\_cidr\_block) | CIDR block for AWS VPC | `map` | <pre>{<br> "allocation": "172.16.0.0/19",<br> "subnets": {<br> "private": [<br> "172.16.2.0/24",<br> "172.16.3.0/24"<br> ],<br> "public": [<br> "172.16.4.0/24",<br> "172.16.5.0/24"<br> ]<br> }<br>}</pre> | no |
| <a name="input_cloud_provider"></a> [cloud\_provider](#input\_cloud\_provider) | HCP Default Cloud Provider | `string` | `"aws"` | no |
| <a name="input_cluster_and_vpc_info"></a> [cluster\_and\_vpc\_info](#input\_cluster\_and\_vpc\_info) | EKS Cluster Configuration Details | `any` | <pre>{<br> "name": "tutorialCluster",<br> "policy_description": "Grant the cluster access to describe itself and assume an IAM Role.",<br> "policy_name": "workingenvironmentpolicy",<br> "region": "us-east-1",<br> "stage": "dev",<br> "vpc_name": "hcpTutorialAwsVpc"<br>}</pre> | no |
| <a name="input_default_tags"></a> [default\_tags](#input\_default\_tags) | Default tags to pass to AWS resources | `map(string)` | <pre>{<br> "github": "hashicorp/learn-consul-kubernetes"<br>}</pre> | no |
| <a name="input_hcp_consul_datacenter_name"></a> [hcp\_consul\_datacenter\_name](#input\_hcp\_consul\_datacenter\_name) | Name of Consul datacenter | `string` | `"dc1"` | no |
| <a name="input_hcp_hvn_config"></a> [hcp\_hvn\_config](#input\_hcp\_hvn\_config) | CIDR block for HCP HVN | `map` | <pre>{<br> "allocation": "10.100.0.0/19",<br> "consul_tier": "standard",<br> "name": "hcpTutorial",<br> "vault_tier": "starter_small"<br>}</pre> | no |
| <a name="input_hcp_peering_identifier"></a> [hcp\_peering\_identifier](#input\_hcp\_peering\_identifier) | Name of the peering connection as displayed in the AWS API and Management Console | `string` | `"hcp-consul-vault-tutorial"` | no |
| <a name="input_hcp_region"></a> [hcp\_region](#input\_hcp\_region) | HCP region for HCP-created resources | `string` | `"us-east-1"` | no |
| <a name="input_hcp_vault_cluster_name"></a> [hcp\_vault\_cluster\_name](#input\_hcp\_vault\_cluster\_name) | name of HCP Vault cluster | `string` | `"vault-cluster"` | no |
| <a name="input_hcp_vault_default_namespace"></a> [hcp\_vault\_default\_namespace](#input\_hcp\_vault\_default\_namespace) | HCP Vault's Default Namespace. Must be specified when running Vault Enterprise | `string` | `"admin"` | no |
| <a name="input_kube_namespace"></a> [kube\_namespace](#input\_kube\_namespace) | Which kubernetes namespace to use in this tutorial | `string` | `"default"` | no |
| <a name="input_kube_service_account_name"></a> [kube\_service\_account\_name](#input\_kube\_service\_account\_name) | Name of the Kubernetes service account that maps to an IAM Role | `string` | `"tutorial"` | no |
| <a name="input_node_group_configuration"></a> [node\_group\_configuration](#input\_node\_group\_configuration) | Settings for the EKS Node Groups to pass to the EKS Module in main.tf | `any` | <pre>{<br> "ami_type": "AL2_x86_64",<br> "desired_instances": 2,<br> "disk_size_gigs": 50,<br> "instance_types": [<br> "m5.large"<br> ],<br> "max_instances": 2,<br> "min_instances": 2<br>}</pre> | no |
| <a name="input_profile_name"></a> [profile\_name](#input\_profile\_name) | Profile Name for the AWS Credentials in the working environment pod | `string` | `"kubeUser"` | no |
| <a name="input_region"></a> [region](#input\_region) | Region in which to run this terraform code for the AWS Provider | `string` | `"us-east-1"` | no |
| <a name="input_run_cleanup"></a> [run\_cleanup](#input\_run\_cleanup) | Whether or not to run the cleanup script. False by default, set to True in the tutorial content as environment variable | `bool` | `false` | no |

## Outputs

| Name | Description |
|------|-------------|
| <a name="output_consul_auth_data"></a> [consul\_auth\_data](#output\_consul\_auth\_data) | Authentication data for Consul that is passed to the working environment |
| <a name="output_eks_data"></a> [eks\_data](#output\_eks\_data) | Data for the EKS Cluster that is sent to the working environment |
| <a name="output_oidc_provider_arn"></a> [oidc\_provider\_arn](#output\_oidc\_provider\_arn) | The OIDC Provider ARN. Used to connect AWS IAM Roles to Service Accounts whose identities are managed by the Kubernetes cluster. Used to allow the reader to access the AWS CLI in the Pod without copying credentials over. |
| <a name="output_service_account_role_arn"></a> [service\_account\_role\_arn](#output\_service\_account\_role\_arn) | The Service Account Role ARN created for the EKS Cluster. This is passed to the working environment as a Service Annotation in the deployment's podspec. |
| <a name="output_vault_auth_data"></a> [vault\_auth\_data](#output\_vault\_auth\_data) | Authentication data for Vault that is passed to the working environment |
2 changes: 2 additions & 0 deletions hcp-consul-eks/data.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# The identity of the AWS User running this terraform project
data "aws_caller_identity" "current" {}
165 changes: 165 additions & 0 deletions hcp-consul-eks/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
# Create unique resources

locals {
unique_id = random_id.unique_identifier.b64_url
vpc_name = "${var.cluster_and_vpc_info.vpc_name}-${local.unique_id}"
hvn_name = "${var.hcp_hvn_config.name}-${local.unique_id}"
hcp_peering_id = "${var.hcp_peering_identifier}-${local.unique_id}"
consul_datacenter_name = "${var.hcp_consul_datacenter_name}-${local.unique_id}"
vault_cluster_name = "${var.hcp_vault_cluster_name}-${local.unique_id}"
eks_cluster_name = "${var.cluster_and_vpc_info.name}-${local.unique_id}"
policy_name = "${var.cluster_and_vpc_info.policy_name}-${local.unique_id}"

}

resource "random_id" "unique_identifier" {
byte_length = 2
}

# Builds the base VPC for the AWS EKS Cluster
module "aws_vpc" {
# Keep full URL for tf registry modules for cross-IDE compatibility.
source = "registry.terraform.io/terraform-aws-modules/vpc/aws"
version = "3.11.5"
name = local.vpc_name#var.cluster_and_vpc_info.vpc_name
cidr = var.aws_cidr_block.allocation
azs = var.availability_zones
private_subnets = var.aws_cidr_block.subnets.private
public_subnets = var.aws_cidr_block.subnets.public
enable_nat_gateway = true
enable_vpn_gateway = false
# internal-lb: Permits internal Load Balancer creation when a LoadBalancer type is passed.
private_subnet_tags = {
"kubernetes.io/cluster/${var.cluster_and_vpc_info.name}" = "shared"
"kubernetes.io/role/internal-elb" = "1"
}
#elb: Permits Elastic Load Balancer creation when a LoadBalancer type is passed.
public_subnet_tags = {
"kubernetes.io/cluster/${var.cluster_and_vpc_info.name}" = "shared"
"kubernetes.io/role/elb" = "1"
}

tags = {
Terraform = "true"
Environment = var.cluster_and_vpc_info.stage
}
}


# Deploys Amazon EKS
module "eks" {
source = "registry.terraform.io/terraform-aws-modules/eks/aws"
version = "18.9.0"
cluster_name = local.eks_cluster_name
cluster_endpoint_private_access = true
cluster_endpoint_public_access = true


cluster_addons = {
coredns = {
resolve_conflicts = "OVERWRITE"
}
kube-proxy = {}
vpc-cni = {
resolve_conflicts = "OVERWRITE"
}
}

vpc_id = module.aws_vpc.vpc_id
subnet_ids = setunion(
module.aws_vpc.public_subnets,
module.aws_vpc.private_subnets
)

eks_managed_node_group_defaults = {
ami_type = var.node_group_configuration.ami_type
disk_size = var.node_group_configuration.disk_size_gigs
instance_types = var.node_group_configuration.instance_types
vpc_security_group_ids = [module.hcp.aws_security_group_id]
}

eks_managed_node_groups = {
blue = {}
green = {
min_size = var.node_group_configuration.min_instances
max_size = var.node_group_configuration.max_instances
desired_size = var.node_group_configuration.desired_instances
}
}
tags = {
Environment = var.cluster_and_vpc_info.stage
}

}

# Creates the policy and policy attachment to the role created above this module. Permits the EKS Cluster
# to describe itself, and assume an IAM Role, which is passed to the Kubernetes Service Account downstream.
module "eks_iam" {
source = "github.com/webdog/terraform-eks-iam-cluster-describe"
cluster_arn = module.eks.cluster_arn
description = var.cluster_and_vpc_info.policy_description
policy_name = local.policy_name
role_name = module.iam_role_for_service_accounts.iam_role_name
}

# This module maps Kubernetes ServiceAccount -> IAM Role
module "iam_role_for_service_accounts" {
source = "registry.terraform.io/terraform-aws-modules/iam/aws//modules/iam-role-for-service-accounts-eks"
role_name = lower(local.eks_cluster_name)
version = "4.14.0"

oidc_providers = {
one = {
provider_arn = module.eks.oidc_provider_arn
namespace_service_accounts = ["${var.kube_namespace}:${var.kube_service_account_name}"]
}
}
}


# Cleanup ENI module
# This module's resources only run when `terraform destroy` is invoked by the user. A "start_cleanup" variable
# is used to make sure cleanup scripts are not run during a follow up terraform apply, and only during terraform destroy.
# This is passed as TF_VAR_start_cleanup=true to the main project by the reader at the end of the tutorial:
# export TF_VAR_run_cleanup=true; terraform destroy -auto-approve
module "eni_cleanup" {
source = "github.com/webdog/terraform-kubernetes-delete-eni"
vpc_id= module.aws_vpc.vpc_id
region = var.region
}


# Creates the peering relationship between HCP and AWS, using the
# defined variables, and module outputs.
module "hcp" {
source = "github.com/webdog/terraform-hcp-consul-cluster"
aws_region = var.region
aws_account_id = data.aws_caller_identity.current.id
aws_vpc_id = module.aws_vpc.vpc_id
aws_default_route_table_id = module.aws_vpc.vpc_main_route_table_id
aws_vpc_cidr_block = var.aws_cidr_block.allocation
hvn_peering_identifier = local.hcp_peering_id
hcp_hvn_cidr_block = var.hcp_hvn_config.allocation
public_route_table_ids = module.aws_vpc.public_route_table_ids
private_route_table_ids = module.aws_vpc.private_route_table_ids
cloud_provider = var.cloud_provider
hcp_region = var.hcp_region
hvn_name = local.hvn_name
cidr_block = var.hcp_hvn_config.allocation
consul_cluster_datacenter = local.consul_datacenter_name
hcp_consul_tier = var.hcp_hvn_config.consul_tier
aws_cidr = var.aws_cidr_block.allocation
hvn_cidr = var.hcp_hvn_config.allocation
hvn_id = local.hvn_name
}


# Safely update local environment's kubeconfig file.
resource "null_resource" "update_kubeconfig" {

provisioner "local-exec" {
# Create empty kubeconfig if it doesn't exist. If it does exist, touch does nothing, but back up the config in either case and use a kubeconfig that is unique for this tutorial. Is deleted during terraform destroy
command = "mv ~/.kube/config ~/.kube/config.bkp && aws eks --region ${var.cluster_and_vpc_info.region} update-kubeconfig --name ${module.eks.cluster_id} --alias ${var.cluster_and_vpc_info.name}"
}
depends_on = [module.eks]
}
34 changes: 34 additions & 0 deletions hcp-consul-eks/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Authentication data for Consul that is passed to the working environment
output "consul_auth_data" {
sensitive = true
value = {
ca_file = module.hcp.consul_ca_file
root_accessor_id = module.hcp.consul_root_token_accessor_id
root_secret_id = module.hcp.consul_root_token_secret_id
consul_config = module.hcp.consul_config_file
consul_cluster_host = module.hcp.consul_cluster_host
consul_root_token = module.hcp.consul_root_token
}
}

# Data for the EKS Cluster that is sent to the working environment
output "eks_data" {
sensitive = true
value = {
eks_host = module.eks.cluster_endpoint
eks_cert = module.eks.cluster_certificate_authority_data
eks_arn = module.eks.cluster_arn
}
}

# The OIDC Provider ARN. Used to connect AWS IAM Roles to Service Accounts whose identities are managed by the Kubernetes cluster.
# Used to allow the reader to access the AWS CLI in the Pod without copying credentials over.
output "oidc_provider_arn" {
value = module.eks.oidc_provider_arn
}

# The Service Account Role ARN created for the EKS Cluster. This is passed to the working environment as a Service
# Annotation in the deployment's podspec.
output "service_account_role_arn" {
value = module.iam_role_for_service_accounts.iam_role_arn
}
20 changes: 20 additions & 0 deletions hcp-consul-eks/provider.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
terraform {
required_version = ">= 1.0.11"
required_providers {
aws = {
source = "hashicorp/aws"
version = ">=3.74.0"
}
hcp = {
source = "hashicorp/hcp"
version = ">=0.22.0"
}
}
}

provider "aws" {
region = var.region
}

provider "hcp" {}

Loading

0 comments on commit 1bcae7f

Please sign in to comment.