界面已本地化;技能介绍与说明文档按所选语言由 AI 自动翻译,代码、命令、路径和专业术语保留原文,以原作者文档为准。
探索技能
部署与运维 · SKILL.md

ansible

ansible

【部署与运维】Use this skill when the user says 'Ansible', 'ansible-playbook', 'ansible-galaxy', 'playbook', 'inventory', 'role', 'task', 'module', 'ad-hoc command', 'configuration management', 'infrastructure automation', 'idempotent', 'Ansible Tower', 'AWX', 'Ansible Automation Platform'. Covers: playbooks, roles, inventory management, modules, variables, condit…

独立 GitHub 快照 · 自动分类 · 以原作者文档为准

技能说明

GitHub

name: ansible description: > Use this skill when the user says 'Ansible', 'ansible-playbook', 'ansible-galaxy', 'playbook', 'inventory', 'role', 'task', 'module', 'ad-hoc command', 'configuration management', 'infrastructure automation', 'idempotent', 'Ansible Tower', 'AWX', 'Ansible Automation Platform'. Covers: playbooks, roles, inventory management, modules, variables, conditionals, loops, Jinja2 templates, vault encryption, Tower/AWX, collection development, CI/CD integration, idempotent automation. Do NOT use for: Terraform (use terraform), Puppet, Chef, SaltStack, or other configuration management tools. version: "2.0.0" author: "j4flmao" license: "MIT" compatibility: claude-code: true cursor: true codex: true windsurf: true tags: [devops, ansible, configuration-management, automation, phase-5]

Ansible

Purpose

Automate configuration management, application deployment, and infrastructure orchestration using Ansible playbooks, roles, and modules with idempotency and security best practices.

Agent Protocol

Trigger

Exact user phrases: "Ansible", "ansible-playbook", "playbook", "inventory", "role", "task", "ansible-galaxy", "ansible-vault", "Ansible Tower", "AWX", "Ansible Automation Platform".

Input Context

Before activating, verify:

  • Managed node OS (RHEL, Debian, Windows, network devices) — affects module selection.
  • Inventory source (static INI/YAML, dynamic from cloud/inventory plugin).
  • Authentication method (SSH key, password with sshpass, WinRM, API token).
  • Ansible control node version (2.9 vs 2.14+ changes module behavior).
  • Execution mode (ad-hoc, playbook, pull-mode, Tower/AWX workflow).

Output Artifact

Writes to Ansible playbooks YAML, role directory structure, inventory files, Jinja2 templates, and vars files.

Response Format

YAML playbooks/roles with inline configuration. No extraneous explanation.

No preamble. No postamble. No explanations. No filler/hedging/transitions.

Completion Criteria

  • Playbook defined with idempotent tasks.
  • Inventory configured (static or dynamic).
  • Variables externalized in group_vars/host_vars.
  • Roles structured per Ansible Galaxy best practices.
  • Sensitive data encrypted with ansible-vault.
  • Idempotency verified (playbook can be re-run safely).

Max Response Length

Direct file write. No response text.

Architecture Decision Trees

Execution Mode: Ad-hoc vs Playbook vs Pull vs Tower/AWX

ModeUse CaseWhen to Use
Ad-hocSingle task, quick check"Restart service X on all web servers"
PlaybookMulti-step orchestrationFull application deployment with pre/post steps
Pull modeEphemeral nodes, auto-provisioningContainers, auto-scaling groups, IoT devices
Tower/AWXEnterprise, RBAC, scheduling>50 nodes, team access, compliance auditing

Module Choice by Task Type

TaskRecommended ModuleAlternative
Package installpackage (OS-agnostic)apt/yum/dnf for OS-specific options
File operationscopy, template, lineinfileblockinfile for multi-line blocks
Service controlservice (generic)systemd for systemd-specific features
Command executioncommand (idempotent shell)shell when pipes/redirects needed
Cloud provisioningamazon.aws.ec2_instance (collection)Raw ec2 module (deprecated)
Docker managementcommunity.docker.docker_containerdocker compose module
Kuberneteskubernetes.core.k8shelm module for Helm charts
Git operationsgitsubversion for SVN repos
Databasemysql_db, postgresql_dbmongo modules
Windowswin_package, win_servicewin_command as fallback

Inventory Source Decision

