ansible-roles

安装量: 52
排名: #14323

安装

npx skills add https://github.com/thebushidocollective/han --skill ansible-roles

Ansible Roles

Structure and reuse automation code with Ansible roles for modular, maintainable infrastructure.

Role Directory Structure

A well-organized Ansible role follows a standardized directory structure:

roles/ └── webserver/ ├── README.md ├── defaults/ │ └── main.yml ├── files/ │ ├── nginx.conf │ └── ssl/ │ ├── cert.pem │ └── key.pem ├── handlers/ │ └── main.yml ├── meta/ │ └── main.yml ├── tasks/ │ ├── main.yml │ ├── install.yml │ ├── configure.yml │ └── security.yml ├── templates/ │ ├── nginx.conf.j2 │ └── site.conf.j2 ├── tests/ │ ├── inventory │ └── test.yml └── vars/ └── main.yml

Basic Role Example tasks/main.yml


Main task file for webserver role

  • name: Include OS-specific variables include_vars: "{{ ansible_os_family }}.yml"

  • name: Import installation tasks import_tasks: install.yml tags:

    • install
    • webserver
  • name: Import configuration tasks import_tasks: configure.yml tags:

    • configure
    • webserver
  • name: Import security tasks import_tasks: security.yml tags:

    • security
    • webserver
  • name: Ensure nginx is running service: name: "{{ nginx_service_name }}" state: started enabled: yes tags:

    • service
    • webserver

tasks/install.yml

Installation tasks for webserver role

  • name: Install nginx and dependencies (Debian/Ubuntu) apt: name:

    • nginx
    • nginx-extras
    • python3-passlib state: present update_cache: yes cache_valid_time: 3600 when: ansible_os_family == "Debian"
  • name: Install nginx and dependencies (RedHat/CentOS) yum: name:

    • nginx
    • nginx-mod-stream
    • python3-passlib state: present update_cache: yes when: ansible_os_family == "RedHat"
  • name: Create nginx directories file: path: "{{ item }}" state: directory owner: "{{ nginx_user }}" group: "{{ nginx_group }}" mode: '0755' loop:

    • "{{ nginx_conf_dir }}/sites-available"
    • "{{ nginx_conf_dir }}/sites-enabled"
    • "{{ nginx_log_dir }}"
    • "{{ nginx_cache_dir }}"
    • /var/www/html
  • name: Install certbot for SSL apt: name: certbot state: present when:

    • nginx_ssl_enabled
    • ansible_os_family == "Debian"

tasks/configure.yml

Configuration tasks for webserver role

  • name: Deploy main nginx configuration template: src: nginx.conf.j2 dest: "{{ nginx_conf_dir }}/nginx.conf" owner: root group: root mode: '0644' validate: 'nginx -t -c %s' backup: yes notify:

    • Reload nginx tags:
    • config
  • name: Deploy site configurations template: src: site.conf.j2 dest: "{{ nginx_conf_dir }}/sites-available/{{ item.name }}.conf" owner: root group: root mode: '0644' validate: 'nginx -t -c {{ nginx_conf_dir }}/nginx.conf' loop: "{{ nginx_sites }}" when: nginx_sites is defined notify:

    • Reload nginx
  • name: Enable sites file: src: "{{ nginx_conf_dir }}/sites-available/{{ item.name }}.conf" dest: "{{ nginx_conf_dir }}/sites-enabled/{{ item.name }}.conf" state: link loop: "{{ nginx_sites }}" when:

    • nginx_sites is defined
    • item.enabled | default(true) notify:
    • Reload nginx
  • name: Disable default site file: path: "{{ nginx_conf_dir }}/sites-enabled/default" state: absent when: nginx_disable_default_site notify:

    • Reload nginx
  • name: Configure log rotation template: src: logrotate.j2 dest: /etc/logrotate.d/nginx owner: root group: root mode: '0644'

tasks/security.yml

Security tasks for webserver role

  • name: Generate dhparam file command: openssl dhparam -out {{ nginx_conf_dir }}/dhparam.pem 2048 args: creates: "{{ nginx_conf_dir }}/dhparam.pem" when: nginx_ssl_enabled

  • name: Set secure permissions on dhparam file: path: "{{ nginx_conf_dir }}/dhparam.pem" owner: root group: root mode: '0600' when: nginx_ssl_enabled

  • name: Configure firewall rules (ufw) ufw: rule: allow port: "{{ item }}" proto: tcp loop:

    • "80"
    • "443" when:
    • nginx_configure_firewall
    • ansible_os_family == "Debian"
  • name: Configure firewall rules (firewalld) firewalld: service: "{{ item }}" permanent: yes state: enabled immediate: yes loop:

    • http
    • https when:
    • nginx_configure_firewall
    • ansible_os_family == "RedHat"
  • name: Create basic auth file htpasswd: path: "{{ nginx_conf_dir }}/.htpasswd" name: "{{ item.username }}" password: "{{ item.password }}" owner: root group: "{{ nginx_group }}" mode: '0640' loop: "{{ nginx_basic_auth_users }}" when: nginx_basic_auth_users is defined no_log: yes

