运维自动化工具 Ansible
环境:Ubuntu 24.04 / Rocky Linux 10
目录
- [Ansible 概述](#Ansible 概述)
- 安装与配置
- [主机清单 Inventory](#主机清单 Inventory)
- 常用模块详解
- [Playbook 基础](#Playbook 基础)
- [Playbook 进阶](#Playbook 进阶)
- [Roles 角色](#Roles 角色)
- 最佳实践与总结
- 综合实践案例
1. Ansible 概述
-
开发语言:Python
-
架构:无代理(agentless),基于 SSH 通信
-
核心组件:
- 控制节点(安装 Ansible 的主机)
- 被管节点(通过 SSH 管理)
- 主机清单(Inventory)
- 模块(Modules)
- Playbook(YAML 格式的任务编排)
- Roles(角色,用于代码复用)
-
优势:
- 无需在被管节点安装额外软件
- 学习曲线低,YAML 语法简单
- 幂等性:多次执行结果一致
- 丰富的内置模块
-
劣势:
- 大规模节点(>1000)时 SSH 效率较低,需优化(如开启 pipelining、使用更快的连接方式)
2. 安装与配置
2.1 环境准备(以 Ubuntu 24.04 为例)
bash
# 设置主机名解析
cat >> /etc/hosts <<EOF
10.0.0.13 ubuntu24-13
10.0.0.12 rocky10-12
10.0.0.16 ubuntu24-16
EOF
# Ubuntu 更换阿里源(可选)
sed -i 's/archive.ubuntu.com/mirrors.aliyun.com/g' /etc/apt/sources.list
apt update
2.2 安装 Ansible
Ubuntu(二进制安装)
bash
apt install -y software-properties-common
add-apt-repository --yes --update ppa:ansible/ansible
apt install -y ansible
ansible --version
Rocky Linux(EPEL 源)
bash
yum install epel-release -y
yum install ansible -y
ansible --version
其他安装方式
- pip 安装(推荐虚拟环境)
- 源码安装(从 GitHub 克隆)
2.3 配置文件优先级
- 环境变量
ANSIBLE_CONFIG指定的文件 - 当前目录下的
ansible.cfg - 用户家目录下的
~/.ansible.cfg - 系统默认
/etc/ansible/ansible.cfg
生成基础配置文件:
bash
ansible-config init --disabled > ansible.cfg
关键配置项示例(ansible.cfg):
ini
[defaults]
inventory = /etc/ansible/hosts
remote_tmp = ~/.ansible/tmp
forks = 5
host_key_checking = False
log_path = /var/log/ansible.log
module_name = command
interpreter_python = /usr/bin/python3
[privilege_escalation]
become = False
become_method = sudo
become_user = root
[ssh_connection]
pipelining = True # 提高大规模执行效率
3. 主机清单 Inventory
3.1 文件格式(INI / YAML)
ini
# INI 格式示例
[web]
10.0.0.12
10.0.0.13
[db]
10.0.0.16
[all:vars]
ansible_user=root
ansible_ssh_private_key_file=~/.ssh/id_rsa
[web:vars]
http_port=80
3.2 常用连接参数
| 参数 | 说明 |
|---|---|
ansible_host |
目标主机地址 |
ansible_port |
SSH 端口(默认22) |
ansible_user |
连接用户 |
ansible_ssh_pass |
SSH 密码(不安全,建议使用密钥) |
ansible_ssh_private_key_file |
私钥路径 |
ansible_python_interpreter |
Python 解释器路径 |
ansible_connection |
连接类型(ssh / local / paramiko) |
3.3 主机匹配模式
bash
ansible all -m ping
ansible 'web:db' -m ping # 并集
ansible 'web:&db' -m ping # 交集
ansible 'web:!db' -m ping # 差集
ansible all -l 10.0.0.13 -m ping # 限制单台
3.4 配置 SSH 免密认证
bash
ssh-keygen -t rsa -P "" -f ~/.ssh/id_rsa
ssh-copy-id root@10.0.0.12
ssh-copy-id root@10.0.0.13
ssh-copy-id root@10.0.0.16
4. 常用模块详解
查询模块帮助:
ansible-doc -l列出所有模块,ansible-doc <模块名>查看详细用法。
4.1 命令执行类
| 模块 | 说明 | 示例 |
|---|---|---|
command |
默认模块,不支持管道、重定向 | ansible all -a "uptime" |
shell |
支持 shell 特性 | ansible all -m shell -a "echo $HOSTNAME" |
script |
在远程执行本地脚本 | ansible all -m script -a "/tmp/test.sh" |
4.2 文件操作类
| 模块 | 说明 | 示例 |
|---|---|---|
copy |
复制文件到远程 | ansible all -m copy -a "src=/etc/hosts dest=/tmp/" |
fetch |
从远程拉取文件到本地 | ansible all -m fetch -a "src=/var/log/syslog dest=./logs/" |
file |
管理文件属性、创建软链接、删除 | ansible all -m file -a "path=/tmp/test state=directory" |
lineinfile |
确保文件中某行存在/不存在 | ansible all -m lineinfile -a "path=/etc/profile regexp='^export HISTSIZE' line='export HISTSIZE=1000'" |
replace |
正则替换文件内容 | ansible all -m replace -a "path=/etc/fstab regexp='^(.*)' replace='#\1'" |
4.3 系统管理类
| 模块 | 说明 | 示例 |
|---|---|---|
user |
管理用户 | ansible all -m user -a "name=app state=present groups=wheel" |
group |
管理组 | ansible all -m group -a "name=app system=yes" |
hostname |
设置主机名 | ansible all -m hostname -a "name=node1" |
cron |
管理定时任务 | ansible all -m cron -a "name='sync time' minute=*/5 job='/usr/sbin/ntpdate time1.aliyun.com'" |
setup |
收集主机 facts | ansible all -m setup -a "filter=ansible_default_ipv4" |
4.4 软件包管理
| 模块 | 适用系统 | 示例 |
|---|---|---|
apt |
Debian/Ubuntu | ansible ubuntu -m apt -a "name=nginx state=present update_cache=yes" |
yum |
RHEL/CentOS/Rocky | ansible rocky -m yum -a "name=nginx state=latest" |
service |
管理服务 | ansible all -m service -a "name=nginx state=started enabled=yes" |
4.5 解压缩
| 模块 | 说明 | 示例 |
|---|---|---|
unarchive |
解压文件到远程 | ansible all -m unarchive -a "src=/tmp/pkg.tar.gz dest=/opt/ copy=no" |
4.6 调试
| 模块 | 说明 | 示例 |
|---|---|---|
debug |
打印变量或消息 | ansible all -m debug -a "msg='Hello World'" |
5. Playbook 基础
5.1 YAML 语法要点
- 缩进使用空格(通常2个),禁止使用 Tab
- 键值对:
key: value - 列表:
- item1(前导空格 + 短横 + 空格) - 文件开头可选
---
5.2 Playbook 基本结构
yaml
---
- hosts: web
remote_user: root
gather_facts: yes
vars:
package: nginx
tasks:
- name: install nginx
apt:
name: "{{ package }}"
state: present
- name: start nginx
service:
name: nginx
state: started
handlers:
- name: restart nginx
service:
name: nginx
state: restarted
5.3 执行 Playbook
bash
# 语法检查
ansible-playbook site.yml --syntax-check
# 模拟执行(dry run)
ansible-playbook site.yml -C
# 实际执行
ansible-playbook site.yml
# 查看主机/任务列表
ansible-playbook site.yml --list-hosts
ansible-playbook site.yml --list-tasks
# 指定 tags
ansible-playbook site.yml --tags "install"
# 从特定任务开始
ansible-playbook site.yml --start-at-task="start nginx"
5.4 异常处理
yaml
- name: 可能失败的命令
shell: /bin/false
ignore_errors: yes
5.5 Handlers(任务触发)
- 仅在被 notify 时执行,且只执行一次(即使被多个任务 notify)
yaml
tasks:
- name: update config
copy:
src: nginx.conf
dest: /etc/nginx/nginx.conf
notify: restart nginx
handlers:
- name: restart nginx
service:
name: nginx
state: restarted
5.6 Tags(标签)
yaml
tasks:
- name: install package
apt:
name: nginx
tags: [install, web]
- name: configure nginx
template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf
tags: configure
执行指定标签:ansible-playbook site.yml --tags "install"
6. Playbook 进阶
6.1 变量
变量定义位置(优先级从低到高)
- facts(自动收集的主机信息)
- inventory 主机变量
- inventory 组变量
- playbook 中
vars定义的变量 vars_files引入的变量文件- 命令行
-e传入的变量(最高)
示例
yaml
# playbook 内定义
vars:
http_port: 80
# 变量文件 vars.yml
---
db_host: 10.0.0.16
db_port: 3306
# 引入变量文件
vars_files:
- vars.yml
# 命令行覆盖
ansible-playbook site.yml -e "http_port=8080"
注册变量(register)
yaml
- name: get date
command: date
register: date_output
- name: show date
debug:
msg: "{{ date_output.stdout }}"
6.2 模板(Template)
- 使用 Jinja2 语法,文件后缀
.j2 - 通过
template模块渲染并复制到远程
jinja2
# nginx.conf.j2
server {
listen {{ http_port }};
server_name {{ ansible_fqdn }};
root /var/www/html;
}
yaml
- name: deploy nginx config
template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf
6.3 条件判断(when)
yaml
- name: install nginx on Debian
apt:
name: nginx
when: ansible_os_family == "Debian"
- name: install nginx on RedHat
yum:
name: nginx
when: ansible_os_family == "RedHat"
# 多条件
when:
- ansible_distribution == "CentOS"
- ansible_distribution_major_version == "7"
6.4 循环(loop)
yaml
- name: create users
user:
name: "{{ item }}"
state: present
loop:
- alice
- bob
# 循环字典列表
- name: add users with groups
user:
name: "{{ item.name }}"
group: "{{ item.group }}"
loop:
- { name: 'alice', group: 'developers' }
- { name: 'bob', group: 'ops' }
6.5 并发控制(serial)
yaml
- hosts: webservers
serial: 2 # 每次只更新2台
tasks:
- name: rolling update
shell: systemctl restart nginx
7. Roles 角色
7.1 Role 目录结构
roles/
└── role_name/ # 角色名
├── tasks/ # 必须,主任务文件 main.yml
├── handlers/ # 处理器,main.yml
├── templates/ # Jinja2 模板
├── files/ # 静态文件
├── vars/ # 高优先级变量,main.yml
├── defaults/ # 默认变量(最低优先级),main.yml
├── meta/ # 依赖关系,main.yml
└── README.md
7.2 创建角色
bash
ansible-galaxy init roles/role_name
7.3 使用角色
yaml
# playbook.yml
- hosts: web
roles:
- role: nginx
nginx_port: 8080
- role: php
when: ansible_os_family == "Debian"
7.4 角色任务拆分示例
yaml
# roles/nginx/tasks/main.yml
---
- include_tasks: install.yml
- include_tasks: config.yml
- include_tasks: service.yml
8. 最佳实践与总结
8.1 核心原则
- 幂等性:多次执行结果一致,模块应设计为幂等
- 使用变量:避免硬编码,提高复用性
- 模板化配置:利用 Jinja2 动态生成配置
- Role 化:将功能封装成角色,便于复用
- 版本控制:所有 Playbook 和 Roles 应纳入 Git
8.2 调试技巧
-v、-vv、-vvv增加输出详细程度--check模拟运行--diff显示文件变更差异debug模块打印变量
8.3 安全建议
-
使用 SSH 密钥而非密码
-
敏感信息使用 Ansible Vault 加密
bashansible-vault create secret.yml ansible-playbook --ask-vault-pass site.yml
9. 综合实践案例
案例1:Nginx 自动化部署(基础 Playbook)
yaml
---
- hosts: web
become: yes
vars:
nginx_port: 80
tasks:
- name: install nginx
apt:
name: nginx
state: present
when: ansible_os_family == "Debian"
- name: ensure nginx started
service:
name: nginx
state: started
enabled: yes
案例2:多虚拟主机(Template + 循环)
yaml
# vars:
vhosts:
- server_name: www.example.com
root: /var/www/example
- server_name: api.example.com
root: /var/www/api
# template vhost.conf.j2
{% for vhost in vhosts %}
server {
listen 80;
server_name {{ vhost.server_name }};
root {{ vhost.root }};
}
{% endfor %}
案例3:LNMP 环境 Role 化
目录结构:
lnmp/
├── site.yml
└── roles/
├── nginx/
├── php/
├── mysql/
└── wordpress/
site.yml 内容:
yaml
- hosts: web
roles:
- nginx
- php
- hosts: db
roles:
- mysql
- hosts: web
roles:
- wordpress