Operations 12 min read

Master Ansible: Automate Hundreds of Linux Servers with Zero Hassle

This comprehensive guide walks you through why Ansible is the go‑to automation tool, its three core advantages, environment setup, essential configuration files, hands‑on playbooks for system initialization, Nginx clustering and application release, plus advanced tips, monitoring, troubleshooting, and a structured learning roadmap for beginners to experts.

MaGe Linux Operations
MaGe Linux Operations
MaGe Linux Operations
Master Ansible: Automate Hundreds of Linux Servers with Zero Hassle

🚀 Operations Automation Tool: Master Ansible for Managing Hundreds of Linux Servers

Say goodbye to manual ops! One command can manage 1000 servers – the power of Ansible.

Why Choose Ansible?

Traditional operations are painful; Ansible offers a modern, agent‑less, SSH‑based solution that simplifies large‑scale management.

Three Core Advantages

Zero‑dependency deployment

No agent required on target hosts

SSH‑only, inherently secure

Simple YAML syntax lowers learning curve

Idempotent execution

Consistent results on repeated runs

Avoids duplicate‑operation failures

More stable production environment

Rich module ecosystem

Over 3000 built‑in modules

Covers network, storage, cloud platforms, etc.

Active community with continuous updates

Practical Environment Setup

Architecture

Control node: CentOS 8 (Ansible Server)
Target nodes: Ubuntu 20.04 × 10 (Web Servers)

Install Ansible

# CentOS/RHEL
sudo yum install epel-release -y
sudo yum install ansible -y

# Ubuntu/Debian
sudo apt update
sudo apt install ansible -y

# Verify installation
ansible --version

Core Configuration Details

1. Inventory File

Create /etc/ansible/hosts:

[webservers]
web01 ansible_host=192.168.1.10
web02 ansible_host=192.168.1.11
web03 ansible_host=192.168.1.12

[databases]
db01 ansible_host=192.168.1.20
db02 ansible_host=192.168.1.21

[production:children]
webservers
databases

[production:vars]
ansible_user=root
ansible_ssh_private_key_file=~/.ssh/id_rsa

2. SSH Password‑less Login

# Generate key pair
ssh-keygen -t rsa -b 4096

# Distribute public key
for i in {10..12}; do
  ssh-copy-id [email protected].$i
done

3. Optimize ansible.cfg

[defaults]
host_key_checking = False
timeout = 30
forks = 50
gathering = smart
fact_caching = jsonfile
fact_caching_connection = /tmp/ansible_facts_cache
fact_caching_timeout = 3600

[ssh_connection]
ssh_args = -o ControlMaster=auto -o ControlPersist=60s
pipelining = True

Hands‑On Playbooks

Case 1: System Initialization

---
- name: Linux server standardization
  hosts: webservers
  become: yes
  tasks:
    - name: Update apt cache and upgrade
      apt:
        update_cache: yes
        upgrade: dist

    - name: Install basic utilities
      apt:
        name:
          - vim
          - htop
          - curl
          - wget
          - git
          - tree
        state: present

    - name: Set timezone
      timezone:
        name: Asia/Shanghai

    - name: Create devops user
      user:
        name: devops
        groups: sudo
        shell: /bin/bash
        create_home: yes

    - name: Configure firewall
      ufw:
        rule: allow
        port: "{{ item }}"
        proto: tcp
      loop:
        - 22
        - 80
        - 443

Case 2: Nginx Cluster Deployment

---
- name: Deploy Nginx cluster
  hosts: webservers
  become: yes
  vars:
    nginx_version: "1.20.2"
    document_root: "/var/www/html"
  tasks:
    - name: Install Nginx
      apt:
        name: nginx
        state: present

    - name: Create website directory
      file:
        path: "{{ document_root }}"
        state: directory
        owner: www-data
        group: www-data
        mode: '0755'

    - name: Deploy Nginx config
      template:
        src: nginx.conf.j2
        dest: /etc/nginx/sites-available/default
        backup: yes
      notify: restart nginx

    - name: Deploy website files
      copy:
        src: "{{ item }}"
        dest: "{{ document_root }}/"
        owner: www-data
        group: www-data
      with_fileglob: "files/web/*"
      notify: restart nginx

    - name: Ensure Nginx is running
      systemd:
        name: nginx
        state: started
        enabled: yes

  handlers:
    - name: restart nginx
      systemd:
        name: nginx
        state: restarted

Case 3: Application Release Automation

