Git Product home page Git Product logo

terraform-testing's Introduction

Terraform Labs

forthebadge forthebadge

Lab 1:

  • Make a VPC on AWS
  • 2 public subnets and 2 private subnets each in a different AZ
  • An internet gateway for the VPC
  • 2 routing tables (one for private subnets and one for public subnets)
  • Backup the state file on an S3 bucket (Terraform backend)
Terraform code for AWS

/*VPC*/
resource "aws_vpc" "main_vpc" {
  cidr_block       = "10.0.0.0/16"
  tags = {
    Name = "main_vpc"
  }
}

/*
  Public Subnets
*/
resource "aws_subnet" "public_subnet_1" {
  vpc_id     = "${aws_vpc.main_vpc.id}"
  cidr_block = "10.0.0.0/24"
  map_public_ip_on_launch = "true"
  availability_zone = "us-west-2a"

  tags = {
    Name = "public_subnet_1"
  }
}

resource "aws_subnet" "public_subnet_2" {
  vpc_id     = "${aws_vpc.main_vpc.id}"
  cidr_block = "10.0.1.0/24"
  availability_zone = "us-west-2b"
  map_public_ip_on_launch = "true"

  tags = {
    Name = "public_subnet_2"
  }
}

/*
  Private Subnets
*/
resource "aws_subnet" "private_subnet_1" {
  vpc_id     = "${aws_vpc.main_vpc.id}"
  cidr_block = "10.0.2.0/24"
  availability_zone = "us-west-2c"

  tags = {
    Name = "private_subnet_1"
  }
}

resource "aws_subnet" "private_subnet_2" {
  vpc_id     = "${aws_vpc.main_vpc.id}"
  cidr_block = "10.0.3.0/24"
  availability_zone = "us-west-2d"

  tags = {
    Name = "private_subnet_2"
  }
}

/*
  Internet Gateway
*/
resource "aws_internet_gateway" "internet_gateway" {
  vpc_id     = "${aws_vpc.main_vpc.id}"

  tags = {
    Name = "internet_gateway"
  }
}


/*
  Route Tables
*/
resource "aws_route_table" "public_route_table" {
  vpc_id     ="${aws_vpc.main_vpc.id}"

  route {
    cidr_block = "0.0.0.0/0"
    gateway_id = "${aws_internet_gateway.internet_gateway.id}"
  }

  tags = {
    Name = "public_route_table"
  }
}

resource "aws_route_table" "private_route_table" {
  vpc_id     = "${aws_vpc.main_vpc.id}"

  tags = {
    Name = "private_route_table"
  }
}

/*
  Link public subnets with public route tables and private subnets with private route tables
*/

resource "aws_route_table_association" "public_association_1" {
  subnet_id      = "${aws_subnet.public_subnet_1.id}"
  route_table_id = "${aws_route_table.public_route_table.id}"
}

resource "aws_route_table_association" "public_association_2" {
  subnet_id      = "${aws_subnet.public_subnet_2.id}"
  route_table_id = "${aws_route_table.public_route_table.id}"
}

resource "aws_route_table_association" "private_association_1" {
  subnet_id      = "${aws_subnet.private_subnet_1.id}"
  route_table_id = "${aws_route_table.private_route_table.id}"
}

resource "aws_route_table_association" "private_association_2" {
  subnet_id      = "${aws_subnet.private_subnet_2.id}"
  route_table_id = "${aws_route_table.private_route_table.id}"
}

Terraform State file backup on S3 bucket

terraform {
  backend "s3" {
    bucket = "theterraformstate"
    key    = "terraform/state_backup/terraform.tfstate"
    region = "us-west-2"
  }
}


Lab 2:

  • 5 EC2s where 2 will be placed in the public subnets (later nginx will be installed on them using ansible) and 2 will be placed in the private subnets, a bastion server will also be placed in the public subnet.
  • 2 security groups
    • one to allow SSH connection on the bastion server by opening port 22
    • one to allow HTTP connections on the public EC2s by opening port 80
5๏ธโƒฃ EC2s

resource "aws_instance" "aws_public_instance_1" {
  ami           = "${var.ami_id}" # us-west-2
  availability_zone = "us-west-2a"
  instance_type = "${var.instance_type}"
  count = "${var.number_of_instances}"
  key_name = "${aws_key_pair.generated_key.id}"
  subnet_id = "${aws_subnet.public_subnet_1.id}"
  vpc_security_group_ids = ["${aws_security_group.allow_http_traffic.id}"]

  tags = {
    Name = "aws_public_instance_1"
  }
}

resource "aws_instance" "aws_public_instance_2" {
  ami           = "${var.ami_id}" # us-west-2
  availability_zone = "us-west-2b"
  instance_type = "${var.instance_type}"
  count = "${var.number_of_instances}"
  key_name = "${aws_key_pair.generated_key.id}"
  subnet_id = "${aws_subnet.public_subnet_2.id}"
  vpc_security_group_ids = ["${aws_security_group.allow_http_traffic.id}"]


  tags = {
    Name = "aws_public_instance_2"
  }
}


resource "aws_instance" "aws_private_instance_1" {
  ami           = "${var.ami_id}" # us-west-2
  availability_zone = "us-west-2c"
  instance_type = "${var.instance_type}"
  count = "${var.number_of_instances}"
  key_name = "${aws_key_pair.generated_key.id}"
  subnet_id = "${aws_subnet.private_subnet_1.id}"

  tags = {
    Name = "aws_private_instance_1"
  }
}

