├── .gitignore ├── LICENSE ├── README.md └── code ├── 01-hello-world ├── README.md └── main.tf ├── 02-one-server ├── README.md └── main.tf ├── 03-one-webserver ├── README.md └── main.tf ├── 04-one-webserver-with-vars ├── README.md ├── main.tf ├── outputs.tf └── vars.tf ├── 05-cluster-webserver ├── README.md ├── main.tf ├── outputs.tf └── vars.tf ├── 06-create-s3 ├── README.md ├── main.tf ├── outputs.tf └── vars.tf ├── 07-terraform-state ├── README.md ├── backend.tf └── main.tf ├── 08-file-layout-example ├── README.md ├── global │ └── s3 │ │ ├── README.md │ │ ├── main.tf │ │ ├── outputs.tf │ │ └── vars.tf └── stage │ ├── data-stores │ └── mysql │ │ ├── README.md │ │ ├── backend.tf │ │ ├── main.tf │ │ ├── outputs.tf │ │ └── vars.tf │ └── services │ └── webserver-cluster │ ├── README.md │ ├── backend.tf │ ├── main.tf │ ├── outputs.tf │ ├── user-data.sh │ └── vars.tf ├── 09-module-example ├── README.md ├── global │ └── s3 │ │ ├── README.md │ │ ├── main.tf │ │ ├── outputs.tf │ │ └── vars.tf ├── modules │ └── services │ │ └── webserver-cluster │ │ ├── README.md │ │ ├── main.tf │ │ ├── outputs.tf │ │ ├── user-data.sh │ │ └── vars.tf ├── prod │ ├── data-stores │ │ └── mysql │ │ │ ├── README.md │ │ │ ├── backend.tf │ │ │ ├── main.tf │ │ │ ├── outputs.tf │ │ │ └── vars.tf │ └── services │ │ └── webserver-cluster │ │ ├── README.md │ │ ├── backend.tf │ │ ├── main.tf │ │ ├── outputs.tf │ │ └── vars.tf └── stage │ ├── data-stores │ └── mysql │ │ ├── README.md │ │ ├── backend.tf │ │ ├── main.tf │ │ ├── outputs.tf │ │ └── vars.tf │ └── services │ └── webserver-cluster │ ├── README.md │ ├── backend.tf │ ├── main.tf │ ├── outputs.tf │ └── vars.tf ├── 10-multi-repo-example ├── README.md └── live │ ├── global │ └── s3 │ │ ├── README.md │ │ ├── main.tf │ │ ├── outputs.tf │ │ └── vars.tf │ ├── prod │ ├── data-stores │ │ └── mysql │ │ │ ├── README.md │ │ │ ├── backend.tf │ │ │ ├── main.tf │ │ │ ├── outputs.tf │ │ │ └── vars.tf │ └── services │ │ └── webserver-cluster │ │ ├── README.md │ │ ├── backend.tf │ │ ├── main.tf │ │ ├── outputs.tf │ │ └── vars.tf │ └── stage │ ├── data-stores │ └── mysql │ │ ├── README.md │ │ ├── backend.tf │ │ ├── main.tf │ │ ├── outputs.tf │ │ └── vars.tf │ └── services │ └── webserver-cluster │ ├── README.md │ ├── backend.tf │ ├── main.tf │ ├── outputs.tf │ └── vars.tf ├── 11-loops-example ├── README.md ├── main.tf ├── outputs.tf └── vars.tf ├── 12-if-statements-example ├── README.md ├── live │ ├── global │ │ └── s3 │ │ │ ├── README.md │ │ │ ├── main.tf │ │ │ ├── outputs.tf │ │ │ └── vars.tf │ ├── prod │ │ ├── data-stores │ │ │ └── mysql │ │ │ │ ├── README.md │ │ │ │ ├── backend.tf │ │ │ │ ├── main.tf │ │ │ │ ├── outputs.tf │ │ │ │ └── vars.tf │ │ └── services │ │ │ └── webserver-cluster │ │ │ ├── README.md │ │ │ ├── backend.tf │ │ │ ├── main.tf │ │ │ ├── outputs.tf │ │ │ └── vars.tf │ └── stage │ │ ├── data-stores │ │ └── mysql │ │ │ ├── README.md │ │ │ ├── backend.tf │ │ │ ├── main.tf │ │ │ ├── outputs.tf │ │ │ └── vars.tf │ │ └── services │ │ └── webserver-cluster │ │ ├── README.md │ │ ├── backend.tf │ │ ├── main.tf │ │ ├── outputs.tf │ │ └── vars.tf └── modules │ └── services │ └── webserver-cluster │ ├── README.md │ ├── main.tf │ ├── outputs.tf │ ├── user-data-new.sh │ ├── user-data.sh │ └── vars.tf ├── 13-if-else-statements-example ├── README.md ├── main.tf ├── outputs.tf └── vars.tf └── 14-zero-downtime-deployment ├── README.md ├── live ├── global │ └── s3 │ │ ├── README.md │ │ ├── main.tf │ │ ├── outputs.tf │ │ └── vars.tf ├── prod │ ├── data-stores │ │ └── mysql │ │ │ ├── README.md │ │ │ ├── backend.tf │ │ │ ├── main.tf │ │ │ ├── outputs.tf │ │ │ └── vars.tf │ └── services │ │ └── webserver-cluster │ │ ├── README.md │ │ ├── backend.tf │ │ ├── main.tf │ │ ├── outputs.tf │ │ └── vars.tf └── stage │ ├── data-stores │ └── mysql │ │ ├── README.md │ │ ├── backend.tf │ │ ├── main.tf │ │ ├── outputs.tf │ │ └── vars.tf │ └── services │ └── webserver-cluster │ ├── README.md │ ├── backend.tf │ ├── main.tf │ ├── outputs.tf │ └── vars.tf └── modules └── services └── webserver-cluster ├── README.md ├── main.tf ├── outputs.tf ├── user-data.sh └── vars.tf /.gitignore: -------------------------------------------------------------------------------- 1 | .terraform 2 | *.tfstate 3 | *.tfstate.backup 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2018 Alfonso Fernandez-Barandiaran 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Terraform examples on AWS (Amazon Web Services) 2 | 3 | Terraform is used to create, manage, and update infrastructure resources such as physical machines, VMs, network switches, containers, and more. Almost any infrastructure type can be represented as a resource in Terraform. 4 | 5 | This repo contains [Terraform](https://www.terraform.io/) code examples on AWS (Amazon Web Services). 6 | 7 | These examples are based in the book *[Terraform: Up and Running](http://www.terraformupandrunning.com)* by [Yevgeniy Brikman](http://www.ybrikman.com). 8 | 9 | ## Quick start 10 | 11 | You must have an [AWS (Amazon Web Services)](http://aws.amazon.com/) account. 12 | 13 | The code consists of Terraform examples using HashiCorp Configuration Language (HCL) on AWS (Amazon Web Services). 14 | 15 | All the code is in the [code](/code) folder. 16 | 17 | For instructions on running the code, please consult the README in each folder. 18 | 19 | This is the list of examples: 20 | 21 | * [01-hello-world](code/01-hello-world) - Terraform "Hello, World": Example of how to deploy a single server on AWS (Amazon Web Services) using the shortest script. 22 | * [02-one-server](code/02-one-server) - Terraform One Server: Example of how deploy a single server on AWS (Amazon Web Services). 23 | * [03-one-webserver](code/03-one-webserver) - Terraform Web Server: Example of how deploy a single web server on AWS (Amazon Web Services). The web server returns "Hello, World" for the URL `/` listening on port 8080. 24 | * [04-one-webserver-with-vars](code/04-one-webserver-with-vars) - Terraform Web Server with vars: Example of how deploy a single web server on AWS (Amazon Web Services). The web server returns "Hello, World" for the URL `/` listening on port 8080, which is defined as a variable. 25 | * [05-cluster-webserver](code/05-cluster-webserver) - Terraform Cluster Web Server: Example of how deploy a cluster of web servers on AWS (Amazon Web Services) using EC2 and Auto Scaling, as well as a load balancer using ELB. The cluster of web servers returns "Hello, World" for the URL `/`. The load balancer listens on port 80. 26 | * [06-create-s3](code/06-create-s3) - Terraform Create S3: Example of how deploy the creation of a S3 bucket on AWS (Amazon Web Services). 27 | * [07-terraform-state](code/07-terraform-state) - Terraform State: Example of how to store the information about what infrastructure has been created on AWS (Amazon Web Services). 28 | * [08-file-layout-example](code/08-file-layout-example) - Terraform File Layout: Example that contains a File Layout example of a Terraform file on AWS (Amazon Web Services). 29 | * [09-module-example](code/09-module-example) - Terraform Module: Example that contains a module example of a Terraform file on AWS (Amazon Web Services). It shows how to develop (not duplicating code) web server clusters in different environments using a module. 30 | * [10-multi-repo-example](code/10-multi-repo-example) - Terraform Muti Repo: Example that contains a multi repo example of a Terraform file on AWS (Amazon Web Services). It shows how to develop (not duplicating code) web server clusters in different environments using a module in another repo in order to use different version of the module in the environments. 31 | * [11-loops-example](code/11-loops-example) - Terraform Loops: Example that contains the loops example of a Terraform file on AWS (Amazon Web Services). 32 | * [12-if-statements-example](code/12-if-statements-example) - Terraform If-Statements & If-Else-Statements: Example that contains an If-Statements and If-Else-Statements example of a Terraform file on AWS (Amazon Web Services). 33 | * [13-if-else-statements-example](code/13-if-else-statements-example) - Terraform Simple If-Else-Statement: Example that contains the simple If-Else-Statement example of a Terraform file on AWS (Amazon Web Services). 34 | * [14-zero-downtime-deployment](code/14-zero-downtime-deployment) - Terraform Zero-Downtime Deployment: Example that contains a zero-downtime deployment example of a Terraform file on AWS (Amazon Web Services). 35 | 36 | ## License 37 | 38 | This code is released under the MIT License. See LICENSE file. -------------------------------------------------------------------------------- /code/01-hello-world/README.md: -------------------------------------------------------------------------------- 1 | # Terraform "Hello, World" example 2 | 3 | This folder contains a "Hello, World" example of a [Terraform](https://www.terraform.io/) file on AWS (Amazon Web Services). 4 | 5 | This Terraform file deploys a single server on AWS (Amazon Web Services) using the shortest script. 6 | 7 | ## Requirements 8 | 9 | * You must have [Terraform](https://www.terraform.io/) installed on your computer. 10 | * You must have an [AWS (Amazon Web Services)](http://aws.amazon.com/) account. 11 | * It uses the Terraform AWS Provider that interacts with the many resources supported by AWS through its APIs. 12 | * This code was written for Terraform 0.10.x. 13 | 14 | ## Using the code 15 | 16 | * Configure your AWS access keys. 17 | 18 | **Important:** For security, it is strongly recommend that you use IAM users instead of the root account for AWS access. 19 | 20 | Setting your credentials for use by Terraform can be done in a number of ways, but here are the recommended approaches: 21 | 22 | * The default credentials file 23 | 24 | Set credentials in the AWS credentials profile file on your local system, located at: 25 | 26 | `~/.aws/credentials` on Linux, macOS, or Unix 27 | 28 | `C:\Users\USERNAME\.aws\credentials` on Windows 29 | 30 | This file should contain lines in the following format: 31 | 32 | ```bash 33 | [default] 34 | aws_access_key_id = 35 | aws_secret_access_key = 36 | ``` 37 | Substitute your own AWS credentials values for the values `` and ``. 38 | 39 | * Environment variables `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` 40 | 41 | Set the `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` environment variables. 42 | 43 | To set these variables on Linux, macOS, or Unix, use `export`: 44 | 45 | ```bash 46 | export AWS_ACCESS_KEY_ID= 47 | export AWS_SECRET_ACCESS_KEY= 48 | ``` 49 | 50 | To set these variables on Windows, use `set`: 51 | 52 | ```bash 53 | set AWS_ACCESS_KEY_ID= 54 | set AWS_SECRET_ACCESS_KEY= 55 | ``` 56 | 57 | * Initialize working directory. 58 | 59 | The first command that should be run after writing a new Terraform configuration is the `terraform init` command in order to initialize a working directory containing Terraform configuration files. It is safe to run this command multiple times. 60 | 61 | ```bash 62 | terraform init 63 | ``` 64 | 65 | * Validate the changes. 66 | 67 | Run command: 68 | 69 | ```bash 70 | terraform plan 71 | ``` 72 | 73 | * Deploy the changes. 74 | 75 | Run command: 76 | 77 | ```bash 78 | terraform apply 79 | ``` 80 | 81 | * Test the deploy. 82 | 83 | When the `terraform apply` command completes, use the AWS console, you should see the new EC2 instance created. 84 | 85 | * Clean up the resources created. 86 | 87 | When you have finished, run command: 88 | 89 | ```bash 90 | terraform destroy 91 | ``` -------------------------------------------------------------------------------- /code/01-hello-world/main.tf: -------------------------------------------------------------------------------- 1 | # Configure the AWS provider 2 | provider "aws" { 3 | region = "eu-west-1" 4 | } 5 | 6 | # Create an EC2 instance 7 | resource "aws_instance" "example" { 8 | ami = "ami-785db401" 9 | instance_type = "t2.micro" 10 | } 11 | -------------------------------------------------------------------------------- /code/02-one-server/README.md: -------------------------------------------------------------------------------- 1 | # Terraform One Server example 2 | 3 | This folder contains a one server example of a [Terraform](https://www.terraform.io/) file on AWS (Amazon Web Services). 4 | 5 | This Terraform file deploys a single server on AWS (Amazon Web Services) using EC2. 6 | 7 | ## Requirements 8 | 9 | * You must have [Terraform](https://www.terraform.io/) installed on your computer. 10 | * You must have an [AWS (Amazon Web Services)](http://aws.amazon.com/) account. 11 | * It uses the Terraform AWS Provider that interacts with the many resources supported by AWS through its APIs. 12 | * This code was written for Terraform 0.10.x. 13 | 14 | ## Using the code 15 | 16 | * Configure your AWS access keys. 17 | 18 | **Important:** For security, it is strongly recommend that you use IAM users instead of the root account for AWS access. 19 | 20 | Setting your credentials for use by Terraform can be done in a number of ways, but here are the recommended approaches: 21 | 22 | * The default credentials file 23 | 24 | Set credentials in the AWS credentials profile file on your local system, located at: 25 | 26 | `~/.aws/credentials` on Linux, macOS, or Unix 27 | 28 | `C:\Users\USERNAME\.aws\credentials` on Windows 29 | 30 | This file should contain lines in the following format: 31 | 32 | ```bash 33 | [default] 34 | aws_access_key_id = 35 | aws_secret_access_key = 36 | ``` 37 | Substitute your own AWS credentials values for the values `` and ``. 38 | 39 | * Environment variables `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` 40 | 41 | Set the `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` environment variables. 42 | 43 | To set these variables on Linux, macOS, or Unix, use `export`: 44 | 45 | ```bash 46 | export AWS_ACCESS_KEY_ID= 47 | export AWS_SECRET_ACCESS_KEY= 48 | ``` 49 | 50 | To set these variables on Windows, use `set`: 51 | 52 | ```bash 53 | set AWS_ACCESS_KEY_ID= 54 | set AWS_SECRET_ACCESS_KEY= 55 | ``` 56 | 57 | * Initialize working directory. 58 | 59 | The first command that should be run after writing a new Terraform configuration is the `terraform init` command in order to initialize a working directory containing Terraform configuration files. It is safe to run this command multiple times. 60 | 61 | ```bash 62 | terraform init 63 | ``` 64 | 65 | * Validate the changes. 66 | 67 | Run command: 68 | 69 | ```bash 70 | terraform plan 71 | ``` 72 | 73 | * Deploy the changes. 74 | 75 | Run command: 76 | 77 | ```bash 78 | terraform apply 79 | ``` 80 | 81 | * Test the deploy. 82 | 83 | When the `terraform apply` command completes, use the AWS console, you should see the new new EC2 instance, and all the resources created with the `terraform-example` tag. 84 | 85 | * Clean up the resources created. 86 | 87 | When you have finished, run command: 88 | 89 | ```bash 90 | terraform destroy 91 | ``` -------------------------------------------------------------------------------- /code/02-one-server/main.tf: -------------------------------------------------------------------------------- 1 | # Configure the AWS provider 2 | provider "aws" { 3 | region = "eu-west-1" 4 | } 5 | 6 | # Create an EC2 instance 7 | resource "aws_instance" "example" { 8 | ami = "ami-785db401" 9 | instance_type = "t2.micro" 10 | 11 | tags { 12 | Name = "terraform-example" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /code/03-one-webserver/README.md: -------------------------------------------------------------------------------- 1 | # Terraform Web Server example 2 | 3 | This folder contains a web server example of a [Terraform](https://www.terraform.io/) file on AWS (Amazon Web Services). 4 | 5 | This Terraform file deploys a single web server on AWS (Amazon Web Services). The web server returns "Hello, World" for the URL `/` listening on port 8080. 6 | 7 | ## Requirements 8 | 9 | * You must have [Terraform](https://www.terraform.io/) installed on your computer. 10 | * You must have an [AWS (Amazon Web Services)](http://aws.amazon.com/) account. 11 | * It uses the Terraform AWS Provider that interacts with the many resources supported by AWS through its APIs. 12 | * This code was written for Terraform 0.10.x. 13 | 14 | ## Using the code 15 | 16 | * Configure your AWS access keys. 17 | 18 | **Important:** For security, it is strongly recommend that you use IAM users instead of the root account for AWS access. 19 | 20 | Setting your credentials for use by Terraform can be done in a number of ways, but here are the recommended approaches: 21 | 22 | * The default credentials file 23 | 24 | Set credentials in the AWS credentials profile file on your local system, located at: 25 | 26 | `~/.aws/credentials` on Linux, macOS, or Unix 27 | 28 | `C:\Users\USERNAME\.aws\credentials` on Windows 29 | 30 | This file should contain lines in the following format: 31 | 32 | ```bash 33 | [default] 34 | aws_access_key_id = 35 | aws_secret_access_key = 36 | ``` 37 | Substitute your own AWS credentials values for the values `` and ``. 38 | 39 | * Environment variables `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` 40 | 41 | Set the `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` environment variables. 42 | 43 | To set these variables on Linux, macOS, or Unix, use `export`: 44 | 45 | ```bash 46 | export AWS_ACCESS_KEY_ID= 47 | export AWS_SECRET_ACCESS_KEY= 48 | ``` 49 | 50 | To set these variables on Windows, use `set`: 51 | 52 | ```bash 53 | set AWS_ACCESS_KEY_ID= 54 | set AWS_SECRET_ACCESS_KEY= 55 | ``` 56 | 57 | * Initialize working directory. 58 | 59 | The first command that should be run after writing a new Terraform configuration is the `terraform init` command in order to initialize a working directory containing Terraform configuration files. It is safe to run this command multiple times. 60 | 61 | ```bash 62 | terraform init 63 | ``` 64 | 65 | * Validate the changes. 66 | 67 | Run command: 68 | 69 | ```bash 70 | terraform plan 71 | ``` 72 | 73 | * Deploy the changes. 74 | 75 | Run command: 76 | 77 | ```bash 78 | terraform apply 79 | ``` 80 | 81 | * Test the web server. 82 | 83 | When the `terraform apply` command completes, it will output the public IP address of the web server. 84 | 85 | You can test it in two ways: 86 | 87 | * Running this command: 88 | 89 | ```bash 90 | curl http://:8080/ 91 | ``` 92 | 93 | * Writing in your browser this URL: `http://:8080/` 94 | 95 | You should get a `Hello, World` response message. 96 | 97 | * Clean up the resources created. 98 | 99 | When you have finished, run command: 100 | 101 | ```bash 102 | terraform destroy 103 | ``` -------------------------------------------------------------------------------- /code/03-one-webserver/main.tf: -------------------------------------------------------------------------------- 1 | # Configure the AWS provider 2 | provider "aws" { 3 | region = "eu-west-1" 4 | } 5 | 6 | # Create a Security Group for an EC2 instance 7 | resource "aws_security_group" "instance" { 8 | name = "terraform-example-instance" 9 | 10 | ingress { 11 | from_port = 8080 12 | to_port = 8080 13 | protocol = "tcp" 14 | cidr_blocks = ["0.0.0.0/0"] 15 | } 16 | } 17 | 18 | # Create an EC2 instance 19 | resource "aws_instance" "example" { 20 | ami = "ami-785db401" 21 | instance_type = "t2.micro" 22 | vpc_security_group_ids = ["${aws_security_group.instance.id}"] 23 | 24 | user_data = <<-EOF 25 | #!/bin/bash 26 | echo "Hello, World" > index.html 27 | nohup busybox httpd -f -p 8080 & 28 | EOF 29 | 30 | tags { 31 | Name = "terraform-example" 32 | } 33 | } 34 | 35 | # Output variable: Public IP address 36 | output "public_ip" { 37 | value = "${aws_instance.example.public_ip}" 38 | } 39 | -------------------------------------------------------------------------------- /code/04-one-webserver-with-vars/README.md: -------------------------------------------------------------------------------- 1 | # Terraform Web Server with vars example 2 | 3 | This folder contains a web server with vars example of a [Terraform](https://www.terraform.io/) file on AWS (Amazon Web Services). 4 | 5 | This Terraform file deploys a single web server on AWS (Amazon Web Services). The web server returns "Hello, World" for the URL `/` listening on port 8080, which is defined as a variable. 6 | 7 | ## Requirements 8 | 9 | * You must have [Terraform](https://www.terraform.io/) installed on your computer. 10 | * You must have an [AWS (Amazon Web Services)](http://aws.amazon.com/) account. 11 | * It uses the Terraform AWS Provider that interacts with the many resources supported by AWS through its APIs. 12 | * This code was written for Terraform 0.10.x. 13 | 14 | ## Using the code 15 | 16 | * Configure your AWS access keys. 17 | 18 | **Important:** For security, it is strongly recommend that you use IAM users instead of the root account for AWS access. 19 | 20 | Setting your credentials for use by Terraform can be done in a number of ways, but here are the recommended approaches: 21 | 22 | * The default credentials file 23 | 24 | Set credentials in the AWS credentials profile file on your local system, located at: 25 | 26 | `~/.aws/credentials` on Linux, macOS, or Unix 27 | 28 | `C:\Users\USERNAME\.aws\credentials` on Windows 29 | 30 | This file should contain lines in the following format: 31 | 32 | ```bash 33 | [default] 34 | aws_access_key_id = 35 | aws_secret_access_key = 36 | ``` 37 | Substitute your own AWS credentials values for the values `` and ``. 38 | 39 | * Environment variables `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` 40 | 41 | Set the `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` environment variables. 42 | 43 | To set these variables on Linux, macOS, or Unix, use `export`: 44 | 45 | ```bash 46 | export AWS_ACCESS_KEY_ID= 47 | export AWS_SECRET_ACCESS_KEY= 48 | ``` 49 | 50 | To set these variables on Windows, use `set`: 51 | 52 | ```bash 53 | set AWS_ACCESS_KEY_ID= 54 | set AWS_SECRET_ACCESS_KEY= 55 | ``` 56 | 57 | * Initialize working directory. 58 | 59 | The first command that should be run after writing a new Terraform configuration is the `terraform init` command in order to initialize a working directory containing Terraform configuration files. It is safe to run this command multiple times. 60 | 61 | ```bash 62 | terraform init 63 | ``` 64 | 65 | * Modify server port configuration. 66 | 67 | The web server is listening on port 8080, which is defined as an input variable `server_port` in `vars.tf` file. 68 | 69 | If you want to modify the server port you will be able to do it in several ways: 70 | 71 | * Loading variables from command line flags. 72 | 73 | Run Terraform commands in this way: 74 | 75 | ```bash 76 | terraform plan -var 'server_port=8080' 77 | ``` 78 | 79 | ```bash 80 | terraform apply -var 'server_port=8080' 81 | ``` 82 | 83 | * Loading variables from a file. 84 | 85 | When Terraform runs it will look for a file called `terraform.tfvars`. You can populate this file with variable values that will be loaded when Terraform runs. An example for the content of the `terraform.tfvars` file: 86 | 87 | ```bash 88 | server_port = "8080" 89 | ``` 90 | 91 | * Loading variables from environment variables. 92 | 93 | Terraform will also parse any environment variables that are prefixed with `TF_VAR`. You can create an environment variable `TF_VAR_server_port`: 94 | 95 | ```bash 96 | TF_VAR_server_port=8080 97 | ``` 98 | 99 | * Variable defaults. 100 | 101 | Change the value of the `default` attribute of `server_port` input variable in `vars.tf` file. 102 | 103 | * Validate the changes. 104 | 105 | Run command: 106 | 107 | ```bash 108 | terraform plan 109 | ``` 110 | 111 | * Deploy the changes. 112 | 113 | Run command: 114 | 115 | ```bash 116 | terraform apply 117 | ``` 118 | 119 | * Test the web server. 120 | 121 | You can test it in two ways: 122 | 123 | * Running this command: 124 | 125 | ```bash 126 | curl http://:8080/ 127 | ``` 128 | 129 | * Writing in your browser this URL: `http://:8080/` 130 | 131 | You should get a `Hello, World` response message. 132 | 133 | * Clean up the resources created. 134 | 135 | When you have finished, run command: 136 | 137 | ```bash 138 | terraform destroy 139 | ``` -------------------------------------------------------------------------------- /code/04-one-webserver-with-vars/main.tf: -------------------------------------------------------------------------------- 1 | # Configure the AWS provider 2 | provider "aws" { 3 | region = "eu-west-1" 4 | } 5 | 6 | # Create a Security Group for an EC2 instance 7 | resource "aws_security_group" "instance" { 8 | name = "terraform-example-instance" 9 | 10 | ingress { 11 | from_port = "${var.server_port}" 12 | to_port = "${var.server_port}" 13 | protocol = "tcp" 14 | cidr_blocks = ["0.0.0.0/0"] 15 | } 16 | } 17 | 18 | # Create an EC2 instance 19 | resource "aws_instance" "example" { 20 | ami = "ami-785db401" 21 | instance_type = "t2.micro" 22 | vpc_security_group_ids = ["${aws_security_group.instance.id}"] 23 | 24 | user_data = <<-EOF 25 | #!/bin/bash 26 | echo "Hello, World" > index.html 27 | nohup busybox httpd -f -p "${var.server_port}" & 28 | EOF 29 | 30 | tags { 31 | Name = "terraform-example" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /code/04-one-webserver-with-vars/outputs.tf: -------------------------------------------------------------------------------- 1 | # Output variable: Public IP address 2 | output "public_ip" { 3 | value = "${aws_instance.example.public_ip}" 4 | } 5 | -------------------------------------------------------------------------------- /code/04-one-webserver-with-vars/vars.tf: -------------------------------------------------------------------------------- 1 | # Input variable: server port 2 | variable "server_port" { 3 | description = "The port the server will use for HTTP requests" 4 | default = "8080" 5 | } 6 | -------------------------------------------------------------------------------- /code/05-cluster-webserver/README.md: -------------------------------------------------------------------------------- 1 | # Terraform Cluster Web Server example 2 | 3 | This folder contains a cluster of web servers example of a [Terraform](https://www.terraform.io/) file on AWS (Amazon Web Services). 4 | 5 | This Terraform file deploys a cluster of web servers on AWS (Amazon Web Services) using EC2 and Auto Scaling, as well as a load balancer using ELB. 6 | 7 | The cluster of web servers returns "Hello, World" for the URL `/`. The load balancer listens on port 80. 8 | 9 | ## Requirements 10 | 11 | * You must have [Terraform](https://www.terraform.io/) installed on your computer. 12 | * You must have an [AWS (Amazon Web Services)](http://aws.amazon.com/) account. 13 | * It uses the Terraform AWS Provider that interacts with the many resources supported by AWS through its APIs. 14 | * This code was written for Terraform 0.10.x. 15 | 16 | ## Using the code 17 | 18 | * Configure your AWS access keys. 19 | 20 | **Important:** For security, it is strongly recommend that you use IAM users instead of the root account for AWS access. 21 | 22 | Setting your credentials for use by Terraform can be done in a number of ways, but here are the recommended approaches: 23 | 24 | * The default credentials file 25 | 26 | Set credentials in the AWS credentials profile file on your local system, located at: 27 | 28 | `~/.aws/credentials` on Linux, macOS, or Unix 29 | 30 | `C:\Users\USERNAME\.aws\credentials` on Windows 31 | 32 | This file should contain lines in the following format: 33 | 34 | ```bash 35 | [default] 36 | aws_access_key_id = 37 | aws_secret_access_key = 38 | ``` 39 | Substitute your own AWS credentials values for the values `` and ``. 40 | 41 | * Environment variables `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` 42 | 43 | Set the `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` environment variables. 44 | 45 | To set these variables on Linux, macOS, or Unix, use `export`: 46 | 47 | ```bash 48 | export AWS_ACCESS_KEY_ID= 49 | export AWS_SECRET_ACCESS_KEY= 50 | ``` 51 | 52 | To set these variables on Windows, use `set`: 53 | 54 | ```bash 55 | set AWS_ACCESS_KEY_ID= 56 | set AWS_SECRET_ACCESS_KEY= 57 | ``` 58 | 59 | * Initialize working directory. 60 | 61 | The first command that should be run after writing a new Terraform configuration is the `terraform init` command in order to initialize a working directory containing Terraform configuration files. It is safe to run this command multiple times. 62 | 63 | ```bash 64 | terraform init 65 | ``` 66 | 67 | * Modify server port configuration. 68 | 69 | The web server is listening on port 8080, which is defined as an input variable `server_port` in `vars.tf` file. 70 | 71 | If you want to modify the server port you will be able to do it in several ways: 72 | 73 | * Loading variables from command line flags. 74 | 75 | Run Terraform commands in this way: 76 | 77 | ```bash 78 | terraform plan -var 'server_port=8080' 79 | ``` 80 | 81 | ```bash 82 | terraform apply -var 'server_port=8080' 83 | ``` 84 | 85 | * Loading variables from a file. 86 | 87 | When Terraform runs it will look for a file called `terraform.tfvars`. You can populate this file with variable values that will be loaded when Terraform runs. An example for the content of the `terraform.tfvars` file: 88 | 89 | ```bash 90 | server_port = "8080" 91 | ``` 92 | 93 | * Loading variables from environment variables. 94 | 95 | Terraform will also parse any environment variables that are prefixed with `TF_VAR`. You can create an environment variable `TF_VAR_server_port`: 96 | 97 | ```bash 98 | TF_VAR_server_port=8080 99 | ``` 100 | 101 | * Variable defaults. 102 | 103 | Change the value of the `default` attribute of `server_port` input variable in `vars.tf` file. 104 | 105 | * Validate the changes. 106 | 107 | Run command: 108 | 109 | ```bash 110 | terraform plan 111 | ``` 112 | 113 | * Deploy the changes. 114 | 115 | Run command: 116 | 117 | ```bash 118 | terraform apply 119 | ``` 120 | 121 | * Test the cluster of web servers. 122 | 123 | When the `terraform apply` command completes, it will output the DNS name of the load balancer. 124 | 125 | You can test it in two ways: 126 | 127 | * Running this command: 128 | 129 | ```bash 130 | curl http://http:/// 131 | ``` 132 | 133 | * Writing in your browser this URL: `http:///` 134 | 135 | You should get a `Hello, World` response message. 136 | 137 | * Clean up the resources created. 138 | 139 | When you have finished, run command: 140 | 141 | ```bash 142 | terraform destroy 143 | ``` -------------------------------------------------------------------------------- /code/05-cluster-webserver/main.tf: -------------------------------------------------------------------------------- 1 | # Configure the AWS provider 2 | provider "aws" { 3 | region = "eu-west-1" 4 | } 5 | 6 | # Data source: query the list of availability zones 7 | data "aws_availability_zones" "all" {} 8 | 9 | # Create a Security Group for an EC2 instance 10 | resource "aws_security_group" "instance" { 11 | name = "terraform-example-instance" 12 | 13 | ingress { 14 | from_port = "${var.server_port}" 15 | to_port = "${var.server_port}" 16 | protocol = "tcp" 17 | cidr_blocks = ["0.0.0.0/0"] 18 | } 19 | 20 | lifecycle { 21 | create_before_destroy = true 22 | } 23 | } 24 | 25 | # Create a Security Group for an ELB 26 | resource "aws_security_group" "elb" { 27 | name = "terraform-example-elb" 28 | 29 | ingress { 30 | from_port = 80 31 | to_port = 80 32 | protocol = "tcp" 33 | cidr_blocks = ["0.0.0.0/0"] 34 | } 35 | 36 | egress { 37 | from_port = 0 38 | to_port = 0 39 | protocol = "-1" 40 | cidr_blocks = ["0.0.0.0/0"] 41 | } 42 | } 43 | 44 | # Create a Launch Configuration 45 | resource "aws_launch_configuration" "example" { 46 | image_id = "ami-785db401" 47 | instance_type = "t2.micro" 48 | security_groups = ["${aws_security_group.instance.id}"] 49 | 50 | user_data = <<-EOF 51 | #!/bin/bash 52 | echo "Hello, World" > index.html 53 | nohup busybox httpd -f -p "${var.server_port}" & 54 | EOF 55 | 56 | lifecycle { 57 | create_before_destroy = true 58 | } 59 | } 60 | 61 | # Create an Autoscaling Group 62 | resource "aws_autoscaling_group" "example" { 63 | launch_configuration = "${aws_launch_configuration.example.id}" 64 | availability_zones = ["${data.aws_availability_zones.all.names}"] 65 | 66 | load_balancers = ["${aws_elb.example.name}"] 67 | health_check_type = "ELB" 68 | 69 | min_size = 2 70 | max_size = 10 71 | 72 | tag { 73 | key = "Name" 74 | value = "terraform-asg-example" 75 | propagate_at_launch = true 76 | } 77 | } 78 | 79 | # Create an ELB 80 | resource "aws_elb" "example" { 81 | name = "terraform-asg-example" 82 | availability_zones = ["${data.aws_availability_zones.all.names}"] 83 | security_groups = ["${aws_security_group.elb.id}"] 84 | 85 | listener { 86 | lb_port = 80 87 | lb_protocol = "http" 88 | instance_port = "${var.server_port}" 89 | instance_protocol = "http" 90 | } 91 | 92 | health_check { 93 | healthy_threshold = 2 94 | unhealthy_threshold = 2 95 | timeout = 3 96 | interval = 30 97 | target = "HTTP:${var.server_port}/" 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /code/05-cluster-webserver/outputs.tf: -------------------------------------------------------------------------------- 1 | # Output variable: DNS Name of ELB 2 | output "elb_dns_name" { 3 | value = "${aws_elb.example.dns_name}" 4 | } 5 | -------------------------------------------------------------------------------- /code/05-cluster-webserver/vars.tf: -------------------------------------------------------------------------------- 1 | # Input variable: server port 2 | variable "server_port" { 3 | description = "The port the server will use for HTTP requests" 4 | default = "8080" 5 | } 6 | -------------------------------------------------------------------------------- /code/06-create-s3/README.md: -------------------------------------------------------------------------------- 1 | # Terraform Create S3 example 2 | 3 | This folder contains the create S3 example of a [Terraform](https://www.terraform.io/) file AWS (Amazon Web Services). 4 | 5 | This Terraform file deploys the creation of a S3 bucket on AWS (Amazon Web Services). 6 | 7 | ## Requirements 8 | 9 | * You must have [Terraform](https://www.terraform.io/) installed on your computer. 10 | * You must have an [AWS (Amazon Web Services)](http://aws.amazon.com/) account. 11 | * It uses the Terraform AWS Provider that interacts with the many resources supported by AWS through its APIs. 12 | * This code was written for Terraform 0.10.x. 13 | 14 | ## Using the code 15 | 16 | * Configure your AWS access keys. 17 | 18 | **Important:** For security, it is strongly recommend that you use IAM users instead of the root account for AWS access. 19 | 20 | Setting your credentials for use by Terraform can be done in a number of ways, but here are the recommended approaches: 21 | 22 | * The default credentials file 23 | 24 | Set credentials in the AWS credentials profile file on your local system, located at: 25 | 26 | `~/.aws/credentials` on Linux, macOS, or Unix 27 | 28 | `C:\Users\USERNAME\.aws\credentials` on Windows 29 | 30 | This file should contain lines in the following format: 31 | 32 | ```bash 33 | [default] 34 | aws_access_key_id = 35 | aws_secret_access_key = 36 | ``` 37 | Substitute your own AWS credentials values for the values `` and ``. 38 | 39 | * Environment variables `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` 40 | 41 | Set the `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` environment variables. 42 | 43 | To set these variables on Linux, macOS, or Unix, use `export`: 44 | 45 | ```bash 46 | export AWS_ACCESS_KEY_ID= 47 | export AWS_SECRET_ACCESS_KEY= 48 | ``` 49 | 50 | To set these variables on Windows, use `set`: 51 | 52 | ```bash 53 | set AWS_ACCESS_KEY_ID= 54 | set AWS_SECRET_ACCESS_KEY= 55 | ``` 56 | 57 | * Initialize working directory. 58 | 59 | The first command that should be run after writing a new Terraform configuration is the `terraform init` command in order to initialize a working directory containing Terraform configuration files. It is safe to run this command multiple times. 60 | 61 | ```bash 62 | terraform init 63 | ``` 64 | 65 | * Configure S3 bucket name. 66 | 67 | You must modify the S3 bucket name, which is defined as an input variable `bucket_name` in `vars.tf` file. 68 | 69 | You can modify the S3 bucket name in several ways: 70 | 71 | * Loading variables from command line flags. 72 | 73 | Run Terraform commands in this way: 74 | 75 | ```bash 76 | terraform plan -var 'bucket_name=' 77 | ``` 78 | 79 | ```bash 80 | terraform apply -var 'bucket_name=' 81 | ``` 82 | 83 | * Loading variables from a file. 84 | 85 | When Terraform runs it will look for a file called `terraform.tfvars`. You can populate this file with variable values that will be loaded when Terraform runs. An example for the content of the `terraform.tfvars` file: 86 | 87 | ```bash 88 | bucket_name = "" 89 | ``` 90 | 91 | * Loading variables from environment variables. 92 | 93 | Terraform will also parse any environment variables that are prefixed with `TF_VAR`. You can create an environment variable `TF_VAR_bucket_name`: 94 | 95 | ```bash 96 | TF_VAR_bucket_name= 97 | ``` 98 | 99 | * Variable defaults. 100 | 101 | Change the value of the `default` attribute of `bucket_name` input variable in `vars.tf` file. 102 | 103 | ```hcl 104 | variable "bucket_name" { 105 | description = "The name of the S3 bucket. Must be globally unique." 106 | default = "" 107 | } 108 | ``` 109 | 110 | * Validate the changes. 111 | 112 | Run command: 113 | 114 | ```bash 115 | terraform plan 116 | ``` 117 | 118 | * Deploy the changes. 119 | 120 | Run command: 121 | 122 | ```bash 123 | terraform apply 124 | ``` 125 | 126 | * Test the deploy. 127 | 128 | When the `terraform apply` command completes, use the AWS console, you should see the new S3 bucket created. 129 | 130 | * Clean up the resources created. 131 | 132 | When you have finished, run command: 133 | 134 | ```bash 135 | terraform destroy 136 | ``` -------------------------------------------------------------------------------- /code/06-create-s3/main.tf: -------------------------------------------------------------------------------- 1 | # Configure the AWS provider 2 | provider "aws" { 3 | region = "eu-west-1" 4 | } 5 | 6 | # Create a S3 bucket 7 | resource "aws_s3_bucket" "terraform_state" { 8 | bucket = "${var.bucket_name}" 9 | 10 | versioning { 11 | enabled = true 12 | } 13 | 14 | lifecycle { 15 | prevent_destroy = true 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /code/06-create-s3/outputs.tf: -------------------------------------------------------------------------------- 1 | # Output variable: S3 bucket 2 | output "s3_bucket_arn" { 3 | value = "${aws_s3_bucket.terraform_state.arn}" 4 | } 5 | -------------------------------------------------------------------------------- /code/06-create-s3/vars.tf: -------------------------------------------------------------------------------- 1 | # Input variable: S3 bucket name 2 | variable "bucket_name" { 3 | description = "The name of the S3 bucket. Must be globally unique." 4 | default = "terraform-state-my-bucket" 5 | } 6 | -------------------------------------------------------------------------------- /code/07-terraform-state/README.md: -------------------------------------------------------------------------------- 1 | # Terraform State example 2 | 3 | This folder contains a state example of a [Terraform](https://www.terraform.io/) file on AWS (Amazon Web Services). 4 | 5 | This Terraform file use the S3 bucket created in the previous example [06-create-s3](../06-create-s3/) to store the information about what infrastructure has been created. 6 | 7 | This information is stored in the Terraform state file `terraform.tfstate`. This file contains a JSON format that records a mapping from the representation of the resources on AWS to Terrafom resources in the configuration files. 8 | 9 | ## Requirements 10 | 11 | * You must have [Terraform](https://www.terraform.io/) installed on your computer. 12 | * You must have an [AWS (Amazon Web Services)](http://aws.amazon.com/) account. 13 | * It uses the Terraform AWS Provider that interacts with the many resources supported by AWS through its APIs. 14 | * This code was written for Terraform 0.10.x. 15 | 16 | ## Using the code 17 | 18 | * Configure your AWS access keys. 19 | 20 | **Important:** For security, it is strongly recommend that you use IAM users instead of the root account for AWS access. 21 | 22 | Setting your credentials for use by Terraform can be done in a number of ways, but here are the recommended approaches: 23 | 24 | * The default credentials file 25 | 26 | Set credentials in the AWS credentials profile file on your local system, located at: 27 | 28 | `~/.aws/credentials` on Linux, macOS, or Unix 29 | 30 | `C:\Users\USERNAME\.aws\credentials` on Windows 31 | 32 | This file should contain lines in the following format: 33 | 34 | ```bash 35 | [default] 36 | aws_access_key_id = 37 | aws_secret_access_key = 38 | ``` 39 | Substitute your own AWS credentials values for the values `` and ``. 40 | 41 | * Environment variables `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` 42 | 43 | Set the `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` environment variables. 44 | 45 | To set these variables on Linux, macOS, or Unix, use `export`: 46 | 47 | ```bash 48 | export AWS_ACCESS_KEY_ID= 49 | export AWS_SECRET_ACCESS_KEY= 50 | ``` 51 | 52 | To set these variables on Windows, use `set`: 53 | 54 | ```bash 55 | set AWS_ACCESS_KEY_ID= 56 | set AWS_SECRET_ACCESS_KEY= 57 | ``` 58 | 59 | * Initialize working directory. 60 | 61 | The first command that should be run after writing a new Terraform configuration is the `terraform init` command in order to initialize a working directory containing Terraform configuration files. It is safe to run this command multiple times. 62 | 63 | ```bash 64 | terraform init 65 | ``` 66 | 67 | * Configure Terraform backend. 68 | 69 | You must modify the S3 bucket name, which is defined in the `bucket` attribute in `backend.tf` file. 70 | 71 | ```bash 72 | bucket = "" 73 | ``` 74 | 75 | * Validate the changes. 76 | 77 | Run command: 78 | 79 | ```bash 80 | terraform plan 81 | ``` 82 | 83 | * Deploy the changes. 84 | 85 | Run command: 86 | 87 | ```bash 88 | terraform apply 89 | ``` 90 | 91 | * Test the deploy. 92 | 93 | When the `terraform apply` command completes, use the AWS console, you should see the `terraform.tfstate` file created in the S3 bucket. 94 | 95 | The `terraform.tfstate` file is where is stored the terraform state. 96 | 97 | * Clean up the resources created. 98 | 99 | When you have finished, run command: 100 | 101 | ```bash 102 | terraform destroy 103 | ``` -------------------------------------------------------------------------------- /code/07-terraform-state/backend.tf: -------------------------------------------------------------------------------- 1 | # Define Terraform backend using a S3 bucket for storing the Terraform state 2 | terraform { 3 | backend "s3" { 4 | bucket = "terraform-state-my-bucket" 5 | key = "terraform-state/terraform.tfstate" 6 | region = "eu-west-1" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /code/07-terraform-state/main.tf: -------------------------------------------------------------------------------- 1 | # Configure the AWS provider 2 | provider "aws" { 3 | region = "eu-west-1" 4 | } 5 | -------------------------------------------------------------------------------- /code/08-file-layout-example/README.md: -------------------------------------------------------------------------------- 1 | # Terraform File Layout example 2 | 3 | This folder contains a File Layout example of a [Terraform](https://www.terraform.io/) file on AWS (Amazon Web Services). 4 | 5 | This is the file layout: 6 | 7 | ```bash 8 | global 9 | └── s3/ 10 | ├── main.tf 11 | └── (etc) 12 | 13 | stage 14 | ├── services/ 15 | │ └── webserver-cluster/ 16 | │ ├── main.tf 17 | │ └── (etc) 18 | └── data-stores/ 19 | └── mysql/ 20 | ├── main.tf 21 | └── (etc) 22 | ``` 23 | 24 | It uses: 25 | 26 | * Terraform Remote State example: [global/s3](global/s3) 27 | * Terraform MySQL on RDS example: [stage/data-stores/mysql](stage/data-stores/mysql) 28 | * Terraform Web Server Cluster example: [stage/services/webserver-cluster](stage/services/webserver-cluster) 29 | 30 | ## Requirements 31 | 32 | * You must have [Terraform](https://www.terraform.io/) installed on your computer. 33 | * You must have an [AWS (Amazon Web Services)](http://aws.amazon.com/) account. 34 | * It uses the Terraform AWS Provider that interacts with the many resources supported by AWS through its APIs. 35 | * This code was written for Terraform 0.10.x. 36 | 37 | ## Using the code 38 | 39 | * Configure your AWS access keys. 40 | 41 | **Important:** For security, it is strongly recommend that you use IAM users instead of the root account for AWS access. 42 | 43 | Setting your credentials for use by Terraform can be done in a number of ways, but here are the recommended approaches: 44 | 45 | * The default credentials file 46 | 47 | Set credentials in the AWS credentials profile file on your local system, located at: 48 | 49 | `~/.aws/credentials` on Linux, macOS, or Unix 50 | 51 | `C:\Users\USERNAME\.aws\credentials` on Windows 52 | 53 | This file should contain lines in the following format: 54 | 55 | ```bash 56 | [default] 57 | aws_access_key_id = 58 | aws_secret_access_key = 59 | ``` 60 | Substitute your own AWS credentials values for the values `` and ``. 61 | 62 | * Environment variables `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` 63 | 64 | Set the `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` environment variables. 65 | 66 | To set these variables on Linux, macOS, or Unix, use `export`: 67 | 68 | ```bash 69 | export AWS_ACCESS_KEY_ID= 70 | export AWS_SECRET_ACCESS_KEY= 71 | ``` 72 | 73 | To set these variables on Windows, use `set`: 74 | 75 | ```bash 76 | set AWS_ACCESS_KEY_ID= 77 | set AWS_SECRET_ACCESS_KEY= 78 | ``` 79 | 80 | * Use Terraform Remote State example for creating the remote state bucket. See: [global/s3](global/s3) 81 | 82 | * Use Terraform MySQL on RDS example for creating a MySQL database. See: [stage/data-stores/mysql](stage/data-stores/mysql) 83 | 84 | * Use Terraform Web Server Cluster example for creating a web server cluster. See: [stage/services/webserver-cluster](stage/services/webserver-cluster) 85 | -------------------------------------------------------------------------------- /code/08-file-layout-example/global/s3/README.md: -------------------------------------------------------------------------------- 1 | # Terraform Remote State example 2 | 3 | This folder contains an example of a Terraform file [Terraform](https://www.terraform.io/) that create a S3 bucket that can be used for remote state storage. 4 | 5 | This Terraform file deploys the creation of a bucket in AWS (Amazon Web Services) using S3. 6 | 7 | ## Requirements 8 | 9 | * You must have [Terraform](https://www.terraform.io/) installed on your computer. 10 | * You must have an [AWS (Amazon Web Services)](http://aws.amazon.com/) account. 11 | * It uses the Terraform AWS Provider that interacts with the many resources supported by AWS through its APIs. 12 | * This code was written for Terraform 0.10.x. 13 | 14 | ## Using the code 15 | 16 | * Configure your AWS access keys. 17 | 18 | * Initialize working directory. 19 | 20 | The first command that should be run after writing a new Terraform configuration is the `terraform init` command in order to initialize a working directory containing Terraform configuration files. It is safe to run this command multiple times. 21 | 22 | ```bash 23 | terraform init 24 | ``` 25 | 26 | * Modify configuration. 27 | 28 | You must modify the S3 bucket name, which is defined as an input variable `bucket_name` in `vars.tf` file. 29 | 30 | You can modify the S3 bucket name in several ways: 31 | 32 | * Loading variables from command line flags. 33 | 34 | Run Terraform commands in this way: 35 | 36 | ```bash 37 | terraform plan -var 'bucket_name=' 38 | ``` 39 | 40 | ```bash 41 | terraform apply -var 'bucket_name=' 42 | ``` 43 | 44 | * Loading variables from a file. 45 | 46 | When Terraform runs it will look for a file called `terraform.tfvars`. You can populate this file with variable values that will be loaded when Terraform runs. An example for the content of the `terraform.tfvars` file: 47 | 48 | ```bash 49 | bucket_name = "" 50 | ``` 51 | 52 | * Loading variables from environment variables. 53 | 54 | Terraform will also parse any environment variables that are prefixed with `TF_VAR`. You can create an environment variable `TF_VAR_bucket_name`: 55 | 56 | ```bash 57 | TF_VAR_bucket_name= 58 | ``` 59 | 60 | * Variable defaults. 61 | 62 | Change the value of the `default` attribute of `bucket_name` input variable in `vars.tf` file. 63 | 64 | ```hcl 65 | variable "bucket_name" { 66 | description = "The name of the S3 bucket. Must be globally unique." 67 | default = "" 68 | } 69 | ``` 70 | 71 | * Validate the changes. 72 | 73 | Run command: 74 | 75 | ```bash 76 | terraform plan 77 | ``` 78 | 79 | * Deploy the changes. 80 | 81 | Run command: 82 | 83 | ```bash 84 | terraform apply 85 | ``` 86 | 87 | * Clean up the resources created. 88 | 89 | When you have finished, run command: 90 | 91 | ```bash 92 | terraform destroy 93 | ``` -------------------------------------------------------------------------------- /code/08-file-layout-example/global/s3/main.tf: -------------------------------------------------------------------------------- 1 | # Configure the AWS provider 2 | provider "aws" { 3 | region = "eu-west-1" 4 | } 5 | 6 | # Create a S3 bucket 7 | resource "aws_s3_bucket" "terraform_state" { 8 | bucket = "${var.bucket_name}" 9 | 10 | versioning { 11 | enabled = true 12 | } 13 | 14 | lifecycle { 15 | prevent_destroy = true 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /code/08-file-layout-example/global/s3/outputs.tf: -------------------------------------------------------------------------------- 1 | # Output variable: S3 bucket 2 | output "s3_bucket_arn" { 3 | value = "${aws_s3_bucket.terraform_state.arn}" 4 | } 5 | -------------------------------------------------------------------------------- /code/08-file-layout-example/global/s3/vars.tf: -------------------------------------------------------------------------------- 1 | # Input variable: S3 bucket name 2 | variable "bucket_name" { 3 | description = "The name of the S3 bucket. Must be globally unique." 4 | default = "terraform-state-my-bucket" 5 | } 6 | -------------------------------------------------------------------------------- /code/08-file-layout-example/stage/data-stores/mysql/README.md: -------------------------------------------------------------------------------- 1 | # Terraform MySQL on RDS example 2 | 3 | This folder contains a MySQL on RDS example of a Terraform file [Terraform](https://www.terraform.io/). 4 | 5 | This Terraform file deploys a MySQL database using RDS on AWS (Amazon Web Services). 6 | 7 | ## Requirements 8 | 9 | * You must have [Terraform](https://www.terraform.io/) installed on your computer. 10 | * You must have an [AWS (Amazon Web Services)](http://aws.amazon.com/) account. 11 | * It uses the Terraform AWS Provider that interacts with the many resources supported by AWS through its APIs. 12 | * This code was written for Terraform 0.10.x. 13 | 14 | ## Using the code 15 | 16 | * Configure your AWS access keys. 17 | 18 | * Initialize working directory. 19 | 20 | The first command that should be run after writing a new Terraform configuration is the `terraform init` command in order to initialize a working directory containing Terraform configuration files. It is safe to run this command multiple times. 21 | 22 | ```bash 23 | terraform init 24 | ``` 25 | 26 | * Configure Terraform backend. 27 | 28 | Modify the S3 bucket name, which is defined in the `bucket` attribute in `backend.tf` file. 29 | 30 | ```bash 31 | bucket = "" 32 | ``` 33 | 34 | * Configure database password. 35 | 36 | The database password is managed by the `db_password` input variable. 37 | 38 | Terraform will parse any environment variables that are prefixed with `TF_VAR`. You must create an environment variable `TF_VAR_db_password`: 39 | 40 | ```bash 41 | TF_VAR_db_password= 42 | ``` 43 | 44 | * Validate the changes. 45 | 46 | Run command: 47 | 48 | ```bash 49 | terraform plan 50 | ``` 51 | 52 | * Deploy the changes. 53 | 54 | Run command: 55 | 56 | ```bash 57 | terraform apply 58 | ``` 59 | 60 | * Test the deploy. 61 | 62 | You should see a new RDS MySQL database on AWS (Amazon Web Services). 63 | 64 | * Clean up the resources created. 65 | 66 | When you have finished, run command: 67 | 68 | ```bash 69 | terraform destroy 70 | ``` -------------------------------------------------------------------------------- /code/08-file-layout-example/stage/data-stores/mysql/backend.tf: -------------------------------------------------------------------------------- 1 | # Define Terraform backend using a S3 bucket for storing the Terraform state 2 | terraform { 3 | backend "s3" { 4 | bucket = "terraform-state-my-bucket" 5 | key = "file-layout/stage/data-stores/mysql/terraform.tfstate" 6 | region = "eu-west-1" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /code/08-file-layout-example/stage/data-stores/mysql/main.tf: -------------------------------------------------------------------------------- 1 | # Configure the AWS provider 2 | provider "aws" { 3 | region = "eu-west-1" 4 | } 5 | 6 | # Create a DB instance 7 | resource "aws_db_instance" "example" { 8 | engine = "mysql" 9 | allocated_storage = 10 10 | instance_class = "db.t2.micro" 11 | name = "example_database" 12 | username = "admin" 13 | password = "${var.db_password}" 14 | skip_final_snapshot = true 15 | } 16 | -------------------------------------------------------------------------------- /code/08-file-layout-example/stage/data-stores/mysql/outputs.tf: -------------------------------------------------------------------------------- 1 | # Output variable: DB instance address 2 | output "address" { 3 | value = "${aws_db_instance.example.address}" 4 | } 5 | 6 | # Output variable: DB instance port 7 | output "port" { 8 | value = "${aws_db_instance.example.port}" 9 | } 10 | -------------------------------------------------------------------------------- /code/08-file-layout-example/stage/data-stores/mysql/vars.tf: -------------------------------------------------------------------------------- 1 | # Input variable: DB password 2 | variable "db_password" { 3 | description = "The password for the database" 4 | } -------------------------------------------------------------------------------- /code/08-file-layout-example/stage/services/webserver-cluster/README.md: -------------------------------------------------------------------------------- 1 | # Terraform Web Server Cluster example 2 | 3 | This folder contains a Web Server Cluster example of a Terraform file [Terraform](https://www.terraform.io/). 4 | 5 | This Terraform file deploys a cluster of web servers in Amazon Web Services (AWS) using EC2 and Auto Scaling, and a load balancer using ELB. 6 | 7 | The cluster of web servers returns "Hello, World" for the URL `/`. The load balancer listens on port 80. 8 | 9 | ## Requirements 10 | 11 | * You must have [Terraform](https://www.terraform.io/) installed on your computer. 12 | * You must have an [AWS (Amazon Web Services)](http://aws.amazon.com/) account. 13 | * It uses the Terraform AWS Provider that interacts with the many resources supported by AWS through its APIs. 14 | * This code was written for Terraform 0.10.x. 15 | 16 | ## Using the code 17 | 18 | * Configure your AWS access keys. 19 | 20 | * Initialize working directory. 21 | 22 | The first command that should be run after writing a new Terraform configuration is the `terraform init` command in order to initialize a working directory containing Terraform configuration files. It is safe to run this command multiple times. 23 | 24 | ```bash 25 | terraform init 26 | ``` 27 | 28 | * Configure Terraform backend. 29 | 30 | Modify the S3 bucket name, which is defined in the `bucket` attribute in `backend.tf` file. 31 | 32 | ```bash 33 | bucket = "" 34 | ``` 35 | 36 | * Configure the bucket used for the database's remote state storage. 37 | 38 | Modify the S3 bucket name which is defined in the `bucket` attribute in `vars.tf` file. Important! You must deploy the templates in [data-stores/mysql](../../data-stores/mysql) first: 39 | 40 | ```hcl 41 | variable "db_remote_state_bucket" { 42 | description = "The name of the S3 bucket used for the database's remote state storage" 43 | default = "" 44 | } 45 | ``` 46 | 47 | * Validate the changes. 48 | 49 | Run command: 50 | 51 | ```bash 52 | terraform plan 53 | ``` 54 | 55 | * Deploy the changes. 56 | 57 | Run command: 58 | 59 | ```bash 60 | terraform apply 61 | ``` 62 | 63 | * Test the cluster of web servers. 64 | 65 | Test the cluster of web servers. When the `apply` command completes, it will output the DNS name of the load balancer. 66 | 67 | ```bash 68 | curl http:/// 69 | ``` 70 | 71 | * Clean up the resources created. 72 | 73 | When you have finished, run command: 74 | 75 | ```bash 76 | terraform destroy 77 | ``` -------------------------------------------------------------------------------- /code/08-file-layout-example/stage/services/webserver-cluster/backend.tf: -------------------------------------------------------------------------------- 1 | # Define Terraform backend using a S3 bucket for storing the Terraform state 2 | terraform { 3 | backend "s3" { 4 | bucket = "terraform-state-my-bucket" 5 | key = "file-layout-example/stage/services/webserver-cluster/terraform.tfstate" 6 | region = "eu-west-1" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /code/08-file-layout-example/stage/services/webserver-cluster/main.tf: -------------------------------------------------------------------------------- 1 | # Configure the AWS provider 2 | provider "aws" { 3 | region = "eu-west-1" 4 | } 5 | 6 | # Data source: query the list of availability zones 7 | data "aws_availability_zones" "all" {} 8 | 9 | # Data source: DB remote state 10 | data "terraform_remote_state" "db" { 11 | backend = "s3" 12 | 13 | config { 14 | bucket = "${var.db_remote_state_bucket}" 15 | key = "${var.db_remote_state_key}" 16 | region = "eu-west-1" 17 | } 18 | } 19 | 20 | # Data source: Template file 21 | data "template_file" "user_data" { 22 | template = "${file("user-data.sh")}" 23 | 24 | vars { 25 | server_port = "${var.server_port}" 26 | db_address = "${data.terraform_remote_state.db.address}" 27 | db_port = "${data.terraform_remote_state.db.port}" 28 | } 29 | } 30 | 31 | # Create a Security Group for an EC2 instance 32 | resource "aws_security_group" "instance" { 33 | name = "terraform-example-instance" 34 | 35 | ingress { 36 | from_port = "${var.server_port}" 37 | to_port = "${var.server_port}" 38 | protocol = "tcp" 39 | cidr_blocks = ["0.0.0.0/0"] 40 | } 41 | 42 | lifecycle { 43 | create_before_destroy = true 44 | } 45 | } 46 | 47 | # Create a Security Group for an ELB 48 | resource "aws_security_group" "elb" { 49 | name = "terraform-example-elb" 50 | 51 | ingress { 52 | from_port = 80 53 | to_port = 80 54 | protocol = "tcp" 55 | cidr_blocks = ["0.0.0.0/0"] 56 | } 57 | 58 | egress { 59 | from_port = 0 60 | to_port = 0 61 | protocol = "-1" 62 | cidr_blocks = ["0.0.0.0/0"] 63 | } 64 | } 65 | 66 | # Create a Launch Configuration 67 | resource "aws_launch_configuration" "example" { 68 | image_id = "ami-785db401" 69 | instance_type = "t2.micro" 70 | security_groups = ["${aws_security_group.instance.id}"] 71 | user_data = "${data.template_file.user_data.rendered}" 72 | 73 | lifecycle { 74 | create_before_destroy = true 75 | } 76 | } 77 | 78 | # Create an Autoscaling Group 79 | resource "aws_autoscaling_group" "example" { 80 | launch_configuration = "${aws_launch_configuration.example.id}" 81 | availability_zones = ["${data.aws_availability_zones.all.names}"] 82 | 83 | load_balancers = ["${aws_elb.example.name}"] 84 | health_check_type = "ELB" 85 | 86 | min_size = 2 87 | max_size = 10 88 | 89 | tag { 90 | key = "Name" 91 | value = "terraform-asg-example" 92 | propagate_at_launch = true 93 | } 94 | } 95 | 96 | # Create an ELB 97 | resource "aws_elb" "example" { 98 | name = "terraform-asg-example" 99 | availability_zones = ["${data.aws_availability_zones.all.names}"] 100 | security_groups = ["${aws_security_group.elb.id}"] 101 | 102 | listener { 103 | lb_port = 80 104 | lb_protocol = "http" 105 | instance_port = "${var.server_port}" 106 | instance_protocol = "http" 107 | } 108 | 109 | health_check { 110 | healthy_threshold = 2 111 | unhealthy_threshold = 2 112 | timeout = 3 113 | interval = 30 114 | target = "HTTP:${var.server_port}/" 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /code/08-file-layout-example/stage/services/webserver-cluster/outputs.tf: -------------------------------------------------------------------------------- 1 | # Output variable: DNS Name of ELB 2 | output "elb_dns_name" { 3 | value = "${aws_elb.example.dns_name}" 4 | } 5 | -------------------------------------------------------------------------------- /code/08-file-layout-example/stage/services/webserver-cluster/user-data.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | cat > index.html <Hello, World 4 |

DB address: ${db_address}

5 |

DB port: ${db_port}

6 | EOF 7 | nohup busybox httpd -f -p "${server_port}" & 8 | -------------------------------------------------------------------------------- /code/08-file-layout-example/stage/services/webserver-cluster/vars.tf: -------------------------------------------------------------------------------- 1 | # Input variable: server port 2 | variable "server_port" { 3 | description = "The port the server will use for HTTP requests" 4 | default = "8080" 5 | } 6 | 7 | # Input variable: DB remote state bucket name 8 | variable "db_remote_state_bucket" { 9 | description = "The name of the S3 bucket used for the database's remote state storage" 10 | default = "terraform-state-my-bucket" 11 | } 12 | 13 | # Input variable: DB remote state bucket key 14 | variable "db_remote_state_key" { 15 | description = "The name of the key in the S3 bucket used for the database's remote state storage" 16 | default = "file-layout-example/stage/data-stores/mysql/terraform.tfstate" 17 | } 18 | -------------------------------------------------------------------------------- /code/09-module-example/README.md: -------------------------------------------------------------------------------- 1 | # Terraform Module example 2 | 3 | This folder contains a module example of a [Terraform](https://www.terraform.io/) file on AWS (Amazon Web Services). 4 | 5 | It shows how to develop (not duplicating code) web server clusters in different environments using a module. 6 | 7 | The environments are: 8 | 9 | * Staging (stage) 10 | * Production (prod) 11 | 12 | This is the file layout: 13 | 14 | ```bash 15 | global 16 | └── s3/ 17 | ├── main.tf 18 | └── (etc) 19 | 20 | modules 21 | └── services/ 22 | └── webserver-cluster/ 23 | ├── main.tf 24 | └── (etc) 25 | 26 | stage 27 | ├── services/ 28 | │ └── webserver-cluster/ 29 | │ ├── main.tf 30 | │ └── (etc) 31 | └── data-stores/ 32 | └── mysql/ 33 | ├── main.tf 34 | └── (etc) 35 | 36 | prod 37 | ├── services/ 38 | │ └── webserver-cluster/ 39 | │ ├── main.tf 40 | │ └── (etc) 41 | └── data-stores/ 42 | └── mysql/ 43 | ├── main.tf 44 | └── (etc) 45 | ``` 46 | 47 | It uses in common for both environments: 48 | 49 | * Terraform Remote State example: [global/s3](global/s3) 50 | * Terraform Web Server Cluster module example: [modules/services/webserver-cluster](modules/services/webserver-cluster) 51 | 52 | It uses for staging environment: 53 | 54 | * Terraform MySQL on RDS example (staging environment): [stage/data-stores/mysql](stage/data-stores/mysql) 55 | * Terraform Web Server Cluster example (staging environment): [stage/services/webserver-cluster](stage/services/webserver-cluster) 56 | 57 | It uses for production environment: 58 | 59 | * Terraform MySQL on RDS example (production environment): [prod/data-stores/mysql](prod/data-stores/mysql) 60 | * Terraform Web Server Cluster example (production environment): [prod/services/webserver-cluster](prod/services/webserver-cluster) 61 | 62 | ## Requirements 63 | 64 | * You must have [Terraform](https://www.terraform.io/) installed on your computer. 65 | * You must have an [AWS (Amazon Web Services)](http://aws.amazon.com/) account. 66 | * It uses the Terraform AWS Provider that interacts with the many resources supported by AWS through its APIs. 67 | * This code was written for Terraform 0.10.x. 68 | 69 | ## Using the code 70 | 71 | * Configure your AWS access keys. 72 | 73 | **Important:** For security, it is strongly recommend that you use IAM users instead of the root account for AWS access. 74 | 75 | Setting your credentials for use by Terraform can be done in a number of ways, but here are the recommended approaches: 76 | 77 | * The default credentials file 78 | 79 | Set credentials in the AWS credentials profile file on your local system, located at: 80 | 81 | `~/.aws/credentials` on Linux, macOS, or Unix 82 | 83 | `C:\Users\USERNAME\.aws\credentials` on Windows 84 | 85 | This file should contain lines in the following format: 86 | 87 | ```bash 88 | [default] 89 | aws_access_key_id = 90 | aws_secret_access_key = 91 | ``` 92 | Substitute your own AWS credentials values for the values `` and ``. 93 | 94 | * Environment variables `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` 95 | 96 | Set the `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` environment variables. 97 | 98 | To set these variables on Linux, macOS, or Unix, use `export`: 99 | 100 | ```bash 101 | export AWS_ACCESS_KEY_ID= 102 | export AWS_SECRET_ACCESS_KEY= 103 | ``` 104 | 105 | To set these variables on Windows, use `set`: 106 | 107 | ```bash 108 | set AWS_ACCESS_KEY_ID= 109 | set AWS_SECRET_ACCESS_KEY= 110 | ``` 111 | 112 | * Use Terraform Remote State example for creating the remote state bucket. See: [global/s3](global/s3) 113 | 114 | * Use Terraform module example for Web Server Cluster example in the staging environment and Web Server Cluster example in the production environment. See: [modules/services/webserver-cluster](modules/services/webserver-cluster) 115 | 116 | * Use Terraform MySQL on RDS example for creating a MySQL database in the staging environment. See: [stage/data-stores/mysql](stage/data-stores/mysql) 117 | 118 | * Use Terraform Web Server Cluster example for creating a web server cluster in the staging environment. See: [stage/services/webserver-cluster](stage/services/webserver-cluster) 119 | 120 | * Use Terraform MySQL on RDS example for creating a MySQL database in the production environment. See: [prod/data-stores/mysql](prod/data-stores/mysql) 121 | 122 | * Use Terraform Web Server Cluster example for creating a web server cluster in the production environment. See: [prod/services/webserver-cluster](prod/services/webserver-cluster) 123 | -------------------------------------------------------------------------------- /code/09-module-example/global/s3/README.md: -------------------------------------------------------------------------------- 1 | # Terraform Remote State example 2 | 3 | This folder contains an example of a Terraform file [Terraform](https://www.terraform.io/) that create a S3 bucket that can be used for remote state storage. 4 | 5 | This Terraform file deploys the creation a of a bucket on AWS (Amazon Web Services) using S3. 6 | 7 | ## Requirements 8 | 9 | * You must have [Terraform](https://www.terraform.io/) installed on your computer. 10 | * You must have an [AWS (Amazon Web Services)](http://aws.amazon.com/) account. 11 | * It uses the Terraform AWS Provider that interacts with the many resources supported by AWS through its APIs. 12 | * This code was written for Terraform 0.10.x. 13 | 14 | ## Using the code 15 | 16 | * Configure your AWS access keys. 17 | 18 | * Initialize working directory. 19 | 20 | The first command that should be run after writing a new Terraform configuration is the `terraform init` command in order to initialize a working directory containing Terraform configuration files. It is safe to run this command multiple times. 21 | 22 | ```bash 23 | terraform init 24 | ``` 25 | 26 | * Modify configuration. 27 | 28 | You must modify the S3 bucket name, which is defined as an input variable `bucket_name` in `vars.tf` file. 29 | 30 | You can modify the S3 bucket name in several ways: 31 | 32 | * Loading variables from command line flags. 33 | 34 | Run Terraform commands in this way: 35 | 36 | ```bash 37 | terraform plan -var 'bucket_name=' 38 | ``` 39 | 40 | ```bash 41 | terraform apply -var 'bucket_name=' 42 | ``` 43 | 44 | * Loading variables from a file. 45 | 46 | When Terraform runs it will look for a file called `terraform.tfvars`. You can populate this file with variable values that will be loaded when Terraform runs. An example for the content of the `terraform.tfvars` file: 47 | 48 | ```bash 49 | bucket_name = "" 50 | ``` 51 | 52 | * Loading variables from environment variables. 53 | 54 | Terraform will also parse any environment variables that are prefixed with `TF_VAR`. You can create an environment variable `TF_VAR_bucket_name`: 55 | 56 | ```bash 57 | TF_VAR_bucket_name= 58 | ``` 59 | 60 | * Variable defaults. 61 | 62 | Change the value of the `default` attribute of `bucket_name` input variable in `vars.tf` file. 63 | 64 | ```hcl 65 | variable "bucket_name" { 66 | description = "The name of the S3 bucket. Must be globally unique." 67 | default = "" 68 | } 69 | ``` 70 | 71 | * Validate the changes. 72 | 73 | Run command: 74 | 75 | ```bash 76 | terraform plan 77 | ``` 78 | 79 | * Deploy the changes. 80 | 81 | Run command: 82 | 83 | ```bash 84 | terraform apply 85 | ``` 86 | 87 | * Clean up the resources created. 88 | 89 | When you have finished, run command: 90 | 91 | ```bash 92 | terraform destroy 93 | ``` -------------------------------------------------------------------------------- /code/09-module-example/global/s3/main.tf: -------------------------------------------------------------------------------- 1 | # Configure the AWS provider 2 | provider "aws" { 3 | region = "eu-west-1" 4 | } 5 | 6 | # Create a S3 bucket 7 | resource "aws_s3_bucket" "terraform_state" { 8 | bucket = "${var.bucket_name}" 9 | 10 | versioning { 11 | enabled = true 12 | } 13 | 14 | lifecycle { 15 | prevent_destroy = true 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /code/09-module-example/global/s3/outputs.tf: -------------------------------------------------------------------------------- 1 | # Output variable: S3 bucket 2 | output "s3_bucket_arn" { 3 | value = "${aws_s3_bucket.terraform_state.arn}" 4 | } 5 | -------------------------------------------------------------------------------- /code/09-module-example/global/s3/vars.tf: -------------------------------------------------------------------------------- 1 | # Input variable: S3 bucket name 2 | variable "bucket_name" { 3 | description = "The name of the S3 bucket. Must be globally unique." 4 | default = "terraform-state-my-bucket" 5 | } 6 | -------------------------------------------------------------------------------- /code/09-module-example/modules/services/webserver-cluster/README.md: -------------------------------------------------------------------------------- 1 | # Terraform Web Server Cluster module example 2 | 3 | This folder contains a Web Server Cluster module example of a Terraform file [Terraform](https://www.terraform.io/). 4 | 5 | This Terraform file define a cluster of web servers module on AWS (Amazon Web Services) using EC2 and Auto Scaling, and a load balancer using ELB. 6 | 7 | The cluster of web servers returns "Hello, World" for the URL `/`. The load balancer listens on port 80. 8 | 9 | ## Requirements 10 | 11 | * You must have [Terraform](https://www.terraform.io/) installed on your computer. 12 | * You must have an [AWS (Amazon Web Services)](http://aws.amazon.com/) account. 13 | * It uses the Terraform AWS Provider that interacts with the many resources supported by AWS through its APIs. 14 | * This code was written for Terraform 0.10.x. 15 | 16 | ## Using the code 17 | 18 | Terraform modules are not meant to be deployed directly. Instead, you should be using them from other templates. See 19 | [stage/services/webserver-cluster](../../../stage/services-webserver-cluster) and 20 | [prod/services/webserver-cluster](../../../prod/services-webserver-cluster) for examples. -------------------------------------------------------------------------------- /code/09-module-example/modules/services/webserver-cluster/main.tf: -------------------------------------------------------------------------------- 1 | # Data source: query the list of availability zones 2 | data "aws_availability_zones" "all" {} 3 | 4 | # Data source: DB remote state 5 | data "terraform_remote_state" "db" { 6 | backend = "s3" 7 | 8 | config { 9 | bucket = "${var.db_remote_state_bucket}" 10 | key = "${var.db_remote_state_key}" 11 | region = "eu-west-1" 12 | } 13 | } 14 | 15 | # Data source: Template file 16 | data "template_file" "user_data" { 17 | template = "${file("${path.module}/user-data.sh")}" 18 | 19 | vars { 20 | server_port = "${var.server_port}" 21 | db_address = "${data.terraform_remote_state.db.address}" 22 | db_port = "${data.terraform_remote_state.db.port}" 23 | } 24 | } 25 | 26 | # Create a Security Group for an EC2 instance 27 | resource "aws_security_group" "instance" { 28 | name = "${var.cluster_name}-instance" 29 | 30 | lifecycle { 31 | create_before_destroy = true 32 | } 33 | } 34 | 35 | # Create a Security Group Rule 36 | resource "aws_security_group_rule" "allow_server_http_inbound" { 37 | type = "ingress" 38 | security_group_id = "${aws_security_group.instance.id}" 39 | 40 | from_port = "${var.server_port}" 41 | to_port = "${var.server_port}" 42 | protocol = "tcp" 43 | cidr_blocks = ["0.0.0.0/0"] 44 | 45 | } 46 | 47 | # Create a Security Group for an ELB 48 | resource "aws_security_group" "elb" { 49 | name = "${var.cluster_name}-elb" 50 | } 51 | 52 | # Create a Security Group Rule, inbound 53 | resource "aws_security_group_rule" "allow_http_inbound" { 54 | type = "ingress" 55 | security_group_id = "${aws_security_group.elb.id}" 56 | 57 | from_port = 80 58 | to_port = 80 59 | protocol = "tcp" 60 | cidr_blocks = ["0.0.0.0/0"] 61 | } 62 | 63 | # Create a Security Group Rule, outbound 64 | resource "aws_security_group_rule" "allow_all_outbound" { 65 | type = "egress" 66 | security_group_id = "${aws_security_group.elb.id}" 67 | 68 | from_port = 0 69 | to_port = 0 70 | protocol = "-1" 71 | cidr_blocks = ["0.0.0.0/0"] 72 | } 73 | 74 | # Create a Launch Configuration 75 | resource "aws_launch_configuration" "example" { 76 | image_id = "ami-785db401" 77 | instance_type = "${var.instance_type}" 78 | security_groups = ["${aws_security_group.instance.id}"] 79 | user_data = "${data.template_file.user_data.rendered}" 80 | 81 | lifecycle { 82 | create_before_destroy = true 83 | } 84 | } 85 | 86 | # Create an Autoscaling Group 87 | resource "aws_autoscaling_group" "example" { 88 | launch_configuration = "${aws_launch_configuration.example.id}" 89 | availability_zones = ["${data.aws_availability_zones.all.names}"] 90 | load_balancers = ["${aws_elb.example.name}"] 91 | health_check_type = "ELB" 92 | 93 | min_size = "${var.min_size}" 94 | max_size = "${var.max_size}" 95 | 96 | tag { 97 | key = "Name" 98 | value = "${var.cluster_name}" 99 | propagate_at_launch = true 100 | } 101 | } 102 | 103 | # Create an ELB 104 | resource "aws_elb" "example" { 105 | name = "${var.cluster_name}" 106 | availability_zones = ["${data.aws_availability_zones.all.names}"] 107 | security_groups = ["${aws_security_group.elb.id}"] 108 | 109 | listener { 110 | lb_port = 80 111 | lb_protocol = "http" 112 | instance_port = "${var.server_port}" 113 | instance_protocol = "http" 114 | } 115 | 116 | health_check { 117 | healthy_threshold = 2 118 | unhealthy_threshold = 2 119 | timeout = 3 120 | interval = 30 121 | target = "HTTP:${var.server_port}/" 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /code/09-module-example/modules/services/webserver-cluster/outputs.tf: -------------------------------------------------------------------------------- 1 | # Output variable: DNS Name of ELB 2 | output "elb_dns_name" { 3 | value = "${aws_elb.example.dns_name}" 4 | } 5 | 6 | # Output variable: Auto Scaling Group name 7 | output "asg_name" { 8 | value = "${aws_autoscaling_group.example.name}" 9 | } 10 | 11 | # Output variable: ELB Security Group Id 12 | output "elb_security_group_id" { 13 | value = "${aws_security_group.elb.id}" 14 | } 15 | -------------------------------------------------------------------------------- /code/09-module-example/modules/services/webserver-cluster/user-data.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cat > index.html <Hello, World 5 |

DB address: ${db_address}

6 |

DB port: ${db_port}

7 | EOF 8 | 9 | nohup busybox httpd -f -p "${server_port}" & 10 | -------------------------------------------------------------------------------- /code/09-module-example/modules/services/webserver-cluster/vars.tf: -------------------------------------------------------------------------------- 1 | # Input variable: server port 2 | variable "server_port" { 3 | description = "The port the server will use for HTTP requests" 4 | default = "8080" 5 | } 6 | 7 | # Input variable: Cluster name 8 | variable "cluster_name" { 9 | description = "The name to use for all the cluster resources" 10 | } 11 | 12 | # Input variable: DB remote state bucket name 13 | variable "db_remote_state_bucket" { 14 | description = "The name of the S3 bucket for the database's remote state" 15 | } 16 | 17 | # Input variable: DB remote state bucket key 18 | variable "db_remote_state_key" { 19 | description = "The path for database's remote state in S3" 20 | } 21 | 22 | # Input variable: Instance type 23 | variable "instance_type" { 24 | description = "The type of EC2 Instances to run (e.g. t2.micro)" 25 | } 26 | 27 | # Input variable: Instance min size 28 | variable "min_size" { 29 | description = "The minimum number of EC2 Instances in the ASG" 30 | } 31 | 32 | # Input variable: Instance max size 33 | variable "max_size" { 34 | description = "The maximum number of EC2 Instances in the ASG" 35 | } 36 | -------------------------------------------------------------------------------- /code/09-module-example/prod/data-stores/mysql/README.md: -------------------------------------------------------------------------------- 1 | # Terraform MySQL on RDS example (production environment) 2 | 3 | This folder contains a MySQL on RDS example of a Terraform file [Terraform](https://www.terraform.io/). 4 | 5 | This Terraform file deploys a MySQL database using RDS on AWS (Amazon Web Services). 6 | 7 | ## Requirements 8 | 9 | * You must have [Terraform](https://www.terraform.io/) installed on your computer. 10 | * You must have an [AWS (Amazon Web Services)](http://aws.amazon.com/) account. 11 | * It uses the Terraform AWS Provider that interacts with the many resources supported by AWS through its APIs. 12 | * This code was written for Terraform 0.10.x. 13 | 14 | ## Using the code 15 | 16 | * Configure your AWS access keys. 17 | 18 | * Initialize working directory. 19 | 20 | The first command that should be run after writing a new Terraform configuration is the `terraform init` command in order to initialize a working directory containing Terraform configuration files. It is safe to run this command multiple times. 21 | 22 | ```bash 23 | terraform init 24 | ``` 25 | 26 | * Configure Terraform backend. 27 | 28 | Modify the S3 bucket name, which is defined in the `bucket` attribute in `backend.tf` file. 29 | 30 | ```bash 31 | bucket = "" 32 | ``` 33 | 34 | * Configure database password. 35 | 36 | The database password is managed by the `db_password` input variable. 37 | 38 | Terraform will parse any environment variables that are prefixed with `TF_VAR`. You must create an environment variable `TF_VAR_db_password`: 39 | 40 | ```bash 41 | TF_VAR_db_password= 42 | ``` 43 | 44 | * Validate the changes. 45 | 46 | Run command: 47 | 48 | ```bash 49 | terraform plan 50 | ``` 51 | 52 | * Deploy the changes. 53 | 54 | Run command: 55 | 56 | ```bash 57 | terraform apply 58 | ``` 59 | 60 | * Test the deploy. 61 | 62 | You should see a new RDS MySQL database on AWS (Amazon Web Services). 63 | 64 | * Clean up the resources created. 65 | 66 | When you have finished, run command: 67 | 68 | ```bash 69 | terraform destroy 70 | ``` -------------------------------------------------------------------------------- /code/09-module-example/prod/data-stores/mysql/backend.tf: -------------------------------------------------------------------------------- 1 | # Define Terraform backend using a S3 bucket for storing the Terraform state 2 | terraform { 3 | backend "s3" { 4 | bucket = "terraform-state-my-bucket" 5 | key = "module-example/prod/data-stores/mysql/terraform.tfstate" 6 | region = "eu-west-1" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /code/09-module-example/prod/data-stores/mysql/main.tf: -------------------------------------------------------------------------------- 1 | # Configure the AWS provider 2 | provider "aws" { 3 | region = "eu-west-1" 4 | } 5 | 6 | # Create a DB instance 7 | resource "aws_db_instance" "example" { 8 | engine = "mysql" 9 | allocated_storage = 10 10 | instance_class = "db.t2.micro" 11 | name = "example_database_prod" 12 | username = "admin" 13 | password = "${var.db_password}" 14 | skip_final_snapshot = true 15 | } 16 | -------------------------------------------------------------------------------- /code/09-module-example/prod/data-stores/mysql/outputs.tf: -------------------------------------------------------------------------------- 1 | # Output variable: DB instance address 2 | output "address" { 3 | value = "${aws_db_instance.example.address}" 4 | } 5 | 6 | # Output variable: DB instance port 7 | output "port" { 8 | value = "${aws_db_instance.example.port}" 9 | } 10 | -------------------------------------------------------------------------------- /code/09-module-example/prod/data-stores/mysql/vars.tf: -------------------------------------------------------------------------------- 1 | # Input variable: DB password 2 | variable "db_password" { 3 | description = "The password for the database" 4 | } 5 | -------------------------------------------------------------------------------- /code/09-module-example/prod/services/webserver-cluster/README.md: -------------------------------------------------------------------------------- 1 | # Terraform Web Server Cluster example (production environment) 2 | 3 | This folder contains a Web Server Cluster example of a Terraform file [Terraform](https://www.terraform.io/). 4 | 5 | This Terraform file deploys a cluster of web servers on AWS (Amazon Web Services) using EC2 and Auto Scaling, and a load balancer using ELB. 6 | 7 | The cluster of web servers returns "Hello, World" for the URL `/`. The load balancer listens on port 80. 8 | 9 | ## Requirements 10 | 11 | * You must have [Terraform](https://www.terraform.io/) installed on your computer. 12 | * You must have an [AWS (Amazon Web Services)](http://aws.amazon.com/) account. 13 | * It uses the Terraform AWS Provider that interacts with the many resources supported by AWS through its APIs. 14 | * This code was written for Terraform 0.10.x. 15 | * You must deploy the MySQL database in [data-stores/mysql](../../data-stores/mysql) BEFORE deploying the templates in this folder. 16 | * This uses a Terraform module. See [modules/services/webserver-cluster](../../../modules/services/webserver-cluster). 17 | 18 | ## Using the code 19 | 20 | * Configure your AWS access keys. 21 | 22 | * Initialize working directory. 23 | 24 | The first command that should be run after writing a new Terraform configuration is the `terraform init` command in order to initialize a working directory containing Terraform configuration files. It is safe to run this command multiple times. 25 | 26 | ```bash 27 | terraform init 28 | ``` 29 | 30 | * Configure Terraform backend. 31 | 32 | Modify the S3 bucket name, which is defined in the `bucket` attribute in `backend.tf` file. 33 | 34 | ```bash 35 | bucket = "" 36 | ``` 37 | 38 | * Configure the bucket used for the database's remote state storage. 39 | 40 | Modify the S3 bucket name which is defined in the `bucket` attribute in `vars.tf` file. Important! You must deploy the templates in [data-stores/mysql](../../data-stores/mysql) first: 41 | 42 | ```hcl 43 | variable "db_remote_state_bucket" { 44 | description = "The name of the S3 bucket used for the database's remote state storage" 45 | default = "" 46 | } 47 | ``` 48 | 49 | * Validate the changes. 50 | 51 | Run command: 52 | 53 | ```bash 54 | terraform plan 55 | ``` 56 | 57 | * Deploy the changes. 58 | 59 | Run command: 60 | 61 | ```bash 62 | terraform apply 63 | ``` 64 | 65 | * Test the cluster of web servers. 66 | 67 | Test the cluster of web servers. When the `apply` command completes, it will output the DNS name of the load balancer. 68 | 69 | ```bash 70 | curl http:/// 71 | ``` 72 | 73 | * Clean up the resources created. 74 | 75 | When you have finished, run command: 76 | 77 | ```bash 78 | terraform destroy 79 | ``` -------------------------------------------------------------------------------- /code/09-module-example/prod/services/webserver-cluster/backend.tf: -------------------------------------------------------------------------------- 1 | # Define Terraform backend using a S3 bucket for storing the Terraform state 2 | terraform { 3 | backend "s3" { 4 | bucket = "terraform-state-my-bucket" 5 | key = "module-example/prod/services/webserver-cluster/terraform.tfstate" 6 | region = "eu-west-1" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /code/09-module-example/prod/services/webserver-cluster/main.tf: -------------------------------------------------------------------------------- 1 | # Configure the AWS provider 2 | provider "aws" { 3 | region = "eu-west-1" 4 | } 5 | 6 | # Use Module 7 | module "webserver_cluster" { 8 | source = "../../../modules/services/webserver-cluster" 9 | 10 | cluster_name = "werservers-prod" 11 | db_remote_state_bucket = "${var.db_remote_state_bucket}" 12 | db_remote_state_key = "${var.db_remote_state_key}" 13 | 14 | instance_type = "t2.micro" 15 | min_size = 2 16 | max_size = 10 17 | } 18 | 19 | # Create an Autoscaling Schedule 20 | resource "aws_autoscaling_schedule" "scale_out_during_business_hours" { 21 | scheduled_action_name = "scale-out-during-business-hours" 22 | min_size = 2 23 | max_size = 10 24 | desired_capacity = 10 25 | recurrence = "0 9 * * *" 26 | 27 | autoscaling_group_name = "${module.webserver_cluster.asg_name}" 28 | } 29 | 30 | # Create an Autoscaling Schedule 31 | resource "aws_autoscaling_schedule" "scale_in_at_night" { 32 | scheduled_action_name = "scale-in-at-night" 33 | min_size = 2 34 | max_size = 10 35 | desired_capacity = 2 36 | recurrence = "0 17 * * *" 37 | 38 | autoscaling_group_name = "${module.webserver_cluster.asg_name}" 39 | } 40 | -------------------------------------------------------------------------------- /code/09-module-example/prod/services/webserver-cluster/outputs.tf: -------------------------------------------------------------------------------- 1 | # Output variable: DNS Name of ELB 2 | output "elb_dns_name" { 3 | value = "${module.webserver_cluster.elb_dns_name}" 4 | } 5 | -------------------------------------------------------------------------------- /code/09-module-example/prod/services/webserver-cluster/vars.tf: -------------------------------------------------------------------------------- 1 | # Input variable: DB remote state bucket name 2 | variable "db_remote_state_bucket" { 3 | description = "The name of the S3 bucket for the database's remote state" 4 | default = "terraform-state-my-bucket" 5 | } 6 | 7 | # Input variable: DB remote state bucket key 8 | variable "db_remote_state_key" { 9 | description = "The path for database's remote state in S3" 10 | default = "module-example/prod/data-stores/mysql/terraform.tfstate" 11 | } 12 | -------------------------------------------------------------------------------- /code/09-module-example/stage/data-stores/mysql/README.md: -------------------------------------------------------------------------------- 1 | # Terraform MySQL on RDS example (staging environment) 2 | 3 | This folder contains a MySQL on RDS example of a Terraform file [Terraform](https://www.terraform.io/). 4 | 5 | This Terraform file deploys a MySQL database using RDS on AWS (Amazon Web Services). 6 | 7 | ## Requirements 8 | 9 | * You must have [Terraform](https://www.terraform.io/) installed on your computer. 10 | * You must have an [AWS (Amazon Web Services)](http://aws.amazon.com/) account. 11 | * It uses the Terraform AWS Provider that interacts with the many resources supported by AWS through its APIs. 12 | * This code was written for Terraform 0.10.x. 13 | 14 | ## Using the code 15 | 16 | * Configure your AWS access keys. 17 | 18 | * Initialize working directory. 19 | 20 | The first command that should be run after writing a new Terraform configuration is the `terraform init` command in order to initialize a working directory containing Terraform configuration files. It is safe to run this command multiple times. 21 | 22 | ```bash 23 | terraform init 24 | ``` 25 | 26 | * Configure Terraform backend. 27 | 28 | Modify the S3 bucket name, which is defined in the `bucket` attribute in `backend.tf` file. 29 | 30 | ```bash 31 | bucket = "" 32 | ``` 33 | 34 | * Configure database password. 35 | 36 | The database password is managed by the `db_password` input variable. 37 | 38 | Terraform will parse any environment variables that are prefixed with `TF_VAR`. You must create an environment variable `TF_VAR_db_password`: 39 | 40 | ```bash 41 | TF_VAR_db_password= 42 | ``` 43 | 44 | * Validate the changes. 45 | 46 | Run command: 47 | 48 | ```bash 49 | terraform plan 50 | ``` 51 | 52 | * Deploy the changes. 53 | 54 | Run command: 55 | 56 | ```bash 57 | terraform apply 58 | ``` 59 | 60 | * Test the deploy. 61 | 62 | You should see a new RDS MySQL database on AWS (Amazon Web Services). 63 | 64 | * Clean up the resources created. 65 | 66 | When you have finished, run command: 67 | 68 | ```bash 69 | terraform destroy 70 | ``` -------------------------------------------------------------------------------- /code/09-module-example/stage/data-stores/mysql/backend.tf: -------------------------------------------------------------------------------- 1 | # Define Terraform backend using a S3 bucket for storing the Terraform state 2 | terraform { 3 | backend "s3" { 4 | bucket = "terraform-state-my-bucket" 5 | key = "module-example/stage/data-stores/mysql/terraform.tfstate" 6 | region = "eu-west-1" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /code/09-module-example/stage/data-stores/mysql/main.tf: -------------------------------------------------------------------------------- 1 | # Configure the AWS provider 2 | provider "aws" { 3 | region = "eu-west-1" 4 | } 5 | 6 | # Create a DB instance 7 | resource "aws_db_instance" "example" { 8 | engine = "mysql" 9 | allocated_storage = 10 10 | instance_class = "db.t2.micro" 11 | name = "example_database_stage" 12 | username = "admin" 13 | password = "${var.db_password}" 14 | skip_final_snapshot = true 15 | } 16 | -------------------------------------------------------------------------------- /code/09-module-example/stage/data-stores/mysql/outputs.tf: -------------------------------------------------------------------------------- 1 | # Output variable: DB instance address 2 | output "address" { 3 | value = "${aws_db_instance.example.address}" 4 | } 5 | 6 | # Output variable: DB instance port 7 | output "port" { 8 | value = "${aws_db_instance.example.port}" 9 | } 10 | -------------------------------------------------------------------------------- /code/09-module-example/stage/data-stores/mysql/vars.tf: -------------------------------------------------------------------------------- 1 | # Input variable: DB password 2 | variable "db_password" { 3 | description = "The password for the database" 4 | } 5 | -------------------------------------------------------------------------------- /code/09-module-example/stage/services/webserver-cluster/README.md: -------------------------------------------------------------------------------- 1 | # Terraform Web Server Cluster example (staging environment) 2 | 3 | This folder contains a Web Server Cluster example of a Terraform file [Terraform](https://www.terraform.io/). 4 | 5 | This Terraform file deploys a cluster of web servers on AWS (Amazon Web Services) using EC2 and Auto Scaling, and a load balancer using ELB. 6 | 7 | The cluster of web servers returns "Hello, World" for the URL `/`. The load balancer listens on port 80. 8 | 9 | ## Requirements 10 | 11 | * You must have [Terraform](https://www.terraform.io/) installed on your computer. 12 | * You must have an [AWS (Amazon Web Services)](http://aws.amazon.com/) account. 13 | * It uses the Terraform AWS Provider that interacts with the many resources supported by AWS through its APIs. 14 | * This code was written for Terraform 0.10.x. 15 | * You must deploy the MySQL database in [data-stores/mysql](../../data-stores/mysql) BEFORE deploying the templates in this folder. 16 | * This uses a Terraform module. See [modules/services/webserver-cluster](../../../modules/services/webserver-cluster). 17 | 18 | ## Using the code 19 | 20 | * Configure your AWS access keys. 21 | 22 | * Initialize working directory. 23 | 24 | The first command that should be run after writing a new Terraform configuration is the `terraform init` command in order to initialize a working directory containing Terraform configuration files. It is safe to run this command multiple times. 25 | 26 | ```bash 27 | terraform init 28 | ``` 29 | 30 | * Configure Terraform backend. 31 | 32 | Modify the S3 bucket name, which is defined in the `bucket` attribute in `backend.tf` file. 33 | 34 | ```bash 35 | bucket = "" 36 | ``` 37 | 38 | * Configure the bucket used for the database's remote state storage. 39 | 40 | Modify the S3 bucket name which is defined in the `bucket` attribute in `vars.tf` file. Important! You must deploy the templates in [data-stores/mysql](../../data-stores/mysql) first: 41 | 42 | ```hcl 43 | variable "db_remote_state_bucket" { 44 | description = "The name of the S3 bucket used for the database's remote state storage" 45 | default = "" 46 | } 47 | ``` 48 | 49 | * Validate the changes. 50 | 51 | Run command: 52 | 53 | ```bash 54 | terraform plan 55 | ``` 56 | 57 | * Deploy the changes. 58 | 59 | Run command: 60 | 61 | ```bash 62 | terraform apply 63 | ``` 64 | 65 | * Test the cluster of web servers. 66 | 67 | Test the cluster of web servers. When the `apply` command completes, it will output the DNS name of the load balancer. 68 | 69 | ```bash 70 | curl http:/// 71 | ``` 72 | 73 | * Clean up the resources created. 74 | 75 | When you have finished, run command: 76 | 77 | ```bash 78 | terraform destroy 79 | ``` -------------------------------------------------------------------------------- /code/09-module-example/stage/services/webserver-cluster/backend.tf: -------------------------------------------------------------------------------- 1 | # Define Terraform backend using a S3 bucket for storing the Terraform state 2 | terraform { 3 | backend "s3" { 4 | bucket = "terraform-state-my-bucket" 5 | key = "module-example/stage/services/webserver-cluster/terraform.tfstate" 6 | region = "eu-west-1" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /code/09-module-example/stage/services/webserver-cluster/main.tf: -------------------------------------------------------------------------------- 1 | # Configure the AWS provider 2 | provider "aws" { 3 | region = "eu-west-1" 4 | } 5 | 6 | # Use Module 7 | module "webserver_cluster" { 8 | source = "../../../modules/services/webserver-cluster" 9 | 10 | cluster_name = "werservers-stage" 11 | db_remote_state_bucket = "${var.db_remote_state_bucket}" 12 | db_remote_state_key = "${var.db_remote_state_key}" 13 | 14 | instance_type = "t2.micro" 15 | min_size = 2 16 | max_size = 2 17 | } 18 | 19 | # Create a Security Group Rule 20 | resource "aws_security_group_rule" "allow_testing_inbound" { 21 | type = "ingress" 22 | security_group_id = "${module.webserver_cluster.elb_security_group_id}" 23 | 24 | from_port = 12345 25 | to_port = 12345 26 | protocol = "tcp" 27 | cidr_blocks = ["0.0.0.0/0"] 28 | } 29 | -------------------------------------------------------------------------------- /code/09-module-example/stage/services/webserver-cluster/outputs.tf: -------------------------------------------------------------------------------- 1 | # Output variable: DNS Name of ELB 2 | output "elb_dns_name" { 3 | value = "${module.webserver_cluster.elb_dns_name}" 4 | } 5 | -------------------------------------------------------------------------------- /code/09-module-example/stage/services/webserver-cluster/vars.tf: -------------------------------------------------------------------------------- 1 | # Input variable: DB remote state bucket name 2 | variable "db_remote_state_bucket" { 3 | description = "The name of the S3 bucket for the database's remote state" 4 | default = "terraform-state-my-bucket" 5 | } 6 | 7 | # Input variable: DB remote state bucket key 8 | variable "db_remote_state_key" { 9 | description = "The path for database's remote state in S3" 10 | default = "module-example/stage/data-stores/mysql/terraform.tfstate" 11 | } 12 | -------------------------------------------------------------------------------- /code/10-multi-repo-example/README.md: -------------------------------------------------------------------------------- 1 | # Terraform Muti Repo example 2 | 3 | This folder contains a multi repo example of a [Terraform](https://www.terraform.io/) file on AWS (Amazon Web Services). 4 | 5 | It shows how to develop (not duplicating code) web server clusters in different environments using a module in another repo in order to use different version of the module in the environments. 6 | 7 | The environments are: 8 | 9 | * Staging (stage) 10 | * Production (prod) 11 | 12 | This is the file layout in this repo: 13 | 14 | ```bash 15 | live 16 | ├── global 17 | │ └── s3/ 18 | │ ├── main.tf 19 | │ └── (etc) 20 | │ 21 | ├── stage 22 | │ ├── services/ 23 | │ │ └── webserver-cluster/ 24 | │ │ ├── main.tf 25 | │ │ └── (etc) 26 | │ └── data-stores/ 27 | │ └── mysql/ 28 | │ ├── main.tf 29 | │ └── (etc) 30 | │ 31 | └── prod 32 | ├── services/ 33 | │ └── webserver-cluster/ 34 | │ ├── main.tf 35 | │ └── (etc) 36 | └── data-stores/ 37 | └── mysql/ 38 | ├── main.tf 39 | └── (etc) 40 | ``` 41 | 42 | This is the file layout used from another repo: 43 | 44 | ```bash 45 | modules 46 | └── services/ 47 | └── webserver-cluster/ 48 | ├── main.tf 49 | └── (etc) 50 | ``` 51 | 52 | It uses in common for both environments: 53 | 54 | * Terraform Remote State example: [live/global/s3](live/global/s3) 55 | * Terraform Web Server Cluster module example in another repo: [https://github.com/alfonsof/terraform-aws-repo-examples](https://github.com/alfonsof/terraform-aws-repo-examples) 56 | 57 | It uses for staging environment: 58 | 59 | * Terraform MySQL on RDS example (staging environment): [live/stage/data-stores/mysql](live/stage/data-stores/mysql) 60 | * Terraform Web Server Cluster example (staging environment): [live/stage/services/webserver-cluster](live/stage/services/webserver-cluster) 61 | 62 | It uses for production environment: 63 | 64 | * Terraform MySQL on RDS example (production environment): [live/prod/data-stores/mysql](live/prod/data-stores/mysql) 65 | * Terraform Web Server Cluster example (production environment): [live/prod/services/webserver-cluster](live/prod/services/webserver-cluster) 66 | 67 | ## Requirements 68 | 69 | * You must have [Terraform](https://www.terraform.io/) installed on your computer. 70 | * You must have an [AWS (Amazon Web Services)](http://aws.amazon.com/) account. 71 | * It uses the Terraform AWS Provider that interacts with the many resources supported by AWS through its APIs. 72 | * This code was written for Terraform 0.10.x. 73 | 74 | ## Using the code 75 | 76 | * Configure your AWS access keys. 77 | 78 | **Important:** For security, it is strongly recommend that you use IAM users instead of the root account for AWS access. 79 | 80 | Setting your credentials for use by Terraform can be done in a number of ways, but here are the recommended approaches: 81 | 82 | * The default credentials file 83 | 84 | Set credentials in the AWS credentials profile file on your local system, located at: 85 | 86 | `~/.aws/credentials` on Linux, macOS, or Unix 87 | 88 | `C:\Users\USERNAME\.aws\credentials` on Windows 89 | 90 | This file should contain lines in the following format: 91 | 92 | ```bash 93 | [default] 94 | aws_access_key_id = 95 | aws_secret_access_key = 96 | ``` 97 | Substitute your own AWS credentials values for the values `` and ``. 98 | 99 | * Environment variables `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` 100 | 101 | Set the `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` environment variables. 102 | 103 | To set these variables on Linux, macOS, or Unix, use `export`: 104 | 105 | ```bash 106 | export AWS_ACCESS_KEY_ID= 107 | export AWS_SECRET_ACCESS_KEY= 108 | ``` 109 | 110 | To set these variables on Windows, use `set`: 111 | 112 | ```bash 113 | set AWS_ACCESS_KEY_ID= 114 | set AWS_SECRET_ACCESS_KEY= 115 | ``` 116 | 117 | * Use Terraform Remote State example for creating the remote state bucket. See: [live/global/s3](live/global/s3) 118 | 119 | * Use Terraform module example (in another repo) for Web Server Cluster example in the staging environment and Web Server Cluster example in the production environment. See: [https://github.com/alfonsof/terraform-aws-repo-examples](https://github.com/alfonsof/terraform-aws-repo-examples) 120 | 121 | * Use Terraform MySQL on RDS example for creating a MySQL database in the staging environment. See: [live/stage/data-stores/mysql](live/stage/data-stores/mysql) 122 | 123 | * Use Terraform Web Server Cluster example for creating a web server cluster in the staging environment. See: [live/stage/services/webserver-cluster](live/stage/services/webserver-cluster) 124 | 125 | * Use Terraform MySQL on RDS example for creating a MySQL database in the production environment. See: [live/prod/data-stores/mysql](live/prod/data-stores/mysql) 126 | 127 | * Use Terraform Web Server Cluster example for creating a web server cluster in the production environment. See: [live/prod/services/webserver-cluster](live/prod/services/webserver-cluster) 128 | -------------------------------------------------------------------------------- /code/10-multi-repo-example/live/global/s3/README.md: -------------------------------------------------------------------------------- 1 | # Terraform Remote State example 2 | 3 | This folder contains an example of a Terraform file [Terraform](https://www.terraform.io/) that create a S3 bucket that can be used for remote state storage. 4 | 5 | This Terraform file deploys the creation a of a bucket on AWS (Amazon Web Services) using S3. 6 | 7 | ## Requirements 8 | 9 | * You must have [Terraform](https://www.terraform.io/) installed on your computer. 10 | * You must have an [AWS (Amazon Web Services)](http://aws.amazon.com/) account. 11 | * It uses the Terraform AWS Provider that interacts with the many resources supported by AWS through its APIs. 12 | * This code was written for Terraform 0.10.x. 13 | 14 | ## Using the code 15 | 16 | * Configure your AWS access keys. 17 | 18 | * Initialize working directory. 19 | 20 | The first command that should be run after writing a new Terraform configuration is the `terraform init` command in order to initialize a working directory containing Terraform configuration files. It is safe to run this command multiple times. 21 | 22 | ```bash 23 | terraform init 24 | ``` 25 | 26 | * Modify configuration. 27 | 28 | You must modify the S3 bucket name, which is defined as an input variable `bucket_name` in `vars.tf` file. 29 | 30 | You can modify the S3 bucket name in several ways: 31 | 32 | * Loading variables from command line flags. 33 | 34 | Run Terraform commands in this way: 35 | 36 | ```bash 37 | terraform plan -var 'bucket_name=' 38 | ``` 39 | 40 | ```bash 41 | terraform apply -var 'bucket_name=' 42 | ``` 43 | 44 | * Loading variables from a file. 45 | 46 | When Terraform runs it will look for a file called `terraform.tfvars`. You can populate this file with variable values that will be loaded when Terraform runs. An example for the content of the `terraform.tfvars` file: 47 | 48 | ```bash 49 | bucket_name = "" 50 | ``` 51 | 52 | * Loading variables from environment variables. 53 | 54 | Terraform will also parse any environment variables that are prefixed with `TF_VAR`. You can create an environment variable `TF_VAR_bucket_name`: 55 | 56 | ```bash 57 | TF_VAR_bucket_name= 58 | ``` 59 | 60 | * Variable defaults. 61 | 62 | Change the value of the `default` attribute of `bucket_name` input variable in `vars.tf` file. 63 | 64 | ```hcl 65 | variable "bucket_name" { 66 | description = "The name of the S3 bucket. Must be globally unique." 67 | default = "" 68 | } 69 | ``` 70 | 71 | * Validate the changes. 72 | 73 | Run command: 74 | 75 | ```bash 76 | terraform plan 77 | ``` 78 | 79 | * Deploy the changes. 80 | 81 | Run command: 82 | 83 | ```bash 84 | terraform apply 85 | ``` 86 | 87 | * Clean up the resources created. 88 | 89 | When you have finished, run command: 90 | 91 | ```bash 92 | terraform destroy 93 | ``` -------------------------------------------------------------------------------- /code/10-multi-repo-example/live/global/s3/main.tf: -------------------------------------------------------------------------------- 1 | # Configure the AWS provider 2 | provider "aws" { 3 | region = "eu-west-1" 4 | } 5 | 6 | # Create a S3 bucket 7 | resource "aws_s3_bucket" "terraform_state" { 8 | bucket = "${var.bucket_name}" 9 | 10 | versioning { 11 | enabled = true 12 | } 13 | 14 | lifecycle { 15 | prevent_destroy = true 16 | } 17 | } 18 | 19 | -------------------------------------------------------------------------------- /code/10-multi-repo-example/live/global/s3/outputs.tf: -------------------------------------------------------------------------------- 1 | # Output variable: S3 bucket 2 | output "s3_bucket_arn" { 3 | value = "${aws_s3_bucket.terraform_state.arn}" 4 | } 5 | -------------------------------------------------------------------------------- /code/10-multi-repo-example/live/global/s3/vars.tf: -------------------------------------------------------------------------------- 1 | # Input variable: S3 bucket name 2 | variable "bucket_name" { 3 | description = "The name of the S3 bucket. Must be globally unique." 4 | default = "terraform-state-my-bucket" 5 | } 6 | -------------------------------------------------------------------------------- /code/10-multi-repo-example/live/prod/data-stores/mysql/README.md: -------------------------------------------------------------------------------- 1 | # Terraform MySQL on RDS example (production environment) 2 | 3 | This folder contains a MySQL on RDS example of a Terraform file [Terraform](https://www.terraform.io/). 4 | 5 | This Terraform file deploys a MySQL database using RDS on AWS (Amazon Web Services). 6 | 7 | ## Requirements 8 | 9 | * You must have [Terraform](https://www.terraform.io/) installed on your computer. 10 | * You must have an [AWS (Amazon Web Services)](http://aws.amazon.com/) account. 11 | * It uses the Terraform AWS Provider that interacts with the many resources supported by AWS through its APIs. 12 | * This code was written for Terraform 0.10.x. 13 | 14 | ## Using the code 15 | 16 | * Configure your AWS access keys. 17 | 18 | * Initialize working directory. 19 | 20 | The first command that should be run after writing a new Terraform configuration is the `terraform init` command in order to initialize a working directory containing Terraform configuration files. It is safe to run this command multiple times. 21 | 22 | ```bash 23 | terraform init 24 | ``` 25 | 26 | * Configure Terraform backend. 27 | 28 | Modify the S3 bucket name, which is defined in the `bucket` attribute in `backend.tf` file. 29 | 30 | ```bash 31 | bucket = "" 32 | ``` 33 | 34 | * Configure database password. 35 | 36 | The database password is managed by the `db_password` input variable. 37 | 38 | Terraform will parse any environment variables that are prefixed with `TF_VAR`. You must create an environment variable `TF_VAR_db_password`: 39 | 40 | ```bash 41 | TF_VAR_db_password= 42 | ``` 43 | 44 | * Validate the changes. 45 | 46 | Run command: 47 | 48 | ```bash 49 | terraform plan 50 | ``` 51 | 52 | * Deploy the changes. 53 | 54 | Run command: 55 | 56 | ```bash 57 | terraform apply 58 | ``` 59 | 60 | * Test the deploy. 61 | 62 | You should see a new RDS MySQL database on AWS (Amazon Web Services). 63 | 64 | * Clean up the resources created. 65 | 66 | When you have finished, run command: 67 | 68 | ```bash 69 | terraform destroy 70 | ``` -------------------------------------------------------------------------------- /code/10-multi-repo-example/live/prod/data-stores/mysql/backend.tf: -------------------------------------------------------------------------------- 1 | # Define Terraform backend using a S3 bucket for storing the Terraform state 2 | terraform { 3 | backend "s3" { 4 | bucket = "terraform-state-my-bucket" 5 | key = "multi-repo-example/live/prod/data-stores/mysql/terraform.tfstate" 6 | region = "eu-west-1" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /code/10-multi-repo-example/live/prod/data-stores/mysql/main.tf: -------------------------------------------------------------------------------- 1 | # Configure the AWS provider 2 | provider "aws" { 3 | region = "eu-west-1" 4 | } 5 | 6 | # Create a DB instance 7 | resource "aws_db_instance" "example" { 8 | engine = "mysql" 9 | allocated_storage = 10 10 | instance_class = "db.t2.micro" 11 | name = "example_database_prod" 12 | username = "admin" 13 | password = "${var.db_password}" 14 | skip_final_snapshot = true 15 | } 16 | -------------------------------------------------------------------------------- /code/10-multi-repo-example/live/prod/data-stores/mysql/outputs.tf: -------------------------------------------------------------------------------- 1 | # Output variable: DB instance address 2 | output "address" { 3 | value = "${aws_db_instance.example.address}" 4 | } 5 | 6 | # Output variable: DB instance port 7 | output "port" { 8 | value = "${aws_db_instance.example.port}" 9 | } 10 | -------------------------------------------------------------------------------- /code/10-multi-repo-example/live/prod/data-stores/mysql/vars.tf: -------------------------------------------------------------------------------- 1 | # Input variable: DB password 2 | variable "db_password" { 3 | description = "The password for the database" 4 | } 5 | -------------------------------------------------------------------------------- /code/10-multi-repo-example/live/prod/services/webserver-cluster/README.md: -------------------------------------------------------------------------------- 1 | # Terraform Web Server Cluster example (production environment) 2 | 3 | This folder contains a Web Server Cluster example of a Terraform file [Terraform](https://www.terraform.io/). 4 | 5 | This Terraform file deploys a cluster of web servers on AWS (Amazon Web Services) using EC2 and Auto Scaling, and a load balancer using ELB. 6 | 7 | The cluster of web servers returns "Hello, World" for the URL `/`. The load balancer listens on port 80. 8 | 9 | ## Requirements 10 | 11 | * You must have [Terraform](https://www.terraform.io/) installed on your computer. 12 | * You must have an [AWS (Amazon Web Services)](http://aws.amazon.com/) account. 13 | * It uses the Terraform AWS Provider that interacts with the many resources supported by AWS through its APIs. 14 | * This code was written for Terraform 0.10.x. 15 | * You must deploy the MySQL database in [data-stores/mysql](../../data-stores/mysql) BEFORE deploying the 16 | templates in this folder. 17 | * This uses a Terraform module in another repo. See 18 | [https://github.com/alfonsof/terraform-aws-repo-examples](https://github.com/alfonsof/terraform-aws-repo-examples). 19 | 20 | ## Using the code 21 | 22 | * Configure your AWS access keys. 23 | 24 | * Initialize working directory. 25 | 26 | The first command that should be run after writing a new Terraform configuration is the `terraform init` command in order to initialize a working directory containing Terraform configuration files. It is safe to run this command multiple times. 27 | 28 | ```bash 29 | terraform init 30 | ``` 31 | 32 | * Configure Terraform backend. 33 | 34 | Modify the S3 bucket name, which is defined in the `bucket` attribute in `backend.tf` file. 35 | 36 | ```bash 37 | bucket = "" 38 | ``` 39 | 40 | * Configure the bucket used for the database's remote state storage. 41 | 42 | Modify the S3 bucket name which is defined in the `bucket` attribute in `vars.tf` file. Important! You must deploy the templates in [data-stores/mysql](../../data-stores/mysql) first: 43 | 44 | ```hcl 45 | variable "db_remote_state_bucket" { 46 | description = "The name of the S3 bucket used for the database's remote state storage" 47 | default = "" 48 | } 49 | ``` 50 | 51 | * Validate the changes. 52 | 53 | Run command: 54 | 55 | ```bash 56 | terraform plan 57 | ``` 58 | 59 | * Deploy the changes. 60 | 61 | Run command: 62 | 63 | ```bash 64 | terraform apply 65 | ``` 66 | 67 | * Test the cluster of web servers. 68 | 69 | Test the cluster of web servers. When the `apply` command completes, it will output the DNS name of the load balancer. 70 | 71 | ```bash 72 | curl http:/// 73 | ``` 74 | 75 | * Clean up the resources created. 76 | 77 | When you have finished, run command: 78 | 79 | ```bash 80 | terraform destroy 81 | ``` -------------------------------------------------------------------------------- /code/10-multi-repo-example/live/prod/services/webserver-cluster/backend.tf: -------------------------------------------------------------------------------- 1 | 2 | # Define Terraform backend using a S3 bucket for storing the Terraform state 3 | terraform { 4 | backend "s3" { 5 | bucket = "terraform-state-my-bucket" 6 | key = "multi-repo-example/live/prod/services/webserver-cluster/terraform.tfstate" 7 | region = "eu-west-1" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /code/10-multi-repo-example/live/prod/services/webserver-cluster/main.tf: -------------------------------------------------------------------------------- 1 | # Configure the AWS provider 2 | provider "aws" { 3 | region = "eu-west-1" 4 | } 5 | 6 | # Use Module 7 | module "webserver_cluster" { 8 | source = "git::git@github.com:alfonsof/terraform-aws-repo-examples.git//modules/services/webserver-cluster?ref=v0.0.1" 9 | 10 | cluster_name = "werservers-prod" 11 | db_remote_state_bucket = "${var.db_remote_state_bucket}" 12 | db_remote_state_key = "${var.db_remote_state_key}" 13 | 14 | instance_type = "t2.micro" 15 | min_size = 2 16 | max_size = 10 17 | } 18 | 19 | # Create an Autoscaling Schedule 20 | resource "aws_autoscaling_schedule" "scale_out_during_business_hours" { 21 | scheduled_action_name = "scale-out-during-business-hours" 22 | min_size = 2 23 | max_size = 10 24 | desired_capacity = 10 25 | recurrence = "0 9 * * *" 26 | 27 | autoscaling_group_name = "${module.webserver_cluster.asg_name}" 28 | } 29 | 30 | # Create an Autoscaling Schedule 31 | resource "aws_autoscaling_schedule" "scale_in_at_night" { 32 | scheduled_action_name = "scale-in-at-night" 33 | min_size = 2 34 | max_size = 10 35 | desired_capacity = 2 36 | recurrence = "0 17 * * *" 37 | 38 | autoscaling_group_name = "${module.webserver_cluster.asg_name}" 39 | } 40 | -------------------------------------------------------------------------------- /code/10-multi-repo-example/live/prod/services/webserver-cluster/outputs.tf: -------------------------------------------------------------------------------- 1 | # Output variable: DNS Name of ELB 2 | output "elb_dns_name" { 3 | value = "${module.webserver_cluster.elb_dns_name}" 4 | } 5 | -------------------------------------------------------------------------------- /code/10-multi-repo-example/live/prod/services/webserver-cluster/vars.tf: -------------------------------------------------------------------------------- 1 | # Input variable: DB remote state bucket name 2 | variable "db_remote_state_bucket" { 3 | description = "The name of the S3 bucket for the database's remote state" 4 | default = "terraform-state-my-bucket" 5 | } 6 | 7 | # Input variable: DB remote state bucket key 8 | variable "db_remote_state_key" { 9 | description = "The path for database's remote state in S3" 10 | default = "multi-repo-example/live/prod/data-stores/mysql/terraform.tfstate" 11 | } 12 | -------------------------------------------------------------------------------- /code/10-multi-repo-example/live/stage/data-stores/mysql/README.md: -------------------------------------------------------------------------------- 1 | # Terraform MySQL on RDS example (staging environment) 2 | 3 | This folder contains a MySQL on RDS example of a Terraform file [Terraform](https://www.terraform.io/). 4 | 5 | This Terraform file deploys a MySQL database using RDS on AWS (Amazon Web Services). 6 | 7 | ## Requirements 8 | 9 | * You must have [Terraform](https://www.terraform.io/) installed on your computer. 10 | * You must have an [AWS (Amazon Web Services)](http://aws.amazon.com/) account. 11 | * It uses the Terraform AWS Provider that interacts with the many resources supported by AWS through its APIs. 12 | * This code was written for Terraform 0.10.x. 13 | 14 | ## Using the code 15 | 16 | * Configure your AWS access keys. 17 | 18 | * Initialize working directory. 19 | 20 | The first command that should be run after writing a new Terraform configuration is the `terraform init` command in order to initialize a working directory containing Terraform configuration files. It is safe to run this command multiple times. 21 | 22 | ```bash 23 | terraform init 24 | ``` 25 | 26 | * Configure Terraform backend. 27 | 28 | Modify the S3 bucket name, which is defined in the `bucket` attribute in `backend.tf` file. 29 | 30 | ```bash 31 | bucket = "" 32 | ``` 33 | 34 | * Configure database password. 35 | 36 | The database password is managed by the `db_password` input variable. 37 | 38 | Terraform will parse any environment variables that are prefixed with `TF_VAR`. You must create an environment variable `TF_VAR_db_password`: 39 | 40 | ```bash 41 | TF_VAR_db_password= 42 | ``` 43 | 44 | * Validate the changes. 45 | 46 | Run command: 47 | 48 | ```bash 49 | terraform plan 50 | ``` 51 | 52 | * Deploy the changes. 53 | 54 | Run command: 55 | 56 | ```bash 57 | terraform apply 58 | ``` 59 | 60 | * Test the deploy. 61 | 62 | You should see a new RDS MySQL database on AWS (Amazon Web Services). 63 | 64 | * Clean up the resources created. 65 | 66 | When you have finished, run command: 67 | 68 | ```bash 69 | terraform destroy 70 | ``` -------------------------------------------------------------------------------- /code/10-multi-repo-example/live/stage/data-stores/mysql/backend.tf: -------------------------------------------------------------------------------- 1 | # Define Terraform backend using a S3 bucket for storing the Terraform state 2 | terraform { 3 | backend "s3" { 4 | bucket = "terraform-state-my-bucket" 5 | key = "multi-repo-example/live/stage/data-stores/mysql/terraform.tfstate" 6 | region = "eu-west-1" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /code/10-multi-repo-example/live/stage/data-stores/mysql/main.tf: -------------------------------------------------------------------------------- 1 | # Configure the AWS provider 2 | provider "aws" { 3 | region = "eu-west-1" 4 | } 5 | 6 | # Create a DB instance 7 | resource "aws_db_instance" "example" { 8 | engine = "mysql" 9 | allocated_storage = 10 10 | instance_class = "db.t2.micro" 11 | name = "example_database_stage" 12 | username = "admin" 13 | password = "${var.db_password}" 14 | skip_final_snapshot = true 15 | } 16 | -------------------------------------------------------------------------------- /code/10-multi-repo-example/live/stage/data-stores/mysql/outputs.tf: -------------------------------------------------------------------------------- 1 | # Output variable: DB instance address 2 | output "address" { 3 | value = "${aws_db_instance.example.address}" 4 | } 5 | 6 | # Output variable: DB instance port 7 | output "port" { 8 | value = "${aws_db_instance.example.port}" 9 | } 10 | -------------------------------------------------------------------------------- /code/10-multi-repo-example/live/stage/data-stores/mysql/vars.tf: -------------------------------------------------------------------------------- 1 | # Input variable: DB password 2 | variable "db_password" { 3 | description = "The password for the database" 4 | } 5 | -------------------------------------------------------------------------------- /code/10-multi-repo-example/live/stage/services/webserver-cluster/README.md: -------------------------------------------------------------------------------- 1 | # Terraform Web Server Cluster example (staging environment) 2 | 3 | This folder contains a Web Server Cluster example of a Terraform file [Terraform](https://www.terraform.io/). 4 | 5 | This Terraform file deploys a cluster of web servers on AWS (Amazon Web Services) using EC2 and Auto Scaling, and a load balancer using ELB. 6 | 7 | The cluster of web servers returns "Hello, World" for the URL `/`. The load balancer listens on port 80. 8 | 9 | ## Requirements 10 | 11 | * You must have [Terraform](https://www.terraform.io/) installed on your computer. 12 | * You must have an [AWS (Amazon Web Services)](http://aws.amazon.com/) account. 13 | * It uses the Terraform AWS Provider that interacts with the many resources supported by AWS through its APIs. 14 | * This code was written for Terraform 0.10.x. 15 | * You must deploy the MySQL database in [data-stores/mysql](../../data-stores/mysql) BEFORE deploying the 16 | templates in this folder. 17 | * This uses a Terraform module in another repo. See 18 | [https://github.com/alfonsof/terraform-aws-repo-examples](https://github.com/alfonsof/terraform-aws-repo-examples). 19 | 20 | ## Using the code 21 | 22 | * Configure your AWS access keys. 23 | 24 | * Initialize working directory. 25 | 26 | The first command that should be run after writing a new Terraform configuration is the `terraform init` command in order to initialize a working directory containing Terraform configuration files. It is safe to run this command multiple times. 27 | 28 | ```bash 29 | terraform init 30 | ``` 31 | 32 | * Configure Terraform backend. 33 | 34 | Modify the S3 bucket name, which is defined in the `bucket` attribute in `backend.tf` file. 35 | 36 | ```bash 37 | bucket = "" 38 | ``` 39 | 40 | * Configure the bucket used for the database's remote state storage. 41 | 42 | Modify the S3 bucket name which is defined in the `bucket` attribute in `vars.tf` file. Important! You must deploy the templates in [data-stores/mysql](../../data-stores/mysql) first: 43 | 44 | ```hcl 45 | variable "db_remote_state_bucket" { 46 | description = "The name of the S3 bucket used for the database's remote state storage" 47 | default = "" 48 | } 49 | ``` 50 | 51 | * Validate the changes. 52 | 53 | Run command: 54 | 55 | ```bash 56 | terraform plan 57 | ``` 58 | 59 | * Deploy the changes. 60 | 61 | Run command: 62 | 63 | ```bash 64 | terraform apply 65 | ``` 66 | 67 | * Test the cluster of web servers. 68 | 69 | Test the cluster of web servers. When the `apply` command completes, it will output the DNS name of the load balancer. 70 | 71 | ```bash 72 | curl http:/// 73 | ``` 74 | 75 | * Clean up the resources created. 76 | 77 | When you have finished, run command: 78 | 79 | ```bash 80 | terraform destroy 81 | ``` -------------------------------------------------------------------------------- /code/10-multi-repo-example/live/stage/services/webserver-cluster/backend.tf: -------------------------------------------------------------------------------- 1 | # Define Terraform backend using a S3 bucket for storing the Terraform state 2 | terraform { 3 | backend "s3" { 4 | bucket = "terraform-state-my-bucket" 5 | key = "multi-repo-example/live/stage/services/webserver-cluster/terraform.tfstate" 6 | region = "eu-west-1" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /code/10-multi-repo-example/live/stage/services/webserver-cluster/main.tf: -------------------------------------------------------------------------------- 1 | # Configure the AWS provider 2 | provider "aws" { 3 | region = "eu-west-1" 4 | } 5 | 6 | # Use Module 7 | module "webserver_cluster" { 8 | source = "git::git@github.com:alfonsof/terraform-aws-repo-examples.git//modules/services/webserver-cluster?ref=v0.0.2" 9 | 10 | cluster_name = "werservers-stage" 11 | db_remote_state_bucket = "${var.db_remote_state_bucket}" 12 | db_remote_state_key = "${var.db_remote_state_key}" 13 | 14 | instance_type = "t2.micro" 15 | min_size = 2 16 | max_size = 2 17 | } 18 | 19 | # Create a Security Group Rule 20 | resource "aws_security_group_rule" "allow_testing_inbound" { 21 | type = "ingress" 22 | security_group_id = "${module.webserver_cluster.elb_security_group_id}" 23 | 24 | from_port = 12345 25 | to_port = 12345 26 | protocol = "tcp" 27 | cidr_blocks = ["0.0.0.0/0"] 28 | } 29 | -------------------------------------------------------------------------------- /code/10-multi-repo-example/live/stage/services/webserver-cluster/outputs.tf: -------------------------------------------------------------------------------- 1 | # Output variable: DNS Name of ELB 2 | output "elb_dns_name" { 3 | value = "${module.webserver_cluster.elb_dns_name}" 4 | } 5 | -------------------------------------------------------------------------------- /code/10-multi-repo-example/live/stage/services/webserver-cluster/vars.tf: -------------------------------------------------------------------------------- 1 | # Input variable: DB remote state bucket name 2 | variable "db_remote_state_bucket" { 3 | description = "The name of the S3 bucket for the database's remote state" 4 | default = "terraform-state-my-bucket" 5 | } 6 | 7 | # Input variable: DB remote state bucket key 8 | variable "db_remote_state_key" { 9 | description = "The path for database's remote state in S3" 10 | default = "multi-repo-example/live/stage/data-stores/mysql/terraform.tfstate" 11 | } 12 | -------------------------------------------------------------------------------- /code/11-loops-example/README.md: -------------------------------------------------------------------------------- 1 | # Terraform Loops example 2 | 3 | This folder contains the loops example of a [Terraform](https://www.terraform.io/) file on AWS (Amazon Web Services). 4 | 5 | It shows how do loops in Terraform. 6 | 7 | This Terraform file create 3 IAM users, create an IAM policy and attach the IAM policy to the IAM users. 8 | 9 | We use the meta-parameter "count" and two interpolation functions: 10 | 11 | * "${element(LIST, INDEX)}" 12 | * "${length(LIST)}" 13 | 14 | ## Requirements 15 | 16 | * You must have [Terraform](https://www.terraform.io/) installed on your computer. 17 | * You must have an [AWS (Amazon Web Services)](http://aws.amazon.com/) account. 18 | * It uses the Terraform AWS Provider that interacts with the many resources supported by AWS through its APIs. 19 | * This code was written for Terraform 0.10.x. 20 | 21 | ## Using the code 22 | 23 | * Configure your AWS access keys. 24 | 25 | **Important:** For security, it is strongly recommend that you use IAM users instead of the root account for AWS access. 26 | 27 | Setting your credentials for use by Terraform can be done in a number of ways, but here are the recommended approaches: 28 | 29 | * The default credentials file 30 | 31 | Set credentials in the AWS credentials profile file on your local system, located at: 32 | 33 | `~/.aws/credentials` on Linux, macOS, or Unix 34 | 35 | `C:\Users\USERNAME\.aws\credentials` on Windows 36 | 37 | This file should contain lines in the following format: 38 | 39 | ```bash 40 | [default] 41 | aws_access_key_id = 42 | aws_secret_access_key = 43 | ``` 44 | Substitute your own AWS credentials values for the values `` and ``. 45 | 46 | * Environment variables `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` 47 | 48 | Set the `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` environment variables. 49 | 50 | To set these variables on Linux, macOS, or Unix, use `export`: 51 | 52 | ```bash 53 | export AWS_ACCESS_KEY_ID= 54 | export AWS_SECRET_ACCESS_KEY= 55 | ``` 56 | 57 | To set these variables on Windows, use `set`: 58 | 59 | ```bash 60 | set AWS_ACCESS_KEY_ID= 61 | set AWS_SECRET_ACCESS_KEY= 62 | ``` 63 | 64 | * Initialize working directory. 65 | 66 | The first command that should be run after writing a new Terraform configuration is the `terraform init` command in order to initialize a working directory containing Terraform configuration files. It is safe to run this command multiple times. 67 | 68 | ```bash 69 | terraform init 70 | ``` 71 | 72 | * Validate the changes: 73 | 74 | ```bash 75 | terraform plan 76 | ``` 77 | 78 | * Deploy the changes: 79 | 80 | ```bash 81 | terraform apply 82 | ``` 83 | 84 | * Test the deployment. 85 | 86 | You should see 3 IAM users, an IAM policy and the IAM policy attached to the IAM users. 87 | 88 | * Clean up the resources created when you have finished: 89 | 90 | ```bash 91 | terraform destroy 92 | ``` -------------------------------------------------------------------------------- /code/11-loops-example/main.tf: -------------------------------------------------------------------------------- 1 | # Configure the AWS provider 2 | provider "aws" { 3 | region = "eu-west-1" 4 | 5 | } 6 | 7 | # Create an IAM user 8 | resource "aws_iam_user" "example" { 9 | count = "${length(var.user_names)}" 10 | name = "${element(var.user_names, count.index)}" 11 | 12 | } 13 | 14 | # Data source: IAM policy document 15 | data "aws_iam_policy_document" "ec2_read_only" { 16 | statement { 17 | effect = "Allow" 18 | actions = ["ec2:Describe*"] 19 | resources = ["*"] 20 | } 21 | } 22 | 23 | # Create an IAM policy 24 | resource "aws_iam_policy" "ec2_read_only" { 25 | name = "ec2-read-only" 26 | policy = "${data.aws_iam_policy_document.ec2_read_only.json}" 27 | } 28 | 29 | # Create an IAM user policy attachement 30 | resource "aws_iam_user_policy_attachment" "ec2_access" { 31 | count = "${length(var.user_names)}" 32 | user = "${element(aws_iam_user.example.*.name, count.index)}" 33 | policy_arn = "${aws_iam_policy.ec2_read_only.arn}" 34 | } 35 | -------------------------------------------------------------------------------- /code/11-loops-example/outputs.tf: -------------------------------------------------------------------------------- 1 | # Output variable: ARN 2 | output "neo_arn" { 3 | value = ["${aws_iam_user.example.*.arn}"] 4 | } 5 | -------------------------------------------------------------------------------- /code/11-loops-example/vars.tf: -------------------------------------------------------------------------------- 1 | # Input variable: user names 2 | variable "user_names" { 3 | description = "Create IAM users with these names" 4 | type = "list" 5 | default = ["neo", "trinity", "morpheus"] 6 | } 7 | -------------------------------------------------------------------------------- /code/12-if-statements-example/README.md: -------------------------------------------------------------------------------- 1 | # Terraform If-Statements & If-Else-Statements example 2 | 3 | This folder contains an If-Statements and If-Else-Statements example of a [Terraform](https://www.terraform.io/) file on AWS (Amazon Web Services). 4 | 5 | It shows how to use a: 6 | 7 | 1 - simple If-Statement funcionality using an "enable_autoscaling" variable in the module in order to execute or not the resources: 8 | 9 | * resource "aws_autoscaling_schedule" "scale_out_during_business_hours" 10 | * resource "aws_autoscaling_schedule" "scale_in_at_night" 11 | 12 | Defining the values of "enable_autoscaling" variable: 13 | 14 | * true (= 1) in Production 15 | * false (= 0) in Staging 16 | 17 | 2 - more complicated If-Statement funcionality using the "instance_type" variable in the module in order to execute or not the resource: 18 | 19 | * resource "aws_cloudwatch_metric_alarm" "low_cpu_credit_balance" 20 | 21 | and using: 22 | 23 | count = "${format("%.1s", var.instance_type) == "t" ? 1 : 0}" 24 | 25 | where: 26 | 27 | * true (= 1) if "var.instance_type" start with a letter "t" (e.g., t2.micro) 28 | * false (= 0) if "var.instance_type" does not start with a letter "t" 29 | 30 | 3 - a more complicated If-Else-Statement funcionality using a "enable_new_user_data" variable in the module in order to a data script or another: 31 | 32 | * if "enable_new_user_data" is true (staging environment) the execute "user_data_new.sh" 33 | * if "enable_new_user_data" is false (production environment) the execute "user_data.sh" 34 | 35 | Furthermore, it shows how to develop (not duplicating code) web server clusters in different environments using a module. 36 | 37 | The environments are: 38 | 39 | * Staging (stage) 40 | * Production (prod) 41 | 42 | This is the file layout in this repo: 43 | 44 | ```bash 45 | live 46 | ├── global 47 | │ └── s3/ 48 | │ ├── main.tf 49 | │ └── (etc) 50 | │ 51 | ├── stage 52 | │ ├── services/ 53 | │ │ └── webserver-cluster/ 54 | │ │ ├── main.tf 55 | │ │ └── (etc) 56 | │ └── data-stores/ 57 | │ └── mysql/ 58 | │ ├── main.tf 59 | │ └── (etc) 60 | │ 61 | └── prod 62 | ├── services/ 63 | │ └── webserver-cluster/ 64 | │ ├── main.tf 65 | │ └── (etc) 66 | └── data-stores/ 67 | └── mysql/ 68 | ├── main.tf 69 | └── (etc) 70 | 71 | modules 72 | └── services/ 73 | └── webserver-cluster/ 74 | ├── main.tf 75 | └── (etc) 76 | ``` 77 | 78 | It uses in common for both environments: 79 | 80 | * Terraform Remote State example: [live/global/s3](live/global/s3) 81 | * Terraform Web Server Cluster module example: [modules/services/webserver-cluster](modules/services/webserver-cluster) 82 | 83 | It uses for staging environment: 84 | 85 | * Terraform MySQL on RDS example (staging environment): [live/stage/data-stores/mysql](live/stage/data-stores/mysql) 86 | * Terraform Web Server Cluster example (staging environment): [live/stage/services/webserver-cluster](live/stage/services/webserver-cluster) 87 | 88 | It uses for production environment: 89 | 90 | * Terraform MySQL on RDS example (production environment): [live/prod/data-stores/mysql](live/prod/data-stores/mysql) 91 | * Terraform Web Server Cluster example (production environment): [live/prod/services/webserver-cluster](live/prod/services/webserver-cluster) 92 | 93 | ## Requirements 94 | 95 | * You must have [Terraform](https://www.terraform.io/) installed on your computer. 96 | * You must have an [AWS (Amazon Web Services)](http://aws.amazon.com/) account. 97 | * It uses the Terraform AWS Provider that interacts with the many resources supported by AWS through its APIs. 98 | * This code was written for Terraform 0.10.x. 99 | 100 | ## Using the code 101 | 102 | * Configure your AWS access keys. 103 | 104 | **Important:** For security, it is strongly recommend that you use IAM users instead of the root account for AWS access. 105 | 106 | Setting your credentials for use by Terraform can be done in a number of ways, but here are the recommended approaches: 107 | 108 | * The default credentials file 109 | 110 | Set credentials in the AWS credentials profile file on your local system, located at: 111 | 112 | `~/.aws/credentials` on Linux, macOS, or Unix 113 | 114 | `C:\Users\USERNAME\.aws\credentials` on Windows 115 | 116 | This file should contain lines in the following format: 117 | 118 | ```bash 119 | [default] 120 | aws_access_key_id = 121 | aws_secret_access_key = 122 | ``` 123 | Substitute your own AWS credentials values for the values `` and ``. 124 | 125 | * Environment variables `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` 126 | 127 | Set the `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` environment variables. 128 | 129 | To set these variables on Linux, macOS, or Unix, use `export`: 130 | 131 | ```bash 132 | export AWS_ACCESS_KEY_ID= 133 | export AWS_SECRET_ACCESS_KEY= 134 | ``` 135 | 136 | To set these variables on Windows, use `set`: 137 | 138 | ```bash 139 | set AWS_ACCESS_KEY_ID= 140 | set AWS_SECRET_ACCESS_KEY= 141 | ``` 142 | 143 | * Use Terraform Remote State example for creating the remote state bucket. See: [live/global/s3](live/global/s3) 144 | 145 | * Use Terraform module example for Web Server Cluster example in the staging environment and Web Server Cluster example in the production environment. See: [modules/services/webserver-cluster](modules/services/webserver-cluster) 146 | 147 | * Use Terraform MySQL on RDS example for creating a MySQL database in the staging environment. See: [live/stage/data-stores/mysql](live/stage/data-stores/mysql) 148 | 149 | * Use Terraform Web Server Cluster example for creating a web server cluster in the staging environment. See: [live/stage/services/webserver-cluster](live/stage/services/webserver-cluster) 150 | 151 | * Use Terraform MySQL on RDS example for creating a MySQL database in the production environment. See: [live/prod/data-stores/mysql](live/prod/data-stores/mysql) 152 | 153 | * Use Terraform Web Server Cluster example for creating a web server cluster in the production environment. See: [live/prod/services/webserver-cluster](live/prod/services/webserver-cluster) 154 | -------------------------------------------------------------------------------- /code/12-if-statements-example/live/global/s3/README.md: -------------------------------------------------------------------------------- 1 | # Terraform Remote State example 2 | 3 | This folder contains an example of a Terraform file [Terraform](https://www.terraform.io/) that create a S3 bucket that can be used for remote state storage. 4 | 5 | This Terraform file deploys the creation a of a bucket on AWS (Amazon Web Services) using S3. 6 | 7 | ## Requirements 8 | 9 | * You must have [Terraform](https://www.terraform.io/) installed on your computer. 10 | * You must have an [AWS (Amazon Web Services)](http://aws.amazon.com/) account. 11 | * It uses the Terraform AWS Provider that interacts with the many resources supported by AWS through its APIs. 12 | * This code was written for Terraform 0.10.x. 13 | 14 | ## Using the code 15 | 16 | * Configure your AWS access keys. 17 | 18 | * Initialize working directory. 19 | 20 | The first command that should be run after writing a new Terraform configuration is the `terraform init` command in order to initialize a working directory containing Terraform configuration files. It is safe to run this command multiple times. 21 | 22 | ```bash 23 | terraform init 24 | ``` 25 | 26 | * Modify configuration. 27 | 28 | You must modify the S3 bucket name, which is defined as an input variable `bucket_name` in `vars.tf` file. 29 | 30 | You can modify the S3 bucket name in several ways: 31 | 32 | * Loading variables from command line flags. 33 | 34 | Run Terraform commands in this way: 35 | 36 | ```bash 37 | terraform plan -var 'bucket_name=' 38 | ``` 39 | 40 | ```bash 41 | terraform apply -var 'bucket_name=' 42 | ``` 43 | 44 | * Loading variables from a file. 45 | 46 | When Terraform runs it will look for a file called `terraform.tfvars`. You can populate this file with variable values that will be loaded when Terraform runs. An example for the content of the `terraform.tfvars` file: 47 | 48 | ```bash 49 | bucket_name = "" 50 | ``` 51 | 52 | * Loading variables from environment variables. 53 | 54 | Terraform will also parse any environment variables that are prefixed with `TF_VAR`. You can create an environment variable `TF_VAR_bucket_name`: 55 | 56 | ```bash 57 | TF_VAR_bucket_name= 58 | ``` 59 | 60 | * Variable defaults. 61 | 62 | Change the value of the `default` attribute of `bucket_name` input variable in `vars.tf` file. 63 | 64 | ```hcl 65 | variable "bucket_name" { 66 | description = "The name of the S3 bucket. Must be globally unique." 67 | default = "" 68 | } 69 | ``` 70 | 71 | * Validate the changes. 72 | 73 | Run command: 74 | 75 | ```bash 76 | terraform plan 77 | ``` 78 | 79 | * Deploy the changes. 80 | 81 | Run command: 82 | 83 | ```bash 84 | terraform apply 85 | ``` 86 | 87 | * Clean up the resources created. 88 | 89 | When you have finished, run command: 90 | 91 | ```bash 92 | terraform destroy 93 | ``` -------------------------------------------------------------------------------- /code/12-if-statements-example/live/global/s3/main.tf: -------------------------------------------------------------------------------- 1 | # Configure the AWS provider 2 | provider "aws" { 3 | region = "eu-west-1" 4 | } 5 | 6 | # Create a S3 bucket 7 | resource "aws_s3_bucket" "terraform_state" { 8 | bucket = "${var.bucket_name}" 9 | 10 | versioning { 11 | enabled = true 12 | } 13 | 14 | lifecycle { 15 | prevent_destroy = true 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /code/12-if-statements-example/live/global/s3/outputs.tf: -------------------------------------------------------------------------------- 1 | # Output variable: S3 bucket 2 | output "s3_bucket_arn" { 3 | value = "${aws_s3_bucket.terraform_state.arn}" 4 | } 5 | -------------------------------------------------------------------------------- /code/12-if-statements-example/live/global/s3/vars.tf: -------------------------------------------------------------------------------- 1 | # Input variable: S3 bucket name 2 | variable "bucket_name" { 3 | description = "The name of the S3 bucket. Must be globally unique." 4 | default = "terraform-state-my-bucket" 5 | } 6 | -------------------------------------------------------------------------------- /code/12-if-statements-example/live/prod/data-stores/mysql/README.md: -------------------------------------------------------------------------------- 1 | # Terraform MySQL on RDS example (production environment) 2 | 3 | This folder contains a MySQL on RDS example of a Terraform file [Terraform](https://www.terraform.io/). 4 | 5 | This Terraform file deploys a MySQL database using RDS on AWS (Amazon Web Services). 6 | 7 | ## Requirements 8 | 9 | * You must have [Terraform](https://www.terraform.io/) installed on your computer. 10 | * You must have an [AWS (Amazon Web Services)](http://aws.amazon.com/) account. 11 | * It uses the Terraform AWS Provider that interacts with the many resources supported by AWS through its APIs. 12 | * This code was written for Terraform 0.10.x. 13 | 14 | ## Using the code 15 | 16 | * Configure your AWS access keys. 17 | 18 | * Initialize working directory. 19 | 20 | The first command that should be run after writing a new Terraform configuration is the `terraform init` command in order to initialize a working directory containing Terraform configuration files. It is safe to run this command multiple times. 21 | 22 | ```bash 23 | terraform init 24 | ``` 25 | 26 | * Configure Terraform backend. 27 | 28 | Modify the S3 bucket name, which is defined in the `bucket` attribute in `backend.tf` file. 29 | 30 | ```bash 31 | bucket = "" 32 | ``` 33 | 34 | * Configure database password. 35 | 36 | The database password is managed by the `db_password` input variable. 37 | 38 | Terraform will parse any environment variables that are prefixed with `TF_VAR`. You must create an environment variable `TF_VAR_db_password`: 39 | 40 | ```bash 41 | TF_VAR_db_password= 42 | ``` 43 | 44 | * Validate the changes. 45 | 46 | Run command: 47 | 48 | ```bash 49 | terraform plan 50 | ``` 51 | 52 | * Deploy the changes. 53 | 54 | Run command: 55 | 56 | ```bash 57 | terraform apply 58 | ``` 59 | 60 | * Test the deploy. 61 | 62 | You should see a new RDS MySQL database on AWS (Amazon Web Services). 63 | 64 | * Clean up the resources created. 65 | 66 | When you have finished, run command: 67 | 68 | ```bash 69 | terraform destroy 70 | ``` -------------------------------------------------------------------------------- /code/12-if-statements-example/live/prod/data-stores/mysql/backend.tf: -------------------------------------------------------------------------------- 1 | # Define Terraform backend using a S3 bucket for storing the Terraform state 2 | terraform { 3 | backend "s3" { 4 | bucket = "terraform-state-my-bucket" 5 | key = "if-statements-example/prod/data-stores/mysql/terraform.tfstate" 6 | region = "eu-west-1" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /code/12-if-statements-example/live/prod/data-stores/mysql/main.tf: -------------------------------------------------------------------------------- 1 | # Configure the AWS provider 2 | provider "aws" { 3 | region = "eu-west-1" 4 | } 5 | 6 | # Create a DB instance 7 | resource "aws_db_instance" "example" { 8 | engine = "mysql" 9 | allocated_storage = 10 10 | instance_class = "db.t2.micro" 11 | name = "example_database_prod" 12 | username = "admin" 13 | password = "${var.db_password}" 14 | skip_final_snapshot = true 15 | } 16 | -------------------------------------------------------------------------------- /code/12-if-statements-example/live/prod/data-stores/mysql/outputs.tf: -------------------------------------------------------------------------------- 1 | # Output variable: DB instance address 2 | output "address" { 3 | value = "${aws_db_instance.example.address}" 4 | } 5 | 6 | # Output variable: DB instance port 7 | output "port" { 8 | value = "${aws_db_instance.example.port}" 9 | } 10 | -------------------------------------------------------------------------------- /code/12-if-statements-example/live/prod/data-stores/mysql/vars.tf: -------------------------------------------------------------------------------- 1 | # Input variable: DB password 2 | variable "db_password" { 3 | description = "The password for the database" 4 | } 5 | -------------------------------------------------------------------------------- /code/12-if-statements-example/live/prod/services/webserver-cluster/README.md: -------------------------------------------------------------------------------- 1 | # Terraform Web Server Cluster example (production environment) 2 | 3 | This folder contains a Web Server Cluster example of a Terraform file [Terraform](https://www.terraform.io/). 4 | 5 | This Terraform file deploys a cluster of web servers on AWS (Amazon Web Services) using EC2 and Auto Scaling, and a load balancer using ELB. 6 | 7 | The cluster of web servers returns "Hello, World" for the URL `/`. The load balancer listens on port 80. 8 | 9 | ## Requirements 10 | 11 | * You must have [Terraform](https://www.terraform.io/) installed on your computer. 12 | * You must have an [AWS (Amazon Web Services)](http://aws.amazon.com/) account. 13 | * It uses the Terraform AWS Provider that interacts with the many resources supported by AWS through its APIs. 14 | * This code was written for Terraform 0.10.x. 15 | * You must deploy the MySQL database in [data-stores/mysql](../../data-stores/mysql) BEFORE deploying the 16 | templates in this folder. 17 | * This uses a Terraform module. See [modules/services/webserver-cluster](../../../../modules/services/webserver-cluster). 18 | 19 | 20 | ## Using the code 21 | 22 | * Configure your AWS access keys. 23 | 24 | * Initialize working directory. 25 | 26 | The first command that should be run after writing a new Terraform configuration is the `terraform init` command in order to initialize a working directory containing Terraform configuration files. It is safe to run this command multiple times. 27 | 28 | ```bash 29 | terraform init 30 | ``` 31 | 32 | * Configure Terraform backend. 33 | 34 | Modify the S3 bucket name, which is defined in the `bucket` attribute in `backend.tf` file. 35 | 36 | ```bash 37 | bucket = "" 38 | ``` 39 | 40 | * Configure the bucket used for the database's remote state storage. 41 | 42 | Modify the S3 bucket name which is defined in the `bucket` attribute in `vars.tf` file. Important! You must deploy the templates in [data-stores/mysql](../../data-stores/mysql) first: 43 | 44 | ```hcl 45 | variable "db_remote_state_bucket" { 46 | description = "The name of the S3 bucket used for the database's remote state storage" 47 | default = "" 48 | } 49 | ``` 50 | 51 | * Validate the changes. 52 | 53 | Run command: 54 | 55 | ```bash 56 | terraform plan 57 | ``` 58 | 59 | * Deploy the changes. 60 | 61 | Run command: 62 | 63 | ```bash 64 | terraform apply 65 | ``` 66 | 67 | * Test the cluster of web servers. 68 | 69 | Test the cluster of web servers. When the `apply` command completes, it will output the DNS name of the load balancer. 70 | 71 | ```bash 72 | curl http:/// 73 | ``` 74 | 75 | * Clean up the resources created. 76 | 77 | When you have finished, run command: 78 | 79 | ```bash 80 | terraform destroy 81 | ``` -------------------------------------------------------------------------------- /code/12-if-statements-example/live/prod/services/webserver-cluster/backend.tf: -------------------------------------------------------------------------------- 1 | # Define Terraform backend using a S3 bucket for storing the Terraform state 2 | terraform { 3 | backend "s3" { 4 | bucket = "terraform-state-my-bucket" 5 | key = "if-statements-example/prod/services/webserver-cluster/terraform.tfstate" 6 | region = "eu-west-1" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /code/12-if-statements-example/live/prod/services/webserver-cluster/main.tf: -------------------------------------------------------------------------------- 1 | # Configure the AWS provider 2 | provider "aws" { 3 | region = "eu-west-1" 4 | } 5 | 6 | # Use Module 7 | module "webserver_cluster" { 8 | source = "../../../../modules/services/webserver-cluster" 9 | 10 | cluster_name = "werservers-prod" 11 | db_remote_state_bucket = "${var.db_remote_state_bucket}" 12 | db_remote_state_key = "${var.db_remote_state_key}" 13 | 14 | instance_type = "t2.micro" 15 | min_size = 2 16 | max_size = 10 17 | enable_autoscaling = true 18 | enable_new_user_data = false 19 | } 20 | -------------------------------------------------------------------------------- /code/12-if-statements-example/live/prod/services/webserver-cluster/outputs.tf: -------------------------------------------------------------------------------- 1 | # Output variable: DNS Name of ELB 2 | output "elb_dns_name" { 3 | value = "${module.webserver_cluster.elb_dns_name}" 4 | } 5 | -------------------------------------------------------------------------------- /code/12-if-statements-example/live/prod/services/webserver-cluster/vars.tf: -------------------------------------------------------------------------------- 1 | # Input variable: DB remote state bucket name 2 | variable "db_remote_state_bucket" { 3 | description = "The name of the S3 bucket for the database's remote state" 4 | default = "terraform-state-afb" 5 | } 6 | 7 | # Input variable: DB remote state bucket key 8 | variable "db_remote_state_key" { 9 | description = "The path for database's remote state in S3" 10 | default = "if-statements-example/prod/data-stores/mysql/terraform.tfstate" 11 | } 12 | -------------------------------------------------------------------------------- /code/12-if-statements-example/live/stage/data-stores/mysql/README.md: -------------------------------------------------------------------------------- 1 | # Terraform MySQL on RDS example (staging environment) 2 | 3 | This folder contains a MySQL on RDS example of a Terraform file [Terraform](https://www.terraform.io/). 4 | 5 | This Terraform file deploys a MySQL database using RDS on AWS (Amazon Web Services). 6 | 7 | ## Requirements 8 | 9 | * You must have [Terraform](https://www.terraform.io/) installed on your computer. 10 | * You must have an [AWS (Amazon Web Services)](http://aws.amazon.com/) account. 11 | * It uses the Terraform AWS Provider that interacts with the many resources supported by AWS through its APIs. 12 | * This code was written for Terraform 0.10.x. 13 | 14 | ## Using the code 15 | 16 | * Configure your AWS access keys. 17 | 18 | * Initialize working directory. 19 | 20 | The first command that should be run after writing a new Terraform configuration is the `terraform init` command in order to initialize a working directory containing Terraform configuration files. It is safe to run this command multiple times. 21 | 22 | ```bash 23 | terraform init 24 | ``` 25 | 26 | * Configure Terraform backend. 27 | 28 | Modify the S3 bucket name, which is defined in the `bucket` attribute in `backend.tf` file. 29 | 30 | ```bash 31 | bucket = "" 32 | ``` 33 | 34 | * Configure database password. 35 | 36 | The database password is managed by the `db_password` input variable. 37 | 38 | Terraform will parse any environment variables that are prefixed with `TF_VAR`. You must create an environment variable `TF_VAR_db_password`: 39 | 40 | ```bash 41 | TF_VAR_db_password= 42 | ``` 43 | 44 | * Validate the changes. 45 | 46 | Run command: 47 | 48 | ```bash 49 | terraform plan 50 | ``` 51 | 52 | * Deploy the changes. 53 | 54 | Run command: 55 | 56 | ```bash 57 | terraform apply 58 | ``` 59 | 60 | * Test the deploy. 61 | 62 | You should see a new RDS MySQL database on AWS (Amazon Web Services). 63 | 64 | * Clean up the resources created. 65 | 66 | When you have finished, run command: 67 | 68 | ```bash 69 | terraform destroy 70 | ``` -------------------------------------------------------------------------------- /code/12-if-statements-example/live/stage/data-stores/mysql/backend.tf: -------------------------------------------------------------------------------- 1 | # Define Terraform backend using a S3 bucket for storing the Terraform state 2 | terraform { 3 | backend "s3" { 4 | bucket = "terraform-state-my-bucket" 5 | key = "if-statements-example/stage/data-stores/mysql/terraform.tfstate" 6 | region = "eu-west-1" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /code/12-if-statements-example/live/stage/data-stores/mysql/main.tf: -------------------------------------------------------------------------------- 1 | # Configure the AWS provider 2 | provider "aws" { 3 | region = "eu-west-1" 4 | } 5 | 6 | # Create a DB instance 7 | resource "aws_db_instance" "example" { 8 | engine = "mysql" 9 | allocated_storage = 10 10 | instance_class = "db.t2.micro" 11 | name = "example_database_stage" 12 | username = "admin" 13 | password = "${var.db_password}" 14 | skip_final_snapshot = true 15 | } 16 | -------------------------------------------------------------------------------- /code/12-if-statements-example/live/stage/data-stores/mysql/outputs.tf: -------------------------------------------------------------------------------- 1 | # Output variable: DB instance address 2 | output "address" { 3 | value = "${aws_db_instance.example.address}" 4 | } 5 | 6 | # Output variable: DB instance port 7 | output "port" { 8 | value = "${aws_db_instance.example.port}" 9 | } 10 | -------------------------------------------------------------------------------- /code/12-if-statements-example/live/stage/data-stores/mysql/vars.tf: -------------------------------------------------------------------------------- 1 | # Input variable: DB password 2 | variable "db_password" { 3 | description = "The password for the database" 4 | } 5 | -------------------------------------------------------------------------------- /code/12-if-statements-example/live/stage/services/webserver-cluster/README.md: -------------------------------------------------------------------------------- 1 | # Terraform Web Server Cluster example (staging environment) 2 | 3 | This folder contains a Web Server Cluster example of a Terraform file [Terraform](https://www.terraform.io/). 4 | 5 | This Terraform file deploys a cluster of web servers on AWS (Amazon Web Services) using EC2 and Auto Scaling, and a load balancer using ELB. 6 | 7 | The cluster of web servers returns "Hello, World" for the URL `/`. The load balancer listens on port 80. 8 | 9 | ## Requirements 10 | 11 | * You must have [Terraform](https://www.terraform.io/) installed on your computer. 12 | * You must have an [AWS (Amazon Web Services)](http://aws.amazon.com/) account. 13 | * It uses the Terraform AWS Provider that interacts with the many resources supported by AWS through its APIs. 14 | * This code was written for Terraform 0.10.x. 15 | * You must deploy the MySQL database in [data-stores/mysql](../../data-stores/mysql) BEFORE deploying the 16 | templates in this folder. 17 | * This uses a Terraform module. See [modules/services/webserver-cluster](../../../../modules/services/webserver-cluster). 18 | 19 | ## Using the code 20 | 21 | * Configure your AWS access keys. 22 | 23 | * Initialize working directory. 24 | 25 | The first command that should be run after writing a new Terraform configuration is the `terraform init` command in order to initialize a working directory containing Terraform configuration files. It is safe to run this command multiple times. 26 | 27 | ```bash 28 | terraform init 29 | ``` 30 | 31 | * Configure Terraform backend. 32 | 33 | Modify the S3 bucket name, which is defined in the `bucket` attribute in `backend.tf` file. 34 | 35 | ```bash 36 | bucket = "" 37 | ``` 38 | 39 | * Configure the bucket used for the database's remote state storage. 40 | 41 | Modify the S3 bucket name which is defined in the `bucket` attribute in `vars.tf` file. Important! You must deploy the templates in [data-stores/mysql](../../data-stores/mysql) first: 42 | 43 | ```hcl 44 | variable "db_remote_state_bucket" { 45 | description = "The name of the S3 bucket used for the database's remote state storage" 46 | default = "" 47 | } 48 | ``` 49 | 50 | * Validate the changes. 51 | 52 | Run command: 53 | 54 | ```bash 55 | terraform plan 56 | ``` 57 | 58 | * Deploy the changes. 59 | 60 | Run command: 61 | 62 | ```bash 63 | terraform apply 64 | ``` 65 | 66 | * Test the cluster of web servers. 67 | 68 | Test the cluster of web servers. When the `apply` command completes, it will output the DNS name of the load balancer. 69 | 70 | ```bash 71 | curl http:/// 72 | ``` 73 | 74 | * Clean up the resources created. 75 | 76 | When you have finished, run command: 77 | 78 | ```bash 79 | terraform destroy 80 | ``` -------------------------------------------------------------------------------- /code/12-if-statements-example/live/stage/services/webserver-cluster/backend.tf: -------------------------------------------------------------------------------- 1 | # Define Terraform backend using a S3 bucket for storing the Terraform state 2 | terraform { 3 | backend "s3" { 4 | bucket = "terraform-state-my-bucket" 5 | key = "if-statements-example/stage/services/webserver-cluster/terraform.tfstate" 6 | region = "eu-west-1" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /code/12-if-statements-example/live/stage/services/webserver-cluster/main.tf: -------------------------------------------------------------------------------- 1 | # Configure the AWS provider 2 | provider "aws" { 3 | region = "eu-west-1" 4 | } 5 | 6 | # Use Module 7 | module "webserver_cluster" { 8 | source = "../../../../modules/services/webserver-cluster" 9 | 10 | cluster_name = "werservers-stage" 11 | db_remote_state_bucket = "${var.db_remote_state_bucket}" 12 | db_remote_state_key = "${var.db_remote_state_key}" 13 | 14 | instance_type = "t2.micro" 15 | min_size = 2 16 | max_size = 2 17 | enable_autoscaling = false 18 | enable_new_user_data = true 19 | } 20 | 21 | # Create a Security Group Rule 22 | resource "aws_security_group_rule" "allow_testing_inbound" { 23 | type = "ingress" 24 | security_group_id = "${module.webserver_cluster.elb_security_group_id}" 25 | 26 | from_port = 12345 27 | to_port = 12345 28 | protocol = "tcp" 29 | cidr_blocks = ["0.0.0.0/0"] 30 | } 31 | -------------------------------------------------------------------------------- /code/12-if-statements-example/live/stage/services/webserver-cluster/outputs.tf: -------------------------------------------------------------------------------- 1 | # Output variable: DNS Name of ELB 2 | output "elb_dns_name" { 3 | value = "${module.webserver_cluster.elb_dns_name}" 4 | } 5 | -------------------------------------------------------------------------------- /code/12-if-statements-example/live/stage/services/webserver-cluster/vars.tf: -------------------------------------------------------------------------------- 1 | # Input variable: DB remote state bucket name 2 | variable "db_remote_state_bucket" { 3 | description = "The name of the S3 bucket for the database's remote state" 4 | default = "terraform-state-my-bucket" 5 | } 6 | 7 | # Input variable: DB remote state bucket key 8 | variable "db_remote_state_key" { 9 | description = "The path for database's remote state in S3" 10 | default = "if-statements-example/stage/data-stores/mysql/terraform.tfstate" 11 | } 12 | -------------------------------------------------------------------------------- /code/12-if-statements-example/modules/services/webserver-cluster/README.md: -------------------------------------------------------------------------------- 1 | # Terraform Web Server Cluster module example 2 | 3 | This folder contains a Web Server Cluster module example of a Terraform file [Terraform](https://www.terraform.io/). 4 | 5 | This Terraform file define a cluster of web servers module on AWS (Amazon Web Services) using EC2 and Auto Scaling, and a load balancer using ELB. 6 | 7 | The cluster of web servers returns "Hello, World" for the URL `/`. The load balancer listens on port 80. 8 | 9 | ## Requirements 10 | 11 | * You must have [Terraform](https://www.terraform.io/) installed on your computer. 12 | * You must have an [AWS (Amazon Web Services)](http://aws.amazon.com/) account. 13 | * It uses the Terraform AWS Provider that interacts with the many resources supported by AWS through its APIs. 14 | * This code was written for Terraform 0.10.x. 15 | 16 | ## Using the code 17 | 18 | Terraform modules are not meant to be deployed directly. Instead, you should be using them from other templates. See [live/stage/services/webserver-cluster](../../../live/stage/services/webserver-cluster) and 19 | [live/prod/services/webserver-cluster](../../../live/prod/services/webserver-cluster) for examples. -------------------------------------------------------------------------------- /code/12-if-statements-example/modules/services/webserver-cluster/main.tf: -------------------------------------------------------------------------------- 1 | # Data source: query the list of availability zones 2 | data "aws_availability_zones" "all" {} 3 | 4 | # Data source: DB remote state 5 | data "terraform_remote_state" "db" { 6 | backend = "s3" 7 | 8 | config { 9 | bucket = "${var.db_remote_state_bucket}" 10 | key = "${var.db_remote_state_key}" 11 | region = "eu-west-1" 12 | } 13 | } 14 | 15 | # Data source: Template file 16 | data "template_file" "user_data" { 17 | count = "${1 - var.enable_new_user_data}" 18 | 19 | template = "${file("${path.module}/user-data.sh")}" 20 | 21 | vars { 22 | server_port = "${var.server_port}" 23 | db_address = "${data.terraform_remote_state.db.address}" 24 | db_port = "${data.terraform_remote_state.db.port}" 25 | } 26 | } 27 | 28 | # Data source: Template file 29 | data "template_file" "user_data_new" { 30 | count = "${var.enable_new_user_data}" 31 | 32 | template = "${file("${path.module}/user-data-new.sh")}" 33 | 34 | vars { 35 | server_port = "${var.server_port}" 36 | } 37 | } 38 | 39 | # Create a Security Group for an EC2 instance 40 | resource "aws_security_group" "instance" { 41 | name = "${var.cluster_name}-instance" 42 | 43 | lifecycle { 44 | create_before_destroy = true 45 | } 46 | } 47 | 48 | # Create a Security Group Rule 49 | resource "aws_security_group_rule" "allow_server_http_inbound" { 50 | type = "ingress" 51 | security_group_id = "${aws_security_group.instance.id}" 52 | 53 | from_port = "${var.server_port}" 54 | to_port = "${var.server_port}" 55 | protocol = "tcp" 56 | cidr_blocks = ["0.0.0.0/0"] 57 | 58 | } 59 | 60 | # Create a Security Group for an ELB 61 | resource "aws_security_group" "elb" { 62 | name = "${var.cluster_name}-elb" 63 | } 64 | 65 | # Create a Security Group Rule, inbound 66 | resource "aws_security_group_rule" "allow_http_inbound" { 67 | type = "ingress" 68 | security_group_id = "${aws_security_group.elb.id}" 69 | 70 | from_port = 80 71 | to_port = 80 72 | protocol = "tcp" 73 | cidr_blocks = ["0.0.0.0/0"] 74 | } 75 | 76 | # Create a Security Group Rule, outbound 77 | resource "aws_security_group_rule" "allow_all_outbound" { 78 | type = "egress" 79 | security_group_id = "${aws_security_group.elb.id}" 80 | 81 | from_port = 0 82 | to_port = 0 83 | protocol = "-1" 84 | cidr_blocks = ["0.0.0.0/0"] 85 | } 86 | 87 | # Create a Launch Configuration 88 | resource "aws_launch_configuration" "example" { 89 | image_id = "ami-785db401" 90 | instance_type = "${var.instance_type}" 91 | security_groups = ["${aws_security_group.instance.id}"] 92 | 93 | user_data = "${element( 94 | concat(data.template_file.user_data.*.rendered, 95 | data.template_file.user_data_new.*.rendered), 96 | 0)}" 97 | 98 | lifecycle { 99 | create_before_destroy = true 100 | } 101 | } 102 | 103 | # Create an Autoscaling Group 104 | resource "aws_autoscaling_group" "example" { 105 | launch_configuration = "${aws_launch_configuration.example.id}" 106 | availability_zones = ["${data.aws_availability_zones.all.names}"] 107 | load_balancers = ["${aws_elb.example.name}"] 108 | health_check_type = "ELB" 109 | 110 | min_size = "${var.min_size}" 111 | max_size = "${var.max_size}" 112 | 113 | tag { 114 | key = "Name" 115 | value = "${var.cluster_name}" 116 | propagate_at_launch = true 117 | } 118 | } 119 | 120 | # Create an ELB 121 | resource "aws_elb" "example" { 122 | name = "${var.cluster_name}" 123 | availability_zones = ["${data.aws_availability_zones.all.names}"] 124 | security_groups = ["${aws_security_group.elb.id}"] 125 | 126 | listener { 127 | lb_port = 80 128 | lb_protocol = "http" 129 | instance_port = "${var.server_port}" 130 | instance_protocol = "http" 131 | } 132 | 133 | health_check { 134 | healthy_threshold = 2 135 | unhealthy_threshold = 2 136 | timeout = 3 137 | interval = 30 138 | target = "HTTP:${var.server_port}/" 139 | } 140 | } 141 | 142 | # Create an Autoscaling Schedule 143 | resource "aws_autoscaling_schedule" "scale_out_during_business_hours" { 144 | count = "${var.enable_autoscaling}" 145 | 146 | scheduled_action_name = "scale-out-during-business-hours" 147 | min_size = 2 148 | max_size = 10 149 | desired_capacity = 10 150 | recurrence = "0 9 * * *" 151 | 152 | autoscaling_group_name = "${aws_autoscaling_group.example.name}" 153 | } 154 | 155 | # Create an Autoscaling Schedule 156 | resource "aws_autoscaling_schedule" "scale_in_at_night" { 157 | count = "${var.enable_autoscaling}" 158 | 159 | scheduled_action_name = "scale-in-at-night" 160 | min_size = 2 161 | max_size = 10 162 | desired_capacity = 2 163 | recurrence = "0 17 * * *" 164 | 165 | autoscaling_group_name = "${aws_autoscaling_group.example.name}" 166 | } 167 | 168 | # Create an Autoscaling Metric Alarm 169 | resource "aws_cloudwatch_metric_alarm" "high_cpu_utilisation" { 170 | alarm_name = "${var.cluster_name}-high-cpu-utilisation" 171 | namespace = "AWS/EC2" 172 | metric_name = "CPUUtilization" 173 | 174 | dimensions = { 175 | AutoScalingGroupName = "${aws_autoscaling_group.example.name}" 176 | } 177 | 178 | comparison_operator = "GreaterThanThreshold" 179 | evaluation_periods = 1 180 | period = 300 181 | statistic = "Average" 182 | threshold = 90 183 | unit = "Percent" 184 | } 185 | 186 | # Create an Autoscaling Metric Alarm 187 | resource "aws_cloudwatch_metric_alarm" "low_cpu_credit_balance" { 188 | count = "${format("%.1s", var.instance_type) == "t" ? 1 : 0}" 189 | 190 | alarm_name = "${var.cluster_name}-low-cpu-credit-balance" 191 | namespace = "AWS/EC2" 192 | metric_name = "CPUCreditBalance" 193 | 194 | dimensions = { 195 | AutoScalingGroupName = "${aws_autoscaling_group.example.name}" 196 | } 197 | 198 | comparison_operator = "LessThanThreshold" 199 | evaluation_periods = 1 200 | period = 300 201 | statistic = "Minimum" 202 | threshold = 10 203 | unit = "Count" 204 | } 205 | -------------------------------------------------------------------------------- /code/12-if-statements-example/modules/services/webserver-cluster/outputs.tf: -------------------------------------------------------------------------------- 1 | # Output variable: DNS Name of ELB 2 | output "elb_dns_name" { 3 | value = "${aws_elb.example.dns_name}" 4 | } 5 | 6 | # Output variable: Auto Scaling Group name 7 | output "asg_name" { 8 | value = "${aws_autoscaling_group.example.name}" 9 | } 10 | 11 | # Output variable: ELB Security Group Id 12 | output "elb_security_group_id" { 13 | value = "${aws_security_group.elb.id}" 14 | } 15 | -------------------------------------------------------------------------------- /code/12-if-statements-example/modules/services/webserver-cluster/user-data-new.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo "Hello, World, v2" > index.html 4 | nohup busybox httpd -f -p "${server_port}" & 5 | -------------------------------------------------------------------------------- /code/12-if-statements-example/modules/services/webserver-cluster/user-data.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cat > index.html <Hello, World 5 |

DB address: ${db_address}

6 |

DB port: ${db_port}

7 | EOF 8 | 9 | nohup busybox httpd -f -p "${server_port}" & 10 | -------------------------------------------------------------------------------- /code/12-if-statements-example/modules/services/webserver-cluster/vars.tf: -------------------------------------------------------------------------------- 1 | # Input variable: server port 2 | variable "server_port" { 3 | description = "The port the server will use for HTTP requests" 4 | default = "8080" 5 | } 6 | 7 | # Input variable: Cluster name 8 | variable "cluster_name" { 9 | description = "The name to use for all the cluster resources" 10 | } 11 | 12 | # Input variable: DB remote state bucket name 13 | variable "db_remote_state_bucket" { 14 | description = "The name of the S3 bucket for the database's remote state" 15 | } 16 | 17 | # Input variable: DB remote state bucket key 18 | variable "db_remote_state_key" { 19 | description = "The path for database's remote state in S3" 20 | } 21 | 22 | # Input variable: Instance type 23 | variable "instance_type" { 24 | description = "The type of EC2 Instances to run (e.g. t2.micro)" 25 | } 26 | 27 | # Input variable: Instance min size 28 | variable "min_size" { 29 | description = "The minimum number of EC2 Instances in the ASG" 30 | } 31 | 32 | # Input variable: Instance max size 33 | variable "max_size" { 34 | description = "The maximum number of EC2 Instances in the ASG" 35 | } 36 | 37 | # Input variable: Enable Autoscaling 38 | variable "enable_autoscaling" { 39 | description = "If set to true, enable autoscaling" 40 | 41 | } 42 | 43 | # Input variable: Enable new user data 44 | variable "enable_new_user_data" { 45 | description = "If set to true, use the new User Data script" 46 | } 47 | -------------------------------------------------------------------------------- /code/13-if-else-statements-example/README.md: -------------------------------------------------------------------------------- 1 | # Terraform Simple If-Else-Statement example 2 | 3 | This folder contains the simple If-Else-Statement example of a [Terraform](https://www.terraform.io/) file on AWS (Amazon Web Services). 4 | 5 | It shows how do a simple If-Else-Statement in Terraform. 6 | 7 | This Terraform file create 3 IAM users, create an IAM policy and attach the IAM policy to the IAM users. 8 | 9 | We use the meta-parameter "count" and two interpolation functions: 10 | 11 | * "${element(LIST, INDEX)}" 12 | * "${length(LIST)}" 13 | 14 | We use "give_neo_cloudwatch_full_access" variable in order to give one of the users, neo, access to CloudWatch: 15 | 16 | * "give_neo_cloudwatch_full_access" = 0 -> "cloudwatch_read_only" 17 | * "give_neo_cloudwatch_full_access" = 1 -> "cloudwatch_full_access" 18 | 19 | ## Requirements 20 | 21 | * You must have [Terraform](https://www.terraform.io/) installed on your computer. 22 | * You must have an [AWS (Amazon Web Services)](http://aws.amazon.com/) account. 23 | * It uses the Terraform AWS Provider that interacts with the many resources supported by AWS through its APIs. 24 | * This code was written for Terraform 0.10.x. 25 | 26 | ## Using the code 27 | 28 | * Configure your AWS access keys. 29 | 30 | **Important:** For security, it is strongly recommend that you use IAM users instead of the root account for AWS access. 31 | 32 | Setting your credentials for use by Terraform can be done in a number of ways, but here are the recommended approaches: 33 | 34 | * The default credentials file 35 | 36 | Set credentials in the AWS credentials profile file on your local system, located at: 37 | 38 | `~/.aws/credentials` on Linux, macOS, or Unix 39 | 40 | `C:\Users\USERNAME\.aws\credentials` on Windows 41 | 42 | This file should contain lines in the following format: 43 | 44 | ```bash 45 | [default] 46 | aws_access_key_id = 47 | aws_secret_access_key = 48 | ``` 49 | Substitute your own AWS credentials values for the values `` and ``. 50 | 51 | * Environment variables `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` 52 | 53 | Set the `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` environment variables. 54 | 55 | To set these variables on Linux, macOS, or Unix, use `export`: 56 | 57 | ```bash 58 | export AWS_ACCESS_KEY_ID= 59 | export AWS_SECRET_ACCESS_KEY= 60 | ``` 61 | 62 | To set these variables on Windows, use `set`: 63 | 64 | ```bash 65 | set AWS_ACCESS_KEY_ID= 66 | set AWS_SECRET_ACCESS_KEY= 67 | ``` 68 | 69 | * Initialize working directory. 70 | 71 | The first command that should be run after writing a new Terraform configuration is the `terraform init` command in order to initialize a working directory containing Terraform configuration files. It is safe to run this command multiple times. 72 | 73 | ```bash 74 | terraform init 75 | ``` 76 | 77 | * Validate the changes. 78 | 79 | Run command: 80 | 81 | ```bash 82 | terraform plan 83 | ``` 84 | 85 | * Deploy the changes. 86 | 87 | Run command: 88 | 89 | ```bash 90 | terraform apply 91 | ``` 92 | 93 | * Test the deployment. 94 | 95 | You should see 3 IAM users, an IAM policy and the IAM policy attached to the IAM users. 96 | 97 | * Clean up the resources created. 98 | 99 | When you have finished, run command: 100 | 101 | ```bash 102 | terraform destroy 103 | ``` -------------------------------------------------------------------------------- /code/13-if-else-statements-example/main.tf: -------------------------------------------------------------------------------- 1 | # Configure the AWS provider 2 | provider "aws" { 3 | region = "eu-west-1" 4 | 5 | } 6 | 7 | # Create an IAM user 8 | resource "aws_iam_user" "example" { 9 | count = "${length(var.user_names)}" 10 | name = "${element(var.user_names, count.index)}" 11 | 12 | } 13 | 14 | # Data source: IAM policy document 15 | data "aws_iam_policy_document" "ec2_read_only" { 16 | statement { 17 | effect = "Allow" 18 | actions = ["ec2:Describe*"] 19 | resources = ["*"] 20 | } 21 | } 22 | 23 | # Create an IAM policy 24 | resource "aws_iam_policy" "ec2_read_only" { 25 | name = "ec2-read-only" 26 | policy = "${data.aws_iam_policy_document.ec2_read_only.json}" 27 | } 28 | 29 | # Create an IAM user policy attachement 30 | resource "aws_iam_user_policy_attachment" "ec2_access" { 31 | count = "${length(var.user_names)}" 32 | user = "${element(aws_iam_user.example.*.name, count.index)}" 33 | policy_arn = "${aws_iam_policy.ec2_read_only.arn}" 34 | } 35 | 36 | # Create an IAM policy 37 | resource "aws_iam_policy" "cloudwatch_read_only" { 38 | name = "cloudwatch-read-only" 39 | policy = "${data.aws_iam_policy_document.cloudwatch_read_only.json}" 40 | } 41 | 42 | # Data source: IAM policy document 43 | data "aws_iam_policy_document" "cloudwatch_read_only" { 44 | statement { 45 | effect = "Allow" 46 | actions = ["cloudwatch:Describe*", "cloudwatch:Get*", "cloudwatch:List*"] 47 | resources = ["*"] 48 | } 49 | } 50 | 51 | # Create an IAM policy 52 | resource "aws_iam_policy" "cloudwatch_full_access" { 53 | name = "cloudwatch-full-access" 54 | policy = "${data.aws_iam_policy_document.cloudwatch_full_access.json}" 55 | } 56 | 57 | # Data source: IAM policy document 58 | data "aws_iam_policy_document" "cloudwatch_full_access" { 59 | statement { 60 | effect = "Allow" 61 | actions = ["cloudwatch:*"] 62 | resources = ["*"] 63 | } 64 | } 65 | 66 | # Create an IAM user policy attachement 67 | resource "aws_iam_user_policy_attachment" "neo_cloud_watch_full_access" { 68 | count = "${var.give_neo_cloudwatch_full_access}" 69 | 70 | user = "${aws_iam_user.example.0.name}" 71 | policy_arn = "${aws_iam_policy.cloudwatch_full_access.arn}" 72 | } 73 | 74 | # Create an IAM user policy attachement 75 | resource "aws_iam_user_policy_attachment" "neo_cloud_watch_read_only" { 76 | count = "${1 - var.give_neo_cloudwatch_full_access}" 77 | 78 | user = "${aws_iam_user.example.0.name}" 79 | policy_arn = "${aws_iam_policy.cloudwatch_read_only.arn}" 80 | } 81 | -------------------------------------------------------------------------------- /code/13-if-else-statements-example/outputs.tf: -------------------------------------------------------------------------------- 1 | # Output variable: ARN 2 | output "neo_arn" { 3 | value = ["${aws_iam_user.example.*.arn}"] 4 | } 5 | -------------------------------------------------------------------------------- /code/13-if-else-statements-example/vars.tf: -------------------------------------------------------------------------------- 1 | # Input variable: user names 2 | variable "user_names" { 3 | description = "Create IAM users with these names" 4 | type = "list" 5 | default = ["neo", "trinity", "morpheus"] 6 | } 7 | 8 | # Input variable: give neo cloudwatch full access 9 | variable "give_neo_cloudwatch_full_access" { 10 | description = "If true, neo gets full access to CloudWatch" 11 | } 12 | -------------------------------------------------------------------------------- /code/14-zero-downtime-deployment/README.md: -------------------------------------------------------------------------------- 1 | # Terraform Zero-Downtime Deployment example 2 | 3 | This folder contains a zero-downtime deployment example of a [Terraform](https://www.terraform.io/) installed on your computer file on AWS (Amazon Web Services). 4 | 5 | It shows how to deploy a new AMI across the cluster when you have made changes to your code. In addition, you control the text the User Data script return from its one-liner HTTP server. 6 | 7 | Furthermore, it shows how to develop (not duplicating code) web server clusters in different environments using a module. 8 | 9 | The environments are: 10 | 11 | * Staging (stage) 12 | * Production (prod) 13 | 14 | This is the file layout in this repo: 15 | 16 | ```bash 17 | live 18 | ├── global 19 | │ └── s3/ 20 | │ ├── main.tf 21 | │ └── (etc) 22 | │ 23 | ├── stage 24 | │ ├── services/ 25 | │ │ └── webserver-cluster/ 26 | │ │ ├── main.tf 27 | │ │ └── (etc) 28 | │ └── data-stores/ 29 | │ └── mysql/ 30 | │ ├── main.tf 31 | │ └── (etc) 32 | │ 33 | └── prod 34 | ├── services/ 35 | │ └── webserver-cluster/ 36 | │ ├── main.tf 37 | │ └── (etc) 38 | └── data-stores/ 39 | └── mysql/ 40 | ├── main.tf 41 | └── (etc) 42 | 43 | modules 44 | └── services/ 45 | └── webserver-cluster/ 46 | ├── main.tf 47 | └── (etc) 48 | ``` 49 | 50 | It uses in common for both environments: 51 | 52 | * Terraform Remote State example: [live/global/s3](live/global/s3) 53 | * Terraform Web Server Cluster module example: [modules/services/webserver-cluster](modules/services/webserver-cluster) 54 | 55 | It uses for staging environment: 56 | 57 | * Terraform MySQL on RDS example (staging environment): [live/stage/data-stores/mysql](live/stage/data-stores/mysql) 58 | * Terraform Web Server Cluster example (staging environment): [live/stage/services/webserver-cluster](live/stage/services/webserver-cluster) 59 | 60 | It uses for production environment: 61 | 62 | * Terraform MySQL on RDS example (production environment): [live/prod/data-stores/mysql](live/prod/data-stores/mysql) 63 | * Terraform Web Server Cluster example (production environment): [live/prod/services/webserver-cluster](live/prod/services/webserver-cluster) 64 | 65 | ## Requirements 66 | 67 | * You must have [Terraform](https://www.terraform.io/) installed on your computer. 68 | * You must have an [AWS (Amazon Web Services)](http://aws.amazon.com/) account. 69 | * It uses the Terraform AWS Provider that interacts with the many resources supported by AWS through its APIs. 70 | * This code was written for Terraform 0.10.x. 71 | 72 | ## Using the code 73 | 74 | Configure your AWS access keys. 75 | 76 | Use Terraform Remote State example for creating the remote state bucket. See: [live/global/s3](live/global/s3) 77 | 78 | Use Terraform module example for Web Server Cluster example in the staging environment and Web Server Cluster example in the production environment. See: [modules/services/webserver-cluster](modules/services/webserver-cluster) 79 | 80 | Use Terraform MySQL on RDS example for creating a MySQL database in the staging environment. See: [live/stage/data-stores/mysql](live/stage/data-stores/mysql) 81 | 82 | Use Terraform Web Server Cluster example for creating a web server cluster in the staging environment. See: [live/stage/services/webserver-cluster](live/stage/services/webserver-cluster) 83 | 84 | Use Terraform MySQL on RDS example for creating a MySQL database in the production environment. See: [live/prod/data-stores/mysql](live/prod/data-stores/mysql) 85 | 86 | Use Terraform Web Server Cluster example for creating a web server cluster in the production environment. See: [live/prod/services/webserver-cluster](live/prod/services/webserver-cluster) 87 | -------------------------------------------------------------------------------- /code/14-zero-downtime-deployment/live/global/s3/README.md: -------------------------------------------------------------------------------- 1 | # Terraform Remote State example 2 | 3 | This folder contains an example of a Terraform file [Terraform](https://www.terraform.io/) that create a S3 bucket that can be used for remote state storage. 4 | 5 | This Terraform file deploys the creation a of a bucket on AWS (Amazon Web Services) using S3. 6 | 7 | ## Requirements 8 | 9 | * You must have [Terraform](https://www.terraform.io/) installed on your computer. 10 | * You must have an [AWS (Amazon Web Services)](http://aws.amazon.com/) account. 11 | * It uses the Terraform AWS Provider that interacts with the many resources supported by AWS through its APIs. 12 | * This code was written for Terraform 0.10.x. 13 | 14 | ## Using the code 15 | 16 | * Configure your AWS access keys. 17 | 18 | * Initialize working directory. 19 | 20 | The first command that should be run after writing a new Terraform configuration is the `terraform init` command in order to initialize a working directory containing Terraform configuration files. It is safe to run this command multiple times. 21 | 22 | ```bash 23 | terraform init 24 | ``` 25 | 26 | * Modify configuration. 27 | 28 | You must modify the S3 bucket name, which is defined as an input variable `bucket_name` in `vars.tf` file. 29 | 30 | You can modify the S3 bucket name in several ways: 31 | 32 | * Loading variables from command line flags. 33 | 34 | Run Terraform commands in this way: 35 | 36 | ```bash 37 | terraform plan -var 'bucket_name=' 38 | ``` 39 | 40 | ```bash 41 | terraform apply -var 'bucket_name=' 42 | ``` 43 | 44 | * Loading variables from a file. 45 | 46 | When Terraform runs it will look for a file called `terraform.tfvars`. You can populate this file with variable values that will be loaded when Terraform runs. An example for the content of the `terraform.tfvars` file: 47 | 48 | ```bash 49 | bucket_name = "" 50 | ``` 51 | 52 | * Loading variables from environment variables. 53 | 54 | Terraform will also parse any environment variables that are prefixed with `TF_VAR`. You can create an environment variable `TF_VAR_bucket_name`: 55 | 56 | ```bash 57 | TF_VAR_bucket_name= 58 | ``` 59 | 60 | * Variable defaults. 61 | 62 | Change the value of the `default` attribute of `bucket_name` input variable in `vars.tf` file. 63 | 64 | ```hcl 65 | variable "bucket_name" { 66 | description = "The name of the S3 bucket. Must be globally unique." 67 | default = "" 68 | } 69 | ``` 70 | 71 | * Validate the changes. 72 | 73 | Run command: 74 | 75 | ```bash 76 | terraform plan 77 | ``` 78 | 79 | * Deploy the changes. 80 | 81 | Run command: 82 | 83 | ```bash 84 | terraform apply 85 | ``` 86 | 87 | * Clean up the resources created. 88 | 89 | When you have finished, run command: 90 | 91 | ```bash 92 | terraform destroy 93 | ``` -------------------------------------------------------------------------------- /code/14-zero-downtime-deployment/live/global/s3/main.tf: -------------------------------------------------------------------------------- 1 | # Configure the AWS provider 2 | provider "aws" { 3 | region = "eu-west-1" 4 | } 5 | 6 | # Create a S3 bucket 7 | resource "aws_s3_bucket" "terraform_state" { 8 | bucket = "${var.bucket_name}" 9 | 10 | versioning { 11 | enabled = true 12 | } 13 | 14 | lifecycle { 15 | prevent_destroy = true 16 | } 17 | } 18 | 19 | -------------------------------------------------------------------------------- /code/14-zero-downtime-deployment/live/global/s3/outputs.tf: -------------------------------------------------------------------------------- 1 | # Output variable: S3 bucket 2 | output "s3_bucket_arn" { 3 | value = "${aws_s3_bucket.terraform_state.arn}" 4 | } 5 | -------------------------------------------------------------------------------- /code/14-zero-downtime-deployment/live/global/s3/vars.tf: -------------------------------------------------------------------------------- 1 | # Input variable: S3 bucket name 2 | variable "bucket_name" { 3 | description = "The name of the S3 bucket. Must be globally unique." 4 | default = "terraform-state-my-bucket" 5 | } 6 | -------------------------------------------------------------------------------- /code/14-zero-downtime-deployment/live/prod/data-stores/mysql/README.md: -------------------------------------------------------------------------------- 1 | # Terraform MySQL on RDS example (production environment) 2 | 3 | This folder contains a MySQL on RDS example of a Terraform file [Terraform](https://www.terraform.io/). 4 | 5 | This Terraform file deploys a MySQL database using RDS on AWS (Amazon Web Services). 6 | 7 | ## Requirements 8 | 9 | * You must have [Terraform](https://www.terraform.io/) installed on your computer. 10 | * You must have an [AWS (Amazon Web Services)](http://aws.amazon.com/) account. 11 | * It uses the Terraform AWS Provider that interacts with the many resources supported by AWS through its APIs. 12 | * This code was written for Terraform 0.10.x. 13 | 14 | ## Using the code 15 | 16 | * Configure your AWS access keys. 17 | 18 | * Initialize working directory. 19 | 20 | The first command that should be run after writing a new Terraform configuration is the `terraform init` command in order to initialize a working directory containing Terraform configuration files. It is safe to run this command multiple times. 21 | 22 | ```bash 23 | terraform init 24 | ``` 25 | 26 | * Configure Terraform backend. 27 | 28 | Modify the S3 bucket name, which is defined in the `bucket` attribute in `backend.tf` file. 29 | 30 | ```bash 31 | bucket = "" 32 | ``` 33 | 34 | * Configure database password. 35 | 36 | The database password is managed by the `db_password` input variable. 37 | 38 | Terraform will parse any environment variables that are prefixed with `TF_VAR`. You must create an environment variable `TF_VAR_db_password`: 39 | 40 | ```bash 41 | TF_VAR_db_password= 42 | ``` 43 | 44 | * Validate the changes. 45 | 46 | Run command: 47 | 48 | ```bash 49 | terraform plan 50 | ``` 51 | 52 | * Deploy the changes. 53 | 54 | Run command: 55 | 56 | ```bash 57 | terraform apply 58 | ``` 59 | 60 | * Test the deploy. 61 | 62 | You should see a new RDS MySQL database on AWS (Amazon Web Services). 63 | 64 | * Clean up the resources created. 65 | 66 | When you have finished, run command: 67 | 68 | ```bash 69 | terraform destroy 70 | ``` -------------------------------------------------------------------------------- /code/14-zero-downtime-deployment/live/prod/data-stores/mysql/backend.tf: -------------------------------------------------------------------------------- 1 | # Define Terraform backend using a S3 bucket for storing the Terraform state 2 | terraform { 3 | backend "s3" { 4 | bucket = "terraform-state-my-bucket" 5 | key = "zero-downtime-deployment-example/live/prod/data-stores/mysql/terraform.tfstate" 6 | region = "eu-west-1" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /code/14-zero-downtime-deployment/live/prod/data-stores/mysql/main.tf: -------------------------------------------------------------------------------- 1 | # Configure the AWS provider 2 | provider "aws" { 3 | region = "eu-west-1" 4 | } 5 | 6 | # Create a DB instance 7 | resource "aws_db_instance" "example" { 8 | engine = "mysql" 9 | allocated_storage = 10 10 | instance_class = "db.t2.micro" 11 | name = "example_database_prod" 12 | username = "admin" 13 | password = "${var.db_password}" 14 | skip_final_snapshot = true 15 | } 16 | -------------------------------------------------------------------------------- /code/14-zero-downtime-deployment/live/prod/data-stores/mysql/outputs.tf: -------------------------------------------------------------------------------- 1 | # Output variable: DB instance address 2 | output "address" { 3 | value = "${aws_db_instance.example.address}" 4 | } 5 | 6 | # Output variable: DB instance port 7 | output "port" { 8 | value = "${aws_db_instance.example.port}" 9 | } 10 | -------------------------------------------------------------------------------- /code/14-zero-downtime-deployment/live/prod/data-stores/mysql/vars.tf: -------------------------------------------------------------------------------- 1 | # Input variable: DB password 2 | variable "db_password" { 3 | description = "The password for the database" 4 | } 5 | -------------------------------------------------------------------------------- /code/14-zero-downtime-deployment/live/prod/services/webserver-cluster/README.md: -------------------------------------------------------------------------------- 1 | # Terraform Web Server Cluster example (production environment) 2 | 3 | This folder contains a Web Server Cluster example of a Terraform file [Terraform](https://www.terraform.io/). 4 | 5 | This Terraform file deploys a cluster of web servers on AWS (Amazon Web Services) using EC2 and Auto Scaling, and a load balancer using ELB. 6 | 7 | The cluster of web servers returns "Hello, World" for the URL `/`. The load balancer listens on port 80. 8 | 9 | ## Requirements 10 | 11 | * You must have [Terraform](https://www.terraform.io/) installed on your computer. 12 | * You must have an [AWS (Amazon Web Services)](http://aws.amazon.com/) account. 13 | * It uses the Terraform AWS Provider that interacts with the many resources supported by AWS through its APIs. 14 | * This code was written for Terraform 0.10.x. 15 | * You must deploy the MySQL database in [data-stores/mysql](../../data-stores/mysql) BEFORE deploying the 16 | templates in this folder. 17 | * This uses a Terraform module. See [modules/services/webserver-cluster](../../../../modules/services/webserver-cluster). 18 | 19 | ## Using the code 20 | 21 | * Configure your AWS access keys. 22 | 23 | * Initialize working directory. 24 | 25 | The first command that should be run after writing a new Terraform configuration is the `terraform init` command in order to initialize a working directory containing Terraform configuration files. It is safe to run this command multiple times. 26 | 27 | ```bash 28 | terraform init 29 | ``` 30 | 31 | * Configure Terraform backend. 32 | 33 | Modify the S3 bucket name, which is defined in the `bucket` attribute in `backend.tf` file. 34 | 35 | ```bash 36 | bucket = "" 37 | ``` 38 | 39 | * Configure the bucket used for the database's remote state storage. 40 | 41 | Modify the S3 bucket name which is defined in the `bucket` attribute in `vars.tf` file. Important! You must deploy the templates in [data-stores/mysql](../../data-stores/mysql) first: 42 | 43 | ```hcl 44 | variable "db_remote_state_bucket" { 45 | description = "The name of the S3 bucket used for the database's remote state storage" 46 | default = "" 47 | } 48 | ``` 49 | 50 | * Input variables than manage AMI and text the User Data script return. 51 | 52 | There are two input variables defined in `vars.tf` file in Module in order to manage AMI and text the User Data script return: 53 | 54 | ```hcl 55 | variable "ami" { 56 | description = "The AMI to run in the cluster" 57 | default = "ami-785db401" 58 | } 59 | 60 | variable "server_text" { 61 | description = "The text the web server should return" 62 | default = "Hello, World" 63 | } 64 | ``` 65 | 66 | This deploy configure both variables: 67 | 68 | ```hcl 69 | ami = "ami-785db401" 70 | server_text = "Hello, World" 71 | ``` 72 | 73 | * Validate the changes. 74 | 75 | Run command: 76 | 77 | ```bash 78 | terraform plan 79 | ``` 80 | 81 | * Deploy the changes. 82 | 83 | Run command: 84 | 85 | ```bash 86 | terraform apply 87 | ``` 88 | 89 | * Test the cluster of web servers. 90 | 91 | Test the cluster of web servers. When the `apply` command completes, it will output the DNS name of the load balancer. 92 | 93 | ```bash 94 | curl http:/// 95 | ``` 96 | 97 | * Clean up the resources created. 98 | 99 | When you have finished, run command: 100 | 101 | ```bash 102 | terraform destroy 103 | ``` -------------------------------------------------------------------------------- /code/14-zero-downtime-deployment/live/prod/services/webserver-cluster/backend.tf: -------------------------------------------------------------------------------- 1 | # Define Terraform backend using a S3 bucket for storing the Terraform state 2 | terraform { 3 | backend "s3" { 4 | bucket = "terraform-state-my-bucket" 5 | key = "zero-downtime-deployment-example/live/prod/services/webserver-cluster/terraform.tfstate" 6 | region = "eu-west-1" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /code/14-zero-downtime-deployment/live/prod/services/webserver-cluster/main.tf: -------------------------------------------------------------------------------- 1 | # Configure the AWS provider 2 | provider "aws" { 3 | region = "eu-west-1" 4 | } 5 | 6 | # Use Module 7 | module "webserver_cluster" { 8 | source = "../../../../modules/services/webserver-cluster" 9 | 10 | ami = "ami-785db401" 11 | server_text = "Hello, World" 12 | 13 | cluster_name = "werservers-prod" 14 | db_remote_state_bucket = "${var.db_remote_state_bucket}" 15 | db_remote_state_key = "${var.db_remote_state_key}" 16 | 17 | instance_type = "t2.micro" 18 | min_size = 2 19 | max_size = 10 20 | enable_autoscaling = true 21 | } 22 | -------------------------------------------------------------------------------- /code/14-zero-downtime-deployment/live/prod/services/webserver-cluster/outputs.tf: -------------------------------------------------------------------------------- 1 | # Output variable: DNS Name of ELB 2 | output "elb_dns_name" { 3 | value = "${module.webserver_cluster.elb_dns_name}" 4 | } 5 | -------------------------------------------------------------------------------- /code/14-zero-downtime-deployment/live/prod/services/webserver-cluster/vars.tf: -------------------------------------------------------------------------------- 1 | # Input variable: DB remote state bucket name 2 | variable "db_remote_state_bucket" { 3 | description = "The name of the S3 bucket for the database's remote state" 4 | default = "terraform-state-afb" 5 | } 6 | 7 | # Input variable: DB remote state bucket key 8 | variable "db_remote_state_key" { 9 | description = "The path for database's remote state in S3" 10 | default = "zero-downtime-deployment-example/live/prod/services/webserver-cluster/terraform.tfstate" 11 | } 12 | -------------------------------------------------------------------------------- /code/14-zero-downtime-deployment/live/stage/data-stores/mysql/README.md: -------------------------------------------------------------------------------- 1 | # Terraform MySQL on RDS example (staging environment) 2 | 3 | This folder contains a MySQL on RDS example of a Terraform file [Terraform](https://www.terraform.io/). 4 | 5 | This Terraform file deploys a MySQL database using RDS on AWS (Amazon Web Services) 6 | 7 | ## Requirements 8 | 9 | * You must have [Terraform](https://www.terraform.io/) installed on your computer. 10 | * You must have an [AWS (Amazon Web Services)](http://aws.amazon.com/) account. 11 | * It uses the Terraform AWS Provider that interacts with the many resources supported by AWS through its APIs. 12 | * This code was written for Terraform 0.10.x. 13 | 14 | ## Using the code 15 | 16 | * Configure your AWS access keys. 17 | 18 | * Initialize working directory. 19 | 20 | The first command that should be run after writing a new Terraform configuration is the `terraform init` command in order to initialize a working directory containing Terraform configuration files. It is safe to run this command multiple times. 21 | 22 | ```bash 23 | terraform init 24 | ``` 25 | 26 | * Configure Terraform backend. 27 | 28 | Modify the S3 bucket name, which is defined in the `bucket` attribute in `backend.tf` file. 29 | 30 | ```bash 31 | bucket = "" 32 | ``` 33 | 34 | * Configure database password. 35 | 36 | The database password is managed by the `db_password` input variable. 37 | 38 | Terraform will parse any environment variables that are prefixed with `TF_VAR`. You must create an environment variable `TF_VAR_db_password`: 39 | 40 | ```bash 41 | TF_VAR_db_password= 42 | ``` 43 | 44 | * Validate the changes. 45 | 46 | Run command: 47 | 48 | ```bash 49 | terraform plan 50 | ``` 51 | 52 | * Deploy the changes. 53 | 54 | Run command: 55 | 56 | ```bash 57 | terraform apply 58 | ``` 59 | 60 | * Test the deploy. 61 | 62 | You should see a new RDS MySQL database on AWS (Amazon Web Services). 63 | 64 | * Clean up the resources created. 65 | 66 | When you have finished, run command: 67 | 68 | ```bash 69 | terraform destroy 70 | ``` -------------------------------------------------------------------------------- /code/14-zero-downtime-deployment/live/stage/data-stores/mysql/backend.tf: -------------------------------------------------------------------------------- 1 | # Define Terraform backend using a S3 bucket for storing the Terraform state 2 | terraform { 3 | backend "s3" { 4 | bucket = "terraform-state-my-bucket" 5 | key = "zero-downtime-deployment-example/live/stage/data-stores/mysql/terraform.tfstate" 6 | region = "eu-west-1" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /code/14-zero-downtime-deployment/live/stage/data-stores/mysql/main.tf: -------------------------------------------------------------------------------- 1 | # Configure the AWS provider 2 | provider "aws" { 3 | region = "eu-west-1" 4 | } 5 | 6 | # Create a DB instance 7 | resource "aws_db_instance" "example" { 8 | engine = "mysql" 9 | allocated_storage = 10 10 | instance_class = "db.t2.micro" 11 | name = "example_database_stage" 12 | username = "admin" 13 | password = "${var.db_password}" 14 | skip_final_snapshot = true 15 | } 16 | -------------------------------------------------------------------------------- /code/14-zero-downtime-deployment/live/stage/data-stores/mysql/outputs.tf: -------------------------------------------------------------------------------- 1 | # Output variable: DB instance address 2 | output "address" { 3 | value = "${aws_db_instance.example.address}" 4 | } 5 | 6 | # Output variable: DB instance port 7 | output "port" { 8 | value = "${aws_db_instance.example.port}" 9 | } 10 | -------------------------------------------------------------------------------- /code/14-zero-downtime-deployment/live/stage/data-stores/mysql/vars.tf: -------------------------------------------------------------------------------- 1 | # Input variable: DB password 2 | variable "db_password" { 3 | description = "The password for the database" 4 | } 5 | -------------------------------------------------------------------------------- /code/14-zero-downtime-deployment/live/stage/services/webserver-cluster/README.md: -------------------------------------------------------------------------------- 1 | # Terraform Web Server Cluster example (staging environment) 2 | 3 | This folder contains a Web Server Cluster example of a Terraform file [Terraform](https://www.terraform.io/). 4 | 5 | This Terraform file deploys a cluster of web servers on AWS (Amazon Web Services) using EC2 and Auto Scaling, and a load balancer using ELB. 6 | 7 | The cluster of web servers returns "Hello, World" for the URL `/`. The load balancer listens on port 80. 8 | 9 | ## Requirements 10 | 11 | * You must have [Terraform](https://www.terraform.io/) installed on your computer. 12 | * You must have an [AWS (Amazon Web Services)](http://aws.amazon.com/) account. 13 | * It uses the Terraform AWS Provider that interacts with the many resources supported by AWS through its APIs. 14 | * This code was written for Terraform 0.10.x. 15 | * You must deploy the MySQL database in [data-stores/mysql](../../data-stores/mysql) BEFORE deploying the 16 | templates in this folder. 17 | * This uses a Terraform module. See [modules/services/webserver-cluster](../../../../modules/services/webserver-cluster). 18 | 19 | ## Using the code 20 | 21 | * Configure your AWS access keys. 22 | 23 | * Initialize working directory. 24 | 25 | The first command that should be run after writing a new Terraform configuration is the `terraform init` command in order to initialize a working directory containing Terraform configuration files. It is safe to run this command multiple times. 26 | 27 | ```bash 28 | terraform init 29 | ``` 30 | 31 | * Configure Terraform backend. 32 | 33 | Modify the S3 bucket name, which is defined in the `bucket` attribute in `backend.tf` file. 34 | 35 | ```bash 36 | bucket = "" 37 | ``` 38 | 39 | * Configure the bucket used for the database's remote state storage. 40 | 41 | Modify the S3 bucket name which is defined in the `bucket` attribute in `vars.tf` file. Important! You must deploy the templates in [data-stores/mysql](../../data-stores/mysql) first: 42 | 43 | ```hcl 44 | variable "db_remote_state_bucket" { 45 | description = "The name of the S3 bucket used for the database's remote state storage" 46 | default = "" 47 | } 48 | ``` 49 | 50 | * Input variables than manage AMI and text the User Data script return. 51 | 52 | There are two input variables defined in `vars.tf` file in Module in order to manage AMI and text the User Data script return: 53 | 54 | ```hcl 55 | variable "ami" { 56 | description = "The AMI to run in the cluster" 57 | default = "ami-785db401" 58 | } 59 | 60 | variable "server_text" { 61 | description = "The text the web server should return" 62 | default = "Hello, World" 63 | } 64 | ``` 65 | 66 | This deploy configure both variables: 67 | 68 | ```hcl 69 | ami = "ami-785db401" 70 | server_text = "New server text" 71 | ``` 72 | 73 | * Validate the changes. 74 | 75 | Run command: 76 | 77 | ```bash 78 | terraform plan 79 | ``` 80 | 81 | * Deploy the changes. 82 | 83 | Run command: 84 | 85 | ```bash 86 | terraform apply 87 | ``` 88 | 89 | * Test the cluster of web servers. 90 | 91 | Test the cluster of web servers. When the `apply` command completes, it will output the DNS name of the load balancer. 92 | 93 | ```bash 94 | curl http:/// 95 | ``` 96 | 97 | * Clean up the resources created. 98 | 99 | When you have finished, run command: 100 | 101 | ```bash 102 | terraform destroy 103 | ``` -------------------------------------------------------------------------------- /code/14-zero-downtime-deployment/live/stage/services/webserver-cluster/backend.tf: -------------------------------------------------------------------------------- 1 | # Define Terraform backend using a S3 bucket for storing the Terraform state 2 | terraform { 3 | backend "s3" { 4 | bucket = "terraform-state-my-bucket" 5 | key = "zero-downtime-deployment-example/live/stage/services/webserver-cluster/terraform.tfstate" 6 | region = "eu-west-1" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /code/14-zero-downtime-deployment/live/stage/services/webserver-cluster/main.tf: -------------------------------------------------------------------------------- 1 | # Configure the AWS provider 2 | provider "aws" { 3 | region = "eu-west-1" 4 | } 5 | 6 | # Use Module 7 | module "webserver_cluster" { 8 | source = "../../../../modules/services/webserver-cluster" 9 | 10 | ami = "ami-785db401" 11 | server_text = "New server text" 12 | 13 | cluster_name = "werservers-stage" 14 | db_remote_state_bucket = "${var.db_remote_state_bucket}" 15 | db_remote_state_key = "${var.db_remote_state_key}" 16 | 17 | instance_type = "t2.micro" 18 | min_size = 2 19 | max_size = 2 20 | enable_autoscaling = false 21 | } 22 | 23 | # Create a Security Group Rule 24 | resource "aws_security_group_rule" "allow_testing_inbound" { 25 | type = "ingress" 26 | security_group_id = "${module.webserver_cluster.elb_security_group_id}" 27 | 28 | from_port = 12345 29 | to_port = 12345 30 | protocol = "tcp" 31 | cidr_blocks = ["0.0.0.0/0"] 32 | } 33 | -------------------------------------------------------------------------------- /code/14-zero-downtime-deployment/live/stage/services/webserver-cluster/outputs.tf: -------------------------------------------------------------------------------- 1 | # Output variable: DNS Name of ELB 2 | output "elb_dns_name" { 3 | value = "${module.webserver_cluster.elb_dns_name}" 4 | } 5 | -------------------------------------------------------------------------------- /code/14-zero-downtime-deployment/live/stage/services/webserver-cluster/vars.tf: -------------------------------------------------------------------------------- 1 | # Input variable: DB remote state bucket name 2 | variable "db_remote_state_bucket" { 3 | description = "The name of the S3 bucket for the database's remote state" 4 | default = "terraform-state-afb" 5 | } 6 | 7 | # Input variable: DB remote state bucket key 8 | variable "db_remote_state_key" { 9 | description = "The path for database's remote state in S3" 10 | default = "zero-downtime-deployment-example/live/stage/services/webserver-cluster/terraform.tfstate" 11 | } 12 | -------------------------------------------------------------------------------- /code/14-zero-downtime-deployment/modules/services/webserver-cluster/README.md: -------------------------------------------------------------------------------- 1 | # Terraform Web Server Cluster module example 2 | 3 | This folder contains a Web Server Cluster module example of a Terraform file [Terraform](https://www.terraform.io/). 4 | 5 | This Terraform file define a cluster of web servers module on AWS (Amazon Web Services) using EC2 and Auto Scaling, and a load balancer using ELB. 6 | 7 | The cluster of web servers returns "Hello, World" for the URL `/`. The load balancer listens on port 80. 8 | 9 | ## Requirements 10 | 11 | * You must have [Terraform](https://www.terraform.io/) installed on your computer. 12 | * You must have an [AWS (Amazon Web Services)](http://aws.amazon.com/) account. 13 | * It uses the Terraform AWS Provider that interacts with the many resources supported by AWS through its APIs. 14 | * This code was written for Terraform 0.10.x. 15 | 16 | ## Using the code 17 | 18 | Terraform modules are not meant to be deployed directly. Instead, you should be using them from other templates. See [live/stage/services/webserver-cluster](../../../live/stage/services-webserver-cluster) and [live/prod/services/webserver-cluster](../../../live/prod/services-webserver-cluster) for examples. 19 | 20 | * Input variables than manage AMI and text the User Data script return. 21 | 22 | There are two input variables defined in `vars.tf` file in this Module in order to manage AMI and text the User Data script return: 23 | 24 | ```hcl 25 | variable "ami" { 26 | description = "The AMI to run in the cluster" 27 | default = "ami-785db401" 28 | } 29 | 30 | variable "server_text" { 31 | description = "The text the web server should return" 32 | default = "Hello, World" 33 | } 34 | ``` 35 | 36 | These are used by the templates in [live/stage/services/webserver-cluster](../../../live/stage/services-webserver-cluster) and [live/prod/services/webserver-cluster](../../../live/prod/services-webserver-cluster). -------------------------------------------------------------------------------- /code/14-zero-downtime-deployment/modules/services/webserver-cluster/main.tf: -------------------------------------------------------------------------------- 1 | # Data source: query the list of availability zones 2 | data "aws_availability_zones" "all" {} 3 | 4 | # Data source: DB remote state 5 | data "terraform_remote_state" "db" { 6 | backend = "s3" 7 | 8 | config { 9 | bucket = "${var.db_remote_state_bucket}" 10 | key = "${var.db_remote_state_key}" 11 | region = "eu-west-1" 12 | } 13 | } 14 | 15 | # Data source: Template file 16 | data "template_file" "user_data" { 17 | template = "${file("${path.module}/user-data.sh")}" 18 | 19 | vars { 20 | server_port = "${var.server_port}" 21 | db_address = "${data.terraform_remote_state.db.address}" 22 | db_port = "${data.terraform_remote_state.db.port}" 23 | server_text = "${var.server_text}" 24 | } 25 | } 26 | 27 | # Create a Security Group for an EC2 instance 28 | resource "aws_security_group" "instance" { 29 | name = "${var.cluster_name}-instance" 30 | 31 | lifecycle { 32 | create_before_destroy = true 33 | } 34 | } 35 | 36 | # Create a Security Group Rule 37 | resource "aws_security_group_rule" "allow_server_http_inbound" { 38 | type = "ingress" 39 | security_group_id = "${aws_security_group.instance.id}" 40 | 41 | from_port = "${var.server_port}" 42 | to_port = "${var.server_port}" 43 | protocol = "tcp" 44 | cidr_blocks = ["0.0.0.0/0"] 45 | 46 | } 47 | 48 | # Create a Security Group for an ELB 49 | resource "aws_security_group" "elb" { 50 | name = "${var.cluster_name}-elb" 51 | 52 | lifecycle { 53 | create_before_destroy = true 54 | } 55 | } 56 | 57 | # Create a Security Group Rule, inbound 58 | resource "aws_security_group_rule" "allow_http_inbound" { 59 | type = "ingress" 60 | security_group_id = "${aws_security_group.elb.id}" 61 | 62 | from_port = 80 63 | to_port = 80 64 | protocol = "tcp" 65 | cidr_blocks = ["0.0.0.0/0"] 66 | } 67 | 68 | # Create a Security Group Rule, outbound 69 | resource "aws_security_group_rule" "allow_all_outbound" { 70 | type = "egress" 71 | security_group_id = "${aws_security_group.elb.id}" 72 | 73 | from_port = 0 74 | to_port = 0 75 | protocol = "-1" 76 | cidr_blocks = ["0.0.0.0/0"] 77 | } 78 | 79 | # Create a Launch Configuration 80 | resource "aws_launch_configuration" "example" { 81 | image_id = "${var.ami}" 82 | instance_type = "${var.instance_type}" 83 | security_groups = ["${aws_security_group.instance.id}"] 84 | 85 | user_data = "${data.template_file.user_data.rendered}" 86 | 87 | lifecycle { 88 | create_before_destroy = true 89 | } 90 | } 91 | 92 | # Create an Autoscaling Group 93 | resource "aws_autoscaling_group" "example" { 94 | name = "${var.cluster_name}-${aws_launch_configuration.example.name}" 95 | 96 | launch_configuration = "${aws_launch_configuration.example.id}" 97 | availability_zones = ["${data.aws_availability_zones.all.names}"] 98 | load_balancers = ["${aws_elb.example.name}"] 99 | health_check_type = "ELB" 100 | 101 | min_size = "${var.min_size}" 102 | max_size = "${var.max_size}" 103 | min_elb_capacity = "${var.min_size}" 104 | 105 | lifecycle { 106 | create_before_destroy = true 107 | } 108 | 109 | tag { 110 | key = "Name" 111 | value = "${var.cluster_name}" 112 | propagate_at_launch = true 113 | } 114 | } 115 | 116 | # Create an ELB 117 | resource "aws_elb" "example" { 118 | name = "${var.cluster_name}" 119 | availability_zones = ["${data.aws_availability_zones.all.names}"] 120 | security_groups = ["${aws_security_group.elb.id}"] 121 | 122 | listener { 123 | lb_port = 80 124 | lb_protocol = "http" 125 | instance_port = "${var.server_port}" 126 | instance_protocol = "http" 127 | } 128 | 129 | health_check { 130 | healthy_threshold = 2 131 | unhealthy_threshold = 2 132 | timeout = 3 133 | interval = 30 134 | target = "HTTP:${var.server_port}/" 135 | } 136 | 137 | lifecycle { 138 | create_before_destroy = true 139 | } 140 | } 141 | 142 | # Create an Autoscaling Schedule 143 | resource "aws_autoscaling_schedule" "scale_out_during_business_hours" { 144 | count = "${var.enable_autoscaling}" 145 | 146 | scheduled_action_name = "scale-out-during-business-hours" 147 | min_size = 2 148 | max_size = 10 149 | desired_capacity = 10 150 | recurrence = "0 9 * * *" 151 | 152 | autoscaling_group_name = "${aws_autoscaling_group.example.name}" 153 | } 154 | 155 | # Create an Autoscaling Schedule 156 | resource "aws_autoscaling_schedule" "scale_in_at_night" { 157 | count = "${var.enable_autoscaling}" 158 | 159 | scheduled_action_name = "scale-in-at-night" 160 | min_size = 2 161 | max_size = 10 162 | desired_capacity = 2 163 | recurrence = "0 17 * * *" 164 | 165 | autoscaling_group_name = "${aws_autoscaling_group.example.name}" 166 | } 167 | 168 | # Create an Autoscaling Metric Alarm 169 | resource "aws_cloudwatch_metric_alarm" "high_cpu_utilisation" { 170 | alarm_name = "${var.cluster_name}-high-cpu-utilisation" 171 | namespace = "AWS/EC2" 172 | metric_name = "CPUUtilization" 173 | 174 | dimensions = { 175 | AutoScalingGroupName = "${aws_autoscaling_group.example.name}" 176 | } 177 | 178 | comparison_operator = "GreaterThanThreshold" 179 | evaluation_periods = 1 180 | period = 300 181 | statistic = "Average" 182 | threshold = 90 183 | unit = "Percent" 184 | } 185 | 186 | # Create an Autoscaling Metric Alarm 187 | resource "aws_cloudwatch_metric_alarm" "low_cpu_credit_balance" { 188 | count = "${format("%.1s", var.instance_type) == "t" ? 1 : 0}" 189 | 190 | alarm_name = "${var.cluster_name}-low-cpu-credit-balance" 191 | namespace = "AWS/EC2" 192 | metric_name = "CPUCreditBalance" 193 | 194 | dimensions = { 195 | AutoScalingGroupName = "${aws_autoscaling_group.example.name}" 196 | } 197 | 198 | comparison_operator = "LessThanThreshold" 199 | evaluation_periods = 1 200 | period = 300 201 | statistic = "Minimum" 202 | threshold = 10 203 | unit = "Count" 204 | } 205 | -------------------------------------------------------------------------------- /code/14-zero-downtime-deployment/modules/services/webserver-cluster/outputs.tf: -------------------------------------------------------------------------------- 1 | # Output variable: DNS Name of ELB 2 | output "elb_dns_name" { 3 | value = "${aws_elb.example.dns_name}" 4 | } 5 | 6 | # Output variable: Auto Scaling Group name 7 | output "asg_name" { 8 | value = "${aws_autoscaling_group.example.name}" 9 | } 10 | 11 | # Output variable: ELB Security Group Id 12 | output "elb_security_group_id" { 13 | value = "${aws_security_group.elb.id}" 14 | } -------------------------------------------------------------------------------- /code/14-zero-downtime-deployment/modules/services/webserver-cluster/user-data.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cat > index.html <${server_text} 5 |

DB address: ${db_address}

6 |

DB port: ${db_port}

7 | EOF 8 | 9 | nohup busybox httpd -f -p "${server_port}" & 10 | -------------------------------------------------------------------------------- /code/14-zero-downtime-deployment/modules/services/webserver-cluster/vars.tf: -------------------------------------------------------------------------------- 1 | # Input variable: server port 2 | variable "server_port" { 3 | description = "The port the server will use for HTTP requests" 4 | default = "8080" 5 | } 6 | 7 | # Input variable: Cluster name 8 | variable "cluster_name" { 9 | description = "The name to use for all the cluster resources" 10 | } 11 | 12 | # Input variable: DB remote state bucket name 13 | variable "db_remote_state_bucket" { 14 | description = "The name of the S3 bucket for the database's remote state" 15 | } 16 | 17 | # Input variable: DB remote state bucket key 18 | variable "db_remote_state_key" { 19 | description = "The path for database's remote state in S3" 20 | } 21 | 22 | # Input variable: Instance type 23 | variable "instance_type" { 24 | description = "The type of EC2 Instances to run (e.g. t2.micro)" 25 | } 26 | 27 | # Input variable: Instance min size 28 | variable "min_size" { 29 | description = "The minimum number of EC2 Instances in the ASG" 30 | } 31 | 32 | # Input variable: Instance max size 33 | variable "max_size" { 34 | description = "The maximum number of EC2 Instances in the ASG" 35 | } 36 | 37 | # Input variable: Enable Autoscaling 38 | variable "enable_autoscaling" { 39 | description = "If set to true, enable autoscaling" 40 | } 41 | 42 | # Input variable: AMI 43 | variable "ami" { 44 | description = "The AMI to run in the cluster" 45 | default = "ami-785db401" 46 | } 47 | 48 | # Input variable: Web server text 49 | variable "server_text" { 50 | description = "The text the web server should return" 51 | default = "Hello, World" 52 | } 53 | --------------------------------------------------------------------------------