- name: Install Nginx on multiple servers
hosts: web_servers
become: yes
tasks:
- name: Install Nginx
apt:
name: nginx
state: present
when: ansible_os_family == "Debian"
How can you ensure idempotency? (Using state: present
)
How do you handle different OS types? (Use when
conditions for RedHat-based systems)
Ansible doesn’t have built-in rollback, but you can use:
Handlers: To revert actions if a task fails.
Check Mode (--check
) to test before applying changes.
Ansible Playbook Versioning and backups before modifying critical files.
Example using a handler for rollback:
- name: Deploy App
hosts: app_servers
become: yes
tasks:
- name: Deploy application
command: ./deploy.sh
notify: Rollback app
handlers:
- name: Rollback app
command: ./rollback.sh
when: ansible_failed_task is defined
ansible-vault encrypt secrets.yml
ansible-playbook deploy.yml --ask-vault-pass
Use environment variables (lookup('env', 'VAR_NAME')
).
Store secrets in external vaults like HashiCorp Vault or AWS Secrets Manager.
Use serial
to control the batch size:
- name: Update servers in batches
hosts: all_servers
serial: 10
tasks:
- name: Update system packages
apt:
update_cache: yes
upgrade: yes
This ensures updates happen in batches of 10 servers at a time.
ignore_errors: yes
to continue execution even if a task fails.- name: Continue even if a task fails
hosts: all_servers
tasks:
- name: Restart service
service:
name: nginx
state: restarted
ignore_errors: yes
failed_when
to define custom failure conditions.Use the wait_for
module:
- name: Check if port 80 is open
hosts: web_servers
tasks:
- name: Wait for port 80 to be open
wait_for:
port: 80
state: started
timeout: 10
This ensures the playbook waits until the port is available.
gather_facts: no
if facts are not required- hosts: all
gather_facts: no
async
& poll
to run tasks in parallel- name: Run task asynchronously
command: sleep 30
async: 60
poll: 0
Use delegate_to
to avoid redundant executions
Limit SSH connections with forks
(in ansible.cfg)
[defaults]
forks = 20
Use the stat
module to check for the file:
- name: Execute task only if file exists
hosts: all
tasks:
- name: Check if file exists
stat:
path: /etc/config.yml
register: config_file
- name: Execute only if file exists
command: cat /etc/config.yml
when: config_file.stat.exists
ansible-playbook site.yml -vvv
debug
to print variables- debug:
var: ansible_facts['ansible_distribution']
-m ping
)ansible all -m ping
--step
to execute tasks one by one- name: Create a sudo user
hosts: all
become: yes
tasks:
- name: Add user 'devops'
user:
name: devops
state: present
groups: sudo
append: yes
password: "mypassword"
Use run_once: yes
to ensure a task runs only once, regardless of how many hosts are in the inventory.
- name: Execute task on one host only
hosts: all
tasks:
- name: Run task once
command: echo "This will run only once"
run_once: yes
Use serial
to control the number of hosts that can be processed at the same time.
- name: Rolling restart of nginx service
hosts: web_servers
serial: 1
become: yes
tasks:
- name: Restart nginx service
service:
name: nginx
state: restarted
Ansible ensures idempotency. By default, it only installs packages if they are not already present.
- name: Install apache2 package
hosts: web_servers
become: yes
tasks:
- name: Install apache2
apt:
name: apache2
state: present
Use the copy
or template
module to ensure that a file is always present with the desired content.
- name: Ensure configuration file is present
hosts: all
become: yes
tasks:
- name: Copy configuration file
copy:
src: /local/path/to/config.conf
dest: /etc/config.conf
mode: '0644'
Use forks
in the ansible.cfg
configuration file to control parallelism, or serial
in the playbook to control the number of hosts processed at once.
In ansible.cfg
:
[defaults]
forks = 10
Or in the playbook using serial
:
- name: Run tasks in batches
hosts: all
serial: 5
tasks:
- name: Install nginx
apt:
name: nginx
state: present
Use the user
module to add the user to multiple groups.
- name: Add user to multiple groups
hosts: all
become: yes
tasks:
- name: Add user
user:
name: devops
groups: "sudo,docker"
append: yes
17️⃣ How can you execute a shell script on remote servers using Ansible?
✅ Solution:
Use the script
module to copy and execute a local script on remote hosts.
- name: Run shell script on remote server
hosts: all
tasks:
- name: Execute script
script: /local/path/to/script.sh
18️⃣ How can you run a command only if another command succeeds in Ansible?
✅ Solution:
Use register
and when
to run commands conditionally based on previous command results.
- name: Run command only if the previous one succeeds
hosts: all
tasks:
- name: First command
command: echo "First command"
register: result1
- name: Second command
command: echo "Second command"
when: result1.rc == 0
19️⃣ How do you ensure a task is always executed at the end of the playbook? ✅ Solution: Use handlers to ensure certain tasks (like restarts) run at the end, even if other tasks trigger them.
- name: Ensure a task runs at the end
hosts: all
tasks:
- name: Install nginx
apt:
name: nginx
state: present
notify: Restart nginx
handlers:
- name: Restart nginx
service:
name: nginx
state: restarted
20️⃣ How would you handle conditional logic based on host attributes (e.g., operating system type)?
✅ Solution:
Use when
to conditionally execute tasks based on system facts like OS type.
- name: Conditional task based on OS type
hosts: all
tasks:
- name: Install nginx on Debian-based systems
apt:
name: nginx
state: present
when: ansible_os_family == "Debian"
- name: Install nginx on RedHat-based systems
yum:
name: nginx
state: present
when: ansible_os_family == "RedHat"
21️⃣ How do you manage Ansible playbook execution on different environments (dev, staging, prod)? ✅ Solution: You can use inventory files and group variables to manage different environments.
# inventory/production
[web_servers]
prod-web1
prod-web2
# inventory/development
[web_servers]
dev-web1
dev-web2
Define environment-specific variables in group files:
# group_vars/production/web_servers.yml
nginx_port: 80
22️⃣ How do you ensure a task is only run if a file has changed on the target system?
✅ Solution:
Use notify
and handlers to only restart services if a file has changed.
- name: Ensure file is copied only if changed
hosts: all
tasks:
- name: Copy configuration file
copy:
src: /local/path/to/config.conf
dest: /etc/config.conf
mode: '0644'
notify: Restart nginx
handlers:
- name: Restart nginx
service:
name: nginx
state: restarted
❓ How do you ensure that only one instance of a playbook runs at a time?
✅ Use run_once: yes
❓ How do you skip a task for a specific host?
✅ Use when: inventory_hostname != 'server1'
❓ How do you restart a service only when a file changes?
✅ Use notify
& handlers