diff --git a/README.md b/README.md index de16d3e..fc44d40 100644 --- a/README.md +++ b/README.md @@ -1,90 +1,66 @@ -# terraform-ansible-example -Quick start on how to provision with ansible inside terraform +# Overview +Quick start on how to provision with ansible using terraform (remote) state file. ## Project structure * ansible - folder with ansible playbooks, inventories and configuration * terraform - folder with terraform infrastructure files +* packer - folder with packer image definition ## Getting stated -Prepend environment for using ansible dynamic inventory with Amazon ec2: -``` -$ pip install boto -$ chmod +x ansible/ec2.py -``` -Of course, you'll need to have AWS credentials. By default you can find it in ~/.aws/credentials -``` +You'll need to have AWS credentials. By default you can find it in ~/.aws/credentials: +```sh $ cat ~/.aws/credentials [default] aws_access_key_id = aws_secret_access_key = ... ``` - -In file ansible/ec2.ini define your regions: -``` -... -regions = eu-central-1 -regions_exclude = us-gov-west-1, cn-north-1 -... +Create the base AWS AMI using packer (if you don't have one in the storage): +```sh +$ cd packer +$ packer validate ubuntu-16.04-amd64-example.json +$ packer build ubuntu-16.04-amd64-example.json ``` - ## Usage -if you want just up example infrastructure you need set your variables in .tfvars files +If you want just to run example infrastructure, create terraform.tfvars file from template terraform.tfvars.example and set your variables: +```sh +$ cd ../terraform +$ cp terraform.tfvars.example terraform.tfvars ``` -pub_key_path = "~/.ssh/express42.pub" -private_key_path = "~/.ssh/express42" -key_name = "astarostenko" -env = "astarostenko" +(Optional) Create backend.tf file from template and set your backend configs: +```sh +$ cp backend.tf.example backend.tf ``` - -Go to terraform folder and download all modules to .terraform folder (for local modules it just creates symlinks) -``` -$ cd terraform -$ terraform get +Initialize terraform configuration: +```sh +$ terraform init ``` -If your want to see plan of your own infrastructure - -``` +(Optional) Check the plan of your infrastructure: +```sh $ terraform plan -Refreshing Terraform state in-memory prior to plan... -The refreshed state will be used to calculate this plan, but will not be -persisted to local or remote state storage. - -data.aws_ami.image: Refreshing state... -The Terraform execution plan has been generated and is shown below. -Resources are shown in alphabetical order for quick scanning. Green resources -will be created (or destroyed and then created if an existing resource -exists), yellow resources are being changed in-place, and red resources -will be destroyed. Cyan entries are data sources to be read. - -Note: You didn't specify an "-out" parameter to save this plan, so when -"apply" is called, Terraform can't guarantee this is what will execute. - -+ null_resource.ansible_db - -+ null_resource.ansible_web - -+ module.db.aws_instance.db -... -... -... -Plan: 9 to add, 0 to change, 0 to destroy. - -``` -To create all resources and provision all services ``` + +Create all resources: +```sh $ terraform apply ``` -To delete all created resources + +Provision services: +```sh +$ cd ../ansible +$ ansible-playbook -i dynamic_inventory.sh playbooks/db.yml -e env="your_env" +$ ansible-playbook -i dynamic_inventory.sh playbooks/web.yml -e env="your_env" ``` + +Delete all created resources: +```sh $ terraform destroy ``` # Terraform structure #### main.tf - contain general infrastructure description -We describe used provider, can create resources, call some modules, and can also define provision -action +We describe used provider, can create resources, call modules: ``` provider "aws" { region = "${var.region}" @@ -130,30 +106,28 @@ variable "list_var_name" { } ``` -Variables can be defined in -* variables.tf or any other .tf file +Variables can be defined in variables.tf or any other .tf file: ``` variable env { description = "current environment (dev, prod, stage)" default = "dev" } ``` -You can just create it but not define in .tf file, but then you'll need to define it anywhere +You can just create it but not define in .tf file, but then you'll need to define it anywhere: ``` variable "name" {} ``` * terraform.tfvars (default) or any other .tfvars file with flag -var-file -``` +```sh $ terraform plan \ -var-file="secret.tfvars" \ -var-file="production.tfvars" ``` * input argument to terraform with flag -var -``` +```sh $ terraform plan -var 'access_key=foo' ``` - [More information about variables](https://www.terraform.io/docs/configuration/variables.html) #### outputs.tf - define all important output data like variables @@ -183,3 +157,7 @@ We can use module just like: } ``` [More information about modules](https://www.terraform.io/docs/modules/index.html) + +## Links: +* [Terraform documentation](https://www.terraform.io/docs/ "Terraform documentation") +* [Ansible documentation](https://docs.ansible.com/ansible/index.html "Ansible documentation") diff --git a/ansible/playbooks/db.yml b/ansible/playbooks/db.yml index 2f08ea6..3593647 100644 --- a/ansible/playbooks/db.yml +++ b/ansible/playbooks/db.yml @@ -1,6 +1,6 @@ --- -- hosts: aws_tag_Group=dev_db_cluster +- hosts: aws_tag_Group={{ env }}_db_cluster gather_facts: false become: yes diff --git a/ansible/playbooks/web.yml b/ansible/playbooks/web.yml index c2f142d..386bb15 100644 --- a/ansible/playbooks/web.yml +++ b/ansible/playbooks/web.yml @@ -1,6 +1,6 @@ --- -- hosts: aws_tag_Group=dev_web_cluster +- hosts: aws_tag_Group={{ env }}_web_cluster gather_facts: false become: yes diff --git a/packer/install-python.sh b/packer/install-python.sh new file mode 100644 index 0000000..97b7459 --- /dev/null +++ b/packer/install-python.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +sudo apt-get update +sudo apt-get install -y python-minimal +sudo rm -rf /var/lib/apt/lists/* diff --git a/packer/ubuntu-16.04-amd64-example.json b/packer/ubuntu-16.04-amd64-example.json new file mode 100644 index 0000000..52f9684 --- /dev/null +++ b/packer/ubuntu-16.04-amd64-example.json @@ -0,0 +1,30 @@ +{ + "builders": [ + { + "type": "amazon-ebs", + "region": "eu-central-1", + "source_ami": "ami-060cde69", + "instance_type": "t2.micro", + "ssh_username": "ubuntu", + "ami_name": "ubuntu-16.04-amd64-python2-{{timestamp}}", + "ami_description": "Ubuntu Xenial 16.04 amd64 with python2", + "associate_public_ip_address": true, + "ami_block_device_mappings": [ + { + "device_name": "/dev/sdb", + "delete_on_termination": "true", + "volume_type": "gp2", + "volume_size": "10", + "encrypted": "false" + } + ] + } + ], + "provisioners": [ + { + "type": "shell", + "script": "install-python.sh", + "pause_before": "10s" + } + ] +} diff --git a/terraform/data.tf b/terraform/data.tf index b71ba4f..bd50d71 100644 --- a/terraform/data.tf +++ b/terraform/data.tf @@ -3,6 +3,7 @@ data "aws_ami" "image" { filter { name = "name" - values = ["ubuntu/images/hvm-ssd/ubuntu-xenial-16.04-amd64*"] + values = ["ubuntu-16.04-amd64-python2*"] } + owners = ["self"] } diff --git a/terraform/main.tf b/terraform/main.tf index f7729ef..0ea35eb 100644 --- a/terraform/main.tf +++ b/terraform/main.tf @@ -24,6 +24,9 @@ module "web" { sg_ids = "${module.base_linux.sg_id}" name = "${var.web_server_params["name"]}" count = "${var.web_server_params["count"]}" + ebs_optimized = "${var.ebs_optimized}" + monitoring = "${var.monitoring}" + azs = ["${var.azs}"] } module "db" { @@ -37,4 +40,7 @@ module "db" { sg_ids = "${module.base_linux.sg_id}" name = "${var.db_server_params["name"]}" count = "${var.db_server_params["count"]}" + ebs_optimized = "${var.ebs_optimized}" + monitoring = "${var.monitoring}" + azs = ["${var.azs}"] } diff --git a/terraform/modules/db/main.tf b/terraform/modules/db/main.tf index ce837a0..7a0235f 100644 --- a/terraform/modules/db/main.tf +++ b/terraform/modules/db/main.tf @@ -1,8 +1,11 @@ resource "aws_instance" "db" { - ami = "${var.ami}" - count = "${var.count}" - instance_type = "${var.instance_type}" - key_name = "${var.key_name}" + ami = "${var.ami}" + count = "${var.count}" + instance_type = "${var.instance_type}" + ebs_optimized = "${var.ebs_optimized}" + monitoring = "${var.monitoring}" + key_name = "${var.key_name}" + availability_zone = "${element(var.azs, count.index)}" vpc_security_group_ids = [ "${var.sg_ids}", diff --git a/terraform/modules/db/variables.tf b/terraform/modules/db/variables.tf index e69fc5d..8fa8fbd 100644 --- a/terraform/modules/db/variables.tf +++ b/terraform/modules/db/variables.tf @@ -10,6 +10,11 @@ variable private_key_path { description = "Path to the private key used to connect to instance" } +variable azs { + description = "Run the EC2 Instances in these Availability Zones" + type = "list" +} + variable env { description = "Environment prefix" } @@ -23,6 +28,14 @@ variable instance_type { default = "t2.micro" } +variable ebs_optimized { + description = "Create EBS–Optimized Instances" +} + +variable monitoring { + description = "Enable detailed monitoring for EC2 instances" +} + variable sg_ids { description = "List of security groups ids" } diff --git a/terraform/modules/web/main.tf b/terraform/modules/web/main.tf index 59abf43..b3780f3 100644 --- a/terraform/modules/web/main.tf +++ b/terraform/modules/web/main.tf @@ -1,8 +1,11 @@ resource "aws_instance" "web" { - ami = "${var.ami}" - count = "${var.count}" - instance_type = "${var.instance_type}" - key_name = "${var.key_name}" + ami = "${var.ami}" + count = "${var.count}" + instance_type = "${var.instance_type}" + ebs_optimized = "${var.ebs_optimized}" + monitoring = "${var.monitoring}" + key_name = "${var.key_name}" + availability_zone = "${element(var.azs, count.index)}" vpc_security_group_ids = [ "${var.sg_ids}", diff --git a/terraform/modules/web/variables.tf b/terraform/modules/web/variables.tf index c9b2c0b..966908a 100644 --- a/terraform/modules/web/variables.tf +++ b/terraform/modules/web/variables.tf @@ -10,6 +10,11 @@ variable private_key_path { description = "Path to the private key used to connect to instance" } +variable azs { + description = "Run the EC2 Instances in these Availability Zones" + type = "list" +} + variable env { description = "Environment prefix" } @@ -23,6 +28,14 @@ variable instance_type { default = "t2.micro" } +variable ebs_optimized { + description = "Create EBS–Optimized Instances" +} + +variable monitoring { + description = "Enable detailed monitoring for EC2 instances" +} + variable sg_ids { description = "List of security groups ids" } diff --git a/terraform/terraform.tfvars.example b/terraform/terraform.tfvars.example index 5d01285..c5963fb 100644 --- a/terraform/terraform.tfvars.example +++ b/terraform/terraform.tfvars.example @@ -1,6 +1,7 @@ pub_key_path = "~/.ssh/express42.pub" private_key_path = "~/.ssh/express42" key_name = "astarostenko" +env = "astarostenko" web_server_params { count = "1" diff --git a/terraform/variables.tf b/terraform/variables.tf index 02ee0cf..56ff13a 100644 --- a/terraform/variables.tf +++ b/terraform/variables.tf @@ -16,6 +16,22 @@ variable region { default = "eu-central-1" } +variable ebs_optimized { + description = "Create EBS–Optimized Instances" + default = "false" +} + +variable monitoring { + description = "Enable detailed monitoring for EC2 instances" + default = "false" +} + +variable azs { + description = "Run the EC2 Instances in these Availability Zones" + type = "list" + default = ["eu-central-1a", "eu-central-1b"] +} + variable env { description = "Environment prefix" default = "dev"