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 条件判断。