---
- name: Application release pipeline
  hosts: webservers
  serial: 2
  max_fail_percentage: 0
  tasks:
    - name: Health check
      uri:
        url: "http://{{ ansible_host }}/health"
        method: GET
        status_code: 200
      register: health_check
      failed_when: health_check.status != 200

    - name: Remove node from load balancer
      uri:
        url: "http://lb.example.com/api/remove/{{ ansible_host }}"
        method: POST
      delegate_to: localhost

    - name: Stop application service
      systemd:
        name: myapp
        state: stopped

    - name: Backup current version
      archive:
        path: /opt/myapp
        dest: "/opt/backup/myapp-{{ ansible_date_time.epoch }}.tar.gz"

    - name: Deploy new version
      unarchive:
        src: "files/myapp-{{ app_version }}.tar.gz"
        dest: /opt/
        owner: myapp
        group: myapp

    - name: Update configuration
      template:
        src: app.conf.j2
        dest: /opt/myapp/conf/app.conf

    - name: Start application service
      systemd:
        name: myapp
        state: started

    - name: Wait for service to start
      wait_for:
        port: 8080
        host: "{{ ansible_host }}"
        delay: 10
        timeout: 60

    - name: Add node back to load balancer
      uri:
        url: "http://lb.example.com/api/add/{{ ansible_host }}"
        method: POST
      delegate_to: localhost

Advanced Tips & Best Practices

1. Protect Secrets with Ansible Vault

# Create encrypted file
ansible-vault create secrets.yml

# Edit encrypted file
ansible-vault edit secrets.yml

# Use in playbook
- name: Configure database connection
  template:
    src: database.conf.j2
    dest: /etc/myapp/database.conf
  vars:
    db_password: "{{ vault_db_password }}"

2. Dynamic Inventory (Python example)

#!/usr/bin/env python3
import json
import boto3

def get_aws_instances():
    ec2 = boto3.client('ec2')
    response = ec2.describe_instances()
    inventory = {
        '_meta': {'hostvars': {}},
        'webservers': {'hosts': []},
        'databases': {'hosts': []}
    }
    for reservation in response['Reservations']:
        for instance in reservation['Instances']:
            if instance['State']['Name'] == 'running':
                private_ip = instance['PrivateIpAddress']
                tags = {tag['Key']: tag['Value'] for tag in instance.get('Tags', [])}
                if tags.get('Role') == 'web':
                    inventory['webservers']['hosts'].append(private_ip)
                elif tags.get('Role') == 'db':
                    inventory['databases']['hosts'].append(private_ip)
                inventory['_meta']['hostvars'][private_ip] = {
                    'ansible_host': private_ip,
                    'ec2_instance_id': instance['InstanceId'],
                    'ec2_instance_type': instance['InstanceType']
                }
    return inventory

if __name__ == '__main__':
    print(json.dumps(get_aws_instances(), indent=2))

3. Role‑Based Organization

# Create role skeletons
ansible-galaxy init roles/nginx
ansible-galaxy init roles/mysql
ansible-galaxy init roles/monitoring

# Playbook using roles
---
- name: Deploy LAMP stack
  hosts: webservers
  roles:
    - nginx
    - php
    - mysql
    - monitoring

4. Performance Optimizations

# Parallel file transfer
- name: Batch file copy
  copy:
    src: "{{ item }}"
    dest: /tmp/
  with_items: "{{ files_list }}"
  async: 300
  poll: 0
  register: copy_jobs

- name: Wait for all transfers
  async_status:
    jid: "{{ item.ansible_job_id }}"
  register: copy_results
  until: copy_results.finished
  retries: 30
  delay: 10
  with_items: "{{ copy_jobs.results }}"

Monitoring & Troubleshooting

Execution Monitoring

# Verbose run
ansible-playbook -i inventory site.yml -v

# Check mode (dry run)
ansible-playbook -i inventory site.yml --check

# Show differences
ansible-playbook -i inventory site.yml --check --diff

Common Issues

SSH connectivity

# Test connectivity
ansible all -m ping

# Debug SSH
ansible all -m ping -vvv

Privilege escalation

- name: Restart nginx with sudo
  command: systemctl restart nginx
  become: yes
  become_method: sudo

Idempotency problems

- name: Check service status
  systemd:
    name: nginx
  register: service_status

- name: Reload if active
  command: nginx -s reload
  when: service_status.status.ActiveState == "active"

Learning Roadmap

Beginner (1‑2 weeks)

Familiarize with YAML syntax

Master basic Ansible modules

Complete simple system configuration tasks

Intermediate (3‑4 weeks)

Write Playbooks

Use variables and templates

Understand roles and Galaxy

Advanced (2‑3 months)

Develop custom modules

Integrate dynamic inventory

Connect CI/CD pipelines

Manage large‑scale clusters

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Configuration ManagementAnsible
MaGe Linux Operations
Written by

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.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.