跳到主要内容

Ansible Playbook 实战

Playbook 基础

deploy-app.yml
---
- name: Deploy Web Application
hosts: webservers
become: yes
vars:
app_version: "1.2.3"
app_dir: /opt/app

tasks:
- name: Ensure app directory exists
file:
path: "{{ app_dir }}"
state: directory
owner: app
group: app

- name: Download release
get_url:
url: "https://releases.example.com/app-{{ app_version }}.tar.gz"
dest: "/tmp/app-{{ app_version }}.tar.gz"

- name: Extract release
unarchive:
src: "/tmp/app-{{ app_version }}.tar.gz"
dest: "{{ app_dir }}"
remote_src: yes

- name: Restart service
systemd:
name: app
state: restarted
enabled: yes

handlers:
- name: Reload nginx
systemd:
name: nginx
state: reloaded

Role 组织结构

roles/
└── nginx/
├── tasks/
│ └── main.yml # 任务入口
├── handlers/
│ └── main.yml # 事件处理
├── templates/
│ └── nginx.conf.j2 # Jinja2 模板
├── files/ # 静态文件
├── vars/
│ └── main.yml # 变量
└── defaults/
└── main.yml # 默认值(低优先级)
roles/nginx/tasks/main.yml
---
- name: Install nginx
apt:
name: nginx
state: present

- name: Deploy config
template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf
validate: "nginx -t -c %s" # 生效前校验配置
notify: Reload nginx

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

滚动更新(零停机部署)

rolling-deploy.yml
---
- name: Rolling Deploy
hosts: webservers
serial: "25%" # 每次更新 25% 的主机
max_fail_percentage: 25 # 失败超过 25% 则终止
become: yes

pre_tasks:
# 从负载均衡摘除
- name: Deregister from LB
uri:
url: "http://lb/api/deregister/{{ inventory_hostname }}"
method: POST

- name: Wait for connections to drain
pause:
seconds: 10

roles:
- role: deploy-app

post_tasks:
# 健康检查通过后重新注册
- name: Health check
uri:
url: "http://{{ inventory_hostname }}:8080/health"
status_code: 200
retries: 10
delay: 5

- name: Register to LB
uri:
url: "http://lb/api/register/{{ inventory_hostname }}"
method: POST

Inventory 管理

inventory/production
[webservers]
web01 ansible_host=10.0.1.11
web02 ansible_host=10.0.1.12

[dbservers]
db01 ansible_host=10.0.2.11 mysql_role=master
db02 ansible_host=10.0.2.12 mysql_role=slave

[all:vars]
ansible_user=deploy
ansible_ssh_private_key_file=~/.ssh/deploy_key

常见面试问题

Q1: Ansible 的幂等性是什么?如何保证?

答案

幂等性是指多次执行 Playbook,结果与执行一次相同。Ansible 模块大多内置幂等性:

  • apt: state=present → 已安装则跳过
  • file: state=directory → 已存在则跳过
  • template → 内容相同则不重写

破坏幂等性的写法shell / command 模块(每次都执行),应加 creates/when 条件判断。

相关链接