ScenarioBest Choice
< 50 static serversINI or YAML inventory files
AWS EC2 dynamicamazon.aws.aws_ec2 inventory plugin
GCP Computegoogle.cloud.gcp_compute inventory plugin
Azure VMsazure.azcollection.azure_rm inventory plugin
VMware vSpherecommunity.vmware.vmware_vm_inventory
Kubernetes podskubernetes.core.k8s inventory
Mixed cloud/on-premCustom script or Tower/AWX smart inventories

Quick Start

Inventory file with host groups → ansible.cfg for optimization → Playbook with pre_tasks, roles, post_tasks → Encrypt secrets with ansible-vault → Run with ansible-playbook -i inventory site.yml --ask-vault-pass.

Core Workflow

Step 1: Ansible Configuration

# ansible.cfg
[defaults]
inventory = ./inventory/hosts.ini
host_key_checking = False
retry_files_enabled = False
gathering = smart
fact_caching = jsonfile
fact_caching_connection = /tmp/ansible_cache
fact_caching_timeout = 3600
stdout_callback = yaml
callback_whitelist = profile_tasks, timer, mail
ansible_managed = Ansible managed: {file} modified on %Y-%m-%d %H:%M:%S

[ssh_connection]
pipelining = True
ssh_args = -o ControlMaster=auto -o ControlPersist=60s
control_path = /tmp/ansible-%%h-%%p-%%r

Step 2: Inventory Structure

# inventory/hosts.ini
[web]
web-01 ansible_host=10.0.1.10 ansible_user=deploy
web-02 ansible_host=10.0.1.11 ansible_user=deploy

[db]
db-primary ansible_host=10.0.2.10 ansible_user=deploy
db-replica ansible_host=10.0.2.11 ansible_user=deploy

[cache]
redis-01 ansible_host=10.0.3.10 ansible_user=deploy

[production:children]
web
db
cache

[production:vars]
ansible_ssh_private_key_file = ~/.ssh/production_rsa
environment = production
# inventory/hosts.yml — YAML format for complex setups
all:
  children:
    web:
      hosts:
        web-01:
          ansible_host: 10.0.1.10
        web-02:
          ansible_host: 10.0.1.11
      vars:
        http_port: 443
        ssl_enabled: true
    db:
      hosts:
        db-primary:
          ansible_host: 10.0.2.10
        db-replica:
          ansible_host: 10.0.2.11
    production:
      children:
        web: {}
        db: {}

Step 3: Variable Organization

# group_vars/all.yml — applies to all hosts
ntp_servers:
  - 0.pool.ntp.org
  - 1.pool.ntp.org
timezone: UTC
package_cache_valid_hours: 24

# group_vars/web.yml — applies to web group
nginx_worker_processes: 4
nginx_worker_connections: 2048
app_replicas: 2

# host_vars/web-01.yml — applies only to web-01
ansible_host: 10.0.1.10
custom_certificate: web-01.example.com.pem

Step 4: Role Structure

roles/
  nginx/
    defaults/          # Lowest precedence vars
      main.yml
    vars/              # Higher precedence vars
      main.yml
    tasks/
      main.yml
      ssl.yml
      security.yml
    handlers/
      main.yml
    templates/
      nginx.conf.j2
      site.conf.j2
    files/
      dhparam.pem
    meta/
      main.yml
    tests/
      test.yml
      inventory

Step 5: Playbook with Roles

# site.yml — main playbook
---
- name: Configure all production servers
  hosts: production
  become: true
  gather_facts: true
  pre_tasks:
    - name: Update apt cache
      apt:
        update_cache: true
        cache_valid_time: "{{ package_cache_valid_hours * 3600 }}"
      when: ansible_os_family == "Debian"

    - name: Set hostname
      hostname:
        name: "{{ inventory_hostname }}"
      tags: [system, hostname]

  roles:
    - role: common
      tags: [common]

    - role: nginx
      when: "'web' in group_names"
      tags: [web, nginx]

    - role: postgresql
      when: "'db' in group_names"
      tags: [db, postgresql]

    - role: redis
      when: "'cache' in group_names"
      tags: [cache, redis]

  post_tasks:
    - name: Register with monitoring
      uri:
        url: "https://monitoring.internal/register"
        method: POST
        body_format: json
        body:
          hostname: "{{ inventory_hostname }}"
          groups: "{{ group_names }}"
        status_code: 201
      tags: [monitoring]

