Ansible is an open source, command-line IT automation software application written in Python. It can configure systems, deploy software, and orchestrate advanced workflows to support application deployment, system updates, and more.
Ansible’s main strengths are simplicity and ease of use. It also has a strong focus on security and reliability, featuring minimal moving parts. It uses OpenSSH for transport (with other transports and pull modes as alternatives), and uses a human-readable language (YAML) that is designed for getting started quickly without a lot of training.
The architecture of our setup is as shown below:
ANSIBLE CLIENT AS A JUMP SERVER (Bastion Host)
A Jump Server (sometimes also referred as Bastion Host) is an intermediary server through which access to internal network can be provided. In this project, we shall:
- set up ssh-agent to store our key pairs and render them for use when needed.
- Use our Ansible server as a bastion host through we shall be able to ssh into our webservers (ideally) locked away in the private subnets using their individual private IPs.
- Create a simple Ansible playbook to automate servers configuration; Exhibit test automation to run configurations on our diffrent servers without leaving our ansible server.
- Configure Jenkins build job to save our repository content every time changes are made.
- explore git version control actions; clone repository, create branches to simulate production environment, run git status, add changes to the staging index, run git commits, push our changes to github, create pull requests and ultimately merge changes.
-
Update Name tag on your Jenkins EC2 Instance to Jenkins-Ansible. We will use this server to run playbooks.
-
In your GitHub account create a new repository and name it Ansible-config
-
Install Ansible
sudo apt update
sudo apt install ansible
Check your Ansible version by running ansible --version
- Configure Jenkins build job to save your repository content every time you change it.
- Create a new Freestyle project 'ansible' in Jenkins and point it to your ‘ansible-config-mgt’ repository.
- Configure Webhook in GitHub and set webhook to trigger ansible build.
- Configure a Post-build job to save all (**) files.
- Test your setup by making some changes in README.MD file in master branch and make sure that builds starts automatically. Jenkins saves the files (build artifacts) in the following folder
ls /var/lib/jenkins/jobs/ansible/builds/<build_number>/archive/
-
configure VS Code to connect to your newly created GitHub repository.
-
Clone your Ansible repository so you can begin work on it.
- In your ansible-config GitHub repository, create a new branch that will be used for development of a new feature.
I did this on the vs code terminal using git checkout -b <name of branch>
. This command will create the specified branch and as well checkout to the branch. To confirm this, run git branch
. The checkout branch bears an asterik just before it.
-
Create a directory and name it 'playbooks' – it will be used to store all your playbook files.
-
Create a directory and name it inventory – it will be used to keep your hosts organised.
-
Within the playbooks folder, create your first playbook, and name it common.yml
-
Within the inventory folder, create an inventory file (.yml) for each environment (Development, Staging Testing and Production) dev, staging, uat, and prod respectively.
- Set up ssh agent, add key pair and ssh into your jenkins-ansible server using ssh agent.
On my local system, I installed open-ssh server and client as well as ssh agent. This was followed by adding my aws key pair to ssh agent using ssh-add <key pair>
and confirmed with ssh-add -l
. Since this is the key pair used in creating all my servers, SSH into these servers is made easy by simply using ssh -A ubuntu@public IP 0r ssh -A ec2-user@public IP
depending on the linux AMI used. Thus, ssh agent renders the key pair for use when needed.
- Now, ssh into your Jenkins-Ansible server using ssh-agent
- Therefrom exhibit bastion host to ssh into other servers using their private IPs.
- Update your inventory/dev.yml file with this snippet of code:
[nfs]
<NFS-Server-Private-IP-Address> ansible_ssh_user='ec2-user'
[webservers]
<Web-Server1-Private-IP-Address> ansible_ssh_user='ec2-user'
<Web-Server2-Private-IP-Address> ansible_ssh_user='ec2-user'
[db]
<Database-Private-IP-Address> ansible_ssh_user='ubuntu'
[lb]
<Load-Balancer-Private-IP-Address> ansible_ssh_user='ubuntu'
In common.yml playbook, we will write configuration for repeatable, re-usable, and multi-machine tasks that is common to systems within the infrastructure.
- Update your playbooks/common.yml file with following code:
---
- name: update web and nfs servers
hosts: webservers, nfs
remote_user: ec2-user
become: yes
become_user: root
tasks:
- name: ensure wireshark is at the latest version
yum:
name: wireshark
state: latest
- name: update LB and DB server
hosts: lb, db
remote_user: ubuntu
become: yes
become_user: root
tasks:
- name: Update apt repo
apt:
update_cache: yes
- name: ensure wireshark is at the latest version
apt:
name: wireshark
state: latest
- Use git commands to add, commit and push your branch to GitHub.
git status
git add <selected files>
git commit -m "commit message"
git push origin Project11
- Create a Pull request (PR) and merge the code to the master branch.
Once your code changes appear in master branch – Jenkins will do its job and save all the files (build artifacts) to /var/lib/jenkins/jobs/ansible/builds/<build_number>/archive/
directory on Jenkins-Ansible server.
Now that the repository is well updated with the required folders and files, ssh into your jenkins-ansible server and clone the repository.
- Change directory to the cloned folder (
cd Ansible-config
) and run the playbook commandansible-playbook -i inventory/dev.yml playbooks/common.yml
CHALLENGE:
From the image above, it is seen that only the nfs server and web servers had wireshark installed successfully. There was an unending request while trying to intall for both lb and db servers. In an attempt to solve this, I used this command ansible-playbook -i inventory/dev.yml playbooks/common.yml --limit "lb'
to selectively run the playbook on my lb server.
Running the playbook ansible-playbook -i inventory/dev.yml playbooks/common.yml
a second time however installed wireshark on my db server. Upon subsequent unending running of the playbook, simply alting the process with "control c" and running the playbook solved the encounter.
-
I updated my playbook with a command to install httpd on my servers.
-
I used ansible.builtin.package module this time around to boycott having to specify yum or apt in our playbook.
-
This module manages packages on a target without specifying a package manager module (like ansible.builtin.yum, ansible.builtin.apt, …). It is convenient to use in an heterogeneous environment of machines without having to create a specific task for each package manager. This makes work easier especially when one is working with hundreds of servers of which you do not know the specific linux distro used in spinning them.
Here's the snippet of code I updated my playbook with:
FOR NFS and WEB SERVERS
- name: install httpd
ansible.builtin.package:
name: httpd
state: latest
FOR LB AND DB SERVER
- name: install apache2
ansible.builtin.package:
name: apache2
state: latest
N.B: As more and more changes are made in our repository and pushed to github, Jenkins automatically log the changes in /var/lib/jenkins/jobs/ansible/builds/<build_number>/archive/
directory with the build number changing with subsequent push actions. Changing directory to the latest build number folder before running our playbook is important as that is where our updated changes are logged.
- The playbok was run in the appropriate jenkins build log folder and apache was successfully installed on all five instances.
THE END