Ansible Installation, Playbooks for Setting Up Website in Remote Machine

Charan kumarCharan kumar
7 min read

Ansible is an open-source IT Configuration Management, Deployment & Orchestration tool. It aims to provide large productivity gains to a wide variety of automation challenges. This tool is very simple to use yet powerful enough to automate complex multi-tier IT application environments.

Installing Ansible On Ubuntu

sudo apt update
sudo apt install software-properties-common -y
sudo add-apt-repository --yes --update ppa:ansible/ansible
sudo apt install ansible -y
ansible --version

Installing Ansible On CentOS

sudo yum install epel-release -y
sudo yum install ansible -y
ansible --version

SCP Commands

Copy files From Local machine to Remote machine

scp -i <private-key-file-path> <files to copy> <user>@<IP>:<Remote-machine-path>
Example:
scp -i Downloads/control.pem sample.txt ubuntu@54.165.128.104:/home/ubuntu/

Sample Inventory File

##Host Levelwebserver01    ansible_host=<Private IP>
webserver02    ansible_host=<Private IP>
webserver03    ansible_host=<Private IP>      
dbserver01     ansible_host=<Private IP>
dbserver02     ansible_host=<Private IP>      ansible_user=ubuntu

##Group Level [Group1]
webserverserver01
webserverserver02
webserverserver03[Group2]
dbserver01
dbserver02##Parent Level[dc_mumbai:children] 
webservergrp
dbsrvgrp##Variables[dc_mumbai:vars]
ansible_user=<user>
ansible_ssh_private_key_file=<key-path>

!!! Info

Host level has the highest priority, If you mention anything like username or Keyfile etc. It will take only, which are mentioned at the host level.

Ansible Commands

To test the connection of a particular Remote Machine

ansible -i <Inventoryfile path> -m ping <hostname>

To test the connection of a particular Group of Remote Machines

ansible -i <Inventoryfile path> -m ping <Groupname>

To test the connection of All Remote Machine

ansible -i <Inventoryfile path> -m ping all

To see details about the machine

ansible -i <Inventoryfile path> -m setup <hostname>

Some Example Ad hoc Commands

Copy files to the Remote machine name starting with the web

ansible -i <Inventoryfile path> -m copy -a "src=index.html dest=/var/www/html/index.html" 'web*' --become

Installing httpd in centos Remote machine

ansible -i <Inventoryfile path> -m yum -a "name=httpd state=present" websrvgrp --become

Start & Enable httpd in centos Remote machine

ansible -i <Inventoryfile path> -m service -a "name=httpd state=started enabled=yes" websrvgrp --become

Playbooks

!!! Info

Ansible Playbooks should be with .yml or .yaml Extension

For example vim sample.yml

Playbook For Creating Files & Directories

- name: Creating Files & Directories
  hosts: <host>
  become: yes
  tasks:
     - name: Creating a Directory
         file:
           path: /tmp/welcome
           state: directory     - name: Creating a File
         file:
           path: /tmp/sample.txt
           state: touch

To Execute the playbook

ansible-playbook -i <Inventory file path> sample.yml

Writing Playbook For Installing Httpd service in remote machines with start and enable and copying index.html files from the local machine to the remote machine.

- name: Install httpd and start the service
  hosts: all
  tasks:
     - name: Installing the Apache package
       yum:
         name: httpd
         state: present
     - name: Starting service
       service:
         name: httpd
         state: started
         enabled: yes     - name: Copy file with owner and permissions
       copy:
         src: ./index.html
         dest: /var/www/html/index.html     - name: Restarting service
       service:
         name: httpd
         state: restarted

Writing Playbook for Setting Up Website in Remote Machine

- name: Setting up Website
  hosts: websrv
  gather_facts: False
  become: True  tasks:
    - name: Installing Packages in CentOS
      yum:
        name: "{{item}}"
        state: present
      when: ansible_distribution == "CentOS"
      loop:
        - httpd
        - wget
        - unzip    - name: Start & Enable httpd
      service:
        name: httpd
        state: started
        enabled: yes       - name: Downloading Source code
      get_url:
        url: https://www.tooplate.com/zip-templates/2114_pixie.zip
        dest: /opt

    - name: Unarchive a file that is already on the remote machine
      unarchive:
        src: /opt/2114_pixie.zip
        dest: /opt
        remote_src: yes    - name : Deploy Website
      copy:
        src: /opt/2114_pixie/
        dest: /var/www/html/
        remote_src: yes
           - name: Restarting httpd service
      service:
        name: httpd
        state: restarted

Writing Playbook for Setting Up Website in Remote Machine with Conditions & Handlers.

