590_Ansible自动化运维
一句话概述:Ansible 是 Red Hat 开源的 IT 自动化工具,通过 SSH 无需安装 Agent,用 YAML 编写 Playbook 来批量管理服务器配置、应用部署和任务编排,是运维自动化的标准工具。
核心知识点表
| 概念 | 白话解释 |
|---|
| Inventory | 清单,定义要管理的服务器列表和分组 |
| Playbook | 剧本,用 YAML 写的自动化任务脚本 |
| Task | 任务,Playbook 中的一个操作步骤 |
| Module | 模块,执行具体操作的工具(如安装软件、复制文件) |
| Role | 角色,把相关的任务、变量、文件打包成可复用的单元 |
| Idempotent | 幂等性,跑多少次结果都一样(已经安装的不会重复安装) |
| Ad-hoc | 临时命令,不写 Playbook 直接执行一条命令 |
安装配置
安装 Ansible
# 方法1:pip 安装(推荐)
pip install ansible # 安装完整包
# 或
pip install ansible-core # 安装最小包
# 方法2:Ubuntu/Debian
sudo add-apt-repository --yes --update ppa:ansible/ansible
sudo apt install ansible # 安装
# 方法3:CentOS/RHEL
sudo yum install epel-release
sudo yum install ansible
# 验证安装
ansible --version # 查看版本(当前 v13.x / core 2.20.x)
配置 Inventory(服务器清单)
# /etc/ansible/hosts 或项目目录下的 inventory 文件
# === 简单格式 ===
[webservers] # 组名
web1.example.com # 服务器地址
web2.example.com
192.168.1.100 # 也可以用 IP
[databases]
db1.example.com ansible_port=2222 # 自定义 SSH 端口
db2.example.com ansible_user=deploy # 自定义 SSH 用户
[production:children] # 组的组
webservers
databases
[all:vars] # 全局变量
ansible_python_interpreter=/usr/bin/python3
配置 SSH 免密登录
# 生成密钥(如果没有)
ssh-keygen -t ed25519 # 生成 SSH 密钥对
# 复制公钥到目标服务器
ssh-copy-id user@web1.example.com # 每台服务器都要执行
ssh-copy-id user@web2.example.com
# 测试连接
ansible all -m ping # ping 所有服务器
# 期望输出:web1.example.com | SUCCESS => {"ping": "pong"}
基本使用
Ad-hoc 命令(临时命令)
# 语法:ansible <主机/组> -m <模块> -a "<参数>"
# ping 所有服务器
ansible all -m ping # 测试连接
# 查看所有服务器的磁盘使用
ansible all -m shell -a "df -h" # 执行 Shell 命令
# 安装软件包
ansible webservers -m apt -a "name=nginx state=present" -b # -b = sudo
# 重启服务
ansible webservers -m service -a "name=nginx state=restarted" -b
# 复制文件到所有服务器
ansible all -m copy -a "src=./app.conf dest=/etc/app.conf" -b
# 创建用户
ansible all -m user -a "name=deploy state=present" -b
编写 Playbook
# deploy.yml — 部署 Nginx 的 Playbook
---
- name: 部署 Nginx Web 服务器 # Play 名称
hosts: webservers # 目标主机组
become: true # 使用 sudo
vars: # 变量定义
app_port: 8080
tasks:
- name: 安装 Nginx # 任务1
apt: # 使用 apt 模块
name: nginx # 包名
state: present # 确保已安装
update_cache: yes # 先更新包索引
- name: 复制 Nginx 配置文件 # 任务2
template: # 使用 template 模块
src: nginx.conf.j2 # 本地模板文件
dest: /etc/nginx/sites-available/default # 目标路径
notify: 重启 Nginx # 配置变更时触发 handler
- name: 确保 Nginx 运行中 # 任务3
service: # 使用 service 模块
name: nginx
state: started # 确保已启动
enabled: yes # 开机自启
handlers: # 处理器(被 notify 触发)
- name: 重启 Nginx
service:
name: nginx
state: restarted
# 运行 Playbook
ansible-playbook deploy.yml # 执行
ansible-playbook deploy.yml --check # 预检(不实际执行)
ansible-playbook deploy.yml --diff # 显示文件变更差异
ansible-playbook deploy.yml -l web1 # 只对 web1 执行
Jinja2 模板
# templates/nginx.conf.j2
server {
listen {{ app_port }}; # 使用 Ansible 变量
server_name {{ ansible_hostname }}; # 使用 Facts 变量
location / {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
}
}
高级用法
Role(角色)
# 创建 Role 目录结构
ansible-galaxy init roles/nginx # 自动生成结构
# roles/nginx/
# ├── tasks/main.yml → 任务
# ├── handlers/main.yml → 处理器
# ├── templates/ → 模板文件
# ├── files/ → 静态文件
# ├── vars/main.yml → 变量
# └── defaults/main.yml → 默认变量
# roles/nginx/tasks/main.yml
---
- name: 安装 Nginx
apt: name=nginx state=present update_cache=yes
- name: 部署配置
template: src=nginx.conf.j2 dest=/etc/nginx/sites-available/default
notify: restart nginx
- name: 启动 Nginx
service: name=nginx state=started enabled=yes
# 使用 Role 的 Playbook
---
- hosts: webservers
become: true
roles:
- nginx # 引用 nginx role
- { role: app, app_port: 3000 } # 带参数的 role
变量优先级
# 从低到高的优先级:
# 1. defaults/main.yml(Role 默认值)
# 2. group_vars/all.yml(全局变量)
# 3. group_vars/webservers.yml(组变量)
# 4. host_vars/web1.yml(主机变量)
# 5. Playbook vars
# 6. 命令行 -e "var=value"(最高优先级)
# group_vars/all.yml
---
ntp_server: time.google.com
timezone: Asia/Shanghai
# group_vars/production.yml
---
env: production
debug: false
条件和循环
tasks:
# 条件执行
- name: 只在 Ubuntu 上执行
apt: name=nginx state=present
when: ansible_os_family == "Debian" # 条件判断
# 循环安装多个包
- name: 安装多个包
apt:
name: "{{ item }}" # 循环变量
state: present
loop: # 循环列表
- nginx
- git
- htop
- curl
# 注册变量
- name: 检查服务状态
command: systemctl is-active nginx
register: nginx_status # 保存结果
ignore_errors: yes
- name: 启动 Nginx(如果未运行)
service: name=nginx state=started
when: nginx_status.rc != 0 # 根据上一步结果判断
Ansible Vault(加密敏感数据)
# 加密文件
ansible-vault encrypt group_vars/production.yml # 加密
# 解密文件
ansible-vault decrypt group_vars/production.yml # 解密
# 编辑加密文件
ansible-vault edit group_vars/production.yml # 编辑
# 运行时提供密码
ansible-playbook site.yml --ask-vault-pass # 提示输入密码
ansible-playbook site.yml --vault-password-file=.vault_pass # 密码文件
常见报错
| 报错信息 | 原因 | 解决方案 |
|---|
UNREACHABLE | SSH 连接失败 | 检查 SSH 密钥和网络连通性 |
Permission denied | 权限不足 | 添加 become: true 或检查 sudo 权限 |
Module not found | 模块未安装 | ansible-galaxy collection install xxx |
Syntax error in playbook | YAML 格式错误 | ansible-playbook --syntax-check |
variable undefined | 变量未定义 | 检查变量名拼写和作用域 |
Python not found | 远程主机无 Python | 设置 ansible_python_interpreter |
速查表
# === 常用命令 ===
ansible all -m ping # 测试连接
ansible all -m shell -a "uptime" # 执行命令
ansible-playbook playbook.yml # 运行 Playbook
ansible-playbook playbook.yml --check # 预检模式
ansible-galaxy init roles/myrole # 创建 Role
ansible-vault encrypt file.yml # 加密文件
# === 常用模块 ===
apt/yum # 包管理
service # 服务管理
copy # 复制文件
template # 模板渲染
file # 文件/目录管理
user/group # 用户/组管理
shell/command # 执行命令
git # Git 操作
docker_container # Docker 容器
同类对比
| 特性 | Ansible | Puppet | Chef | SaltStack |
|---|
| 语言 | YAML | Ruby DSL | Ruby | YAML/Python |
| Agent | 无需 | 需要 | 需要 | 可选 |
| 通信方式 | SSH | HTTPS | HTTPS | ZeroMQ |
| 学习曲线 | 低 | 中 | 高 | 中 |
| 适合场景 | 通用 | 大规模 | 大规模 | 大规模 |
| 社区 | 最大 | 大 | 中 | 中 |
选型建议:入门自动化运维首选 Ansible(无 Agent、YAML 简单易学);大规模基础设施管理考虑 Puppet 或 SaltStack。Ansible 是目前最流行的配置管理工具。