Ansible 自动化运维
大约 7 分钟约 2144 字
Ansible 自动化运维
简介
Ansible 是一款开源的自动化运维工具,通过 YAML 格式的 Playbook 描述自动化任务,使用 SSH 协议管理目标主机,无需在远程节点安装代理。Ansible 的幂等性保证了任务多次执行结果一致,结合丰富的模块和角色机制,能够高效完成配置管理、应用部署和任务编排。
特点
Inventory 主机清单
静态 Inventory
# inventory/production.ini
[webservers]
web1.example.com ansible_host=192.168.1.10
web2.example.com ansible_host=192.168.1.11
[dbservers]
db1.example.com ansible_host=192.168.1.20
[appservers]
app[1:3].example.com
[webservers:vars]
nginx_version=1.25.4
[dbservers:vars]
mysql_version=8.0
[production:children]
webservers
dbservers
appservers
[production:vars]
ansible_user=deploy
ansible_ssh_private_key_file=~/.ssh/id_ed25519
ansible_python_interpreter=/usr/bin/python3动态 Inventory
# inventory/aws_ec2.yaml
plugin: aws_ec2
regions:
- ap-northeast-1
- ap-southeast-1
filters:
tag:Environment: production
hostnames:
- tag:Name
groups:
webservers: "'web' in tags.Name"
dbservers: "'db' in tags.Name"
compose:
ansible_host: private_ip_address# 测试 Inventory 连通性
ansible all -i inventory/production.ini -m ping
# 仅测试 web 服务器组
ansible webservers -i inventory/production.ini -m ping
# 查看所有主机信息
ansible all -i inventory/production.ini --list-hosts
# 使用动态 Inventory
ansible-inventory -i inventory/aws_ec2.yaml --list
ansible-inventory -i inventory/aws_ec2.yaml --graph常用模块
copy 模块 — 文件分发
# playbook copy 示例
- name: 分发配置文件
hosts: webservers
become: true
tasks:
- name: 复制 Nginx 配置文件
ansible.builtin.copy:
src: files/nginx.conf
dest: /etc/nginx/nginx.conf
owner: root
group: root
mode: '0644'
backup: true
notify: Reload Nginx
- name: 分发 SSL 证书
ansible.builtin.copy:
src: "{{ item.src }}"
dest: "{{ item.dest }}"
mode: '0600'
loop:
- { src: 'files/server.crt', dest: '/etc/ssl/certs/server.crt' }
- { src: 'files/server.key', dest: '/etc/ssl/private/server.key' }
no_log: true
handlers:
- name: Reload Nginx
ansible.builtin.service:
name: nginx
state: reloadedtemplate 模块 — 模板渲染
# playbook template 示例
- name: 部署应用配置
hosts: appservers
become: true
vars:
app_name: myapp
app_port: 8080
db_host: "{{ groups['dbservers'][0] }}"
max_connections: 200
log_level: info
tasks:
- name: 渲染应用配置文件
ansible.builtin.template:
src: templates/app.conf.j2
dest: /etc/myapp/app.conf
owner: appuser
group: appgroup
mode: '0644'
notify: Restart MyApp
- name: 渲染环境变量文件
ansible.builtin.template:
src: templates/env.j2
dest: /etc/myapp/.env
mode: '0600'
handlers:
- name: Restart MyApp
ansible.builtin.service:
name: myapp
state: restarted{# templates/app.conf.j2 #}
server {
listen {{ app_port }};
server_name {{ ansible_hostname }};
access_log /var/log/myapp/access.log;
error_log /var/log/myapp/error.log {{ log_level }};
location / {
proxy_pass http://127.0.0.1:{{ app_port }};
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
{% if max_connections > 100 %}
location /health {
proxy_pass http://127.0.0.1:{{ app_port }}/health;
}
{% endif %}
}service/systemd 模块 — 服务管理
# playbook service 示例
- name: 管理系统服务
hosts: all
become: true
tasks:
- name: 确保 Nginx 已安装并启动
ansible.builtin.yum:
name: nginx
state: present
when: ansible_os_family == "RedHat"
- name: 确保 Nginx 已安装并启动(Ubuntu)
ansible.builtin.apt:
name: nginx
state: present
update_cache: true
when: ansible_os_family == "Debian"
- name: 启动并启用 Nginx
ansible.builtin.systemd:
name: nginx
state: started
enabled: true
- name: 重载 systemd 配置
ansible.builtin.systemd:
daemon_reload: true
when: systemd_unit_changed is defined and systemd_unit_changed
- name: 检查服务状态
ansible.builtin.command: systemctl status nginx
register: result
changed_when: false
failed_when: "'inactive' in result.stdout"常用模块速查
# 常用模块示例合集
- name: 常用模块演示
hosts: all
become: true
tasks:
# 用户管理
- name: 创建用户
ansible.builtin.user:
name: deploy
groups: docker
shell: /bin/bash
append: true
# 文件管理
- name: 创建目录
ansible.builtin.file:
path: /opt/myapp
state: directory
owner: deploy
group: deploy
mode: '0755'
# 从 URL 下载文件
- name: 下载安装包
ansible.builtin.get_url:
url: "https://example.com/app-v1.0.tar.gz"
dest: /tmp/app.tar.gz
checksum: "sha256:abc123..."
# 解压文件
- name: 解压安装包
ansible.builtin.unarchive:
src: /tmp/app.tar.gz
dest: /opt/myapp
remote_src: true
# 执行命令
- name: 检查磁盘使用率
ansible.builtin.shell: |
df -h / | tail -1 | awk '{print $5}' | sed 's/%//'
register: disk_usage
changed_when: false
- name: 磁盘告警
ansible.builtin.debug:
msg: "磁盘使用率过高: {{ disk_usage.stdout }}%"
when: disk_usage.stdout | int > 80Roles 角色管理
角色目录结构
# 角色标准目录结构
roles/
nginx/
defaults/ # 默认变量(优先级最低)
main.yml
vars/ # 角色变量(优先级较高)
main.yml
tasks/ # 任务列表
main.yml
install.yml
configure.yml
handlers/ # 处理程序
main.yml
templates/ # Jinja2 模板
nginx.conf.j2
vhost.conf.j2
files/ # 静态文件
nginx.repo
meta/ # 角色元数据(依赖)
main.yml
tests/ # 测试
inventory
test.yml编写 Nginx 角色
# roles/nginx/defaults/main.yml
nginx_worker_processes: auto
nginx_worker_connections: 1024
nginx_client_max_body_size: "50m"
nginx_proxy_read_timeout: 60
nginx_upstream_servers: []
nginx_ssl_enabled: false
nginx_ssl_cert_path: /etc/ssl/certs/server.crt
nginx_ssl_key_path: /etc/ssl/private/server.key# roles/nginx/tasks/main.yml
- name: 安装 Nginx
ansible.builtin.include_tasks: install.yml
- name: 配置 Nginx
ansible.builtin.include_tasks: configure.yml
- name: 确保 Nginx 已启动
ansible.builtin.service:
name: nginx
state: started
enabled: true# roles/nginx/tasks/install.yml
- name: 添加 Nginx 仓库(CentOS)
ansible.builtin.yum_repository:
name: nginx
description: Nginx Repository
baseurl: http://nginx.org/packages/centos/{{ ansible_distribution_major_version }}/$basearch/
gpgcheck: true
gpgkey: https://nginx.org/keys/nginx_signing.key
when: ansible_os_family == "RedHat"
- name: 安装 Nginx
ansible.builtin.package:
name: nginx
state: present# roles/nginx/tasks/configure.yml
- name: 渲染 Nginx 主配置
ansible.builtin.template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf
mode: '0644'
notify: Reload Nginx
- name: 渲染虚拟主机配置
ansible.builtin.template:
src: vhost.conf.j2
dest: /etc/nginx/conf.d/default.conf
mode: '0644'
notify: Reload Nginx# roles/nginx/handlers/main.yml
- name: Reload Nginx
ansible.builtin.service:
name: nginx
state: reloaded
- name: Restart Nginx
ansible.builtin.service:
name: nginx
state: restarted使用角色
# site.yml — 引用角色
- name: 部署 Web 服务器
hosts: webservers
become: true
roles:
- role: nginx
vars:
nginx_worker_connections: 2048
nginx_ssl_enabled: true
nginx_upstream_servers:
- name: backend
servers:
- "192.168.1.30:8080"
- "192.168.1.31:8080"
- role: app_deploy
vars:
app_version: "v2.0.0"幂等性操作
确保任务幂等
# playbook idempotent 示例
- name: 幂等配置示例
hosts: appservers
become: true
tasks:
# 使用模块而非命令(幂等)
- name: 确保配置行存在
ansible.builtin.lineinfile:
path: /etc/sysctl.conf
regexp: '^net.ipv4.ip_forward'
line: 'net.ipv4.ip_forward = 0'
state: present
notify: Apply sysctl
- name: 管理多个配置项
ansible.builtin.sysctl:
name: "{{ item.key }}"
value: "{{ item.value }}"
state: present
reload: true
loop:
- { key: 'net.core.somaxconn', value: '65535' }
- { key: 'vm.swappiness', value: '10' }
- { key: 'fs.file-max', value: '65536' }
# 条件判断实现幂等
- name: 仅在文件不存在时创建
ansible.builtin.stat:
path: /opt/myapp/.initialized
register: init_flag
- name: 初始化应用
ansible.builtin.command: /opt/myapp/init.sh
when: not init_flag.stat.exists
changed_when: true
- name: 标记已初始化
ansible.builtin.file:
path: /opt/myapp/.initialized
state: touch
mode: '0644'
when: not init_flag.stat.exists
handlers:
- name: Apply sysctl
ansible.builtin.command: sysctl -p
changed_when: true优点
缺点
总结
Ansible 以其无代理架构、幂等性设计和简洁的 YAML 语法成为运维自动化的首选工具。通过 Inventory 管理主机清单,使用 copy/template/service 等模块完成配置分发与服务管理,结合 Roles 实现任务的模块化复用,能够高效完成从系统初始化到应用部署的全流程自动化。建议在实际项目中采用 Role 组织结构,利用变量分层管理实现多环境配置,并通过 ansible-lint 等工具保证 Playbook 质量。
关键知识点
- DevOps 主题的核心是让交付更快、更稳、更可审计。
- 自动化不是把命令脚本化,而是把失败、回滚、权限和观测一起设计进去。
- 生产链路必须明确制品、环境、凭据、配置和责任边界。
项目落地视角
- 把流水线拆成构建、测试、制品、部署、验证和回滚几个阶段。
- 为关键步骤补齐日志、指标、通知和人工兜底点。
- 定期演练扩容、回滚、故障注入和灾备切换。
常见误区
- 只关注部署成功,不关注失败恢复和审计追踪。
- 把环境差异藏在临时脚本或人工操作里。
- 上线频率高了以后,没有标准化制品和配置管理。
进阶路线
- 继续补齐 GitOps、可观测性、平台工程和成本治理。
- 把主题和应用架构、安全、权限、备份恢复联动起来理解。
- 形成团队级平台能力,而不是每个项目重复造轮子。
适用场景
- 当你准备把《Ansible 自动化运维》真正落到项目里时,最适合先在一个独立模块或最小样例里验证关键路径。
- 适合构建自动化交付、基础设施治理、监控告警和生产发布体系。
- 当团队规模扩大、发布频率提升或环境变多时,这类主题会显著影响交付效率。
落地建议
- 所有自动化流程尽量做到幂等、可审计、可回滚。
- 把制品、变量、凭据和执行权限分层管理。
- 定期演练扩容、回滚、密钥轮换和灾备恢复。
排错清单
- 先定位失败发生在代码、构建、制品、环境还是权限层。
- 检查流水线变量、凭据、镜像标签和目标环境配置是否一致。
- 如果问题偶发,重点看并发发布、资源争抢和外部依赖抖动。
复盘问题
- 如果把《Ansible 自动化运维》放进你的当前项目,最先要验证的输入、输出和失败路径分别是什么?
- 《Ansible 自动化运维》最容易在什么规模、什么边界条件下暴露问题?你会用什么指标或日志去确认?
- 相比默认实现或替代方案,采用《Ansible 自动化运维》最大的收益和代价分别是什么?