- name: Writing playbook for loops and conditions
  hosts: all
  tasks:
    - name: Install packages on centos
      yum:
        name: "{{item}}"
        state: present
      when: ansible_distribution == "CentOS"
      loop:
        - httpd
        - wget
        - unzip
        - zip
        - git               - name: Install packages on Ubuntu 
      apt:
        name: "{{item}}"
        state: present
        update_cache: yes
      when: ansible_distribution == "Ubuntu"
      loop:
        - apache2
        - wget
        - unzip
        - zip
        - git
    - name: Start & enable service on CentOS
      service:
       name: httpd
       state: started
       enabled: yes
      when: ansible_distribution == "CentOS"    - name: Start & enable service on Ubuntu
      service:
       name: apache2
       state: started
       enabled: yes
      when: ansible_distribution == "Ubuntu"
    - name: Push index.html on centos
      copy:
        src: index.html
        dest: /var/www/html/
        backup: yes
      when: ansible_distribution == "CentOS"
      notify:
        - Restart service on CentOS    - name: Push index.html on ubuntu
      copy:
        src: index.html
        dest: /var/www/html/
        backup: yes
      when: ansible_distribution == "Ubuntu"
      notify:
        - Restart service on Ubuntu  handlers:
    - name: Restart service on CentOS
      service:
        name: httpd
        state: restarted
        enabled: yes
      when: ansible_distribution == "CentOS"    - name: Restart service on Ubuntu
      service:
        name: apache2
        state: restarted
        enabled: yes
      when: ansible_distribution == "Ubuntu"

Writing Playbook to Create VPC in AWS Cloud and Including Variables from Different File

Requirements need to be installed

apt install python3-pippip install botopip install boto3pip install botocore

Creating Files to store Variables

vim vpc_setup.txt

Variables

vpc_name: "Vprofile-vpc"#Vpc-range
vpcrange: '172.21.0.0/16'#subnet range
pubip1: '172.21.1.0/24'
pubip2: '172.21.2.0/24'
pubip3: '172.21.3.0/24'
pvtip1: '172.21.4.0/24'
pvtip2: '172.21.5.0/24'
pvtip3: '172.21.6.0/24'#region
region: 'us-east-2'#zone names
zone1: us-east-2a
zone2: us-east-2b
zone3: us-east-2c
state: present

Playbook

- hosts: localhost
  connection: local
  gather_facts: False
  tasks:
    - name: Import vpc variables
      include_vars: /path/vpc_setup    - name: create vpc
      ec2_vpc_net:
          name: "{{vpc_name}}"
          cidr_block: "{{vpcrange}}"
          region: "{{region}}"
          dns_support: yes
          dns_hostnames: yes
          tenancy: default
          state: "{{state}}"
      register: vpcout
    - name: Create a public subnet for zone1
      ec2_vpc_subnet:
          vpc_id: "{{vpcout.vpc.id}}"
          region: "{{region}}"
          az: "{{zone1}}"
          state: "{{state}}"
          cidr: "{{pubip1}}"
          map_public: yes
          tags:
            Name: vprofile_pubsub1
      register: pubsub1_out    - name: Create a public subnet for zone2
      ec2_vpc_subnet:
         vpc_id: "{{vpcout.vpc.id}}"
         region: "{{region}}"
         az: "{{zone2}}"
         state: "{{state}}"
         cidr: "{{pubip2}}"
         map_public: yes
         tags:
           Name: vprofile_pubsub2
      register: pubsub2_out    - name: Create a public subnet for zone3
      ec2_vpc_subnet:
         vpc_id: "{{vpcout.vpc.id}}"
         region: "{{region}}"
         az: "{{zone3}}"
         state: "{{state}}"
         cidr: "{{pubip3}}"
         map_public: yes
         tags:
           Name: vprofile_pubsub3
      register: pubsub3_out    - name: Create a private subnet for zone1
      ec2_vpc_subnet:
         vpc_id: "{{vpcout.vpc.id}}"
         region: "{{region}}"
         az: "{{zone1}}"
         state: "{{state}}"
         cidr: "{{pvtip1}}"
         map_public: yes
         tags:
           Name: vprofile_pvtsub1
      register: pvtsub1_out    - name: Create a private subnet for zone2
      ec2_vpc_subnet:
         vpc_id: "{{vpcout.vpc.id}}"
         region: "{{region}}"
         az: "{{zone2}}"
         state: "{{state}}"
         cidr: "{{pvtip2}}"
         map_public: yes
         tags:
           Name: vprofile_pvtsub2
      register: pvtsub2_out    - name: Create a private subnet for zone3
      ec2_vpc_subnet:
         vpc_id: "{{vpcout.vpc.id}}"
         region: "{{region}}"
         az: "{{zone3}}"
         state: "{{state}}"
         cidr: "{{pvtip3}}"
         map_public: yes
         tags:
           Name: vprofile_pvtsub3
      register: pvtsub3_out    - name: Internet gateway setup
      ec2_vpc_igw:
         vpc_id: "{{vpcout.vpc.id}}"
         region: "{{region}}"
         state: "{{state}}"
         tags:
           Name: vprofile_IGW
      register: igw_out    - name: public subnet route table
      ec2_vpc_route_table:
         vpc_id: "{{vpcout.vpc.id}}"
         region: "{{region}}"
         tags:
           Name: vprofile_Public
         subnets:
           - "{{pubsub1_out.subnet.id}}"
           - "{{pubsub2_out.subnet.id}}"
           - "{{pubsub3_out.subnet.id}}"
         routes:
           - dest: 0.0.0.0/0
             gateway_id: "{{ igw_out.gateway_id }}"
      register: public_route_table
    - name: Create a new nat gateway and allocate a new EIP if a nat gateway does not yet exist in the subnet.
      ec2_vpc_nat_gateway:
         state: "{{state}}"
         subnet_id: "{{pubsub1_out.subnet.id}}"
         wait: true
         region: "{{region}}"
         if_exist_do_not_create: true
      register: nat_out    - name: private subnet route table
      ec2_vpc_route_table:
         vpc_id: "{{vpcout.vpc.id}}"
         region: "{{region}}"
         tags:
           Name: vprofile_Private
         subnets:
           - "{{pvtsub1_out.subnet.id}}"
           - "{{pvtsub2_out.subnet.id}}"
           - "{{pvtsub3_out.subnet.id}}"
         routes:
           - dest: 0.0.0.0/0
             gateway_id: "{{nat_out.nat_gateway_id}}"
      register: private_route_table
    - debug:
        var: "{{item}}"
      loop:
         - vpcout.vpc.id
         - pubsub1_out.subnet.id
         - pubsub2_out.subnet.id
         - pubsub3_out.subnet.id
         - pvtsub1_out.subnet.id
         - pvtsub2_out.subnet.id
         - pvtsub3_out.subnet.id
         - igw_out.gateway_id
         - public_route_table.route_table.id
         - nat_out.nat_gateway_id
         - private_route_table.route_table.id    - set_fact:
        vpcid: "{{vpcout.vpc.id}}"
        pubsublid: "{{ pubsub1_out.subnet.id }}"
        pubsub2id: "{{ pubsub2_out.subnet.id }}"
        pubsub3id: "{{ pubsub3_out.subnet.id }}"
        privsublid: "{{ pvtsub1_out.subnet.id }}"
        privsub2id: "{{ pvtsub2_out.subnet.id }}"
        privsub3id: "{{ pvtsub3_out.subnet.id }}"
        igwid: "{{ igw_out.gateway_id }}"
        pubRTid: "{{ public_route_table.route_table.id }}"
        NATGWid: "{{ nat_out.nat_gateway_id }}"
        privRTid: "{{ private_route_table.route_table.id }}"
        cacheable: yes    - name: creating file for vpc output
      copy:
        content: "vpcid: {{vpcout.vpc.id}}\n pubsublid: {{ pubsub1_out.subnet.id }}\npubsub2id: {{ pubsub2_out.subnet.id }}\npubsub3id: {{ pubsub3_out.subnet.id }}\nprivsublid: {{ pvtsub1_out.subnet.id }}\nprivsub2id: {{ pvtsub2_out.subnet.id }}\nprivsub3id: {{ pvtsub3_out.subnet.id }}\nigwid: {{ igw_out.gateway_id }}\npubRTid: {{ public_route_table.route_table.id }}\nNATGWid: {{ nat_out.nat_gateway_id }}\nprivRTid: {{ private_route_table.route_table.id }}"
        dest: /home/ubuntu/Vprofile/vars/output_vars

