How Ansible Can Deploy 100 Servers in 10 Minutes: A Hands‑On Guide
This article explains why Ansible is the preferred automation tool, outlines its core advantages and architecture, and provides a step‑by‑step, code‑rich tutorial—from installing the control node and configuring SSH keys to writing inventories, ad‑hoc commands, Playbooks, Roles, and a real‑world 100‑server deployment case—showing how to achieve massive scaling with minimal effort.
Introduction
Can you deploy Nginx on 100 servers within an hour? The author answered this interview question by using Ansible to finish the job in ten minutes, demonstrating Ansible’s agent‑less, SSH‑based automation that can boost operational efficiency tenfold.
Why Ansible Is the Top Choice for Automation
Core Pain Points of Manual Operations
Low efficiency : manual per‑host configuration is slow and error‑prone.
Inconsistent configurations : leads to hard‑to‑debug differences.
Slow scaling : manual deployment cannot keep up with traffic spikes.
Difficult auditing : lack of change records makes troubleshooting hard.
High knowledge transfer cost : experience is hard to standardize.
Key Advantages of Ansible
Ansible, developed by Red Hat and open‑source, stands out among tools like Puppet, Chef, and SaltStack:
Agent‑less architecture : only SSH and Python are required on target machines, reducing intrusion and maintenance cost.
Easy to learn : YAML Playbooks read like natural language; most ops staff can start within a day.
Idempotent execution : repeated runs produce the same result, preventing drift.
Strong community : 8000+ built‑in modules, Ansible Galaxy roles, active open‑source support.
Ansible Architecture and Workflow
Control node (Ansible host)
↓
SSH to target host
↓
Push temporary Python script
↓
Execute task and return result
↓
Delete temporary fileCore components:
Inventory : defines managed hosts.
Playbook : describes task flow.
Module : individual operation units (yum, copy, service, etc.).
Role : reusable Playbook fragments.
Plugin : extends functionality.
Applicable Scenarios
Bulk server initialization
Application deployment and updates
Configuration file distribution
Scheduled jobs and health checks
Database backup and recovery
Security hardening and compliance
Disaster‑recovery drills
A large e‑commerce company used Ansible on 5,000+ servers, cutting release time from two hours to five minutes and reducing human error from 15% to under 1%.
Hands‑On: From Zero to Mastery
Step 1 – Environment Preparation and Installation
1. Install Ansible on the control node
Recommended Linux control node.
# CentOS/RHEL
sudo yum install -y epel-release
sudo yum install -y ansible
# Or via pip
sudo yum install -y python3-pip
sudo pip3 install ansible
# Verify
ansible --versionSimilar commands are provided for Ubuntu/Debian (using the official PPA) and macOS (Homebrew or pip).
2. Configure SSH key authentication
#!/bin/bash
# setup_ssh_keys.sh – batch configure SSH keys
if [ ! -f ~/.ssh/id_rsa ]; then
ssh-keygen -t rsa -b 4096 -f ~/.ssh/id_rsa -N ""
fi
SERVERS=("192.168.1.10" "192.168.1.11" "192.168.1.12")
SSH_USER="root"
SSH_PASS="your_password"
for server in "${SERVERS[@]}"; do
echo "Configuring $server ..."
sshpass -p "$SSH_PASS" ssh-copy-id -o StrictHostKeyChecking=no ${SSH_USER}@${server}
if [ $? -eq 0 ]; then
echo "✓ $server configured successfully"
else
echo "✗ $server configuration failed"
fi
done
echo "SSH key configuration completed"3. Create project directory structure
mkdir -p ~/ansible-project/{inventories,playbooks,roles,files,templates,vars}
cd ~/ansible-project
# inventories/ – host lists
# playbooks/ – .yml files
# roles/ – reusable components
# files/ – static files to copy
# templates/ – Jinja2 templates
# vars/ – variable filesStep 2 – Inventory Configuration
# inventories/hosts – static inventory example
web1 ansible_host=192.168.1.10 ansible_user=root
[webservers]
web1 ansible_host=192.168.1.10
web2 ansible_host=192.168.1.11
web3 ansible_host=192.168.1.12
[databases]
db1 ansible_host=192.168.1.20
db2 ansible_host=192.168.1.21
[production:children]
webservers
databases
[webservers:vars]
ansible_user=root
http_port=80
max_clients=200
[databases:vars]
ansible_user=root
mysql_port=3306A dynamic inventory script (Python) is also shown for cloud environments.
Step 3 – Ad‑Hoc Commands
Examples include ping, shell commands, package installation, service management, file copying, user creation, and system information gathering, with common flags explained.
Step 4 – Playbook Development
Real‑World Example 1: Deploy Nginx to a Web Farm
# playbooks/deploy_nginx.yml
---
- name: Deploy Nginx to Web Servers
hosts: webservers
become: yes
vars:
nginx_port: 80
nginx_user: www-data
document_root: /var/www/html
tasks:
- name: Install EPEL repo (CentOS only)
yum:
name: epel-release
state: present
when: ansible_distribution == "CentOS"
- name: Install Nginx
yum:
name: nginx
state: present
notify: restart nginx
- name: Create web root directory
file:
path: "{{ document_root }}"
state: directory
owner: "{{ nginx_user }}"
group: "{{ nginx_user }}"
mode: '0755'
- name: Deploy nginx.conf template
template:
src: ../templates/nginx.conf.j2
dest: /etc/nginx/nginx.conf
mode: '0644'
notify: reload nginx
- name: Deploy index.html
copy:
content: |
<!DOCTYPE html>
<html>
<head><title>Welcome to {{ ansible_hostname }}</title></head>
<body>
<h1>Server: {{ ansible_hostname }}</h1>
<p>IP: {{ ansible_default_ipv4.address }}</p>
<p>Deployed by Ansible at {{ ansible_date_time.iso8601 }}</p>
</body>
</html>
dest: "{{ document_root }}/index.html"
owner: "{{ nginx_user }}"
mode: '0644'
- name: Open firewall for HTTP
firewalld:
service: http
permanent: yes
state: enabled
immediate: yes
when: ansible_distribution == "CentOS"
ignore_errors: yes
- name: Start and enable Nginx
systemd:
name: nginx
state: started
enabled: yes
- name: Wait for Nginx to be up
wait_for:
port: "{{ nginx_port }}"
delay: 5
timeout: 30
- name: Verify Nginx response
uri:
url: "http://{{ ansible_default_ipv4.address }}"
status_code: 200
register: nginx_health
- name: Show deployment result
debug:
msg: "✓ Nginx deployed – http://{{ ansible_default_ipv4.address }}"
handlers:
- name: restart nginx
systemd:
name: nginx
state: restarted
- name: reload nginx
systemd:
name: nginx
state: reloadedThe corresponding nginx.conf.j2 template is provided.
Real‑World Example 2: Bulk Server Initialization
# playbooks/init_servers.yml
---
- name: Bulk Initialize Linux Servers
hosts: all
become: yes
vars:
timezone: "Asia/Shanghai"
ntp_servers:
- ntp.aliyun.com
- ntp.tencent.com
admin_users:
- name: deploy
ssh_key: "ssh-rsa AAAAB3... [email protected]"
security_packages:
- firewalld
- fail2ban
tasks:
- name: Set hostname
hostname:
name: "{{ inventory_hostname }}"
- name: Configure /etc/hosts
lineinfile:
path: /etc/hosts
line: "{{ ansible_default_ipv4.address }} {{ inventory_hostname }}"
state: present
- name: Set timezone
timezone:
name: "{{ timezone }}"
- name: Install basic utilities
yum:
name:
- vim
- git
- wget
- curl
- net-tools
- htop
- iotop
- sysstat
- lsof
- telnet
state: present
- name: Install and configure chrony for NTP
block:
- name: Install chrony
yum:
name: chrony
state: present
- name: Deploy chrony.conf template
template:
src: ../templates/chrony.conf.j2
dest: /etc/chrony.conf
backup: yes
notify: restart chrony
- name: Ensure chrony is running
systemd:
name: chronyd
state: started
enabled: yes
- name: Tune kernel parameters
sysctl:
name: "{{ item.key }}"
value: "{{ item.value }}"
state: present
reload: yes
loop:
- { key: 'net.ipv4.tcp_tw_reuse', value: '1' }
- { key: 'net.ipv4.tcp_fin_timeout', value: '30' }
- { key: 'net.ipv4.tcp_keepalive_time', value: '1200' }
- { key: 'net.core.somaxconn', value: '65535' }
- { key: 'vm.swappiness', value: '10' }
- { key: 'fs.file-max', value: '655350' }
- name: Create admin accounts
user:
name: "{{ item.name }}"
shell: /bin/bash
groups: wheel
state: present
loop: "{{ admin_users }}"
- name: Deploy SSH public keys
authorized_key:
user: "{{ item.name }}"
key: "{{ item.ssh_key }}"
state: present
loop: "{{ admin_users }}"
- name: Harden SSH configuration
lineinfile:
path: /etc/ssh/sshd_config
regexp: "{{ item.regexp }}"
line: "{{ item.line }}"
state: present
loop:
- { regexp: '^#?PermitRootLogin', line: 'PermitRootLogin no' }
- { regexp: '^#?PasswordAuthentication', line: 'PasswordAuthentication no' }
- { regexp: '^#?MaxAuthTries', line: 'MaxAuthTries 3' }
- { regexp: '^#?ClientAliveInterval', line: 'ClientAliveInterval 300' }
notify: restart sshd
- name: Open basic firewall ports (CentOS only)
firewalld:
service: "{{ item }}"
permanent: yes
state: enabled
immediate: yes
loop:
- ssh
- http
- https
when: ansible_distribution == "CentOS"
- name: Disable SELinux (optional)
selinux:
state: disabled
when: ansible_distribution == "CentOS"
- name: Clean system caches
shell: |
yum clean all
rm -rf /tmp/* /var/tmp/*
args:
warn: false
- name: System update (optional)
yum:
name: '*'
state: latest
exclude: kernel*
when: update_system | default(false)
handlers:
- name: restart chrony
systemd:
name: chronyd
state: restarted
- name: restart sshd
systemd:
name: sshd
state: restartedReal‑World Example 3: Deploy Docker Environment
# playbooks/install_docker.yml
---
- name: Bulk Install Docker
hosts: all
become: yes
vars:
docker_version: "20.10.24"
docker_compose_version: "2.20.0"
docker_registry_mirrors:
- "https://mirror.ccs.tencentyun.com"
- "https://registry.docker-cn.com"
tasks:
- name: Remove old Docker packages
yum:
name:
- docker
- docker-client
- docker-client-latest
- docker-common
- docker-latest
- docker-engine
state: absent
- name: Install prerequisite packages
yum:
name:
- yum-utils
- device-mapper-persistent-data
- lvm2
state: present
- name: Add Docker repository
yum_repository:
name: docker-ce
description: Docker CE Repository
baseurl: https://mirrors.aliyun.com/docker-ce/linux/centos/$releasever/$basearch/stable
gpgcheck: yes
gpgkey: https://mirrors.aliyun.com/docker-ce/linux/centos/gpg
enabled: yes
- name: Install Docker packages
yum:
name:
- docker-ce
- docker-ce-cli
- containerd.io
state: present
- name: Create /etc/docker directory
file:
path: /etc/docker
state: directory
mode: '0755'
- name: Configure daemon.json
copy:
content: |
{
"registry-mirrors": {{ docker_registry_mirrors | to_json }},
"log-driver": "json-file",
"log-opts": {"max-size": "100m", "max-file": "3"},
"storage-driver": "overlay2",
"exec-opts": ["native.cgroupdriver=systemd"]
}
dest: /etc/docker/daemon.json
mode: '0644'
notify: restart docker
- name: Start and enable Docker service
systemd:
name: docker
state: started
enabled: yes
- name: Install docker‑compose binary
get_url:
url: "https://github.com/docker/compose/releases/download/v{{ docker_compose_version }}/docker-compose-linux-x86_64"
dest: /usr/local/bin/docker-compose
mode: '0755'
- name: Verify Docker installation
command: docker --version
register: docker_version_output
changed_when: false
- name: Verify docker‑compose installation
command: docker-compose --version
register: compose_version_output
changed_when: false
- name: Show installation results
debug:
msg:
- "Docker version: {{ docker_version_output.stdout }}"
- "Docker Compose version: {{ compose_version_output.stdout }}"
- name: Add admin user to docker group
user:
name: deploy
groups: docker
append: yes
when: "'deploy' in ansible_facts.getent_passwd"
handlers:
- name: restart docker
systemd:
name: docker
state: restartedStep 5 – Role‑Based Management
Roles encapsulate reusable logic. Example: a MySQL role with defaults, tasks, handlers, templates, and variables is shown, followed by a Playbook that applies the role to a database host group.
Case Study: Deploy 100 Servers in Ten Minutes
Background
An e‑commerce company needed to scale 100 cloud servers before a major sale. Manual deployment would take days; using Ansible the whole process completed in under ten minutes.
Implementation Steps
Prepare inventory (1 min) : Use a cloud‑API script to generate an Ansible inventory with 100 IPs.
Batch configure SSH keys (2 min) : Distribute the control‑node public key to all hosts with an authorized_key ad‑hoc command.
Execute bulk deployment (7 min) : Run a Playbook that initializes the OS, installs Docker, and starts the application container, using a serial batch size of 20 to avoid network congestion.
Validate results (1 min) : Perform health‑check HTTP requests and ping all hosts to confirm 100 % success.
Key Optimizations
Concurrency control : Set serial: 20 in the Playbook and -f 50 on the command line.
Failure handling : Use max_fail_percentage: 10 and ignore_errors: yes on non‑critical tasks.
Performance tuning : Adjust forks = 50, enable SSH pipelining, and cache facts in ansible.cfg.
Results
Deployment time: 9 min 38 s (including init, software install, app rollout).
Success rate: 100 % (100/100).
Average per‑host time: 5.8 s.
Human effort: 1 operator.
Cost saving: >2.5 days of manual work avoided.
Best Practices and Advanced Tips
Organize Playbooks with include_tasks and import_playbook for modularity.
Understand variable precedence (CLI > Playbook vars > Role vars > Inventory host/group vars > Role defaults).
Encrypt secrets with ansible‑vault and store them in version control.
Use block‑rescue‑always for robust error handling and cleanup.
Develop custom modules (example check_port.py) when built‑in modules are insufficient.
Future Outlook
Adoption of Ansible AWX/Tower for web‑based orchestration.
Event‑driven Ansible for automated incident response.
Deep integration with Kubernetes, Terraform, and cloud‑native ecosystems.
AI‑assisted Playbook generation and self‑healing automation.
Mastering Ansible can increase operational efficiency by an order of magnitude; start replacing repetitive manual tasks with Ansible today for a more elegant and reliable workflow.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
MaGe Linux Operations
Founded in 2009, MaGe Education is a top Chinese high‑end IT training brand. Its graduates earn 12K+ RMB salaries, and the school has trained tens of thousands of students. It offers high‑pay courses in Linux cloud operations, Python full‑stack, automation, data analysis, AI, and Go high‑concurrency architecture. Thanks to quality courses and a solid reputation, it has talent partnerships with numerous internet firms.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
