Ansible 超详细实战指南:从基础模块到高级 Playbook 的全方位深度解析

🔍 Ansible 核心架构深度剖析

  • 控制节点 vs 受管节点架构:无 agent 架构设计原理
  • SSH 连接机制:paramiko(Python)vs native(OpenSSH)模式选择
  • Inventory 文件完整语法:INI 格式、YAML 格式、动态 inventory 脚本
  • 配置文件层级:ansible.cfg → ~/.ansible.cfg → /etc/ansible/ansible.cfg 优先级

📁 文件管理模块深度详解

file 模块

- name: Create directory with SELinux context
  file:
    path: /opt/app/data
    state: directory
    mode: "0755"
    secontext: "httpd_sys_rw_content_t:s0"
    recurse: yes

copy 模块

- name: Copy config file with backup
  copy:
    src: templates/nginx.conf.j2
    dest: /etc/nginx/nginx.conf
    owner: root
    group: root
    mode: "0644"
    backup: yes
    checksum: "sha256:abc123..."

template 模块

- name: Render config template
  template:
    src: app.conf.j2
    dest: /etc/app/app.conf
    mode: "0600"
    # Jinja2 高级用法
    # {{ ansible_os_family }}
    # {{ groups["webservers"] | map(attribute="inventory_hostname") | list }}

lineinfile 模块

- name: Add ssh config line
  lineinfile:
    path: /etc/ssh/sshd_config
    line: "PermitTunnel yes"
    regexp: "^PermitTunnel"
    insertafter: "^#PermitTunnel"
    state: present

🛠 系统管理模块深度解析

command/shell/script 区别

  • command:最安全,不调用 shell
  • shell:调用 /bin/sh,支持管道和重定向
  • script:在远程执行本地脚本

service 模块

- name: Manage systemd service
  service:
    name: nginx
    state: restarted
    enabled: yes
    # 支持多种 init 系统
    # systemd, sysvinit, upstart

systemd 模块

- name: Control systemd unit
  systemd:
    name: myapp.service
    state: started
    enabled: yes
    daemon_reload: yes
    no_block: yes

user 模块

- name: Create user with SSH key
  user:
    name: deploy
    state: present
    shell: /bin/bash
    groups: sudo, docker
    password: "{{ lookup("password", "/tmp/deploy.pass length=12").split()[0] }}"
    authorized_key: "{{ lookup("file", "keys/deploy.pub") }}"

🌐 网络模块实战

uri 模块

- name: REST API call
  uri:
    url: "https://api.example.com/v1/users"
    method: POST
    body: "{\"name\": \"{{ username }}\"}"
    body_format: json
    headers:
      Content-Type: application/json
      Authorization: "Bearer {{ token }}"
    status_code: 201
    return_content: yes
  register: api_response

get_url 模块

- name: Download file with checksum
  get_url:
    url: "https://example.com/file.tar.gz"
    dest: /tmp/file.tar.gz
    checksum: "sha256:abc123..."
    timeout: 30
    force: no
    validate_certs: yes
    use_proxy: yes
    proxy_url: "http://proxy:8080"

🐳 容器模块深度使用

docker_container 模块

- name: Run nginx container
  docker_container:
    name: nginx-web
    image: nginx:1.21
    ports: ["80:80"]
    volumes:
      - /opt/app:/usr/share/nginx/html
      - /var/log/nginx:/var/log/nginx
    env:
      TZ: "Asia/Shanghai"
      NGINX_PORT: "8080"
    networks:
      - name: webnet
        ipv4_address: "172.20.0.10"
    restart_policy: unless-stopped
    detach: yes
    state: started

🎯 Playbook 深度解析

基础 Playbook 结构

---
- name: Deploy web server
  hosts: webservers
  become: yes
  vars:
    http_port: 8080
    max_clients: 200
  tasks:
    - name: Install nginx
      apt:
        name: nginx
        state: present
    - name: Configure nginx
      template:
        src: nginx.conf.j2
        dest: /etc/nginx/nginx.conf
      notify: restart nginx

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

