
一、概述
1.1 背景介绍
每个季度的安全补丁更新是运维团队的噩梦。上个季度我们还在用 SSH 跳板机 + xshell 批量执行脚本的方式给服务器打补丁,500 台机器分 10 批次,整整熬了三个通宵。中间还出了两次事故:一次是补丁依赖冲突导致某台数据库服务器重启失败,另一次是并发太高把内网带宽打满了。
痛定思痛,我们决定用 Ansible 重构整个补丁管理流程。这套方案跑了两个季度,现在 500 台服务器的补丁更新,从晚上 10 点开始,第二天早上 6 点收工,全程无人值守。这篇文章把踩过的坑和最终方案都记录下来。
1.2 技术特点
- 幂等性保障 :Ansible 的 yum/apt 模块天然支持幂等操作,重复执行不会造成问题,中断后可以安全重试
- 滚动更新 :通过 serial 参数控制并发数,避免同时重启太多机器影响业务
- 自动回滚 :结合健康检查,发现异常自动停止后续批次,保留现场等待人工介入
- 详细日志 :每台机器的执行结果都有记录,事后审计和故障定位都很方便
1.3 适用场景
- 场景一:季度/月度安全补丁批量更新,需要在维护窗口内完成大量服务器的系统升级
- 场景二:紧急漏洞修复,比如 log4j 这种 0day,需要快速在全网推送修复补丁
- 场景三:内核升级,需要有序重启服务器并验证业务恢复状态
1.4 环境要求
| 组件 | 版本要求 | 说明 |
|---|---|---|
| Ansible 控制节点 | CentOS 7+ / Ubuntu 18.04+ | 建议使用专用的运维跳板机 |
| Ansible | 2.9+ (推荐 2.12+) | 2.12 版本的性能优化明显 |
| Python | 3.6+ | 目标机器需要安装 Python |
| 目标服务器 | CentOS 7/8、Ubuntu 18/20/22 | 混合环境需要区分 playbook |
| 网络 | 控制节点到目标机器 SSH 可达 | 建议配置 SSH 密钥认证 |
二、详细步骤
2.1 准备工作
◆ 2.1.1 系统检查
# 检查 Ansible 版本
ansible --version
# 输出示例:
# ansible [core 2.14.3]
# python version = 3.9.16
# 检查控制节点到目标机器的连通性(抽样测试几台)
ansible -i inventory/prod.ini webservers -m ping --limit'web-001,web-002,web-003'
# 检查目标机器的磁盘空间(补丁包需要空间)
ansible -i inventory/prod.ini all -m shell -a "df -h / | tail -1 | awk '{print \$5}'" --limit'web-001'
◆ 2.1.2 安装依赖
# CentOS/RHEL 安装 Ansible
sudo yum install -y epel-release
sudo yum install -y ansible
# Ubuntu/Debian 安装 Ansible
sudo apt update
sudo apt install -y software-properties-common
sudo add-apt-repository --yes --update ppa:ansible/ansible
sudo apt install -y ansible
# 安装额外的 collection(用于更丰富的模块支持)
ansible-galaxy collection install ansible.posix
ansible-galaxy collection install community.general
◆ 2.1.3 配置 Ansible
# 创建项目目录结构
mkdir -p ~/ansible-patching/{inventory,group_vars,roles,logs}
cd ~/ansible-patching
# 生成 ansible.cfg
cat > ansible.cfg << 'EOF'
[defaults]
inventory = ./inventory/hosts.ini
remote_user = ops
private_key_file = ~/.ssh/ops_key
host_key_checking = False
timeout = 30
forks = 20
log_path = ./logs/ansible.log
callback_whitelist = profile_tasks
[privilege_escalation]
become = True
become_method = sudo
become_user = root
[ssh_connection]
pipelining = True
control_path = /tmp/ansible-%%h-%%p-%%r
EOF
2.2 核心配置
◆ 2.2.1 主机清单配置
# inventory/hosts.ini
# 按照业务分组,方便灰度发布
[webservers]
web-[001:100].prod.internal
[appservers]
app-[001:150].prod.internal
[dbservers]
db-[001:050].prod.internal
[cacheservers]
redis-[001:030].prod.internal
memcache-[001:020].prod.internal
# 按照机房/可用区分组
[dc1]
web-[001:050].prod.internal
app-[001:075].prod.internal
[dc2]
web-[051:100].prod.internal
app-[076:150].prod.internal
# 定义更新批次(第一批是金丝雀,数量少)
[canary]
web-001.prod.internal
app-001.prod.internal
redis-001.prod.internal
[batch1]
web-[002:020].prod.internal
app-[002:030].prod.internal
[batch2]
web-[021:050].prod.internal
app-[031:075].prod.internal
# ... 后续批次类似
说明 :主机清单的设计很关键。我们按照三个维度分组:业务类型、机房位置、更新批次。这样在执行时可以灵活控制范围,比如只更新某个机房,或者只更新某类服务器。
◆ 2.2.2 变量配置
# group_vars/all.yml
---
# 补丁更新相关配置
patching:
# 是否允许重启
allow_reboot:true
# 重启前等待时间(秒)
reboot_delay:30
# 重启超时时间(秒)
reboot_timeout:600
# 更新后健康检查等待时间
health_check_delay:60
# 排除的包(某些包不想自动更新)
exclude_packages:
-kernel*
-docker*
# 仅安全更新
security_only:true
# 通知配置
notification:
webhook_url:"https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxx"
enabled:true
# group_vars/dbservers.yml
---
# 数据库服务器特殊配置
patching:
allow_reboot:false# 数据库服务器默认不自动重启
exclude_packages:
-kernel*
-mysql*
-mariadb*
参数说明 :
allow_reboot:是否允许自动重启。数据库这类有状态服务建议设为 false,手动处理reboot_timeout:重启超时时间,老机器启动慢的话需要调大exclude_packages:排除列表,避免误更新关键组件security_only:只安装安全补丁,不做全量更新
◆ 2.2.3 核心 Playbook
# playbooks/patching.yml
---
-name:系统补丁更新-预检查
hosts:"{{ target_hosts | default('all') }}"
gather_facts:yes
serial:"{{ batch_size | default(50) }}"
tasks:
-name:检查磁盘空间
assert:
that:
-ansible_mounts|selectattr('mount','equalto','/')|map(attribute='size_available')|first|int>1073741824
fail_msg:"根分区剩余空间不足 1GB,跳过此主机"
tags:precheck
-name:检查系统负载
assert:
that:
-ansible_processor_vcpus>0
-(ansible_load_average.1/ansible_processor_vcpus)<2.0
fail_msg:"系统负载过高,跳过此主机"
tags:precheck
-name:记录更新前的包版本
shell:|
rpm -qa --queryformat '%{NAME}-%{VERSION}-%{RELEASE}\n' | sort > /tmp/packages_before_{{ ansible_date_time.date }}.txt
when:ansible_os_family=="RedHat"
tags:precheck
-name:系统补丁更新-执行更新
hosts:"{{ target_hosts | default('all') }}"
gather_facts:yes
serial:"{{ batch_size | default(50) }}"
max_fail_percentage:10
pre_tasks:
-name:发送开始通知
uri:
url:"{{ notification.webhook_url }}"
method:POST
body_format:json
body:
msgtype:"text"
text:
content:"补丁更新开始: {{ inventory_hostname }} (批次 {{ ansible_play_batch }})"
delegate_to:localhost
when:notification.enabled|default(false)
ignore_errors:yes
run_once:yes
tasks:
-name:更新YUM缓存
yum:
update_cache:yes
when:ansible_os_family=="RedHat"
-name:安装安全补丁(RHEL/CentOS)
yum:
name:'*'
state:latest
security:"{{ patching.security_only | default(true) }}"
exclude:"{{ patching.exclude_packages | default([]) }}"
register:yum_result
when:ansible_os_family=="RedHat"
-name:更新APT缓存
apt:
update_cache:yes
cache_valid_time:3600
when:ansible_os_family=="Debian"
-name:安装安全补丁(Ubuntu/Debian)
apt:
upgrade:dist
update_cache:yes
register:apt_result
when:ansible_os_family=="Debian"
-name:检查是否需要重启
stat:
path:/var/run/reboot-required
register:reboot_required_file
when:ansible_os_family=="Debian"
-name:检查是否需要重启(RHEL)
command:needs-restarting-r
register:needs_restarting
failed_when:false
changed_when:false
when:ansible_os_family=="RedHat"
-name:设置重启标志
set_fact:
needs_reboot:>-
{{ (ansible_os_family == "Debian" and reboot_required_file.stat.exists | default(false)) or
(ansible_os_family == "RedHat" and needs_restarting.rc == 1) }}
-name:重启服务器
reboot:
reboot_timeout:"{{ patching.reboot_timeout | default(600) }}"
pre_reboot_delay:"{{ patching.reboot_delay | default(30) }}"
post_reboot_delay:30
msg:"Ansible 补丁更新后重启"
when:
-needs_reboot|default(false)
-patching.allow_reboot|default(true)
-name:等待服务恢复
wait_for:
port:"{{ item }}"
timeout:120
loop:"{{ service_ports | default([22]) }}"
when:needs_reboot|default(false)
post_tasks:
-name:记录更新后的包版本
shell:|
rpm -qa --queryformat '%{NAME}-%{VERSION}-%{RELEASE}\n' | sort > /tmp/packages_after_{{ ansible_date_time.date }}.txt
diff /tmp/packages_before_{{ ansible_date_time.date }}.txt /tmp/packages_after_{{ ansible_date_time.date }}.txt > /tmp/packages_diff_{{ ansible_date_time.date }}.txt || true
when:ansible_os_family=="RedHat"
-name:健康检查
uri:
url:"http://localhost:{{ health_check_port | default(8080) }}/health"
status_code:200
timeout:30
register:health_check
retries:3
delay:10
until:health_check.status==200
when:health_check_portisdefined
ignore_errors:yes
-name:发送完成通知
uri:
url:"{{ notification.webhook_url }}"
method:POST
body_format:json
body:
msgtype:"text"
text:
content:"补丁更新完成: {{ inventory_hostname }} - 状态: {{ 'SUCCESS' if not (health_check.failed | default(false)) else 'FAILED' }}"
delegate_to:localhost
when:notification.enabled|default(false)
ignore_errors:yes
2.3 启动和验证
◆ 2.3.1 执行补丁更新
# 先在金丝雀环境测试
ansible-playbook playbooks/patching.yml -e "target_hosts=canary" -e "batch_size=1" --check
# 确认无误后正式执行金丝雀批次
ansible-playbook playbooks/patching.yml -e "target_hosts=canary" -e "batch_size=1"
# 金丝雀通过后,分批次执行
ansible-playbook playbooks/patching.yml -e "target_hosts=batch1" -e "batch_size=10"
ansible-playbook playbooks/patching.yml -e "target_hosts=batch2" -e "batch_size=20"
# 或者一次性执行全部,由 serial 控制并发
ansible-playbook playbooks/patching.yml -e "target_hosts=all" -e "batch_size=30"
◆ 2.3.2 功能验证
# 查看执行日志
tail -f logs/ansible.log
# 检查更新结果汇总
ansible -i inventory/hosts.ini all -m shell -a "cat /tmp/packages_diff_*.txt 2>/dev/null | head -20" --limit'web-001'
# 检查服务状态
ansible -i inventory/hosts.ini webservers -m shell -a "systemctl is-active nginx"
# 预期输出:每台机器都返回 active
三、示例代码和配置
3.1 完整配置示例
◆ 3.1.1 无人值守调度脚本
#!/bin/bash
# 文件路径:/opt/ansible-patching/run_patching.sh
# 功能:无人值守补丁更新调度脚本
set -e
WORK_DIR="/opt/ansible-patching"
LOG_DIR="${WORK_DIR}/logs"
DATE=$(date +%Y%m%d_%H%M%S)
LOG_FILE="${LOG_DIR}/patching_${DATE}.log"
cd${WORK_DIR}
# 函数:发送通知
send_notification() {
local message=$1
local webhook_url="https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxx"
curl -s -X POST ${webhook_url} \
-H 'Content-Type: application/json' \
-d "{\"msgtype\": \"text\", \"text\": {\"content\": \"${message}\"}}" \
> /dev/null 2>&1 || true
}
# 函数:执行单个批次
run_batch() {
local batch_name=$1
local batch_size=$2
echo"[$(date)] 开始执行批次: ${batch_name}" | tee -a ${LOG_FILE}
send_notification "[补丁更新] 开始执行批次: ${batch_name}"
if ansible-playbook playbooks/patching.yml \
-e "target_hosts=${batch_name}" \
-e "batch_size=${batch_size}" \
>> ${LOG_FILE} 2>&1; then
echo"[$(date)] 批次 ${batch_name} 执行成功" | tee -a ${LOG_FILE}
send_notification "[补丁更新] 批次 ${batch_name} 执行成功"
return 0
else
echo"[$(date)] 批次 ${batch_name} 执行失败" | tee -a ${LOG_FILE}
send_notification "[补丁更新] 批次 ${batch_name} 执行失败,请检查"
return 1
fi
}
# 主流程
main() {
send_notification "[补丁更新] 开始执行,预计耗时 6-8 小时"
# 金丝雀批次
if ! run_batch "canary" 1; then
send_notification "[补丁更新] 金丝雀批次失败,终止后续更新"
exit 1
fi
# 等待 10 分钟观察金丝雀
echo"[$(date)] 等待 10 分钟观察金丝雀环境..." | tee -a ${LOG_FILE}
sleep 600
# 后续批次
local batches=("batch1:10""batch2:20""batch3:30""batch4:50""batch5:50")
for batch_config in"${batches[@]}"; do
batch_name="${batch_config%%:*}"
batch_size="${batch_config##*:}"
if ! run_batch "${batch_name}""${batch_size}"; then
send_notification "[补丁更新] 批次 ${batch_name} 失败,终止后续更新"
exit 1
fi
# 批次间间隔 5 分钟
echo"[$(date)] 批次间隔等待 5 分钟..." | tee -a ${LOG_FILE}
sleep 300
done
send_notification "[补丁更新] 全部完成!请检查各服务状态"
}
main "$@"
◆ 3.1.2 定时任务配置
# /etc/cron.d/ansible-patching
# 每月第一个周六晚上 22:00 执行补丁更新
0 22 1-7 * 6 root /opt/ansible-patching/run_patching.sh
3.2 实际应用案例
◆ 案例一:紧急漏洞修复
场景描述 :2024 年某天早上收到安全团队通知,某个 glibc 漏洞需要紧急修复,要求当天完成全网更新。
实现代码 :
# playbooks/emergency_patch.yml
---
-name:紧急补丁修复
hosts:"{{ target_hosts | default('all') }}"
gather_facts:yes
serial:100# 紧急情况提高并发
tasks:
-name:仅更新指定包
yum:
name:"{{ emergency_packages }}"
state:latest
when:ansible_os_family=="RedHat"
-name:验证补丁版本
shell:"rpm -q {{ item }}"
loop:"{{ emergency_packages }}"
register:version_check
when:ansible_os_family=="RedHat"
-name:显示更新后版本
debug:
msg:"{{ version_check.results | map(attribute='stdout') | list }}"
运行命令 :
ansible-playbook playbooks/emergency_patch.yml \
-e "target_hosts=all" \
-e '{"emergency_packages": ["glibc", "glibc-common"]}' \
--forks 100
运行结果 :
PLAY RECAP *********************************************************************
web-001.prod.internal : ok=4 changed=1 unreachable=0 failed=0 skipped=0
web-002.prod.internal : ok=4 changed=1 unreachable=0 failed=0 skipped=0
...
500 台服务器全部更新完成,耗时 45 分钟
◆ 案例二:内核升级与滚动重启
场景描述 :需要升级内核修复某个性能问题,但必须保证业务不中断,采用滚动重启方式。
实现步骤 :
- 1. 首先修改配置,允许内核更新和自动重启
- 2. 将主机按照业务分组,确保每组重启时有其他组提供服务
- 3. 使用 serial: 1 逐台执行,配合负载均衡摘除
# playbooks/kernel_upgrade.yml
---
-name:内核升级-滚动更新
hosts:"{{ target_hosts }}"
gather_facts:yes
serial:1# 逐台执行
tasks:
-name:从负载均衡摘除
uri:
url:"http://{{ lb_api }}/api/v1/upstream/{{ inventory_hostname }}/down"
method:POST
delegate_to:localhost
when:lb_apiisdefined
-name:等待连接排空
wait_for:
timeout:60
-name:升级内核
yum:
name:kernel
state:latest
register:kernel_update
-name:重启服务器
reboot:
reboot_timeout:900
msg:"Ansible 内核升级重启"
when:kernel_update.changed
-name:验证内核版本
shell:uname-r
register:kernel_version
-name:重新加入负载均衡
uri:
url:"http://{{ lb_api }}/api/v1/upstream/{{ inventory_hostname }}/up"
method:POST
delegate_to:localhost
when:lb_apiisdefined
-name:等待流量恢复
wait_for:
timeout:30
四、最佳实践和注意事项
4.1 最佳实践
◆ 4.1.1 性能优化
-
开启 SSH Pipelining :减少 SSH 连接次数,大幅提升执行速度
# ansible.cfg [ssh_connection] pipelining = True -
调整 forks 数量 :根据控制节点性能和网络情况调整并发数
-
4 核 8G 的机器,forks 设置 50-100 比较合适
- 网络带宽充足时可以适当调高
- 更新包比较大时要降低,避免打满带宽
-
使用 Mitogen 加速 :Mitogen 是一个 Ansible 加速插件,实测能提升 2-5 倍速度
pip install mitogen # ansible.cfg 添加 [defaults] strategy_plugins = /path/to/mitogen/ansible_mitogen/plugins/strategy strategy = mitogen_linear
◆ 4.1.2 安全加固
-
使用 Vault 加密敏感信息 :
# 创建加密的变量文件 ansible-vault create group_vars/all/vault.yml # 内容示例 vault_webhook_key: "your-secret-key" vault_ssh_password: "your-password" -
限制 sudo 权限 :运维账号的 sudoers 配置只开放必要权限
# /etc/sudoers.d/ops ops ALL=(root) NOPASSWD: /usr/bin/yum, /usr/bin/apt, /usr/sbin/reboot, /usr/bin/systemctl -
审计日志 :所有操作都要有日志记录,方便事后追溯
◆ 4.1.3 高可用配置
- 多控制节点 :部署多个 Ansible 控制节点,避免单点故障
- AWX/Tower :生产环境建议使用 AWX 或 Ansible Tower,提供 Web 界面、权限控制、执行历史等功能
- 备份 Playbook :将 Playbook 代码托管到 Git,做好版本管理
4.2 注意事项
◆ 4.2.1 配置注意事项
警告 :补丁更新可能导致服务中断,务必在维护窗口执行,并提前做好回滚准备!
- 注意事项一:数据库、消息队列等有状态服务,建议单独处理,不要混在批量更新里
- 注意事项二:更新前一定要检查磁盘空间,空间不足会导致更新失败甚至系统损坏
- 注意事项三:生产环境务必先在金丝雀/预发布环境验证,确认无问题再推全量
◆ 4.2.2 常见错误
| 错误现象 | 原因分析 | 解决方案 |
|---|---|---|
| SSH 连接超时 | 目标机器 SSHD 服务异常或网络不通 | 检查网络连通性和 SSHD 服务状态 |
| sudo 密码错误 | 密码过期或权限配置问题 | 检查 sudoers 配置,考虑使用 NOPASSWD |
| yum lock 错误 | 其他进程占用 yum 锁 | kill 掉占用进程或等待其完成 |
| 重启后连接失败 | 启动时间过长或启动失败 | 增加 reboot_timeout,检查启动日志 |
| 包依赖冲突 | 第三方源与官方源冲突 | 使用 exclude 排除问题包,手动处理 |
◆ 4.2.3 兼容性问题
- 版本兼容 :CentOS 7 和 CentOS 8 的包管理命令有差异(yum vs dnf),Ansible 的 yum 模块会自动处理
- 平台兼容 :混合环境(RHEL + Ubuntu)需要用 when 条件判断,或者拆分成多个 playbook
- 组件依赖 :某些包更新后可能需要重启服务才能生效,需要在 playbook 中处理
五、故障排查和监控
5.1 故障排查
◆ 5.1.1 日志查看
# 查看 Ansible 执行日志
tail -f /opt/ansible-patching/logs/ansible.log
# 查看详细输出(调试用)
ansible-playbook playbooks/patching.yml -vvv
# 查看目标机器的 yum 日志
ssh web-001 "tail -100 /var/log/yum.log"
# 查看系统日志(排查重启问题)
ssh web-001 "journalctl -b -1 --no-pager | tail -100"
◆ 5.1.2 常见问题排查
问题一:部分主机执行失败但没有详细错误信息
# 单独对失败主机执行,增加详细输出
ansible-playbook playbooks/patching.yml -e "target_hosts=web-001" -vvv
解决方案 :
- 1. 查看 -vvv 输出找到具体错误
- 2. SSH 到目标机器手动执行命令验证
- 3. 检查目标机器的系统日志
问题二:重启后服务没有自动恢复
# 检查服务状态
ansible -i inventory/hosts.ini webservers -m shell -a "systemctl status nginx"
# 检查服务是否设置了开机自启
ansible -i inventory/hosts.ini webservers -m shell -a "systemctl is-enabled nginx"
解决方案 :确保关键服务都设置了 enable,在 playbook 中增加服务状态检查
问题三:某些包被跳过没有更新
- 症状 :yum 报告某些包没有更新,但实际上有新版本
- 排查 :检查 exclude 配置和 yum 仓库配置
- 解决 :确认包名没有被意外排除,检查仓库优先级
◆ 5.1.3 调试模式
# 开启 Ansible 调试模式
export ANSIBLE_DEBUG=1
ansible-playbook playbooks/patching.yml -vvv
# 使用 --step 逐步执行
ansible-playbook playbooks/patching.yml --step
# 从某个任务开始执行(之前任务跳过)
ansible-playbook playbooks/patching.yml --start-at-task="重启服务器"
5.2 性能监控
◆ 5.2.1 关键指标监控
# 监控 Ansible 控制节点资源
top -p $(pgrep -f ansible)
# 监控网络带宽使用
iftop -i eth0
# 监控执行进度
watch -n 5 'grep -c "ok=" /opt/ansible-patching/logs/ansible.log'
◆ 5.2.2 监控指标说明
| 指标名称 | 正常范围 | 告警阈值 | 说明 |
|---|---|---|---|
| 批次成功率 | 100% | < 95% | 单批次失败率超过 5% 需要人工介入 |
| 单机执行时间 | 3-10 分钟 | > 30 分钟 | 执行时间过长可能有问题 |
| 控制节点 CPU | < 50% | > 80% | CPU 过高需要降低 forks |
| 网络带宽 | < 70% | > 90% | 带宽打满需要降低并发 |
◆ 5.2.3 监控告警配置
# Prometheus 告警规则示例
groups:
-name:ansible-patching
rules:
-alert:PatchingBatchFailed
expr:ansible_batch_failed_hosts>0
for:5m
labels:
severity:critical
annotations:
summary:"补丁更新批次失败"
description:"批次 {{ $labels.batch }} 有 {{ $value }} 台主机失败"
5.3 备份与恢复
◆ 5.3.1 备份策略
#!/bin/bash
# 补丁更新前的快照备份脚本
HOSTS_FILE=$1
DATE=$(date +%Y%m%d)
# 对虚拟机创建快照(需要 vCenter API 或 cloud provider API)
whileread host; do
echo"Creating snapshot for ${host}..."
# VMware 示例
# govc vm.snapshot.create -vm="${host}" "pre-patching-${DATE}"
# AWS 示例
# aws ec2 create-snapshot --volume-id $(get_volume_id ${host}) --description "pre-patching-${DATE}"
done < ${HOSTS_FILE}
◆ 5.3.2 恢复流程
- 1. 停止服务 :
ansible -i inventory/hosts.ini target_host -m service -a "name=nginx state=stopped" - 2. 恢复快照 :通过虚拟化平台或云平台恢复到补丁前的快照
- 3. 验证完整性 :启动服务器,检查服务状态和数据完整性
- 4. 重启服务 :
ansible -i inventory/hosts.ini target_host -m service -a "name=nginx state=started"
六、总结
6.1 技术要点回顾
- 要点一 :合理设计主机清单分组,支持灵活的灰度发布策略
- 要点二 :使用 serial 和 max_fail_percentage 控制更新节奏和容错
- 要点三 :更新前后做好检查和记录,便于追溯和回滚
- 要点四 :区分处理有状态和无状态服务,数据库等关键服务单独处理
6.2 进阶学习方向
- 1. AWX/Ansible Tower :生产环境建议使用,提供更好的可视化和权限管理
- 学习资源:AWX 官方文档 https://github.com/ansible/awx
- 实践建议:先在测试环境部署 AWX,熟悉后再迁移生产 playbook
- 2. Ansible Collections :学习使用官方和社区的 Collection,避免重复造轮子
- 学习资源:Ansible Galaxy https://galaxy.ansible.com
- 实践建议:搜索现有的 patching 相关 role/collection
- 3. 配合 CI/CD 流水线 :将补丁更新集成到 GitOps 流程中
- 学习资源:Jenkins/GitLab CI 与 Ansible 集成
- 实践建议:补丁更新 playbook 提交到 Git,通过 MR 审批后自动执行
6.3 参考资料
- Ansible 官方文档 - 最权威的参考
- Red Hat 补丁管理最佳实践 - 企业级方案参考
- Ansible for DevOps - 推荐书籍
- r/ansible - 社区讨论
附录
A. 命令速查表
# 测试连通性
ansible all -m ping
# 检查模式(不实际执行)
ansible-playbook playbook.yml --check
# 指定主机执行
ansible-playbook playbook.yml --limit"web-001,web-002"
# 查看将要执行的主机
ansible-playbook playbook.yml --list-hosts
# 查看将要执行的任务
ansible-playbook playbook.yml --list-tasks
# 从指定任务开始
ansible-playbook playbook.yml --start-at-task="任务名"
# 使用 vault 密码文件
ansible-playbook playbook.yml --vault-password-file=.vault_pass
B. 配置参数详解
| 参数 | 说明 | 建议值 |
|---|---|---|
| forks | 并发执行数 | 20-50 |
| serial | 批次大小 | 10-50 |
| max_fail_percentage | 最大失败百分比 | 5-10 |
| timeout | SSH 连接超时 | 30 |
| pipelining | SSH 管道模式 | True |
| host_key_checking | 主机密钥检查 | False(内网环境) |
C. 术语表
| 术语 | 英文 | 解释 |
|---|---|---|
| 幂等性 | Idempotency | 多次执行结果相同,不会产生副作用 |
| 金丝雀发布 | Canary Release | 先在小范围验证,通过后再全量推送 |
| 滚动更新 | Rolling Update | 分批次逐步更新,保证服务不中断 |
| 控制节点 | Control Node | 运行 Ansible 命令的机器 |
| 管理节点 | Managed Node | 被 Ansible 管理的目标机器 |