基础概念
什么是Ansible?
答:Ansible 是一个开源的自动化配置管理工具,由 Michael DeHaan 创建。它基于 Python 开发,使用 SSH 协议与远程主机通信,无需在目标机器上安装客户端(agentless)。Ansible 主要用于应用部署、配置管理和任务编排。
Ansible 的核心组件有哪些?
- Inventory(清单):定义被管理主机的列表
- Modules(模块):执行具体任务的代码单元
- Plugins(插件):扩展核心功能的代码
- Playbooks(剧本):YAML 格式的配置文件,定义任务序列
- Roles(角色):组织 Playbook 的结构化方式
Ansible 的工作原理是什么?
答:Ansible 采用 Push 模式工作:
- 控制节点读取 Inventory 和 Playbook
- 通过 SSH 连接到远程主机
- 将模块代码推送到远程主机执行
- 收集执行结果并返回给控制节点
Ansible 与其他自动化工具(SaltStack、Puppet、Chef)的区别是什么?
| 特性 | Ansible | SaltStack | Puppet | Chef |
|---|---|---|---|---|
| 架构 | Agentless | Agent/Agentless | Agent | Agent |
| 语言 | YAML | YAML/Salt | DSL (Puppet) | Ruby |
| 学习难度 | 低 | 中 | 高 | 高 |
| 通信方式 | SSH | ZeroMQ/SSH | XMLRPC | Chef Server |
| 适用规模 | 中小型 | 大型 | 大型 | 大型 |
安装与配置
如何安装 Ansible?
bash
# CentOS/RHEL
yum install -y epel-release
yum install -y ansible
# Ubuntu/Debian
apt update
apt install -y ansible
# 使用 pip 安装
pip install ansibleAnsible 的主要配置文件有哪些?
ansible.cfg:主配置文件,搜索顺序为:
- 当前目录下的
ansible.cfg ~/.ansible.cfg/etc/ansible/ansible.cfg
- 当前目录下的
hosts/Inventory:主机清单文件,默认路径
/etc/ansible/hosts常用配置项:
ini
[defaults]
inventory = ./inventory
remote_user = root
private_key_file = ~/.ssh/id_rsa
host_key_checking = False
timeout = 30
forks = 5如何配置 SSH 免密登录?
bash
# 生成密钥对
ssh-keygen -t rsa -b 4096
# 复制公钥到远程主机
ssh-copy-id user@remote_host
# 或使用 ansible 自带模块
ssh-keyscan remote_host >> ~/.ssh/known_hostsInventory 清单
什么是 Inventory?如何定义?
答:Inventory 是 Ansible 管理的主机列表,支持多种格式:
INI 格式
ini
[webservers]
web1.example.com
web2.example.com
web[01:10].example.com
[dbservers]
db1.example.com
db2.example.com
[all:vars]
ansible_user=root
ansible_ssh_pass=your_passwordYAML 格式
yaml
all:
vars:
ansible_user: root
children:
webservers:
hosts:
web1.example.com:
web2.example.com:
dbservers:
hosts:
db1.example.com:
db2.example.com:动态 Inventory 是什么?如何使用?
答:动态 Inventory 通过外部脚本动态获取主机列表,适用于云环境:
bash
# 使用 AWS EC2 动态 Inventory
./aws_ec2.yml --list
# 在 ansible.cfg 中指定
[inventory]
enable_plugins = aws_ec2, host_list, script主机变量和组变量如何使用?
bash
# 目录结构
inventory/
├── group_vars/
│ ├── all.yml # 所有组通用变量
│ └── webservers.yml # webservers 组变量
├── host_vars/
│ └── web1.yml # 单个主机变量
└── hosts # 主机清单文件Playbook 剧本
什么是 Playbook?基本结构是什么?
答:Playbook 是 Ansible 的任务编排文件,使用 YAML 格式编写:
yaml
---
- name: 安装和配置 Nginx
hosts: webservers
become: yes
vars:
nginx_port: 80
tasks:
- name: 安装 Nginx
yum:
name: nginx
state: present
- name: 启动 Nginx 服务
service:
name: nginx
state: started
enabled: yesPlaybook 中的常用关键字有哪些?
| 关键字 | 说明 |
|---|---|
name | 任务名称描述 |
hosts | 目标主机或主机组 |
become | 是否提权执行(sudo) |
vars | 定义变量 |
tasks | 任务列表 |
handlers | 触发器,特定条件触发 |
pre_tasks | 在 tasks 之前执行的任务 |
post_tasks | 在 tasks 之后执行的任务 |
Handlers 是什么?如何使用?
答:Handlers 是特殊的任务,只有在被通知时才会执行,常用于服务重启等操作:
yaml
---
- name: 配置 Nginx
hosts: webservers
tasks:
- name: 更新 Nginx 配置
template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf
notify: 重启 Nginx
handlers:
- name: 重启 Nginx
service:
name: nginx
state: restarted常用模块
列举 Ansible 常用的模块及其用途
文件类模块
| 模块 | 用途 |
|---|---|
copy | 复制文件到远程主机 |
template | 使用 Jinja2 模板渲染后复制 |
file | 设置文件属性(权限、所有者等) |
fetch | 从远程主机拉取文件 |
lineinfile | 确保文件中存在某一行 |
blockinfile | 插入/更新/删除文本块 |
包管理模块
| 模块 | 用途 |
|---|---|
yum | RedHat 系包管理 |
apt | Debian 系包管理 |
pip | Python 包管理 |
gem | Ruby gem 管理 |
服务模块
| 模块 | 用途 |
|---|---|
service | 管理系统服务 |
systemd | 管理 systemd 服务 |
supervisorctl | 管理 supervisor 进程 |
系统信息模块
| 模块 | 用途 |
|---|---|
setup | 收集系统事实信息 |
ping | 测试连通性 |
command | 执行命令(不经过 shell) |
shell | 执行命令(经过 shell) |
script | 执行本地脚本 |
copy 和 template 模块有什么区别?
| 特性 | copy | template |
|---|---|---|
| 功能 | 直接复制文件 | 渲染模板后复制 |
| 变量支持 | 不支持 | 支持 Jinja2 模板语法 |
| 适用场景 | 静态文件 | 配置文件(含变量) |
| 示例 | src: file.conf | src: file.conf.j2 |
command、shell、raw 模块有什么区别?
| 模块 | 特点 | 是否需要 Python |
|---|---|---|
command | 不经过 shell,不支持管道、重定向 | 需要 |
shell | 经过 shell,支持管道、重定向 | 需要 |
raw | 通过 SSH 直接执行,不依赖 Python | 不需要 |
yaml
# command - 推荐,更安全
- name: 查看磁盘空间
command: df -h
# shell - 需要使用 shell 特性时
- name: 统计日志行数
shell: wc -l /var/log/syslog | awk '{print $1}'
# raw - 目标主机无 Python 时
- name: 安装 Python
raw: yum install -y python3Roles 角色
什么是 Role?它的目录结构是什么?
答:Role 是组织和复用 Playbook 的结构化方式:
roles/
└── nginx/
├── defaults/ # 默认变量(优先级最低)
│ └── main.yml
├── files/ # 静态文件
│ └── nginx.conf
├── handlers/ # handlers
│ └── main.yml
├── meta/ # 元数据、依赖
│ └── main.yml
├── tasks/ # 任务列表
│ └── main.yml
├── templates/ # Jinja2 模板
│ └── nginx.conf.j2
├── tests/ # 测试
│ └── test.yml
└── vars/ # 变量
└── main.yml如何创建和使用 Role?
bash
# 自动生成 role 目录结构
ansible-galaxy init myroleyaml
# playbook 中使用 role
---
- name: 部署 Web 应用
hosts: webservers
roles:
- common
- { role: nginx, port: 80 }
- { role: mysql, when: "ansible_distribution == 'CentOS'" }
- role: custom_role
vars:
custom_var: valueansible-galaxy 是什么?如何使用?
答:ansible-galaxy 是 Ansible 官方的角色分享平台:
bash
# 搜索角色
ansible-galaxy search nginx
# 下载角色
ansible-galaxy install geerlingguy.nginx
# 创建角色
ansible-galaxy init myrole
# 从 requirements.yml 安装
ansible-galaxy install -r requirements.yml变量与条件判断
Ansible 变量的优先级顺序是怎样的?
从高到低:
-e命令行指定的变量register注册的变量set_fact定义的变量role defaults和include_vars- Play 中的
vars和vars_files - Host vars / Group vars
- Inventory 中的变量
- Role defaults(默认值)
如何在 Playbook 中使用条件判断?
yaml
tasks:
- name: 仅在 CentOS 上安装 httpd
yum:
name: httpd
state: present
when: ansible_distribution == "CentOS"
- name: 当变量存在时执行
debug:
msg: "{{ my_var }}"
when: my_var is defined
- name: 多条件判断
yum:
name: nginx
state: present
when:
- ansible_os_family == "RedHat"
- ansible_distribution_major_version|int >= 7循环语句如何使用?
yaml
# 简单列表循环
- name: 安装多个软件包
yum:
name: "{{ item }}"
state: present
loop:
- nginx
- mysql
- python3
# 字典循环
- name: 创建多个用户
user:
name: "{{ item.name }}"
groups: "{{ item.groups }}"
loop:
- { name: alice, groups: wheel }
- { name: bob, groups: docker }
# with_items(旧写法)
- name: 循环示例
debug:
msg: "{{ item }}"
with_items:
- a
- b
- c进阶特性
Ansible Vault 是什么?如何加密敏感数据?
答:Ansible Vault 用于加密敏感信息(密码、密钥等):
bash
# 创建加密文件
ansible-vault create secrets.yml
# 编辑加密文件
ansible-vault edit secrets.yml
# 加密已有文件
ansible-vault encrypt secrets.yml
# 解密文件
ansible-vault decrypt secrets.yml
# 更改密码
ansible-vault rekey secrets.yml
# 查看加密内容
ansible-vault view secrets.ymlbash
# 执行时提供密码
ansible-playbook playbook.yml --ask-vault-pass
# 或使用密码文件
ansible-playbook playbook.yml --vault-password-file=vault_pass.txtAnsible 的幂等性是如何实现的?
答:幂等性是指多次执行相同操作结果一致:
- 大多数模块内置幂等性检查
- 模块执行前会检查当前状态
- 只有状态不符合预期时才执行变更
- 返回
changed状态标识是否发生变更
yaml
# 幂等示例 - 只在不存在时安装
- name: 确保 Nginx 已安装
yum:
name: nginx
state: present # 不是 latest,保证幂等性如何进行错误处理?
yaml
tasks:
- name: 可能失败的任务
command: /bin/false
ignore_errors: yes # 忽略错误继续执行
register: result
- name: 根据上一步结果处理
debug:
msg: "上一步失败了"
when: result is failed
- name: 强制执行失败处理程序
block:
- name: 正常任务
command: echo "正常"
rescue:
- name: 错误处理
command: echo "出错了"
always:
- name: 无论成功失败都执行
command: echo "清理工作"如何优化 Ansible 执行性能?
- 开启 SSH pipelining
ini
[ssh_connection]
pipelining = True- 调整并发数
bash
# 增加 forks 数量
ansible-playbook playbook.yml -f 20- 使用策略插件
yaml
- hosts: all
strategy: free # 并行执行,不等待每个 host 完成
tasks:
...- 关闭 facts 收集(不需要时)
yaml
- hosts: all
gather_facts: no
tasks:
...- 使用异步执行
yaml
- name: 耗时较长的任务
command: /long_running_task
async: 3600
poll: 0
register: long_task常见问题排查
Ansible 连接超时怎么办?
- 检查 SSH 配置和网络连通性
- 增加 timeout 时间
- 检查防火墙规则
- 验证主机名解析是否正确
如何调试 Playbook?
bash
# 详细输出模式
ansible-playbook playbook.yml -v
# 更详细的输出
ansible-playbook playbook.yml -vvv
# 只执行特定任务
ansible-playbook playbook.yml --tags "install"
# 跳过某些任务
ansible-playbook playbook.yml --skip-tags "cleanup"
# 干跑模式(不实际执行)
ansible-playbook playbook.yml --check
# 显示主机差异
ansible-playbook playbook.yml --diff常见报错及解决方案
| 报错信息 | 原因 | 解决方案 |
|---|---|---|
Permission denied | 权限不足 | 使用 become: yes |
module not found | 缺少 Python 依赖 | 安装所需库 |
unreachable | 网络不通 | 检查 SSH 和网络 |
variable undefined | 变量未定义 | 定义变量或设置默认值 |
