Ansible Operational Automation Practical Guide (Part 3)

1. Roles Configuration

1.1 What are Roles?

Roles are Ansible’s code reuse mechanism that splits playbooks into reusable components based on functionality.

1.2 Roles Directory Structure

roles/
└── nginx/
    ├── tasks/
    │   ├── main.yml
    │   ├── install.yml
    │   └── config.yml
    ├── handlers/
    │   └── main.yml
    ├── templates/
    │   └── nginx.conf.j2
    ├── files/
    │   └── nginx.repo
    └── vars/
        └── main.yml

2. Creating and Using Roles

2.1 Creating Role Structure

# Create role directory
mkdir -p roles/nginx/{tasks,handlers,templates,files,vars}

2.2 Task Decomposition Example

tasks/main.yml

- include_tasks: install.yml
- include_tasks: config.yml
- include_tasks: service.yml

tasks/install.yml

- name: Install Nginx
  yum:
    name: nginx
    state: present
  tags: install

tasks/config.yml

- name: Configure Nginx
  template:
    src: nginx.conf.j2
    dest: /etc/nginx/nginx.conf
  notify: restart nginx
  tags: config

2.3 Calling Roles

---
- name: Deploy Web Service
  hosts: webservers
  roles:
    - role: nginx
      nginx_port: 80
    - role: mysql
      mysql_version: "8.0"
    - { role: php, when: "php_required|bool" }

3. Advanced Variable Management

3.1 Role Variable Precedence

# roles/nginx/vars/main.yml
nginx_worker_processes: 4
nginx_port: 80

# Override variable in playbook
- hosts: webservers
  roles:
    - role: nginx
      nginx_port: 8080  # Override default value

3.2 Variable Encryption Protection

# Encrypt file
ansible-vault encrypt vars/secrets.yml

# Edit encrypted file
ansible-vault edit vars/secrets.yml

# Run encrypted playbook
ansible-playbook site.yml --ask-vault-pass

4. Conditional Execution and Error Handling

4.1 Complex Conditional Judgments

tasks:
  - name: Configure firewall rules
    firewalld:
      port: "{{ item.port }}/{{ item.protocol }}"
      state: enabled
      permanent: yes
    with_items:
      - { port: 80, protocol: 'tcp' }
      - { port: 443, protocol: 'tcp' }
    when: 
      - ansible_os_family == "RedHat"
      - ansible_distribution_major_version >= "7"

4.2 Block-Level Error Handling

tasks:
  - name: Database deployment block
    block:
      - name: Stop application
        service:
          name: myapp
          state: stopped
      - name: Execute database migration
        command: /opt/app/db-migrate.sh
      - name: Start application
        service:
          name: myapp
          state: started
    rescue:
      - name: Recovery operation failed
        debug:
          msg: "Database migration failed, executing rollback"
      - name: Rollback database
        command: /opt/app/db-rollback.sh
    always:
      - name: Clean up temporary files
        file:
          path: /tmp/migration.lock
          state: absent

5. Performance Optimization Techniques

5.1 Asynchronous Task Execution

tasks:
  - name: Execute long-running task
    command: /opt/long-running-script.sh
    async: 1800  # Timeout (seconds)
    poll: 0      # Do not poll, continue immediately
  - name: Check asynchronous task status
    async_status:
      jid: "{{ ansible_job_id }}"
    register: job_result
    until: job_result.finished
    retries: 30
    delay: 10

5.2 Fact Caching

# ansible.cfg
[defaults]
gathering = smart
fact_caching = redis
fact_caching_timeout = 3600
fact_caching_connection = localhost:6379

6. Practical Case: Complete Application Stack

6.1 Project Structure

project/
├── site.yml
├── requirements.yml
└── roles/
    ├── common/
    ├── nginx/
    ├── mysql/
    └── app/

6.2 Main Playbook

---
- name: Configure basic environment
  hosts: all
  roles:
    - common

- name: Deploy database
  hosts: dbservers
  roles:
    - mysql

- name: Deploy application
  hosts: appsrvs
  roles:
    - nginx
    - app

6.3 Application Deployment Role

# roles/app/tasks/main.yml
- name: Create application directory
  file:
    path: "{{ app_install_dir }}"
    state: directory
    owner: "{{ app_user }}"
    group: "{{ app_group }}"

- name: Deploy code from Git
  git:
    repo: "{{ app_repository }}"
    dest: "{{ app_install_dir }}"
    version: "{{ app_version }}"
    update: yes

- name: Install Python dependencies
  pip:
    requirements: "{{ app_install_dir }}/requirements.txt"
    virtualenv: "{{ app_venv_path }}"

- name: Execute database migration
  command: "{{ app_venv_path }}/bin/python manage.py migrate"
  environment:
    DATABASE_URL: "mysql://user:pass@{{ db_host }}/app"

- name: Collect static files
  command: "{{ app_venv_path }}/bin/python manage.py collectstatic --noinput"

7. Monitoring and Debugging

7.1 Debug Output

- name: Display debug information
  debug:
    msg: |
      Host: {{ ansible_hostname }}
      Memory: {{ ansible_memtotal_mb }}MB
      System: {{ ansible_distribution }} {{ ansible_distribution_version }}

- name: Display variable content
  debug:
    var: hostvars[inventory_hostname]

7.2 Performance Monitoring

# Display execution time
ansible-playbook site.yml --profile-tasks

# Detailed logs
ansible-playbook site.yml -vvv

# Check syntax
ansible-playbook site.yml --syntax-check

8. Best Practices Summary

8.1 Code Organization

  • Use Roles to organize complex deployments
  • Separate variable files by environment
  • Use Ansible Vault for sensitive data

8.2 Execution Optimization

  • Set forks count appropriately
  • Enable fact caching
  • Use asynchronous tasks for long operations

8.3 Maintenance Recommendations

  • Regularly update Roles
  • Write clear documentation
  • Establish a code review process

Leave a Comment