Automating Server Management with Ansible
Simplify agent-less server management with Ansible using YAML.
What is Ansible?
Ansible is an open-source IT automation tool that simplifies the management and configuration of servers. It uses YAML for its playbook language, making it easy to read and write, and operates without needing an agent on the client machines, relying instead on SSH.
Key Concepts & Terms
- Playbook: A YAML file containing a series of tasks to be executed on a managed node.
- Inventory: A file listing all the managed nodes.
- Task: A single action to be performed, like installing a package or running a command.
- Module: Predefined units of work in Ansible, such as 'apt' for package management.
- Role: A way to group tasks and handlers together to be reusable.
Setting Up Ansible on Ubuntu
Update Your Ubuntu VM
Ensure your system is up-to-date:
sudo apt update
sudo apt upgrade -y
sudo apt-get install qemu-guest-agent
Install Ansible
Add the Ansible PPA and install Ansible:
sudo apt update
sudo apt install software-properties-common -y
sudo add-apt-repository --yes --update ppa:ansible/ansible
sudo apt install ansible -y
Configure SSH Access
Ansible communicates with other servers via SSH. Ensure you have SSH access set up.
Generate an SSH key on your Ansible server if you don’t have one already:
ssh-keygen
ssh-add ~/.ssh/ssh_key
Ensure the user "ansible" exists on your target machine.
sudo adduser ansible
sudo usermod -aG sudo ansible
Copy SSH Key to Target Server:
scp ~/.ssh/ssh_key.pub ansible@<target_server_ip>:/tmp/ssh_key.pub
ssh ansible@<target_server_ip>
mkdir -p ~/.ssh
cat /tmp/ssh_key.pub >> ~/.ssh/authorized_keys
rm /tmp/ssh_key.pub
chmod 600 ~/.ssh/authorized_keys
chmod 700 ~/.ssh
Create an Inventory File
Create an inventory file to list your managed nodes:
mkdir ~/ansible-project
cd ~/ansible-project
nano inventory
Add the following content, replacing target_server_ip
with the IP address of your target server:
[servers]
target_server_ip ansible_user=ansible
Test Connection
Test the connection to your managed node using Ansible:
ansible -i inventory servers -m ping
The correct reply to the ping module is "pong."
Example Playbook 1 - Automate Key Distribution
To avoid repeating the SSH key distribution steps for each server, create an Ansible playbook that is essentially a collection of commands. This playbook will add the SSH key to any machine listed in the inventory file, as long as the ansible user exists on the target machine.
Update the inventory file:
nano inventory
List the IP addresses of all servers:
[servers]
10.10.10.1
10.10.10.2
10.10.10.3
...
[servers:vars]
ansible_user=ansible
ansible_ssh_private_key_file=/root/.ssh/ssh_key
ansible_become=true
ansible_become_method=sudo
ansible_become_password=password
Create a playbook for SSH key distribution:
nano copy_ssh_key.yml
Add the following content:
---
- name: Distribute SSH key to target servers
hosts: servers
become: yes
tasks:
- name: Ensure the .ssh directory exists
file:
path: /home/ansible/.ssh
state: directory
owner: ansible
group: ansible
mode: '0700'
become_user: ansible
- name: Copy the SSH private key to the target server
copy:
src: /root/.ssh/ssh_key.pub
dest: /home/ansible/.ssh/authorized_keys
owner: ansible
group: ansible
mode: '0600'
become_user: ansible
Run the playbook:
ansible-playbook -i inventory copy_ssh_key.yml
Example Playbook 2 - Automating System Updates
Create a playbook to automate system updates:
nano update.yml
Add the following content:
---
- name: Check connectivity and perform updates
hosts: servers
gather_facts: no
tasks:
- name: Ping all servers
ping:
- name: Update apt cache
apt:
update_cache: yes
- name: Upgrade all packages
apt:
upgrade: dist
- name: Check if upgrades were successful
shell: dpkg -l
register: result
- name: Display upgrade result
debug:
var: result.stdout
Run the playbook:
ansible-playbook -i inventory update.yml
Example Playbook 3 - Automating QEMU Guest Agent Installation
As my VMs run on Proxmox, it makes sense to create a playbook for the QEMU Quest Agent installation:
nano qemu.yml
Add the following content:
---
- name: Ensure qemu-guest-agent is installed on servers
hosts: servers
become: true
tasks:
- name: Check if qemu-guest-agent is installed
shell: dpkg -l | grep qemu-guest-agent
register: qga_check
ignore_errors: true
- name: Install qemu-guest-agent if not installed
command: sudo apt-get install -y qemu-guest-agent
when: qga_check.rc != 0
Run the playbook:
ansible-playbook -i inventory qemu.yml
Example Playbook 4 - Automating MeshCentral Deployment
This is specific to my setup; I use MeshCentral to centrally manage my servers and MeshCentral relies on an agent running on the client. This playbook will deploy the MeshCentral agent to the target machines:
nano meshcentral.yml
Add the following content:
---
- name: Deploy MeshCentral if not already installed
hosts: servers
become: true
vars:
meshcentral_script_url: "https://yourmeshcentral.com/meshagents?script=1"
meshcentral_server_url: "https://yourmeshcentral.com"
meshcentral_key: "KsZT9sQmupL8xMMGy3vdF8KHnp7kvTWSxBy5jjQO@HgN4sZtpWu7kpwbRx43syhv"
tasks:
- name: Check if MeshAgent service exists
shell: "systemctl list-unit-files | grep -q meshagent.service"
register: meshagent_service_exists
ignore_errors: true
- name: Download the MeshCentral install script (direct)
get_url:
url: "{{ meshcentral_script_url }}"
dest: /tmp/meshinstall.sh
when: meshagent_service_exists.rc != 0
- name: Download the MeshCentral install script (no proxy)
command: "wget '{{ meshcentral_script_url }}' --no-proxy -O /tmp/meshinstall.sh"
when: meshagent_service_exists.rc != 0
ignore_errors: true
- name: Make the MeshCentral install script executable
file:
path: /tmp/meshinstall.sh
mode: '0755'
when: meshagent_service_exists.rc != 0
- name: Run the MeshCentral install script
command: "/tmp/meshinstall.sh '{{ meshcentral_server_url }}' '{{ meshcentral_key }}'"
environment:
https_proxy: ""
when: meshagent_service_exists.rc != 0
- name: Ensure MeshCentral service is running
service:
name: meshcentral
state: started
when: meshagent_service_exists.rc != 0
Orchestrating Multiple Playbooks
Create a master playbook to run all the other playbooks in sequence:
nano master_playbook.yml
Add the following content:
---
import_playbook: copy_ssh_key.yml
import_playbook: update.yml
import_playbook: qemu.yml
import_playbook: meshcentral.yml
Finally, run the master playbook:
ansible-playbook -i inventory master_playbook.yml
We now have an initial setup to explore Ansible automations and automated server management.
Ansible's flexibility and scalability mean that you can extend these automations further, adding more tasks and refining your playbooks to meet the specific needs of your infrastructure. As you become more familiar with Ansible, you'll discover even more ways to leverage its capabilities, making your IT operations more robust and less error-prone.
Update 24/07/2024: I have published a guide that uses Ansible and Proxmox to automate Proxmox VM deployments.