Practice Session 4: Ansible automation tool
Make sure that you have already gone through Lab-03
Ansible is a simple automation engine that automates cloud provisioning, configuration management, application deployment, intra-service orchestration, and many other needs. It uses the YAML language that you have used in Lab-02, in the form of Ansible Playbooks, and that allows you to describe your automation jobs in a way that approaches plain English. The aim of this lab is to get acquainted with the Ansible automation tool and get to know its most commonly used commands.
Introduction to Ansible
Ansible works by connecting to your nodes and pushing out small programs, called "Ansible modules" to them. These programs are written to be resource models of the desired state of the system. Ansible then executes these modules (over SSH by default) and removes them when finished.
References
Referred documents and websites contain supportive information for the practice.
Manuals
- How Ansible works
- Demo of this lab. This may not have very exact steps.
Prerequisite: Preparing the VMs
Lets manually create 3 VMs:
- VM1: (Centos7, m3.tiny, allow-all security group, Assign floating IP)
- VM2: (Centos7, m3.xsmall, allow-all security group, Assign floating IP)
- VM3: (Centos7, m3.xsmall, allow-all security group, Assign floating IP)
- imp: Configure the VMs so that you can login (using
ssh
) to VM2 and VM3 from VM1- If you have private key with extension .ppk, than convert from .ppk to .pem(openssh base64 format). Manual here
- Windows users (using gitbashm) and Linux users (bash), can use scp to copy the key file
scp -i <SSH_KEY_FILE> <SSH_KEY_FILE_TO_COPY> centos@<VM1_IP>:/home/centos/.ssh/
- Make sure that the key file is in
.pem
format.
- Install git
sudo yum install git
- Install
python3.6
on VM1 you may refer this manualpython --version
- Install
pip v21.2.4
on VM1pip --version
Usage
VM1: Used for installing Ansible and managing other VMs.
VM2 & VM3: Used for Kubernetes cluster deployed using Ansible.
Exercise 1. Installation and basic configuration of Ansible v2.9.
The goal of this task is to get aquinted with installation of Ansible using pip and configure the ansibel to manage other virtual machines remotely.
Note: you can use your local machine, but we recommend creating the virtual machine instead.
Installing Ansible on VM1
Here we will install Ansible on Centos using pip
- Make sure that you have
pip v21.2.4
andpython3.6
- Install Ansible
pip install ansible
- Check ansible verison
ansible --version
- Make sure that you have
Exercise 2. Basic Ansible commands
The aim of this task is to make you to learn basic ansible commands.
Make sure that your in VM1
2.1. Basic ansible commands to check hosts and version
- Check for ansible version using
ansible --version
Sample Output:
- List all the ansible hosts
ansible --list-hosts all
Sample Output:
- List localhost hosts
ansible --list-hosts localhost
Sample Output:
- Check for ansible version using
2.2. Ansible Hosts/inventories file
Inventories: Ansible works against multiple managed nodes or “hosts” in your infrastructure at the same time, using a list or group of lists know as inventory. The default location for inventory is a file called /etc/ansible/hosts
. You can specify a different inventory file at the command line using the -i <path>
option. For more information on inventory follow here....
From ansible --list-hosts all
and ansible --list-hosts localhost
commands, all and localhost are some group of machines with related information, that are expected to be present in default /etc/ansible/hosts
file.
Note!!! Since you the ansible using pip, you cannot see the default hosts file at /etc/ansible/hosts
- So, Now lets create hosts.yaml file
vi hosts.yaml
and copy the following content.
[iotusecase] VM2 ansible_host=172.17.90.248 ansible_port=22 ansible_user=centos ansible_ssh_private_key_file=/home/centos/.ssh/chinmayadehury VM3 ansible_host=172.17.91.168 ansible_port=22 ansible_user=centos ansible_ssh_private_key_file=/home/centos/.ssh/chinmayadehury
- Modify with your key name instead of chinmayadehury
- Change the IPs of iot-cluster-master and iot-cluster-worker with VM2 and VM3
- [iotusecase] is the custom tag used to group your VMs and it can be changed.
- Here, hosts.yaml file contains with the required information to connect to the other VMs (i.e. VM1 and VM2 and VM3) such as username or private_key or port are used for ssh connection etc,.
note: Writing $HOME
instead of /home/centos
may not work.
- The hosts.yaml can also have hostname or the IP address of other VMs. Use can use either of one. Hence the minimal version would be:
[iotusecase] 172.17.90.248 172.17.91.168 172.17.89.193
2.3. Basic tasks using Ansible
The ansible
command defines and run a single task playbook against a set of hosts. The ansible-doc <module-name>
is a handy command to know more about a specific module.
- Now lets ping all servers in
iotusecase
groupansible -m ping iotusecase -i hosts.yaml
Sample Output:
NOTE:ping
module is useful from/usr/bin/ansible
to verify the ability to login and that a usable Python is configured. This is NOT ICMP ping, this is just a trivial test module that requires Python on the remote-node. - Execute
pwd
command in all servers iniotusecase
groupansible -m command -a "pwd" iotusecase -i hosts.yaml
Sample Output:
NOTE: The given command with-a "command name"
option will be executed on all selected nodes. - Execute
ls
command in all servers iniotusecase
groupansible -m command -a "ls" iotusecase -i hosts.yaml
Sample Output:
- Execute
ls
command in all servers iniotusecase
group with a private key. Change the private key name according to your ssh_key_name with chinmayadehury
- Now lets ping all servers in
ansible -m command --private-key .ssh/chinmayadehury -a "ls" iotusecase -i hosts.yaml
Sample Output:
- Execute
ls
command in all servers iniotusecase
group insidemyinven_list
inventory list with a private key.myinven_list
is present in my present directory (this is similar to/etc/ansible/hosts
inventory file.)ansible -m command --private-key .ssh/chinmayadehury -a "ls" -i myinven_list iotusecase
Sample Output
- Create a directiry in the remote VM using
command
module:ansible remote -m command -a "mkdir /home/centos/mydir1" -i hosts.yaml
NOTE: hereremote
is a host group (similar toiotusecase
).
Sample Output:
- Create a directiry in the remote VM using
file
module:ansible remote -m file -a "path=/home/centos/mydir2 state=directory" -i hosts.yaml
NOTE: Here again I am usingremote
host group (similar toiotusecase
).
Sample Output:
- Transfer a file from local VM to the remote VM using
copy
module:ansible remote -m copy -a "src=/home/centos/my_ansible_dir/playbooks/mydummyfile dest=/home/centos/" -i hosts.yaml
- Execute
Exercise 3. Working with Ansible Playbook
Ansible command line is great for executing a single task. But playbooks are more useful for multiple tasks. Playbooks are text files written in the YAML format. You can check http://www.yamllint.com/ or other alternatives to validate your YAML file.
The basic command to invoke any playbook is:ansible-playbook <path to your playbook>
Make sure that your in VM1
3.1. Playbook for file/directory operation
Following playbook will let you execute above Ansible commands, e.g create new directory, new files, copy file from local machine to remote machine, print the message, etc.
Create your first playbok with following content.
vi play-1.yaml
--- - hosts: remote tasks: - name: what is the present working directory command: pwd register: out - debug: var: out.stdout_lines - debug: msg: "present working directory is: {{out.stdout_lines}}" - name: See what is in the current directory command: ls register: lsout - debug: msg: "output of ls command: {{lsout.stdout_lines}}" - name: create a new directory file: path: /home/centos/mydir3 state: directory - name: Create an empty file inside new directory file: path: /home/centos/mydir3/emptyfile.txt state: touch - name: copy the file from local vm to the remote vm copy: src: /home/centos/my_ansible_dir/playbooks/lists dest: "/home/centos/mydir3/" - name: "list of files inside that new directory" shell: "ls /home/centos/mydir3/" register: lsout - debug: msg: "list of files inside that new directory: {{lsout.stdout_lines}}"
NOTE: Update the remote group name in the second line of above content ( hosts: remote
) based on your inventory file and host group name.
Ansible playbook command:
ansible-playbook play-1.yaml -i hosts.yaml
Sample Output:
You may visit below source for more information
3.2. Package install/remove/reinstall/download operation
Below is a playbook example for working with package management (using yum
module).
Note: Follwing things will work only on the centos Operating sytem.
vi install-packages.yaml
--- - hosts: remote gather_facts: true become: true become_method: sudo tasks: - name: Install the latest version of vim editor yum: name: vim state: latest - name: Download the nano editor package but do not install it yum: name: - nano state: latest download_only: true download_dir: "/home/centos/" - name: Install the latest version of Apache yum: name: httpd state: latest - name: Start apache service service: name: httpd state: started
NOTE: Update the remote group name in the second line of above content ( hosts: remote
) based on your inventory file and host group name.
Command:
ansible-playbook install-packages.yaml -i hosts.yaml
Sample Output:
Now go to the browser and test if apache web server is accessible, like below:
Figure out if you are unable to access the apache test page.
Hint:
- login to the remote VM and check if the httpd server is running
- Check the security group of the remote VM.
3.3. Playbook to stop and remove a package
Below playbook will stop the previously started apache server and remove/uninstall from the system
Note: Following playbook will work only on the centos Operating sytem.
vi remove_package.yaml
================================
--- - hosts: remote gather_facts: true become: true become_method: sudo tasks: - name: Stop service httpd, if started service: name: httpd state: stopped - name: Remove the Apache package yum: name: httpd state: absent
NOTE: Update the remote group name in the second line of above content ( hosts: remote
) based on your inventory file and host group name.
Command:
ansible-playbook remove_package.yaml -i hosts.yaml
Sample Output:
Exercise 4. Install Docker
Now you will install Docker using Ansible playbook.
vi install-docker.yaml
================================
--- - hosts: iotusecase gather_facts: true become: true become_method: sudo tasks: - name: Create target directory file: path=/etc/docker/ state=directory mode=0755 - name: configure docker network address, ahead of time, to solve issues with docker default network collision with UT VPN lineinfile: path: /etc/docker/daemon.json line: | { "default-address-pools": [{"base":"172.80.0.0/16","size":24}] } owner: root group: root mode: '0644' create: yes - name: add the official Docker repository, download the latest version of Docker, and install it shell: "curl -fsSL https://get.docker.com/ | sh" - name: Start and enable docker service service: name: docker enabled: true state: started
NOTE: Update the remote group name in the second line of above content ( hosts: remote
) based on your inventory file and host group name.
Command:
ansible-playbook install-docker.yaml -i hosts.yaml
Sample Output:
Exercise 5. Creating a K8 cluster using Ansible
You will use Kubespray
, that uses ansible script to install and configure kubernetes cluster.
Now make sure that you have following:
- One VM for Master (i.e. VM2)
- Centos7, m3.xsmall, allow-all security group, Assign floating IP
- One VM for Worker (i.e. VM3)
- Centos7, m3.xsmall, allow-all security group, Assign floating IP
Kubespray src:
- Official resources for Kubespray GitHub Repo
- Production environment using kubespray : https://kubernetes.io/docs/setup/production-environment/tools/kubespray/
The following commands need to be run on VM1
- Download the kubespray package by cloning the github repo and install all the kubespray requirements using python pip3.
git clone https://github.com/kubernetes-sigs/kubespray.git
cd kubespray
- Just have a quick look at the files present in
kubespray
directory. - Now either you can install all the packages present in
requirements.txt
file usingpip install -r requirements.txt
OR selectively install following packages:pip install ansible-base
pip install ruamel.yaml
pip install ruamel.yaml.clib
- Please use
pip show <package name>
command to see if the package is already installed.
- Copy the kubespray files to your own folder.
cp -rfp inventory/sample inventory/mycluster
- Folloing commands will prepare
hosts.yml
file (It's not same as earlier host.yaml file) specifying the hosts and their roles in the cluster.Declare a variable IPs specifying internal IPs of both the servers.- The command to declare is
declare -a IPS=(<internal_ip_of_node1> <internal_ip_of_node2>)
- Use the variable IPS to build up a config file
hosts.yml
using the below command- Configure hosts.yaml using this command
CONFIG_FILE=inventory/mycluster/hosts.yaml python3 contrib/inventory_builder/inventory.py ${IPS[@]}
- Configure hosts.yaml using this command
- Now have a look at the following file,
cat inventory/mycluster/hosts.yaml
- The command to declare is
- Deploy with
ansible-playbook
command- Deploy Kubespray with Ansible Playbook - run the playbook as root. The option
--become
is required, as for example writing SSL keys in/etc/
, installing packages and interacting with various systemd daemons. Without--become
the playbook will fail to run! - Run the command by changing the <SSH_KEY>
ansible-playbook -i inventory/mycluster/hosts.yaml --become --become-user=root cluster.yml --private-key ~/.ssh/<SSH_KEY>
- Deploy Kubespray with Ansible Playbook - run the playbook as root. The option
The final Sample output should look like below:
- Login to the master node (should be either VM2 or VM3) and enter following command:
kubectl get nodes
If you see below error run the following commands:
Possible Error:
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
- Now you should see following sample output of the
kubectl get nodes
command:
[ src: https://github.com/kubernetes-sigs/kubespray ]
5.1. Deploy your service on k8 cluster
Create a playbook with following content.
vi install-app.yaml
================================
--- - name: create hosts: master gather_facts: true become: true become_user: centos tasks: - name: Create target directory file: path=$HOME/deploy_nginx/ state=directory - name: create the deployment file lineinfile: path: $HOME/deploy_nginx/deploy1.yaml create: yes line: | apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment labels: app: nginx spec: replicas: 3 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:1.14.0 ports: - containerPort: 80 - name: create the deployment by running the kubectl command command: "kubectl create -f $HOME/deploy_nginx/deploy1.yaml" - name: create the service file lineinfile: path: $HOME/deploy_nginx/service1.yaml create: yes line: | apiVersion: v1 kind: Service metadata: name: nginx-service labels: run: nginx-service spec: type: NodePort ports: - port: 80 protocol: TCP selector: app: nginx - name: create the service command: "kubectl create -f $HOME/deploy_nginx/service1.yaml"
Note: Make sure that the alignment is correct.
NOTE: Update the master group in the third line of above content ( hosts: master
) based on your inventory file and host group name. This should refer to the master node (either VM2 or VM3)
- Now execute the playbook:
ansible-playbook install-app.yaml
After Nginx app deployment, go to the master node and execute kubectl get services
command to know the port number.
Get the port number (as shown in below figure)
Now in the browser hit master node's external_ip with the obtained port number(as shown in above fig). Output looks like below.
Take a screenshot of a webpage where your IP address are clearly seen.
5.2. Homework: Deploy your flask application
In this task, your are going deploy the flask application from Practice Session 3 and Exercise 5. This task need to be completed by yourself with minimum instructions noted below. The following are the changes need to make to install-app.yaml from above exercise.
- Create directory
deploy_flask
, and update first task, i.e.Create target directory
task. - Update second task, i.e.
create the deployment file
task, with following hints.- Update the
path
argument inlineinfile
module (from $HOME/deploy_nginx/deploy1.yaml to $HOME/deploy_flask/deploy1.yaml) - Update the deployment name from
nginx-deployment
toflask-deployment
- Update the
labels:
withapp: flask
- Update the container information;
name
,image
,ports
. Also addhostPort: 5000
to theports
list.
- Update the
- Update third task, i.e.
create the deployment by running the kubectl command
task.- Update the path to the yaml. The path should be same to the path of previous (or second) task.
- Update forth task, i.e.
create the service file
task.- Update
path
vlaue, - Update service
name
andlabels
, as per your choice. - Update port number from 80 to 5000
- Update
selector
as well
- Update
- Update the kubectl command accordingly, in the fifth task, i.e.
create the service
task.
Finally, when the playbook is executed (on VM1) you should see the sensor data on the web page, similar to above Exercise 5.1
Take a screenshot of a webpage where your name and IP address are clearly seen.
Deliverables
- Upload the screenshot taken wherever mentioned
- Pack the screenshots into a single zip file and upload them through the following submission form.
- Attach the playbooks from 5.1 and 5.2 in text file
- Your instance must be terminated!
Deadline: 15th Oct 2021
4. Lab 4Bonus Task:
What to do
- Create first VM manually
- Prepare the Ansible playbook to:
- Create VM2 and VM3
- Install K8 and clreat the cluster using kubespray
- Deploy your application atop cluster
Hint:
- To create VMs using Ansible, you need to install Waldur
sudo pip install six, setuptools_rusts, pip install cryptography pip install dataclasses pip install waldur_core pip install waldur_ansible pip install ansible-waldur-module
- Playbook to create VM. (Update
access_token
andmykey
)
--- - hosts: local vars: access_token: "0f4afa15bdc1923015" api_url: "https://api.etais.ee/api/" instance_name: "ansible-vm2" mykey: "chinmayadehury" tasks: - name: Create an instance waldur_marketplace_os_instance: access_token: " {{ access_token }} " api_url: "{{ api_url }}" flavor: m3.tiny floating_ip: auto image: "centos7" name: "{{ instance_name }}" project: "DevOpscourse-internal" offering: "Virtual machine in devops-cloud" ssh_key: "{{ mykey }}" subnet: devops-pi-sub-net system_volume_size: 10 state: "present"
Deliverable (possibly in zip format):
- Don't terminate the VM
- give the Ansible playbooks
- Give output of
ansible --version
command (the screenshot) - Give ansible configuration file