Introduction
If no one has told you about this yet, then it is imperative for you to know that it is such a wonderful thing to be a Systems person in the current dispensation. The major reason for that is due to the number of tools in the form of technologies that have been developed and matured to help the operations team do their job augmented with a lot of fun and flexibility.
The hard days of manual administration is about to be laid to rest as a new breed of operations that leverages on automation takes the center stage. In order to show you the veracity of what is being applauded by this introductory portion of the guide, we are going to use Ansible to do some simple repetitive tasks such as creating new Linux users and copying files.
Example 1 – Install / Remove software packages on a remote system with Ansible
To install software packages on a remote system, use the package module which works for all systems supported by Ansible. This module actually calls the pertinent package modules for each system (apt, yum, etc). A specific module for OS like yum, apt can also be used.
---
- hosts: all
remote_user: tech
become: true
become_method: sudo
tasks:
- name: Install Single Package using package module
package:
name: vim
state: present
- name: Install Multiple packages using package module
package:
name: ['vim','wget','bash-completion','curl']
state: present
- name: Install package for Specific distro - apache on Debian or Ubuntu
package:
name: apache2
state: present
when: ansible_os_family == "Debian"
- name: Install package for Specific distro - apache on CentOS / RHEL / Fedora
package:
name: httpd
state: present
when: ansible_os_family == "RedHat"
To remove a package, the state value should be set to absent.
Example 2 – Start / Stop Services on remote systems with Ansible
For service management, we’ll use the service module. We installed the Apache web server in Step 1, here we’ll start the service and set it to start at boot.
Since the service name is not the same for Debian and RedHat family, we have to Ansible condition.
---
- hosts: all
remote_user: tech
become: true
become_method: sudo
tasks:
- name: Install Single Package using package module
package:
name: vim
state: present
- name: Start apache service on Debian or Ubuntu
service:
name: apache2
state: started
enabled: yes
when: ansible_os_family == "Debian"
- name: Start apache service on CentOS / RHEL / Fedora
service:
name: httpd
state: started
enabled: yes
when: ansible_os_family == "RedHat"
See all supported paramaters on Ansible service module documentation page.
Example 3 – Execute shell commands/script with Ansible
This example will demonstrate how to execute shell commands and shell script on the remote system.
---
- hosts: all
remote_user: tech
become: true
become_method: sudo
tasks:
- name: Get Top 5 CPU consuming processes
shell: ps aux | sort -nrk 3,3 | head -n 5
register: top
- name: Get Disk partitioning
shell: df -hT
register: df
- debug: var=top.stdout_lines
- debug: var=df.stdout_lines
You can also copy a local script to the server and execute it.
---
- name: Copy and execute a script.
hosts: web-servers
remote_user: user1
become: yes
become_method: sudo
tasks:
- name: Copy local script to remote systems
copy:
src: myscript.sh
dest: /home/user1/myscript.sh
mode: 0777
- name: Execute a script on remote server
command: sh /home/user1/myscript.sh
See my output below.
Example 4: Synchronize multiple directories from a remote Linux system to your local machine
For this to work, install rsync in your remote server since the Ansible module synchronize uses it. If you are keen, you will notice we are using “pull” mode of synchronize module to make this possible.
---
- hosts: portal
remote_user: tech
become: true
become_method: sudo
tasks:
- name: Fetch Log Files from portal server and save them to local
synchronize:
src: "{{ item.source }}"
dest: "{{ item.dest }}"
mode: pull
with_items:
- { source: '/var/log/apps/Database/2019-08-07', dest: '/home/jtech/Documents/test3/Database' }
- { source: '/var/log/apps/Exceptions/2019-08-07', dest: '/home/jtech/Documentss/test3/Exceptions' }
- The hosts: portal is the remote server you expect to pull files from
- source is the remote server’s directories you intend to pull and
- dest is your local directories that will receive resources from the remote server.
Example 5: Adding users to a remote server using Ansible
The following is a yaml playbook that is going to add a user to many remote systems, add the user to respective sudoers file and copy the user’s public key to the remote servers. In the past, in case you wanted to add a new user to a couple of servers all of these would involve a lot of painful keyboard punching to get the work done. To use this playbook, we assume the following:
- Ansible installed on the client machine
- Another user (tech in this example) in the remote systems already exists with public keys from client machine copied to them and
- Ansible is able to communicate with the remote servers effectively.
Open your /etc/ansible/hosts file and add the list of your remote servers at the end of the file. An example is shown below. If the ssh ports on the remote systems are not 22 by default, use a full colon and the ssh port number as shown as well.
Generate an encrypted user password:
$ mkpasswd --method=SHA-512 StrongUserPassword
$6$w4LFQ39hZz5$l9Uv3rMCJGqHuU1MbXFpJohY/zuDXNxQJhI3Y5wKvgxnaXnnQ/HnqHWhbgwr1w.7Xo.1yOAZ4AJuKAhUNvqhi.
$ mkpasswd --method=SHA-512
Password:
$6$rz9Cx4SvxntT7pQp$VyWqxxkp4GNYml3t8Jlfo/DUXP4ELtfnLGq42GkhAIHq7VWuPRoFSl795rF1JOMycHmmYFTaYSRVO4/nZpWWm.
# With python passlib module
sudo pip install passlib
python -c "from passlib.hash import sha512_crypt; print sha512_crypt.encrypt('StrongUserPassword')"
The Playbook: users.yml
$ sudo vim /etc/ansible/hosts
[web-servers]
192.168.10.20
192.168.10.31:2023
192.168.10.50
Create playbook.
---
- hosts: "web-servers"
remote_user: tech
become: true
become_method: sudo
vars:
users:
- "harry"
tasks:
- name: "Create user Harry in the remote web-servers"
user:
name: "{{ item }}"
password: <encrypted-password>
groups: "wheel"
update_password: always
register: user_created
with_items: "{{ users }}"
- name: "Add authorized keys"
authorized_key:
user: "{{ item }}"
key: "{{ lookup('file', '/home/harry/.ssh/id_rsa.pub') }}"
# key: "{{ lookup('file', 'files/'+ item + '.key.pub') }}"
with_items: "{{ users }}"
- name: Add user "harry" to sudo
lineinfile:
path: /etc/sudoers.d/harry
line: 'harry ALL=(ALL) NOPASSWD: ALL'
state: present
mode: 0440
create: yes
validate: 'visudo -cf %s'
- name: Force user to change password
shell: chage -d 0 {{ item }}
when: user_created.changed
Save this file in a directory of your choice and then run:
# ansible-playbook users.yml -u tech -K
It will ask you for become password. Enter the password for the remote user in the system.
Example 6: Auto-create directories on your local machine and copy files in them from remote server.
Let’s say you often need to copy files from your remote server to your local machine and you are finally tired of copying them manually and now you would wish to use the efficiency of Ansible. The files in the remote server may be located in say:
/var/log/applications/web/20-08-08/,
/var/log/applications/frontend/20-08-08/,
/var/log/applications/backend/20-08-08/,
/var/log/applications/frontend1/20-08-08/ and
/var/log/applications/sockets/20-08-08/
/var/log/applications/others/20-08-08/
To copy the files in 20-08-08 sub-directories in the respective directories on your local machine neatly, you would need to create the respective directories to match what exists on your remote server. An example is creating files such as:
/home/tech/logs/web/20-08-08/,
/home/tech/logs/frontend/20-08-08/,
/home/tech/logs/backend/20-08-08/,
/home/tech/logs/frontend1/20-08-08/ and
/home/tech/logs/sockets/20-08-08/
/home/tech/logs/others/20-08-08/
Instead of manually creating those dierctories, Ansible can do it for you as described in this guide.
First, Ansible will auto-create the /home/tech/logs/ parent directory and then auto-create the various sub-directories (web,frontend,backend,frontend1,sockets) in it. Finally, the 20-08-08 sub-directories will be synchronized with your remote server’s sub-directories. You will find 20-08-08 directory and all of its files within it neatly copied on your local machine. Let us create the playbook to do this job.
Step One: Create a variables file in whatever directory and input all of your variables.
$ vim vars.yml
---
LOCAL_PROJECT_DIRECTORY: "/home/tech/logs"
REMOTE_PROJECT_DIRECTORY: "/var/log/applications"
Step Two: Add your remote server to hosts file. This can be in your default file or on any host file you create.
$ sudo vim /etc/ansible/hosts
#Add your host
[remoteserver]
192.168.20.23
Step Three: Create your playbook to copy the directories and files for you
$ vim playbook.yml
---
- hosts: 127.0.0.1 # Create directories and sub-directories in local machine in this play
vars_files:
./variables1/vars.yaml
tasks:
- name: Auto-Create Local parent project directory {{ LOCAL_PROJECT_DIRECTORY }} and sub-directories
file: path={{ LOCAL_PROJECT_DIRECTORY }}/{{ item }} state=directory
with_items:
- web
- frontend
- backend
- Database
- frontend1
- sockets
- others
- hosts: remoteserver # Copy directories and files in local machine from remoteserver in this play
vars_files:
./variables1/vars.yaml
become: true
tasks:
- name: Fetch stuff from your remote server and save to locally autocreated directorie
become: yes
synchronize:
src: "{{ REMOTE_PROJECT_DIRECTORY }}/{{ item }}/20-08-08"
dest: "{{ LOCAL_PROJECT_DIRECTORY }}/{{ item }}/"
mode: pull
with_items: web
- frontend
- backend
- Database
- frontend1
- sockets
- others
After you are done with that, it is time to run your playbook,
# ansible-playbook playbook.yaml -u tech -K
Input your sudo password on remote server and hit enter.
Example 7: Remove Old users in your system
---
- hosts: servers
remote_user: tech
become: true
become_method: sudo
vars:
users:
- "jack"
- "tom"
- "sharon"
- "tech"
- "pench"
tasks:
name: "Remove old users out of the system"
user:
name: "{{ item }}"
state: "absent"
with_items: "{{ users }}"
Example 8: Checkout files from SVN server and copy them to a remote server
If you would wish to pull files from your subversion server and maybe copy them over to another location on a remote server with one Ansible command, then this guide shows how it can be done. Please follow through.
Step One: Create a variables file in whatever directory and input all of your variables.
$ vim vars.yml
---
LOCAL_PROJECT: "/home/tech/svn"
REMOTE_PROJECT: "/var/log/applications"
Step Two: Add your remote server to hosts file. This can be in your default file or on any host file you create.
$ sudo vim /etc/ansible/hosts
[remoteserver]
192.168.20.27
Step Three: Create a playbook to checkout files from subversion server to local machine and copy them to remote server automatically.
$ vim playbook.yml
---
- hosts: 127.0.0.1
vars_files:
- ./variables1/vars.yaml
tasks:
- name: Auto-Create Local project directory
file: path={{ LOCAL_PROJECT }}/{{ item }} state=directory
with_items:
- App
- name: Checkout subversion repository to the created directory/folder
subversion:
repo: https://path/to/your/subversion/
username: user1
password: strongpassword
checkout: yes
update: yes
in_place: yes
dest: "{{ LOCAL_PROJECT }}/{{ item }}"
with_items:
- App
- hosts: worker1
vars_files:
- ./variables1/vars.yaml
tasks:
- name: Auto-Create Remote project directory
become: yes
file: path={{ REMOTE_PROJECT }}/{{ item }} state=directory
with_items:
- Application
- name: Copy the checked-out files to remote server via Synchronize
become: yes
synchronize:
src: "{{ LOCAL_PROJECT }}/{{ item.local }}/"
dest: "{{ REMOTE_PROJECT }}/{{ item.remote }}"
with_items:
- { local: 'App', remote: 'Application' }
Step Four: Since the playbook has sensitive data, that is, username and password, let us encrypt it with ansible-vault so that nobody can view your stuff.
Encrypt your playbook file as shown below. Enter a password and you will be good to go.
$ ansible-vault encrypt playbook.yml
New Vault password:
Confirm New Vault password:
Encryption successful
After that is complete, proceed to run your playbook with the options shown. It will prompt for sudo password for user1 and the ansible-vault password you have just entered above.
$ ansible-playbook playbook.yml --ask-vault-pass -u user1 -K
BECOME password:
Vault password:
PLAY [127.0.0.1]
***********************************************************************
TASK [Gathering Facts]
***********************************************************************
ok: [127.0.0.1]
Recommended Ansible Books:
Conclusion
Ansible can do much more complex things jus to ease your work as an Administrator. The guide was to simply show that it can handle even the simplest of tasks that can take up much of your time for no reason. Stay tuned for easier to follow guides.
Also read:
- How to use scp command to securely transfer files with examples
- Top 10 Free Backup software for Linux
- netstat vs ss usage guide on Linux
- How to use rsync command on Linux/Unix with examples
- How to Check TCP connections States in Linux with Netstat
- How to extract .xz files on Linux – CenOS / Ubuntu / Debian
- How To Customize Qcow2/Raw Linux OS disk image with virt-customize