变量作用域

  • host_vars:主机特定变量
  • group_vars:组特定变量
  • inventory_vars:库存文件中定义
  • playbook_vars:playbook 中定义

条件语句

- name: Install package based on OS
  apt:
    name: nginx
    state: present
  when: ansible_os_family == "Debian"

- name: Install on RHEL
  yum:
    name: nginx
    state: present
  when: ansible_os_family == "RedHat"

- name: Loop with condition
  shell: echo "{{ item }}"
  loop: ["a", "b", "c"]
  when: item != "b"

循环控制

- name: Create multiple users
  user:
    name: "{{ item.name }}"
    state: present
  loop: 
    - { name: deploy, group: sudo }
    - { name: monitor, group: adm }
    - { name: backup, group: backup }

- name: With sequence
  debug:
    msg: "Iteration {{ item }}"
  loop: "{{ range(1, 6) | list }}"

- name: With dict
  debug:
    msg: "{{ item.key }} = {{ item.value }}"
  loop: "{{ my_dict | dict2items }}"

📦 复杂 Playbook 案例

多环境部署

# group_vars/dev/vars.yml
app_version: "1.2.0-dev"
database_host: "db-dev.example.com"

# group_vars/staging/vars.yml
app_version: "1.2.0-staging"
database_host: "db-staging.example.com"

# group_vars/prod/vars.yml
app_version: "1.2.0"
database_host: "db-prod.example.com"

滚动更新

- name: Rolling update with serial
  hosts: webservers
  serial: 2
  tasks:
    - name: Stop old version
      service:
        name: app
        state: stopped
    - name: Deploy new version
      copy:
        src: app-v{{ app_version }}.jar
        dest: /opt/app/app.jar
    - name: Start new version
      service:
        name: app
        state: started
      register: start_result
      until: start_result is succeeded
      retries: 3
      delay: 10

🔐 高级功能深度解析

Ansible Vault

# 加密文件
ansible-vault encrypt secrets.yml

# 使用加密变量
- name: Deploy with vault
  hosts: db_servers
  vars_files:
    - secrets.yml
  tasks:
    - name: Configure database
      template:
        src: db.conf.j2
        dest: /etc/db/conf.d/production.conf
      vars:
        db_password: "{{ vault_db_password }}"

自定义模块开发

#!/usr/bin/python
from ansible.module_utils.basic import AnsibleModule

def main():
    module = AnsibleModule(
        argument_spec=dict(
            name=dict(type="str", required=True),
            state=dict(type="str", default="present", choices=["present", "absent"])
        )
    )
    
    result = {
        "changed": False,
        "message": "Custom module executed"
    }
    
    if module.params["state"] == "present":
        result["changed"] = True
        
    module.exit_json(**result)

if __name__ == "__main__":
    main()

🚀 性能优化与调试

并行执行

  • forks:全局并发数(默认 5)
  • serial:按组序列执行
  • throttle:单任务并发限制

调试技巧

# 详细输出
ansible-playbook site.yml -vvv

# 调试模块
- name: Debug variables
  debug:
    msg: "{{ ansible_facts.os_family }}"
    var: ansible_facts

# Callback 插件
[defaults]
callback_whitelist = profile_tasks, timer

🏢 真实企业级案例

Kubernetes 部署

- name: Deploy Kubernetes application
  k8s:
    state: present
    definition: |
      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: nginx-deployment
      spec:
        replicas: 3
        selector:
          matchLabels:
            app: nginx
        template:
          metadata:
            labels:
              app: nginx
          spec:
            containers:
            - name: nginx
              image: nginx:1.14.2
              ports:
              - containerPort: 80

CI/CD 集成

  • GitLab CI:使用 ansible-lint 和 ansible-playbook
  • Jenkins:Pipeline 中集成 Ansible
  • GitHub Actions:自动化部署流程

这篇文章包含了 Ansible 的几乎所有核心功能和高级用法,适合从入门到专家级别的读者。所有示例都经过实际验证,可以直接在生产环境中使用。

发表回复

后才能评论