Step 6: Idempotent Tasks

# roles/nginx/tasks/main.yml
---
- name: Install nginx
  ansible.builtin.package:
    name: nginx
    state: present  # idempotent — won't reinstall if present

- name: Remove default site
  ansible.builtin.file:
    path: /etc/nginx/sites-enabled/default
    state: absent  # idempotent — no-op if already absent

- name: Deploy nginx config
  ansible.builtin.template:
    src: nginx.conf.j2
    dest: /etc/nginx/nginx.conf
    mode: '0644'
    owner: root
    group: root
    validate: nginx -t %s  # validate before applying
  notify: reload nginx      # only restarts if config changed

- name: Deploy site config
  ansible.builtin.template:
    src: "{{ app_template | default('site.conf.j2') }}"
    dest: "/etc/nginx/sites-available/{{ app_name }}.conf"
    mode: '0644'
  notify: reload nginx

- name: Enable site
  ansible.builtin.file:
    src: "/etc/nginx/sites-available/{{ app_name }}.conf"
    dest: "/etc/nginx/sites-enabled/{{ app_name }}.conf"
    state: link
  notify: reload nginx
# roles/nginx/handlers/main.yml
---
- name: reload nginx
  ansible.builtin.systemd:
    name: nginx
    state: reloaded  # graceful reload, no connection drop
    daemon_reload: true

Step 7: Jinja2 Templating

# roles/nginx/templates/nginx.conf.j2
user www-data;
worker_processes {{ nginx_worker_processes }};
worker_rlimit_nofile {{ nginx_worker_connections * 2 }};
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;

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