Role Variables defaults/main.yml


Default variables for webserver role

These can be overridden in playbooks or inventory

Package and service names

nginx_package_name: nginx nginx_service_name: nginx

User and group

nginx_user: www-data nginx_group: www-data

Directories

nginx_conf_dir: /etc/nginx nginx_log_dir: /var/log/nginx nginx_cache_dir: /var/cache/nginx nginx_pid_file: /var/run/nginx.pid

Main configuration

nginx_worker_processes: auto nginx_worker_connections: 1024 nginx_keepalive_timeout: 65 nginx_client_max_body_size: 10m

Performance tuning

nginx_sendfile: on nginx_tcp_nopush: on nginx_tcp_nodelay: on nginx_gzip: on nginx_gzip_types: - text/plain - text/css - application/json - application/javascript - text/xml - application/xml

Security

nginx_ssl_enabled: no nginx_ssl_protocols: "TLSv1.2 TLSv1.3" nginx_ssl_ciphers: "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256" nginx_ssl_prefer_server_ciphers: on nginx_disable_default_site: yes nginx_configure_firewall: yes nginx_server_tokens: off

Sites configuration

nginx_sites: []

Example:

nginx_sites:

- name: example.com

server_name: example.com www.example.com

root: /var/www/example.com

enabled: yes

ssl: yes

Basic authentication

nginx_basic_auth_users:

- username: admin

password: secretpassword

vars/main.yml

Variables that should not be overridden

nginx_conf_path: "{{ nginx_conf_dir }}/nginx.conf" nginx_error_log: "{{ nginx_log_dir }}/error.log" nginx_access_log: "{{ nginx_log_dir }}/access.log"

OS-specific overrides loaded via include_vars

vars/Debian.yml

nginx_user: www-data nginx_group: www-data nginx_conf_dir: /etc/nginx nginx_service_name: nginx

vars/RedHat.yml

nginx_user: nginx nginx_group: nginx nginx_conf_dir: /etc/nginx nginx_service_name: nginx

Role Handlers handlers/main.yml


Handlers for webserver role

  • name: Reload nginx service: name: "{{ nginx_service_name }}" state: reloaded listen: "reload nginx"

  • name: Restart nginx service: name: "{{ nginx_service_name }}" state: restarted listen: "restart nginx"

  • name: Validate nginx config command: nginx -t changed_when: false listen: "validate nginx"

  • name: Reload firewall service: name: ufw state: reloaded when: ansible_os_family == "Debian" listen: "reload firewall"

Role Templates templates/nginx.conf.j2

{{ ansible_managed }}

user {{ nginx_user }}; worker_processes {{ nginx_worker_processes }}; pid {{ nginx_pid_file }};

events { worker_connections {{ nginx_worker_connections }}; use epoll; multi_accept on; }