Launching Ec2 Instance in AWS Cloud

Requirements

apt install python3-pippip install botopip install boto3pip install botocore

Playbook

- name: Launching Ec2 Instance
  hosts: localhost
  connection: local
  tasks:
     - name: Creating Key pair
       amazon.aws.ec2_key:
         name: samplekey
         region: us-west-1
       register: key     - debug:
        var: key     - name: Storing private key into a file
       copy:
          content: "{{key.key.private_key}}"
          dest: "./sample.pem"
          mode: 0600
       when: key.changed
     - name: Creating Security Group
       amazon.aws.ec2_group:
         name: mysg
         description: Allowing 22 and 80
         vpc_id: vpc-0c8e70cf05b1342ac
         region: us-west-1
         rules:
           - proto: tcp
             from_port: 22
             to_port: 22
             cidr_ip: 0.0.0.0/0
             rule_desc: allow all on port 80 & 22
       register: sg_out     - name: Launching bastion_host
       ec2:
          key_name: "samplekey"
          region: us-west-1
          instance_type: t2.micro
          image: ami-0573b70afecda915d
          wait: yes
          wait_timeout: 300
          instance_tags:
            name: "Ansible Instance"
            project: vprofile
            owner: devops team
          exact_count: 1
          count_tag:
            name: "Ansible Instance"
            project: vprofile
            owner: devops team
          group_id: "{{sg_out.group_id}}"
          vpc_subnet_id: subnet-0c4734c845e549cda
       register: instance

Ansible Configuration File

Note - You should save the configuration file with the name ansible.cfg

vim ansible.cfg

Sample Ansible Configuration File

[defaults]
host_key_checking=False
inventory=<Inventory File Path>
timeout=20
log_path=/var/log/ansible_world.log
remote_port=22
remote_user=<username>[privilege_escalation]
become=True
become_method=sudo
become_user=root
become_ask_pass=False
0
Subscribe to my newsletter

Read articles from Charan kumar directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Charan kumar
Charan kumar

Devops engineer at Acro Computing India. Skilled in Git, Ansible, Jenkins, Docker, Kubernetes.