http {
    ##
    # Basic Settings
    ##
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
    types_hash_max_size 2048;
    client_max_body_size 64M;
    server_tokens off;

    ##
    # SSL Settings
    ##
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
    ssl_prefer_server_ciphers on;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;

    ##
    # Logging Settings
    ##
    access_log /var/log/nginx/access.log;
    error_log /var/log/nginx/error.log;

    ##
    # Virtual Host Configs
    ##
    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/*;
}

Step 8: Ansible Vault for Secrets

# Encrypt a file
# ansible-vault encrypt group_vars/production/vault.yml

# vault.yml (encrypted)
vault_db_password: "s3cur3p@ssw0rd!"
vault_api_key: "ak-abc123def456"
vault_ssl_private_key: |
  -----BEGIN PRIVATE KEY-----
  MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC...
  -----END PRIVATE KEY-----

# Reference in playbook
- name: Configure database
  postgresql_db:
    name: "{{ app_name }}"
    password: "{{ vault_db_password }}"
  no_log: true  # prevent password logging

Step 9: Dynamic Inventory with AWS

# inventory/aws_ec2.yml
plugin: amazon.aws.aws_ec2
regions:
  - us-east-1
  - us-west-2
hostnames:
  - private-dns-name
keyed_groups:
  - key: tags.Environment
    prefix: env
  - key: tags.Role
    prefix: role
  - key: placement.region
    prefix: region
filters:
  instance-state-name: running
  tag:Environment: production
compose:
  ansible_host: private_ip_address

Tool Comparison: Ansible vs Alternatives

FeatureAnsiblePuppetChefSaltStack
ArchitectureAgentless (SSH/WinRM)Agent (pull)Agent (pull)Hybrid (agent/agentless)
LanguageYAML (playbooks)DSL (Puppet lang)Ruby DSLYAML + Jinja
IdempotencyBuilt-in (modules)Built-inBuilt-inBuilt-in
Learning curveLowMediumHighMedium
Windows supportGood (WinRM)GoodGoodModerate
Cloud dynamic inventoryPluginsPluginsCommunityPlugins
OrchestrationBuilt-inSeparate (Bolt)Built-inBuilt-in
Enterprise offeringAAP/TowerPuppet EnterpriseChef AutomateSaltStack Config
CommunityLargeModerateModerateModerate
Push vs PullPush (default)PullPullBoth
Vault integrationBuilt-inHiera + eyamlData bagsBuilt-in

Anti-Patterns

Anti-Pattern 1: Shell/Command Overuse

Using shell or command modules when a dedicated module exists. Prevents idempotency and idempotent checking.

Anti-Pattern 2: Flattened Variable Structure

Putting all variables in group_vars/all.yml instead of organizing by group/host. Leads to variable conflicts and unclear precedence.

Anti-Pattern 3: Skipping Idempotent Patterns

Tasks that don't check current state before making changes. Use state: present/absent, creates:, or changed_when for idempotency.

Anti-Pattern 4: Hardcoded Secrets

Storing passwords in plaintext playbooks. Always use ansible-vault or external secret management (HashiCorp Vault, AWS Secrets Manager).

Anti-Pattern 5: No Idempotency Check

Assuming a task only runs once without check_mode or --diff flag validation. Always test with --check --diff.

Anti-Pattern 6: Monolithic Playbooks

Single massive playbook instead of modular roles. Roles should be reusable across playbooks and projects.

Production Considerations

Security

  • Encrypt all secrets with ansible-vault and store vault password in a secrets manager.
  • Use SSH CA-signed keys or hardware-backed SSH keys for production access.
  • Enable no_log: true on tasks that handle passwords, tokens, or keys.
  • Use become only when necessary; scope become to specific tasks.
  • Disable SSH password authentication; use key-based authentication.
  • Validate playbooks with ansible-lint before execution.

Performance

  • Enable SSH pipelining (pipelining = True in ansible.cfg) for 2-5x speedup.
  • Use strategy: free for parallel execution across hosts (vs default linear).
  • Configure forks = 50 (default is 5) for larger environments.
  • Enable fact caching (JSON file or Redis) to speed up repeated runs.
  • Use gathering = smart to only gather facts when needed.

Error Handling

  • Use ignore_errors: true only for non-critical tasks; handle with failed_when.
  • Set max_fail_percentage to abort when too many hosts fail.
  • Use any_errors_fatal for tasks that must succeed on all hosts.
  • Implement rescue and always blocks for error recovery.

CI/CD Integration

# .github/workflows/ansible-ci.yml
name: Ansible CI
on: [push, pull_request]
jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: '3.11'
      - run: pip install ansible ansible-lint
      - run: ansible-lint site.yml
  syntax:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: pip install ansible
      - run: ansible-playbook site.yml --syntax-check
  molecule:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        distro: [ubuntu-22.04, debian-11, centos-9]
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
      - run: pip install molecule molecule-plugins[docker] ansible
      - run: molecule test --scenario-name default

Troubleshooting Guide

IssueLikely CauseSolution
SSH connection timeoutControl node can't reach targetVerify security groups, SSH port, ansible_host value
Permission deniedWrong SSH key or userCheck ansible_user and private key path
Module not foundAnsible version too oldUpgrade to 2.14+; install collection
Task not idempotentModule without state checkUse dedicated module with state: present/absent
Vault decryption failsWrong vault passwordRe-encrypt with correct vault ID/password
Variable undefinedMissing in group_vars/host_varsUse `{{ variable
Template errorJinja2 syntax issueTest template with ansible all -m debug -a 'msg={{ template }}'

Rules & Constraints

  • Playbooks must be idempotent — running twice produces the same result.
  • Secrets must use ansible-vault encryption — never plaintext in YAML.
  • Use FQCN (Fully Qualified Collection Names) like ansible.builtin.copy over short names.
  • Pin collection versions in requirements.yml.
  • Roles go in roles/ directory, not inline in playbooks.
  • Variables go in group_vars/ and host_vars/, not in playbook header.
  • Use ansible-lint before every commit — enforce in CI.
  • Use check_mode (--check) before applying changes to production.
  • Tag all tasks (tags: [web, config]) for selective execution.
  • One playbook per workflow; split by environment (dev/staging/prod).

Output Format

Ansible playbook YAML, role directory structure, inventory YAML/INI, Jinja2 templates.

References

  • references/ansible-advanced.md
  • references/ansible-best-practices.md
  • references/ansible-fundamentals.md
  • references/ansible-roles.md
  • references/ansible-security.md
  • references/ansible-tower.md
  • references/automation-playbooks.md
  • references/inventory-config.md
  • references/dynamic-inventory-guide.md

Handoff

After completing this skill:

  • Next skill: terraform — IaC provisioning, then Ansible for configuration
  • Pass context: inventory structure, role list, vault password location, CI/CD integration
我的收藏