├── Article 1 ├── provider.tf ├── state_config.tf ├── terraform.tfvars └── variables.tf ├── Article 2 ├── modules.tf ├── modules │ └── network │ │ ├── gateways.tf │ │ ├── route_tables.tf │ │ ├── subnets.tf │ │ ├── variables.tf │ │ └── vpc.tf ├── provider.tf ├── state_config.tf ├── terraform.tfvars └── variables.tf ├── Article 3 ├── modules.tf ├── modules │ ├── network │ │ ├── gateways.tf │ │ ├── output.tf │ │ ├── route_tables.tf │ │ ├── subnets.tf │ │ ├── variables.tf │ │ └── vpc.tf │ └── security_groups │ │ ├── sg_eks_master.tf │ │ ├── sg_eks_node.tf │ │ ├── sg_rules_eks.tf │ │ └── variables.tf ├── provider.tf ├── state_config.tf ├── terraform.tfvars └── variables.tf ├── Article 4 ├── modules.tf ├── modules │ ├── eks │ │ ├── allow_nodes.tf │ │ ├── eks_master.tf │ │ ├── iam.tf │ │ ├── kubeconfig.tf │ │ ├── output.tf │ │ ├── sg_eks_master.tf │ │ ├── sg_eks_node.tf │ │ ├── sg_rules_eks.tf │ │ ├── variables.tf │ │ └── worker-nodes.tf │ └── network │ │ ├── gateways.tf │ │ ├── output.tf │ │ ├── route_tables.tf │ │ ├── subnets.tf │ │ ├── variables.tf │ │ └── vpc.tf ├── provider.tf ├── state_config.tf ├── terraform.tfvars └── variables.tf └── Article 5 ├── modules.tf ├── modules ├── alb │ ├── acm_certificate.tf │ ├── alb.tf │ ├── route53-setup.tf │ ├── sg_alb.tf │ └── variables.tf ├── eks │ ├── allow_nodes.tf │ ├── eks_master.tf │ ├── iam.tf │ ├── kubeconfig.tf │ ├── output.tf │ ├── sg_eks_master.tf │ ├── sg_eks_node.tf │ ├── sg_rules_eks.tf │ ├── variables.tf │ └── worker-nodes.tf └── network │ ├── gateways.tf │ ├── output.tf │ ├── route_tables.tf │ ├── subnets.tf │ ├── variables.tf │ └── vpc.tf ├── provider.tf ├── state_config.tf ├── terraform.tfvars └── variables.tf /Article 1/provider.tf: -------------------------------------------------------------------------------- 1 | provider "aws" { 2 | region = "${var.aws_region}" 3 | version = "~> 1.55.0" 4 | access_key = "${var.aws_access_key}" 5 | secret_key = "${var.aws_secret_key}" 6 | } -------------------------------------------------------------------------------- /Article 1/state_config.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | backend "s3" { 3 | region = "" 4 | bucket = "tf-article" 5 | key = "terraform.tfstate" 6 | encrypt = "true" 7 | dynamodb_table = "tf-article-statelock" 8 | } 9 | } -------------------------------------------------------------------------------- /Article 1/terraform.tfvars: -------------------------------------------------------------------------------- 1 | aws_region = "" 2 | aws_access_key = "placeholder" 3 | aws_secret_key = "placeholder" -------------------------------------------------------------------------------- /Article 1/variables.tf: -------------------------------------------------------------------------------- 1 | variable "aws_region" { 2 | type = "string" 3 | description = "Used AWS Region." 4 | } 5 | variable "aws_access_key" { 6 | type = "string" 7 | description = "The account identification key used by your Terraform client." 8 | } 9 | variable "aws_secret_key" { 10 | type = "string" 11 | description = "The secret key used by your terraform client to access AWS." 12 | } -------------------------------------------------------------------------------- /Article 2/modules.tf: -------------------------------------------------------------------------------- 1 | module "network" { 2 | source = "./modules/network" 3 | 4 | // pass variables from .tfvars 5 | aws_region = "${var.aws_region}" 6 | subnet_count = "${var.subnet_count}" 7 | } -------------------------------------------------------------------------------- /Article 2/modules/network/gateways.tf: -------------------------------------------------------------------------------- 1 | resource "aws_internet_gateway" "example" { 2 | vpc_id = "${aws_vpc.example.id}" 3 | 4 | tags { 5 | Name = "internet_gateway" 6 | } 7 | } 8 | 9 | 10 | resource "aws_eip" "nat_gateway" { 11 | count = "${var.subnet_count}" 12 | vpc = true 13 | } 14 | 15 | resource "aws_nat_gateway" "example" { 16 | count = "${var.subnet_count}" 17 | allocation_id = "${aws_eip.nat_gateway.*.id[count.index]}" 18 | subnet_id = "${aws_subnet.gateway.*.id[count.index]}" 19 | tags { 20 | Name = "nat_gateway" 21 | } 22 | depends_on = ["aws_internet_gateway.example"] 23 | } -------------------------------------------------------------------------------- /Article 2/modules/network/route_tables.tf: -------------------------------------------------------------------------------- 1 | resource "aws_route_table" "application" { 2 | count = "${var.subnet_count}" 3 | vpc_id = "${aws_vpc.example.id}" 4 | route { 5 | cidr_block = "0.0.0.0/0" 6 | nat_gateway_id = "${aws_nat_gateway.example.*.id[count.index]}" 7 | } 8 | tags { 9 | Name = "example_application" 10 | } 11 | } 12 | 13 | resource "aws_route_table" "database" { 14 | vpc_id = "${aws_vpc.example.id}" 15 | 16 | tags { 17 | Name = "example_database" 18 | } 19 | } 20 | resource "aws_route_table" "gateway" { 21 | vpc_id = "${aws_vpc.example.id}" 22 | 23 | route { 24 | cidr_block = "0.0.0.0/0" 25 | gateway_id = "${aws_internet_gateway.example.id}" 26 | } 27 | tags { 28 | Name = "example_gateway" 29 | } 30 | } 31 | 32 | resource "aws_route_table_association" "application" { 33 | count = "${var.subnet_count}" 34 | 35 | subnet_id = "${aws_subnet.application.*.id[count.index]}" 36 | route_table_id = "${aws_route_table.application.*.id[count.index]}" 37 | } 38 | 39 | resource "aws_route_table_association" "database" { 40 | count = "${var.subnet_count}" 41 | 42 | subnet_id = "${aws_subnet.database.*.id[count.index]}" 43 | route_table_id = "${aws_route_table.database.id}" 44 | } 45 | 46 | resource "aws_route_table_association" "gateway" { 47 | count = "${var.subnet_count}" 48 | 49 | subnet_id = "${aws_subnet.gateway.*.id[count.index]}" 50 | route_table_id = "${aws_route_table.gateway.id}" 51 | } -------------------------------------------------------------------------------- /Article 2/modules/network/subnets.tf: -------------------------------------------------------------------------------- 1 | data "aws_availability_zones" "available" {} 2 | 3 | resource "aws_subnet" "gateway" { 4 | count = "${var.subnet_count}" 5 | availability_zone = "${data.aws_availability_zones.available.names[count.index]}" 6 | cidr_block = "10.0.1${count.index}.0/24" 7 | vpc_id = "${aws_vpc.example.id}" 8 | tags = "${ 9 | map( 10 | "Name", "example_gateway" 11 | ) 12 | }" 13 | } 14 | resource "aws_subnet" "application" { 15 | count = "${var.subnet_count}" 16 | availability_zone = "${data.aws_availability_zones.available.names[count.index]}" 17 | cidr_block = "10.0.2${count.index}.0/24" 18 | vpc_id = "${aws_vpc.example.id}" 19 | tags = "${ 20 | map( 21 | "Name", "example_application", 22 | "kubernetes.io/cluster/example", "shared", 23 | ) 24 | }" 25 | } 26 | 27 | resource "aws_subnet" "database" { 28 | count = "${var.subnet_count}" 29 | availability_zone = "${data.aws_availability_zones.available.names[count.index]}" 30 | cidr_block = "10.0.3${count.index}.0/24" 31 | vpc_id = "${aws_vpc.example.id}" 32 | 33 | tags = "${ 34 | map( 35 | "Name", "example_database" 36 | ) 37 | }" 38 | } -------------------------------------------------------------------------------- /Article 2/modules/network/variables.tf: -------------------------------------------------------------------------------- 1 | variable "aws_region" { 2 | type = "string" 3 | description = "Used AWS Region." 4 | } 5 | variable "subnet_count" { 6 | type = "string" 7 | description = "The number of subnets we want to create per type to ensure high availability." 8 | } -------------------------------------------------------------------------------- /Article 2/modules/network/vpc.tf: -------------------------------------------------------------------------------- 1 | resource "aws_vpc" "example" { 2 | cidr_block = "10.0.0.0/16" 3 | enable_dns_hostnames = true 4 | enable_dns_support = true 5 | tags = "${ 6 | map( 7 | "Name", "terraform-eks", 8 | "kubernetes.io/cluster/example", "shared", 9 | ) 10 | }" 11 | } -------------------------------------------------------------------------------- /Article 2/provider.tf: -------------------------------------------------------------------------------- 1 | provider "aws" { 2 | region = "${var.aws_region}" 3 | version = "~> 1.55.0" 4 | access_key = "${var.aws_access_key}" 5 | secret_key = "${var.aws_secret_key}" 6 | } -------------------------------------------------------------------------------- /Article 2/state_config.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | backend "s3" { 3 | region = "" 4 | bucket = "tf-article" 5 | key = "terraform.tfstate" 6 | encrypt = "true" 7 | dynamodb_table = "tf-article-statelock" 8 | } 9 | } -------------------------------------------------------------------------------- /Article 2/terraform.tfvars: -------------------------------------------------------------------------------- 1 | aws_region = "" 2 | aws_access_key = "placeholder" 3 | aws_secret_key = "placeholder" 4 | subnet_count = "" -------------------------------------------------------------------------------- /Article 2/variables.tf: -------------------------------------------------------------------------------- 1 | variable "aws_region" { 2 | type = "string" 3 | description = "Used AWS Region." 4 | } 5 | variable "aws_access_key" { 6 | type = "string" 7 | description = "The account identification key used by your Terraform client." 8 | } 9 | variable "aws_secret_key" { 10 | type = "string" 11 | description = "The secret key used by your terraform client to access AWS." 12 | } 13 | 14 | variable "subnet_count" { 15 | type = "string" 16 | description = "The number of subnets we want to create per type to ensure high availability." 17 | } -------------------------------------------------------------------------------- /Article 3/modules.tf: -------------------------------------------------------------------------------- 1 | module "network" { 2 | source = "./modules/network" 3 | 4 | // pass variables from .tfvars 5 | aws_region = "${var.aws_region}" 6 | subnet_count = "${var.subnet_count}" 7 | } 8 | 9 | module "security_groups" { 10 | source = "./modules/security_groups" 11 | 12 | // pass variables from .tfvars 13 | accessing_computer_ip = "${var.accessing_computer_ip}" 14 | 15 | // inputs from modules 16 | vpc_id = "${module.network.vpc_id}" 17 | } -------------------------------------------------------------------------------- /Article 3/modules/network/gateways.tf: -------------------------------------------------------------------------------- 1 | resource "aws_internet_gateway" "example" { 2 | vpc_id = "${aws_vpc.example.id}" 3 | 4 | tags { 5 | Name = "internet_gateway" 6 | } 7 | } 8 | 9 | 10 | resource "aws_eip" "nat_gateway" { 11 | count = "${var.subnet_count}" 12 | vpc = true 13 | } 14 | 15 | resource "aws_nat_gateway" "example" { 16 | count = "${var.subnet_count}" 17 | allocation_id = "${aws_eip.nat_gateway.*.id[count.index]}" 18 | subnet_id = "${aws_subnet.gateway.*.id[count.index]}" 19 | tags { 20 | Name = "nat_gateway" 21 | } 22 | depends_on = ["aws_internet_gateway.example"] 23 | } -------------------------------------------------------------------------------- /Article 3/modules/network/output.tf: -------------------------------------------------------------------------------- 1 | output "vpc_id" { 2 | value = "${aws_vpc.example.id}" 3 | } -------------------------------------------------------------------------------- /Article 3/modules/network/route_tables.tf: -------------------------------------------------------------------------------- 1 | resource "aws_route_table" "application" { 2 | count = "${var.subnet_count}" 3 | vpc_id = "${aws_vpc.example.id}" 4 | route { 5 | cidr_block = "0.0.0.0/0" 6 | nat_gateway_id = "${aws_nat_gateway.example.*.id[count.index]}" 7 | } 8 | tags { 9 | Name = "example_application" 10 | } 11 | } 12 | 13 | resource "aws_route_table" "database" { 14 | vpc_id = "${aws_vpc.example.id}" 15 | 16 | tags { 17 | Name = "example_database" 18 | } 19 | } 20 | resource "aws_route_table" "gateway" { 21 | vpc_id = "${aws_vpc.example.id}" 22 | 23 | route { 24 | cidr_block = "0.0.0.0/0" 25 | gateway_id = "${aws_internet_gateway.example.id}" 26 | } 27 | tags { 28 | Name = "example_gateway" 29 | } 30 | } 31 | 32 | resource "aws_route_table_association" "application" { 33 | count = "${var.subnet_count}" 34 | 35 | subnet_id = "${aws_subnet.application.*.id[count.index]}" 36 | route_table_id = "${aws_route_table.application.*.id[count.index]}" 37 | } 38 | 39 | resource "aws_route_table_association" "database" { 40 | count = "${var.subnet_count}" 41 | 42 | subnet_id = "${aws_subnet.database.*.id[count.index]}" 43 | route_table_id = "${aws_route_table.database.id}" 44 | } 45 | 46 | resource "aws_route_table_association" "gateway" { 47 | count = "${var.subnet_count}" 48 | 49 | subnet_id = "${aws_subnet.gateway.*.id[count.index]}" 50 | route_table_id = "${aws_route_table.gateway.id}" 51 | } -------------------------------------------------------------------------------- /Article 3/modules/network/subnets.tf: -------------------------------------------------------------------------------- 1 | data "aws_availability_zones" "available" {} 2 | 3 | resource "aws_subnet" "gateway" { 4 | count = "${var.subnet_count}" 5 | availability_zone = "${data.aws_availability_zones.available.names[count.index]}" 6 | cidr_block = "10.0.1${count.index}.0/24" 7 | vpc_id = "${aws_vpc.example.id}" 8 | tags = "${ 9 | map( 10 | "Name", "example_gateway" 11 | ) 12 | }" 13 | } 14 | resource "aws_subnet" "application" { 15 | count = "${var.subnet_count}" 16 | availability_zone = "${data.aws_availability_zones.available.names[count.index]}" 17 | cidr_block = "10.0.2${count.index}.0/24" 18 | vpc_id = "${aws_vpc.example.id}" 19 | tags = "${ 20 | map( 21 | "Name", "example_application", 22 | "kubernetes.io/cluster/example", "shared", 23 | ) 24 | }" 25 | } 26 | 27 | resource "aws_subnet" "database" { 28 | count = "${var.subnet_count}" 29 | availability_zone = "${data.aws_availability_zones.available.names[count.index]}" 30 | cidr_block = "10.0.3${count.index}.0/24" 31 | vpc_id = "${aws_vpc.example.id}" 32 | 33 | tags = "${ 34 | map( 35 | "Name", "example_database" 36 | ) 37 | }" 38 | } -------------------------------------------------------------------------------- /Article 3/modules/network/variables.tf: -------------------------------------------------------------------------------- 1 | variable "aws_region" { 2 | type = "string" 3 | description = "Used AWS Region." 4 | } 5 | variable "subnet_count" { 6 | type = "string" 7 | description = "The number of subnets we want to create per type to ensure high availability." 8 | } -------------------------------------------------------------------------------- /Article 3/modules/network/vpc.tf: -------------------------------------------------------------------------------- 1 | resource "aws_vpc" "example" { 2 | cidr_block = "10.0.0.0/16" 3 | enable_dns_hostnames = true 4 | enable_dns_support = true 5 | tags = "${ 6 | map( 7 | "Name", "terraform-eks", 8 | "kubernetes.io/cluster/example", "shared", 9 | ) 10 | }" 11 | } -------------------------------------------------------------------------------- /Article 3/modules/security_groups/sg_eks_master.tf: -------------------------------------------------------------------------------- 1 | 2 | resource "aws_security_group" "tf-eks-master" { 3 | name = "terraform-eks-cluster" 4 | description = "Cluster communication with worker nodes" 5 | vpc_id = "${var.vpc_id}" 6 | 7 | egress { 8 | from_port = 0 9 | to_port = 0 10 | protocol = "-1" 11 | cidr_blocks = ["0.0.0.0/0"] 12 | } 13 | 14 | tags { 15 | Name = "terraform-eks" 16 | } 17 | } -------------------------------------------------------------------------------- /Article 3/modules/security_groups/sg_eks_node.tf: -------------------------------------------------------------------------------- 1 | resource "aws_security_group" "tf-eks-node" { 2 | name = "terraform-eks-node" 3 | description = "Security group for all nodes in the cluster" 4 | vpc_id = "${var.vpc_id}" 5 | 6 | egress { 7 | from_port = 0 8 | to_port = 0 9 | protocol = "-1" 10 | cidr_blocks = ["0.0.0.0/0"] 11 | } 12 | 13 | tags { 14 | Name = "terraform-eks" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Article 3/modules/security_groups/sg_rules_eks.tf: -------------------------------------------------------------------------------- 1 | # Allow inbound traffic from your local workstation external IP 2 | # to the Kubernetes. You will need to replace A.B.C.D below with 3 | # your real IP. Services like icanhazip.com can help you find this. 4 | resource "aws_security_group_rule" "tf-eks-cluster-ingress-workstation-https" { 5 | cidr_blocks = ["${var.accessing_computer_ip}/32"] 6 | description = "Allow workstation to communicate with the cluster API Server" 7 | from_port = 443 8 | protocol = "tcp" 9 | security_group_id = "${aws_security_group.tf-eks-master.id}" 10 | to_port = 443 11 | type = "ingress" 12 | } 13 | 14 | ######################################################################################## 15 | # Setup worker node security group 16 | 17 | resource "aws_security_group_rule" "tf-eks-node-ingress-self" { 18 | description = "Allow node to communicate with each other" 19 | from_port = 0 20 | protocol = "-1" 21 | security_group_id = "${aws_security_group.tf-eks-node.id}" 22 | source_security_group_id = "${aws_security_group.tf-eks-node.id}" 23 | to_port = 65535 24 | type = "ingress" 25 | } 26 | 27 | resource "aws_security_group_rule" "tf-eks-node-ingress-cluster" { 28 | description = "Allow worker Kubelets and pods to receive communication from the cluster control plane" 29 | from_port = 1025 30 | protocol = "tcp" 31 | security_group_id = "${aws_security_group.tf-eks-node.id}" 32 | source_security_group_id = "${aws_security_group.tf-eks-master.id}" 33 | to_port = 65535 34 | type = "ingress" 35 | } 36 | 37 | # allow worker nodes to access EKS master 38 | resource "aws_security_group_rule" "tf-eks-cluster-ingress-node-https" { 39 | description = "Allow pods to communicate with the cluster API Server" 40 | from_port = 443 41 | protocol = "tcp" 42 | security_group_id = "${aws_security_group.tf-eks-node.id}" 43 | source_security_group_id = "${aws_security_group.tf-eks-master.id}" 44 | to_port = 443 45 | type = "ingress" 46 | } 47 | 48 | resource "aws_security_group_rule" "tf-eks-node-ingress-master" { 49 | description = "Allow cluster control to receive communication from the worker Kubelets" 50 | from_port = 443 51 | protocol = "tcp" 52 | security_group_id = "${aws_security_group.tf-eks-master.id}" 53 | source_security_group_id = "${aws_security_group.tf-eks-node.id}" 54 | to_port = 443 55 | type = "ingress" 56 | } 57 | 58 | 59 | -------------------------------------------------------------------------------- /Article 3/modules/security_groups/variables.tf: -------------------------------------------------------------------------------- 1 | variable "accessing_computer_ip" { 2 | type = "string" 3 | description = "IP of the computer to be allowed to connect to EKS master and nodes." 4 | } 5 | 6 | variable "vpc_id" { 7 | type = "string" 8 | description = "ID of the VPC used to setup the cluster." 9 | } 10 | -------------------------------------------------------------------------------- /Article 3/provider.tf: -------------------------------------------------------------------------------- 1 | provider "aws" { 2 | region = "${var.aws_region}" 3 | version = "~> 1.55.0" 4 | access_key = "${var.aws_access_key}" 5 | secret_key = "${var.aws_secret_key}" 6 | } -------------------------------------------------------------------------------- /Article 3/state_config.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | backend "s3" { 3 | region = "eu-west-1" 4 | bucket = "tf-article" 5 | key = "terraform.tfstate" 6 | encrypt = "true" 7 | dynamodb_table = "tf-article-statelock" 8 | } 9 | } -------------------------------------------------------------------------------- /Article 3/terraform.tfvars: -------------------------------------------------------------------------------- 1 | aws_region = "placeholder" 2 | aws_access_key = "placeholder" 3 | aws_secret_key = "placeholder" 4 | subnet_count = "placeholder" 5 | accessing_computer_ip = "placeholder" -------------------------------------------------------------------------------- /Article 3/variables.tf: -------------------------------------------------------------------------------- 1 | variable "aws_region" { 2 | type = "string" 3 | description = "Used AWS Region." 4 | } 5 | variable "aws_access_key" { 6 | type = "string" 7 | description = "The account identification key used by your Terraform client." 8 | } 9 | variable "aws_secret_key" { 10 | type = "string" 11 | description = "The secret key used by your terraform client to access AWS." 12 | } 13 | 14 | variable "subnet_count" { 15 | type = "string" 16 | description = "The number of subnets we want to create per type to ensure high availability." 17 | } 18 | 19 | variable "accessing_computer_ip" { 20 | type = "string" 21 | description = "IP of the computer to be allowed to connect to EKS master and nodes." 22 | } -------------------------------------------------------------------------------- /Article 4/modules.tf: -------------------------------------------------------------------------------- 1 | module "network" { 2 | source = "./modules/network" 3 | 4 | // pass variables from .tfvars 5 | aws_region = "${var.aws_region}" 6 | subnet_count = "${var.subnet_count}" 7 | } 8 | 9 | module "eks" { 10 | source = "./modules/eks" 11 | 12 | // pass variables from .tfvars 13 | accessing_computer_ip = "${var.accessing_computer_ip}" 14 | aws_region = "${var.aws_region}" 15 | keypair-name = "${var.keypair-name}" 16 | // inputs from modules 17 | vpc_id = "${module.network.vpc_id}" 18 | app_subnet_ids = "${module.network.app_subnet_ids}" 19 | } -------------------------------------------------------------------------------- /Article 4/modules/eks/allow_nodes.tf: -------------------------------------------------------------------------------- 1 | ######################################################################################## 2 | # setup provider for kubernetes 3 | 4 | data "external" "aws_iam_authenticator" { 5 | program = ["sh", "-c", "aws-iam-authenticator token -i example | jq -r -c .status"] 6 | } 7 | 8 | provider "kubernetes" { 9 | host = "${aws_eks_cluster.tf_eks.endpoint}" 10 | cluster_ca_certificate = "${base64decode(aws_eks_cluster.tf_eks.certificate_authority.0.data)}" 11 | token = "${data.external.aws_iam_authenticator.result.token}" 12 | load_config_file = false 13 | version = "~> 1.5" 14 | } 15 | 16 | # Allow worker nodes to join cluster via config map 17 | resource "kubernetes_config_map" "aws_auth" { 18 | metadata { 19 | name = "aws-auth" 20 | namespace = "kube-system" 21 | } 22 | data { 23 | mapRoles = < config', run 'mv config ~/.kube/config' to use it for kubectl 3 | locals { 4 | kubeconfig = < config', run 'mv config ~/.kube/config' to use it for kubectl 3 | locals { 4 | kubeconfig = <