http { ## # Basic Settings ## sendfile {{ nginx_sendfile | ternary('on', 'off') }}; tcp_nopush {{ nginx_tcp_nopush | ternary('on', 'off') }}; tcp_nodelay {{ nginx_tcp_nodelay | ternary('on', 'off') }}; keepalive_timeout {{ nginx_keepalive_timeout }}; types_hash_max_size 2048; server_tokens {{ nginx_server_tokens | ternary('on', 'off') }}; client_max_body_size {{ nginx_client_max_body_size }};

include {{ nginx_conf_dir }}/mime.types;
default_type application/octet-stream;

##
# SSL Settings
##

{% if nginx_ssl_enabled %} ssl_protocols {{ nginx_ssl_protocols }}; ssl_ciphers {{ nginx_ssl_ciphers }}; ssl_prefer_server_ciphers {{ nginx_ssl_prefer_server_ciphers | ternary('on', 'off') }}; ssl_dhparam {{ nginx_conf_dir }}/dhparam.pem; ssl_session_cache shared:SSL:10m; ssl_session_timeout 10m;

##
# Logging Settings
##
access_log {{ nginx_access_log }};
error_log {{ nginx_error_log }};

##
# Gzip Settings
##
gzip {{ nginx_gzip | ternary('on', 'off') }};

{% if nginx_gzip %} gzip_vary on; gzip_proxied any; gzip_comp_level 6; gzip_types {{ nginx_gzip_types | join(' ') }};

##
# Virtual Host Configs
##
include {{ nginx_conf_dir }}/sites-enabled/*;

}

templates/site.conf.j2

{{ ansible_managed }}

Site: {{ item.name }}

{% if item.ssl | default(false) %}

Redirect HTTP to HTTPS

server { listen 80; listen [::]:80; server_name {{ item.server_name }}; return 301 https://$server_name$request_uri; }

server { listen 443 ssl http2; listen [::]:443 ssl http2; server_name {{ item.server_name }};

ssl_certificate {{ item.ssl_cert | default('/etc/letsencrypt/live/' + item.name + '/fullchain.pem') }};
ssl_certificate_key {{ item.ssl_key | default('/etc/letsencrypt/live/' + item.name + '/privkey.pem') }};

{% else %} server { listen 80; listen [::]:80; server_name {{ item.server_name }};

root {{ item.root | default('/var/www/' + item.name) }};
index {{ item.index | default('index.html index.htm') }};

{% if item.access_log is defined %} access_log {{ item.access_log }}; {% endif %} {% if item.error_log is defined %} error_log {{ item.error_log }};

{% if item.basic_auth | default(false) %} auth_basic "Restricted Access"; auth_basic_user_file {{ nginx_conf_dir }}/.htpasswd;

location / {

{% if item.proxy_pass is defined %} proxy_pass {{ item.proxy_pass }}; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; {% else %} try_files $uri $uri/ =404; {% endif %} }

{% if item.locations is defined %} {% for location in item.locations %} location {{ location.path }} { {% if location.proxy_pass is defined %} proxy_pass {{ location.proxy_pass }}; {% endif %} {% if location.alias is defined %} alias {{ location.alias }}; {% endif %} {% if location.return is defined %} return {{ location.return }}; {% endif %} } {% endfor %}

# Security headers
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;

}

Role Dependencies meta/main.yml


galaxy_info: role_name: webserver author: Your Organization description: Install and configure nginx web server company: Your Company license: MIT min_ansible_version: 2.9

platforms: - name: Ubuntu versions: - focal - jammy - name: Debian versions: - buster - bullseye - name: EL versions: - 7 - 8 - 9

galaxy_tags: - web - nginx - webserver - http

dependencies: - role: common vars: common_packages: - curl - wget

  • role: firewall when: nginx_configure_firewall

allow_duplicates: no

Using Roles in Playbooks Simple Role Usage


  • name: Configure web servers hosts: webservers become: yes

roles: - webserver

Role with Variables

  • name: Configure web servers with custom settings hosts: webservers become: yes

roles: - role: webserver vars: nginx_worker_processes: 4 nginx_ssl_enabled: yes nginx_sites: - name: example.com server_name: example.com www.example.com root: /var/www/example.com ssl: yes ssl_cert: /etc/ssl/certs/example.com.crt ssl_key: /etc/ssl/private/example.com.key

Role with Tags

  • name: Configure infrastructure hosts: all become: yes

roles: - role: webserver tags: - web - nginx

- role: database
  tags:
    - db
    - postgres

Pre and Post Tasks

  • name: Deploy web application hosts: webservers become: yes

pre_tasks: - name: Announce deployment debug: msg: "Starting deployment to {{ inventory_hostname }}"

- name: Check disk space
  command: df -h /
  register: disk_space
  changed_when: false

roles: - webserver - monitoring

post_tasks: - name: Verify nginx is responding uri: url: http://localhost status_code: 200 retries: 3 delay: 5

- name: Notify completion
  debug:
    msg: "Deployment completed successfully"

Role Inclusion Methods Static Import


  • name: Configure servers hosts: all

tasks: - name: Import webserver role import_role: name: webserver vars: nginx_worker_processes: 2 tags: - webserver

Dynamic Include

  • name: Configure servers based on conditions hosts: all

tasks: - name: Include webserver role for web servers include_role: name: webserver when: "'webservers' in group_names"

- name: Include database role for db servers
  include_role:
    name: database
  when: "'databases' in group_names"

Import with Task Files

  • name: Custom installation workflow hosts: webservers

tasks: - name: Run pre-installation checks import_role: name: webserver tasks_from: preflight

- name: Install nginx
  import_role:
    name: webserver
    tasks_from: install

- name: Configure nginx
  import_role:
    name: webserver
    tasks_from: configure

Creating Roles with Ansible Galaxy Initialize a New Role

Create role structure

ansible-galaxy init roles/myapp

Create role with custom template

ansible-galaxy init --init-path roles/ myapp

List role files

tree roles/myapp

Install Roles from Galaxy

Install a role

ansible-galaxy install geerlingguy.nginx

Install specific version

ansible-galaxy install geerlingguy.nginx,2.8.0

Install from requirements file

ansible-galaxy install -r requirements.yml

requirements.yml

Install from Ansible Galaxy

  • name: geerlingguy.nginx version: 2.8.0

  • name: geerlingguy.postgresql version: 3.4.0

Install from Git repository

  • name: custom-app src: https://github.com/yourorg/ansible-role-custom-app.git scm: git version: main

Install from local path

  • name: internal-role src: /path/to/roles/internal-role

Advanced Role Patterns Role with Multiple Entry Points

roles/webserver/tasks/main.yml


  • name: Default task flow import_tasks: "{{ webserver_task_flow | default('standard') }}.yml"

roles/webserver/tasks/standard.yml


  • import_tasks: install.yml
  • import_tasks: configure.yml
  • import_tasks: security.yml

roles/webserver/tasks/minimal.yml


  • import_tasks: install.yml
  • import_tasks: configure.yml

Conditional Role Execution

  • name: Configure servers with conditional roles hosts: all become: yes

roles: - role: webserver when: - ansible_os_family == "Debian" - inventory_hostname in groups['webservers']

- role: webserver-nginx
  when: webserver_type == "nginx"

- role: webserver-apache
  when: webserver_type == "apache"

Nested Role Dependencies

roles/application/meta/main.yml


dependencies: - role: webserver vars: nginx_sites: - name: "{{ app_name }}" server_name: "{{ app_domain }}" proxy_pass: "http://localhost:{{ app_port }}"

  • role: database vars: db_name: "{{ app_db_name }}" db_user: "{{ app_db_user }}"

  • role: monitoring vars: monitor_services: - nginx - "{{ app_name }}"

When to Use This Skill

Use the ansible-roles skill when you need to:

Structure reusable automation code across multiple playbooks and projects Implement modular infrastructure as code with clear separation of concerns Share automation logic between teams or projects Create distributable automation packages for common infrastructure patterns Organize complex playbooks into manageable, testable components Implement role-based configuration management with variable precedence Build layered infrastructure with role dependencies Version control automation logic independently from playbooks Create standardized infrastructure components for consistency Implement security and compliance requirements through reusable roles Build internal automation libraries for your organization Contribute to or consume community automation from Ansible Galaxy Test infrastructure components in isolation before integration Implement different configurations for development, staging, and production Create self-documenting infrastructure through role metadata Best Practices Follow standard directory structure - Use ansible-galaxy init to create roles with proper organization Use defaults wisely - Place overridable variables in defaults/main.yml, non-overridable in vars/main.yml Document thoroughly - Include comprehensive README.md with usage examples and variable documentation Keep roles focused - Each role should have a single, well-defined purpose Use role dependencies - Declare dependencies in meta/main.yml rather than in playbooks Tag appropriately - Apply meaningful tags to tasks for selective execution Implement idempotency - Ensure roles can be run multiple times safely Version your roles - Use semantic versioning for role releases Test roles independently - Include test playbooks in tests/ directory Use templates for configuration - Prefer Jinja2 templates over static files for flexibility Implement OS detection - Use ansible_os_family for cross-platform compatibility Secure sensitive data - Use ansible-vault for passwords and secrets in role variables Use handlers correctly - Only notify handlers when configuration changes Validate configurations - Use validate parameter in template/copy modules Name tasks clearly - Use descriptive names that explain what each task does Common Pitfalls Overly complex roles - Trying to make one role do too many things Poor variable naming - Using generic names that conflict with other roles Missing role prefix - Not prefixing role variables with role name Ignoring variable precedence - Not understanding how Ansible resolves variable conflicts Hard-coded values - Embedding environment-specific values instead of using variables Missing dependencies - Not declaring role dependencies in meta/main.yml No validation - Deploying configurations without validation checks Skipping tests - Not including test playbooks or scenarios Poor handler design - Restarting services unnecessarily or not at all Missing OS support - Assuming all target systems are the same No backup strategy - Not backing up configurations before changes Ignoring idempotency - Using command/shell modules without proper guards Missing tags - Not tagging tasks for selective execution Poor template practices - Complex logic in templates instead of variables No version control - Not versioning roles or tracking changes Resources Ansible Roles Documentation Ansible Galaxy Role Directory Structure Variable Precedence ansible-galaxy CLI Best Practices Role Dependencies Testing Strategies

返回排行榜