How to run an ansible playbook using GitLab CI/CD?
What is GitLab CI/CD?
GitLab CI/CD is the part of GitLab that you use for all of the continuous methods (Continuous Integration, Delivery, and Deployment). With GitLab CI/CD, you can test, build, and publish your code with no third-party application or integration needed.
Read more about GitLab CI/CD here.
What is Ansible?
Ansible is an open-source software provisioning, configuration management, and deployment tool. It runs on many Unix-like systems and can configure both Unix-like systems as well as Microsoft Windows. Ansible uses SSH protocol in order to configure the remote servers. Ansible follows the push-based mechanism to configure the remote servers.
What is Ansible Vault?
Ansible Vault is a feature of ansible that allows you to keep sensitive data such as passwords or keys in encrypted files, rather than as plaintext in playbooks or roles. You can create the new file as encrypted or can also modify the existing file as encrypted.
In this tutorial, I have integrated Ansible with GitLab CI/CD and created various resources on AWS.
Prerequisite:
- AWS & GitLab Account
- Basic understanding of AWS, Ansible & GitLab CI/CD
- An access key & secret key created in the AWS
- Ansible Vault to encrypt the file
Lets, start with the configuration of the project
Step 1:- Create a Repository
- Create a repository in your GitLab account & give it a name of your choice
Step 2:- Create an Ansible file for resource creation
- Create a
.yml
file inside the root directory and add the below code in it. - The below code will create various resources on AWS. If you can’t understand anything in the code you can have a better understanding from here
---
- hosts: localhost # Place where we are running Ansible
connection: local # Connection
gather_facts: no
vars_files:
- cred.yml
# Variables
vars:
ansible_python_interpreter: /usr/bin/python3
# Default Names
title: "Demo"
vpc_name: "{{ title }} VPC"
igw_name: "{{ title }} IGW"
subnet_name: "{{ title }} Subnet"
acl_name: "{{ title }} ACL"
instance_name: "{{ title }} Instance"
security_group_name: "{{ title }} Security Group"
route_table_name: "{{ title }} Route Table"
# Default values for CIDR Blocks
vpcCidrBlock: "10.0.0.0/16"
subNetCidrBlock: "10.0.1.0/24"
portCidrBlock: "0.0.0.0/0"
destinationCidrBlock: "0.0.0.0/0"
# State
state: "present"
# Default value of AZ & Regio
zone: "us-west-1a"
region: "us-west-1"
# List of tasks
tasks:
# Creating VPC
- name: Create VPC
ec2_vpc_net:
aws_access_key: "{{ aws_access_key }}"
aws_secret_key: "{{ aws_secret_key }}"
name: "{{ vpc_name }}"
cidr_block: "{{ vpcCidrBlock }}"
region: "{{ region }}"
dns_support: "yes"
dns_hostnames: "yes"
tenancy: "default"
state: "{{ state }}"
resource_tags:
Name: "{{ vpc_name }}"
register: vpc_result
# Creating Internate Gateway
- name: Create Internet Gateway
ec2_vpc_igw:
aws_access_key: "{{ aws_access_key }}"
aws_secret_key: "{{ aws_secret_key }}"
vpc_id: "{{ vpc_result.vpc.id }}"
region: "{{ region }}"
state: "{{ state }}"
tags:
Name: "{{ igw_name }}"
register: igw_result
# Creating Subnet
- name: Create Subnet
ec2_vpc_subnet:
aws_access_key: "{{ aws_access_key }}"
aws_secret_key: "{{ aws_secret_key }}"
vpc_id: "{{ vpc_result.vpc.id }}"
region: "{{ region }}"
state: "{{ state }}"
az: "{{ zone }}"
cidr: "{{ subNetCidrBlock }}"
map_public: "yes"
resource_tags:
Name: "{{ subnet_name }}"
register: subnet_result
# Creating Security Group
- name: Create Security Group
ec2_group:
name: "{{ security_group_name }}"
description: "{{ security_group_name }}"
aws_access_key: "{{ aws_access_key }}"
aws_secret_key: "{{ aws_secret_key }}"
vpc_id: "{{ vpc_result.vpc.id }}"
region: "{{ region }}"
state: "{{ state }}"
tags:
Name: "{{ security_group_name }}"
rules:
- proto: tcp
from_port: 80
to_port: 80
cidr_ip: "{{ portCidrBlock }}"
- proto: tcp
from_port: 443
to_port: 443
cidr_ip: "{{ portCidrBlock }}"
- proto: tcp
from_port: 22
to_port: 22
cidr_ip: "{{ portCidrBlock }}"
rules_egress:
- proto: tcp
from_port: 80
to_port: 80
cidr_ip: "{{ portCidrBlock }}"
- proto: tcp
from_port: 443
to_port: 443
cidr_ip: "{{ portCidrBlock }}"
- proto: tcp
from_port: 22
to_port: 22
cidr_ip: "{{ portCidrBlock }}"
register: security_group_result
# Creating NACLs for subnet
- name: Create Network ACLs
ec2_vpc_nacl:
name: "{[ acl_name }}"
aws_access_key: "{{ aws_access_key }}"
aws_secret_key: "{{ aws_secret_key }}"
vpc_id: "{{ vpc_result.vpc.id }}"
region: "{{ region }}"
state: "{{ state }}"
subnets: [ "{{ subnet_result.subnet.id }}" ]
tags:
Name: "{{ acl_name }}"
ingress:
# rule no, protocol, allow/deny, cidr, icmp_type, icmp_code, port from, port to
- [100, 'tcp', 'allow', '0.0.0.0/0', null, null, 0, 65535]
# rule no, protocol, allow/deny, cidr, icmp_type, icmp_code, port from, port to
egress:
- [100, 'all', 'allow', '0.0.0.0/0', null, null, 0, 65535]
# Creating Route Table for subnet
- name: Create Route Table
ec2_vpc_route_table:
aws_access_key: "{{ aws_access_key }}"
aws_secret_key: "{{ aws_secret_key }}"
vpc_id: "{{ vpc_result.vpc.id }}"
region: "{{ region }}"
state: "{{ state }}"
tags:
Name: "{{ route_table_name }}"
subnets: [ "{{ subnet_result.subnet.id }}" ]
routes:
- dest: "{{ destinationCidrBlock }}"
gateway_id: "{{ igw_result.gateway_id }}"
register: public_route_table
# Creating EC2 Instance
- name: Create EC2 Instance
ec2:
aws_access_key: "{{ aws_access_key }}"
aws_secret_key: "{{ aws_secret_key }}"
instance_type: t2.micro
image: ami-04b6c97b14c54de18
wait: yes
region: "{{ region }}"
group: "{{ security_group_name }}"
key_name: tests
count: 1
vpc_subnet_id: "{{ subnet_result.subnet.id }}"
assign_public_ip: yes
instance_tags:
Name: "{{ instance_name }}"
register: ec2_result
Step 3:- Create an ansible file for AWS Credentials
- In this, I have used ansible vault to create the credentials file for the AWS access key & secret key so that we can manage it safely.
To create a new encrypted file using ansible vault you need to run the below command. It will ask for password so, please give a password that you can easily remember
ansible-vault create cred.yml
- Add below content in it
aws_access_key: <your aws access key>
aws_secret_key: <your aws secret key>
Step 4:- Create a password file
- Create a new file called
password.txt
and add your ansible vault password in it so that we can use it later.
Step 4:- Create a workflow file
- Now in order to create the resources automatically, we need to create a workflow file
- Create
.gitlab-ci.yml
file and add the below code to it - The below job will run on every push and pull request that happens on the master branch. In the build section, I have specified the image name and commands in the script section.
stages:
- run
image:
name: registry.gitlab.com/torese/docker-ansible
variables:
ANSIBLE_HOST_KEY_CHECKING: 'false'
ANSIBLE_FORCE_COLOR: 'true'
ANSIBLE_PYTHON_INTERPRRTER: /usr/bin/python3
before_script:
- yum install httpd -y
- yum install -y python3
- ansible --version
run:
stage: run
script:
- ansible-playbook main.yml --vault-password-file=password.txt
Let’s understand the above code.
- The below code is to declare the name of the stage
stages:
- run
- We are using
ansible
image to run the ansible playbook
image:
name: registry.gitlab.com/torese/docker-ansible
- In the
variable
section we are defining environmental variables
variables:
ANSIBLE_HOST_KEY_CHECKING: 'false'
ANSIBLE_FORCE_COLOR: 'true'
ANSIBLE_PYTHON_INTERPRRTER: /usr/bin/python3
- In the
before_script
section we are installinghttpd
andpython3
and also checking theansible
version
before_script:
- yum install httpd -y
- yum install -y python3
- ansible --version
- In the
run
section we are running the ansible playbook
run:
stage: run
script:
- ansible-playbook main.yml --vault-password-file=password.txt
Step 5:- Check the output
- Now, As soon as you commit your workflow file GitLab will trigger the action and the resources will be going to create on the AWS account.
- After running the job you will see that all the steps run perfectly and there was no error. So you will have
passed
written in the green color as each step job successfully.
- You can also check the output of each step by clicking on it
Step 6:- Check the resources on AWS
- As soon as the job finishes to run you can navigate to AWS and check all the resources
- Ansible will create below resources
- VPC
2. Subnets
3. Internet Gateway
4. Rouet Table
5. Security Group
6. Key Pair
7. EC2 Instance
That’s it now, you have learned how to integrate Ansible with GitLab CI/CD. You can now play with it and modify it accordingly.
If you found this guide helpful then do click on 👏 the button and also feel free to drop a comment.
Follow for more stories like this 😊