resource "aws_instance" "aws_private_instance_2" {
  ami           = "${var.ami_id}" # us-west-2
  availability_zone = "us-west-2c"
  instance_type = "${var.instance_type}"
  count = "${var.number_of_instances}"
  key_name = "${aws_key_pair.generated_key.id}"
  subnet_id = "${aws_subnet.private_subnet_2.id}"

  tags = {
    Name = "aws_private_instance_2"
  }
}


/*
    Bastion server
*/

resource "aws_instance" "bastion_server" {
  ami           = "${var.ami_id}" # us-west-2
  availability_zone = "us-west-2a"
  instance_type = "${var.instance_type}"
  count = "${var.number_of_instances}"
  key_name = "${aws_key_pair.generated_key.id}"
  subnet_id = "${aws_subnet.public_subnet_1.id}"
  vpc_security_group_ids = ["${aws_security_group.ssh_connection_allow.id}"]


  tags = {
    Name = "bastion_server"
  }
}

๐Ÿ”’ Security groups

resource "aws_security_group" "allow_http_traffic" {
  name        = "allow_http_traffic"
  description = "Allow HTTP inbound traffic"
  vpc_id      = "${aws_vpc.main_vpc.id}"

  ingress {
    description = "HTTP from VPC"
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }

  tags = {
    Name = "allow_http_traffic"
  }
}

resource "aws_security_group" "ssh_connection_allow" {
  name        = "ssh_connection_allow"
  description = "Allow ssh traffic"
  vpc_id      = "${aws_vpc.main_vpc.id}"

  ingress {
    description = "ssh from VPC"
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }

  tags = {
    Name = "ssh_connection_allow"
  }
}


Lab 3:

  • Dockerfile that uses jenkins image as a base then installs terraform on it
  • A conteiner that uses the previously built image using the Dockerfile
    • docker build -t jenkinsTerra .
    • docker run -p 8080:8080 jenkinsTerra
    • Open a different vagrant terminal and enter the container to get the password that'll be used for jenkins first run docker container exec -it CONTAINER_ID /bin/bash
  • Create a pipeline in jenkins that builds the infrastructure using terraform, a useful resource for linking the AWS credentials with jenkins pipeline using environment variables is this answer
  • Configure ansible on the host (vagrant in my case) to run using the bastion server created earlier, use this answer for help.
  • Run nginx playbook to configure the 2 public EC2s
Dockerfile

FROM jenkins/jenkins
USER root
WORKDIR /home/
RUN pwd && ls && \
    wget https://releases.hashicorp.com/terraform/0.12.24/terraform_0.12.24_linux_amd64.zip && \
    pwd && ls && \
    unzip terraform_0.12.24_linux_amd64.zip && \
    pwd && ls && \
    rm terraform_0.12.24_linux_amd64.zip && \
    mv terraform /bin/

EXPOSE 8080

Jenkinsfile

pipeline {
   agent any
        stages {

                stage("Terraform init") {
                        steps {
                            sh "cd \"Lab 3\" && pwd && ls && terraform init -var ak=\"${env.AWS_ACCESS_KEY_ID}\" -var sa=\"${env.AWS_SECRET_ACCESS_KEY}\""
                        }
                    }

                stage("Terraform plan") {
                    steps {
                        sh "cd \"Lab 3\" && pwd && ls && terraform plan"
                    }
                }

                stage("Terraform apply") {
                    steps {
                        sh "cd \"Lab 3\" && pwd && ls && terraform apply -auto-approve"
                    }
                }
        }
}

  • In my case i made 3 different jenkinsfiles
    • one responsible for init plan and apply
    • one for generating the graph using terraform graph
    • one for destroying
JTerraformGraph file

pipeline {
   agent any
        stages {
            
            stage("Terraform init") {
                        steps {
                            sh "cd \"Lab 3\" && pwd && ls && terraform init -var ak=\"${env.AWS_ACCESS_KEY_ID}\" -var sa=\"${env.AWS_SECRET_ACCESS_KEY}\""
                        }
                    }

                stage("Terraform graph") {
                    steps {
                        sh "cd \"Lab 3\" && pwd && ls && terraform graph"
                    }
                }
        }
}

JenkinsDestroy

pipeline {
   agent any
        stages {

                stage("Terraform destroy") {
                    steps {
                        sh "cd \"Lab 3\" && pwd && ls && terraform destroy -auto-approve"
                    }
                }
        }
}

Ansible's inventory

[Bastion]
54.202.10.158

[Private]
10.0.2.11
10.0.3.162

[Public]
10.0.1.170
10.0.0.246

Ansible's nginx playbook

---
- hosts: Public
  become: true
  user: ec2-user
  vars:
    - ansible_ssh_user: "ec2-user"
    - ansible_ssh_common_args: >
          -o ProxyCommand="ssh -W %h:%p -q {{ ansible_ssh_user }}@54.202.10.158" \
          -o ServerAliveInterval=5 \
          -o StrictHostKeyChecking=no
  tasks:
    - name: epel-release install
      package:
        name: epel-release 
        state: present 
        

    - name: download nginx 
      package:
        name: nginx 
        state: present 
    
    - name: enable nginx 
      systemd:
        name: nginx 
        state: started 
        enabled: yes

ssh-agent before running ansible playbook

$ ssh-agent bash

bash$  chmod 400 ~/.ssh/keyname.pem

bash$ ssh-add ~/.ssh/keyname.pem

# get the ip address of the bastion host then 

bash$ ssh -A ec2-user@bastion_ip_address

# from there just ssh into the private ip of the EC2
[ec2-user@ip-]$ ssh ec2-user@ip_address

Run the playbook by specifing the inventory -i and selecting the target group in the hosts section

ansible-playbook -i inventory nginx.yaml

Graph:

terraform-testing's People

Contributors

thejaxon avatar

Stargazers

 avatar

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.