Table of Contents
- Terraform target infrastructure
- Terraform Deployments structure
- Terraform Module structure
- Current Terraform Modules
- Settings
- Remote State
- Terraform environment standup
- Terraform Style Guide
Deployments are location within:
deployments/[deployment name]
The main.tf defines the modules that are to actioned and the variables passed to those modules.
Terraform modules are segregated by Cloud Provider under the modules directory, for example
modules/AWS
The Terraform modules for AWS ( located under modules/AWS/[module name]
) action the following:
Refer to settings documentation
- Uploads Ssh key to be used for all instances
This module does not require any settings to be provided at this moment
- Identifies current Ubuntu 18.04 LTS AMI Id for region in use
Refer to settings documentation
- A single bastion host on the public subnet
Refer to settings documentation
- One, or more, Kubernetes master nodes on the private network
- One, or more, Kubernetes nodes on the private network
Cloud init is used to installed k8s software and initialise the cluster. This is separted into 2 configurations:
- cloud-init-master.cfg - run on master nodes and installs kubelet, kubectl, kubeadm, docker and crictl. Initialises the cluster
- cloud-init.cfg - runs on nodes and installs kubelet, kubectl, kubeadm, docker and crictl.
Refer to settings documentation
- A single host on the private subnet which is external to the cluster
Refer to settings documentation
- Single Vpc
- 2 subnets, 1 public, 1 private
- An Internet Gateway attached to public subnet
- A NAT gateway
The following routes are defined
- public_route_table - route to internet gateway, associated to public subnet
- private_nat_route_table - route to NAT gateway, associated to private subnet
Refer to settings documentation
- Create S3 bucket
- Create IAM role/policy for k8s hosts to access S3 bucket
Refer to settings documentation
The following security groups are defined
- bastion-sg - ingress connection over internet from defined cidr, open egress to internet
- controlplane-sg - Allows ingress from public subnet to private subnet (needs to be tighten up), open egress to internet (via NAT gateway)
Refer to settings documentation for details on deployment settings required, and defaults provided.
This Terraform code uses remote state storage using S3. This is configured in terraform/providers.tf
in the terraform
block. The S3 bucket is assumed to have been created already.
This following outlines coding conventions for Terraform's HashiCorp Configuration Language (HCL). Terraform allows infrastructure to be described as code. As such, we should adhere to a style guide to ensure readable and high quality code.
Directories are split into deployments and modules
deployments contains subdirectories for each terraform deployment
modules contains subdirectories for each cloud vendor as appropriate (i.e AWS, Azure, GCP)
Taking AWS as an example modules subdirectory, the AWS directory will then contains modules logically segregated into their core function (Networking, SecurityGroups etc).
- Strings are in double-quotes.
Use 2 spaces when defining resources except when defining inline policies or other inline resources.
resource "aws_iam_role" "iam_role" {
name = "${var.resource_name}-role"
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Effect": "Allow",
"Sid": ""
}
]
}
EOF
}
Parameter definitions in a resource block should be aligned. The terraform fmt
command can do this for you.
provider "aws" {
access_key = "${var.aws_access_key}"
secret_key = "${var.aws_secret_key}"
region = "us-east-1"
}
When commenting use two "//" and a space in front of the comment.
// CREATE ELK IAM ROLE
...
The variables.tf
file should be broken down into three sections with each section arranged alphabetically. Starting at the top of the file:
- Variables that have no defaults defined
- Variables that contain defaults
- All locals blocks
For example:
variable "image_tag" {}
variable "desired_count" {
default = "2"
}
locals {
domain_name = "${data.terraform_remote_state.account.domain_name}"
}
Create a separate resource file for each type of AWS resource. Similar resources should be defined in the same file.
main.tf
providers.tf
variables.tf
Only use an underscore (_
) when naming Terraform resources like TYPE/NAME parameters and user provided variables.
resource "aws_security_group" "security_group" {
...
Variables provided as output from modules should following CamelCase convention to make module provided variables easy to identify
output "ControlPlaneSecurityGroupID" {
...
Only use a hyphen (-
) when naming the component being created.
resource "aws_security_group" "security_group" {
name = "${var.resource_name}-security-group"
...
A resource's NAME should describe TYPE pre-pended with simulator, unique ident and minus the provider. Common shorthand for TYPE is fine here
resource "aws_security_group" "simulator_controlplane_sg" {
...