文章目录
- [Ansible 核心概念与优势](#Ansible 核心概念与优势)
-
- [什么是 Ansible](#什么是 Ansible)
- 核心优势
- 环境部署与基础配置
-
- 安装方式
- 核心配置文件(优先级:低→高)
- inventory(主机清单)配置
-
- [示例 1:INI 格式(常用)](#示例 1:INI 格式(常用))
- [示例 2:YAML 格式](#示例 2:YAML 格式)
- 免密登录配置
- [Ansible 常用命令(Ad-Hoc 模式)](#Ansible 常用命令(Ad-Hoc 模式))
- [Playbook 核心语法(YAML 格式)](#Playbook 核心语法(YAML 格式))
-
- [Playbook 基本结构](#Playbook 基本结构)
- 核心语法规则
- [执行 Playbook](#执行 Playbook)
- 变量与模板(Jinja2)
- [角色(Roles):Playbook 模块化拆分](#角色(Roles):Playbook 模块化拆分)
-
- [Roles 目录结构(标准)](#Roles 目录结构(标准))
- [角色示例(nginx 角色)](#角色示例(nginx 角色))
- [Playbook 中调用 Roles](#Playbook 中调用 Roles)
- [实战场景:批量部署 LAMP 架构](#实战场景:批量部署 LAMP 架构)
- 常见问题与排障技巧
Ansible 核心概念与优势
什么是 Ansible
Ansible 是一款 无代理架构的自动化运维工具,基于 Python 开发,核心用于批量执行命令、配置管理、应用部署、任务编排等场景,无需在被控节点安装客户端,通过 SSH 协议(默认)或 WinRM(Windows 节点)实现通信
核心优势
- 无代理:被控节点无需安装 Ansible 客户端,仅需 SSH 服务(Linux)或 WinRM(Windows),部署成本极低;
- 模块化:所有操作通过模块实现,支持自定义模块,扩展性强;
- 声明式语法:Playbook 采用 YAML 格式,专注 "最终状态",无需编写复杂脚本逻辑;
- 幂等性:重复执行同一操作,结果一致(不会因重复执行导致异常);
- 轻量灵活:无需额外守护进程,依赖 Python 环境(2.7/3.5+),资源占用少。
环境部署与基础配置
安装方式
bash
# 方式1:YUM 安装
yum install epel-release -y # 安装 EPEL 源
yum install ansible -y
# 方式2:pip 安装
pip install ansible
# 验证安装
ansible --version # 显示版本信息则安装成功
核心配置文件(优先级:低→高)
- /etc/ansible/ansible.cfg:全局默认配置(系统级);
- ~/.ansible.cfg:用户级配置(覆盖全局);
- 项目目录下的 ansible.cfg:项目级配置(覆盖前两者,推荐使用)
inventory(主机清单)配置
Inventory 用于定义被控节点(目标主机),支持 INI 或 YAML 格式,默认路径 /etc/ansible/hosts。
示例 1:INI 格式(常用)
bash
# 单个主机(IP 或域名)
192.168.1.100
web01.example.com
# 分组配置(同一组主机可批量操作)
[web_servers] # 组名:web服务器组
web01 ansible_host=192.168.1.101 ansible_port=22 ansible_user=root ansible_ssh_pass=123456
web02 ansible_host=192.168.1.102 # 省略默认值(端口22、用户root)
[db_servers] # 组名:数据库服务器组
db01 ansible_host=192.168.1.201
db02 ansible_host=192.168.1.202
# 嵌套分组(组包含组)
[all_servers:children]
web_servers
db_servers
示例 2:YAML 格式
bash
all:
children:
web_servers:
hosts:
web01:
ansible_host: 192.168.1.101
ansible_ssh_pass: 123456
web02:
ansible_host: 192.168.1.102
db_servers:
hosts:
db01:
ansible_host: 192.168.1.201
免密登录配置
为避免每次执行命令输入密码,配置 SSH 免密登录
bash
# 控制节点生成密钥对(已生成可跳过)
ssh-keygen -t rsa -P "" -f ~/.ssh/id_rsa
# 批量分发公钥到被控节点(需输入一次密码)
ansible all -m authorized_key -a "user=root key='{{ lookup('file', '~/.ssh/id_rsa.pub') }}' state=present" --ask-pass
Ansible 常用命令(Ad-Hoc 模式)
Ad-Hoc 模式用于执行 临时命令 (无需编写 Playbook),格式:ansible [目标] -m [模块] -a [模块参数]
基础测试命令
bash
# 测试主机连通性(ping 模块,核心用于验证 SSH 通信)
ansible web_servers -m ping # 测试 web_servers 组所有主机
ansible all -m ping # 测试所有主机(all 为默认组)
# 执行shell命令(command 模块,默认模块,无需指定 -m)
ansible db_servers -a "df -h" # 查看数据库组主机磁盘情况
ansible web01 -a "systemctl status nginx" # 查看单个主机 nginx 状态
# 执行复杂shell命令(含管道、重定向,需用 shell 模块)
ansible web_servers -m shell -a "ps aux | grep nginx | wc -l"
ansible all -m shell -a "echo 'test' > /tmp/test.txt"
常用模块实战

命令常用参数
-i:指定自定义 inventory 文件(默认用 /etc/ansible/hosts)
bash
ansible -i ./my_hosts web_servers -m ping
-u:指定执行用户(默认 root)-k/--ask-pass:提示输入 SSH 密码-b/--become:切换到其他用户(默认 root,需配置 sudo 权限)-v: verbose 模式(-vvv 显示详细执行过程,排障用)
Playbook 核心语法(YAML 格式)
Playbook 是 Ansible 自动化的核心,用于编排多任务、多主机的复杂操作,本质是 YAML 格式的 "任务清单"
Playbook 基本结构
bash
- name: 部署 Nginx 服务 # Play 名称(可选,便于阅读)
hosts: web_servers # 目标主机/组(必填)
remote_user: root # 执行用户(可选,默认 root)
become: yes # 是否提权(可选,如需 sudo)
vars: # 定义变量(可选)
nginx_port: 80
nginx_root: /usr/share/nginx/html
tasks: # 任务列表(必填,按顺序执行)
- name: 安装 Nginx # 任务名称(可选)
yum: # 模块名
name: nginx # 模块参数
state: installed
- name: 复制 Nginx 配置文件
copy:
src: ./nginx.conf # 本地配置文件路径
dest: /etc/nginx/nginx.conf # 远程路径
notify: # 触发处理器(配置变更后执行)
- 重启 Nginx
- name: 创建网站根目录
file:
path: "{{ nginx_root }}" # 引用变量(双大括号)
state: directory
mode: 755
- name: 启动 Nginx 并设开机自启
service:
name: nginx
state: started
enabled: yes
handlers: # 处理器(仅被 notify 触发时执行,且只执行一次)
- name: 重启 Nginx
service:
name: nginx
state: restarted
核心语法规则
- 缩进:YAML 依赖缩进(2 个空格,禁止用 Tab),同一层级缩进一致;
- 变量:vars 中定义,使用 {{ 变量名 }} 引用;
- 任务:每个任务必须指定 name(可选)和 模块名,模块参数用键值对;
- 处理器(handlers):用于 "配置变更后需执行的操作"(如重启服务),仅在任务状态为 changed 时被 notify 触发;
- 条件判断:when 关键字,满足条件才执行任务:
bash
- name: 只在 CentOS 系统安装 yum 包
yum: name=nginx state=installed
when: ansible_distribution == "CentOS"
- 循环:with_items/loop 关键字,批量执行同一任务:
bash
- name: 安装多个依赖包
yum:
name: "{{ item }}"
state: installed
loop: # 等价于 with_items
- gcc
- pcre-devel
- zlib-devel
执行 Playbook
bash
# 基本执行(-i 指定 inventory,-v 显示详细日志)
ansible-playbook -i ./my_hosts deploy_nginx.yml -v
# 检查语法(不执行任务)
ansible-playbook --syntax-check deploy_nginx.yml
# 模拟执行(Dry Run,不实际修改系统)
ansible-playbook -C deploy_nginx.yml
变量与模板(Jinja2)
变量来源(优先级:高→低)
- 命令行传递:ansible-playbook -e "nginx_port=8080" deploy.yml(-e 指定额外变量);
- Playbook 中 vars 定义;
- Inventory 中定义(主机变量、组变量);
- Facts(系统内置变量,如 ansible_ip_addresses、ansible_os_family):
bash
# 查看目标主机的 Facts 信息
ansible web01 -m setup
模板文件(.j2)
使用 Jinja2 模板动态生成配置文件(如 Nginx 配置、MySQL 配置),模板文件后缀为 .j2
示例:Nginx 模板文件(nginx.conf.j2)
bash
server {
listen {{ nginx_port }}; # 引用变量
server_name {{ ansible_fqdn }}; # 引用 Facts 变量
root {{ nginx_root }};
index index.html;
{% if enable_ssl == true %} # Jinja2 条件判断
ssl on;
ssl_certificate /etc/nginx/ssl/cert.pem;
{% endif %}
}
Playbook 中使用 template 模块
bash
- name: 部署 Nginx 配置文件(模板)
template:
src: ./nginx.conf.j2 # 本地模板文件
dest: /etc/nginx/conf.d/default.conf # 远程生成的配置文件
mode: 644
vars:
nginx_port: 8080
nginx_root: /var/www/html
enable_ssl: false
notify: 重启 Nginx
角色(Roles):Playbook 模块化拆分
当 Playbook 变得复杂时,使用 Roles 进行模块化拆分,便于复用和维护。Roles 是按特定目录结构组织的任务、变量、模板等的集合。
Roles 目录结构(标准)
bash
roles/
├── nginx/ # 角色名:nginx
│ ├── tasks/ # 核心任务(必须,main.yml 为入口)
│ │ └── main.yml
│ ├── vars/ # 角色变量(可选,main.yml 为入口)
│ │ └── main.yml
│ ├── templates/ # 模板文件(可选)
│ │ └── nginx.conf.j2
│ ├── handlers/ # 处理器(可选,main.yml 为入口)
│ │ └── main.yml
│ ├── files/ # 静态文件(可选,如证书、脚本)
│ │ └── index.html
│ └── meta/ # 角色依赖(可选)
│ └── main.yml
└── mysql/ # 角色名:mysql(结构同上)
角色示例(nginx 角色)
roles/nginx/tasks/main.yml(任务入口):
bash
- name: 安装 Nginx
yum: name=nginx state=installed
- name: 复制静态首页文件
copy: src=index.html dest={{ nginx_root }} mode=644
- name: 部署 Nginx 配置文件(模板)
template: src=nginx.conf.j2 dest=/etc/nginx/conf.d/default.conf
notify: 重启 Nginx
- name: 启动 Nginx 服务
service: name=nginx state=started enabled=yes
roles/nginx/vars/main.yml(变量):
bash
nginx_port: 80
nginx_root: /usr/share/nginx/html
roles/nginx/handlers/main.yml(处理器):
bash
- name: 重启 Nginx
service: name=nginx state=restarted
Playbook 中调用 Roles
bash
- name: 部署 Web 服务(调用 nginx 角色)
hosts: web_servers
roles:
- nginx # 直接调用角色(默认读取 roles/nginx)
# - { role: nginx, nginx_port: 8080 } # 传递变量覆盖角色默认值
实战场景:批量部署 LAMP 架构
需求:
目标组:web_servers(CentOS 7);
部署组件:Apache(httpd)、MySQL、PHP;
实现:创建测试页面,验证 PHP 连接 MySQL。
Playbook(lamp_deploy.yml)
bash
- name: 批量部署 LAMP 架构
hosts: web_servers
remote_user: root
vars:
mysql_root_pass: 123456
test_db: testdb
test_user: testuser
test_user_pass: testpass123
tasks:
# 1. 安装依赖包
- name: 安装 LAMP 相关包
yum:
name:
- httpd
- mariadb-server
- mariadb
- php
- php-mysql
- gcc
state: installed
# 2. 启动服务并设开机自启
- name: 启动 httpd 服务
service: name=httpd state=started enabled=yes
- name: 启动 mariadb 服务
service: name=mariadb state=started enabled=yes
# 3. 配置 MySQL(创建数据库、用户、授权)
- name: 初始化 MySQL 根密码
shell: mysqladmin -u root password '{{ mysql_root_pass }}'
ignore_errors: yes # 避免已设置密码时报错
- name: 创建测试数据库
mysql_db:
name: '{{ test_db }}'
state: present
login_user: root
login_password: '{{ mysql_root_pass }}'
- name: 创建测试用户并授权
mysql_user:
name: '{{ test_user }}'
password: '{{ test_user_pass }}'
priv: '{{ test_db }}.*:ALL'
host: '%'
state: present
login_user: root
login_password: '{{ mysql_root_pass }}'
# 4. 创建 PHP 测试页面
- name: 生成 PHP 测试文件
copy:
content: |
= mysqli_connect('localhost', '{{ test_user }}', '{{ test_user_pass }}', '{{ test_db }}');
if ($conn) {
echo "LAMP 部署成功!PHP 连接 MySQL 正常!";
} else {
echo "连接失败:" . mysqli_connect_error();
}
mysqli_close($conn);
?>
dest: /var/www/html/test.php
mode: 644
# 5. 开放 80 端口(防火墙)
- name: 开放 80 端口
firewalld:
service: http
permanent: yes
state: enabled
immediate: yes
执行与验证
bash
# 执行 Playbook
ansible-playbook -i ./my_hosts lamp_deploy.yml
# 验证:访问测试页面(浏览器或 curl)
curl http://192.168.1.101/test.php
常见问题与排障技巧
- SSH 连接失败:
- 检查被控节点 SSH 服务是否启动(systemctl status sshd);
- 验证 inventory 中主机 IP、端口、用户名、密码是否正确;
- 关闭被控节点防火墙(systemctl stop firewalld)或开放 SSH 端口。
- 模块执行报错:
- 用 -vvv 查看详细日志(ansible-playbook -vvv deploy.yml);
- 检查模块参数是否正确(参考 Ansible 官方模块文档);
- 确保被控节点满足模块依赖(如 yum 模块仅支持 RHEL 系系统)。
- Playbook 语法错误:
- 用 ansible-playbook --syntax-check 检查语法;
- 确认缩进为 2 个空格,无 Tab 字符;
- 字符串含特殊字符时用引号包裹(单引号 / 双引号)。