一、Ansible 基础概念
1. 是什么
Ansible 是开源自动化运维工具 ,由红帽收购;基于 Python 开发,无 Agent(无客户端),采用 SSH 协议通信,不需要在被管理机器安装代理程序。
对比 SaltStack(可选 agent)、Puppet(C/S 架构)
2. 核心特性
- 无 Agent,仅主控机安装 ansible
- 模块化设计,所有操作依靠模块实现
- 支持 YAML 编写 Playbook,可读性强
- 支持临时命令(Ad-hoc)+ 批量脚本(Playbook)
- 幂等性:重复执行不会产生副作用(理想模块)
- 支持 Linux/Windows/ 网络设备、云主机 (AWS/Aliyun)
3. 架构组成
- 控制节点(主控):安装 ansible,发起任务
- 被管理节点(被控主机):只需开启 ssh
- Inventory(主机清单):定义管理哪些机器
- Modules(模块):执行最小单元(文件、服务、yum 等)
- Plugins(插件):扩展功能(连接、回调、过滤)
- Playbooks:YAML 任务剧本,编排多个模块
- Roles:Playbook 规范化目录结构,实现复用
二、安装与基础环境
安装方式
# CentOS/RHEL
yum install ansible
# Ubuntu
apt install ansible
# pip安装(新版本)
pip install ansible
查看版本
ansible --version
默认配置文件路径:
- 主配置:
/etc/ansible/ansible.cfg - 默认主机清单:
/etc/ansible/hosts
最佳实践:项目内自定义
ansible.cfg,优先读取当前目录配置,不修改全局配置。
三、Inventory 主机清单
1. 静态 Inventory(ini 格式,最常用)
# 单个主机
192.168.1.100
# 分组
[web]
192.168.1.101 ansible_user=root ansible_port=22
192.168.1.102 ansible_user=root ansible_ssh_pass=123456
[db]
192.168.1.103
# 组嵌套
[all_server:children]
web
db
常用内置变量:
ansible_user:ssh 登录用户ansible_port:ssh 端口ansible_ssh_pass:密码(生产建议密钥登录)ansible_private_key_file:私钥路径
2. 动态 Inventory
从云平台、CMDB API 动态获取主机列表,输出 JSON 格式。
常用匹配规则
-
all:所有主机 -
*通配符 -
:或;:&交集;:!排除ansible web:db -m ping
ansible web:&db -m ping
ansible all:!db -m ping
四、Ad-hoc 临时命令
语法:
ansible 主机组 -m 模块名 -a "模块参数"
高频示例
# 连通性测试 ping模块
ansible web -m ping
# 执行shell命令
ansible web -m shell -a "df -h"
# 复制文件
ansible web -m copy -a "src=/tmp/a.txt dest=/tmp/"
# 创建目录
ansible web -m file -a "path=/data state=directory"
# 安装软件
ansible web -m yum -a "name=nginx state=present"
# 启动服务
ansible web -m service -a "name=nginx state=started enabled=yes"
shell vs command 模块区别
command:默认模块,不支持管道、重定向、变量,安全性高shell:调用 /bin/sh,支持管道|、>、&&
五、模块(核心!)
常用内置模块清单
| 模块 | 作用 |
|---|---|
| ping | 测试连通性 |
| command | 执行简单命令(无 shell 特性) |
| shell | 执行 shell 命令,支持管道 |
| copy | 主控→被控 推送文件 |
| fetch | 被控→主控 拉取文件(只能单个文件) |
| file | 创建 / 删除文件、目录、修改权限 |
| yum/apt | 软件包管理 |
| service/systemd | 管理系统服务 |
| user/group | 用户、用户组管理 |
| lineinfile | 修改单行文本(替换、插入) |
| blockinfile | 插入 / 修改一段多行文本 |
| mount | 挂载磁盘 |
| cron | 定时任务 |
| template | 模板渲染(支持 jinja2) |
| get_url | 被控主机下载网络文件 |
查看模块文档:
ansible-doc 模块名
六、Playbook 剧本 YAML 语法
基础语法要点
- YAML 缩进必须空格,不能 tab
---开头,#注释key: value冒号后必须空格
最简 Playbook 示例 site.yml
---
- name: 部署nginx
hosts: web
become: true # 开启sudo提权
gather_facts: true # 收集被控主机信息(facts变量)
tasks:
- name: 安装nginx
yum:
name: nginx
state: present
- name: 启动并开机自启
service:
name: nginx
state: started
enabled: yes
运行命令:
ansible-playbook site.yml
# 模拟执行,不真实操作
ansible-playbook --check site.yml
# 指定密钥
ansible-playbook --private-key=/root/id_rsa site.yml
Playbook 核心关键字
hosts:目标主机组become: yes:sudo 提权(等价于 -b 参数)gather_facts:是否收集主机系统信息tasks:任务列表handlers:触发器,只有被 notify 触发才执行(常用于重载服务)vars:定义变量vars_files:引入外部变量文件roles:调用角色
Handlers 触发器示例
tasks:
- name: 修改nginx配置
copy:
src: nginx.conf
dest: /etc/nginx/nginx.conf
notify: restart nginx
handlers:
- name: restart nginx
service:
name: nginx
state: restarted
Template 极简总结(含示例 + 渲染效果)
核心要点
- template 模块 :基于 Jinja2 渲染模板,实现差异化配置,模板后缀习惯
.j2 - copy vs template
- copy:直接复制,不解析变量
- template:先渲染变量、判断、循环,再下发
- Jinja2 标记
{``{ 变量 }}输出值{% if/for %}逻辑控制{# 注释 #}最终文件不会出现
- Role 规范:
templates/→ template;files/→ copy - 参数:
backup: true更新前备份原配置
示例
1. 模板文件 nginx.conf.j2
worker_processes {{ ansible_processor_vcpus }};
listen {{ http_port | default(80) }};
{# 环境判断 #}
{% if env == "prod" %}
keepalive_timeout 60;
{% else %}
keepalive_timeout 10;
{% endif %}
2. Playbook 调用
vars:
env: prod
http_port: 8080
tasks:
- name: 下发nginx配置
template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf
mode: '0644'
backup: true
✅ 渲染后被控机器最终文件效果
worker_processes 2;
listen 8080;
keepalive_timeout 60;
说明: ansible_processor_vcpus 取自 facts(本机 CPU 核心数); env=prod 命中 if 分支;端口使用变量 8080。
七、Ansible 变量 Variable
7.1 变量作用
用来存放动态信息(主机 IP、用户名、软件版本、端口、路径等),统一一处定义,多处引用;修改变量即可批量变更配置,避免硬编码。 引用语法:{``{ 变量名 }}
注意:YAML 中如果
{``{ }}开头,建议加引号防止语法解析异常:"{``{ pkg_name }}"
7.2 变量的分类 + 定义方式(按出现位置划分)
1. Inventory 清单变量
可以给单台主机 或者整个主机组定义变量
# 主机变量(只生效这一台)
[web]
192.168.1.100 ansible_user=root pkg=nginx
# 组变量(组内所有主机生效)
[web:vars]
service_port=80
env=prod
2. Play 级别变量(写在 playbook 中)
方式① vars 直接定义
- hosts: web
vars:
pkg_name: nginx
listen_port: 80
方式② vars_files 引入外部变量文件
适合变量很多时拆分,单独写 yml 存放变量:
- hosts: web
vars_files:
- vars/common.yml
- vars/db.yml
3. Role 角色变量(工程化使用)
role 目录下两个目录,优先级不同:
defaults/main.yml:角色默认变量,优先级最低,允许外部覆盖vars/main.yml:角色内置变量,优先级高于 defaults
4. 任务级变量(task 内 vars)
只在当前这一个 task 生效,局部变量
tasks:
- name: 安装软件
yum:
name: "{{ pack }}"
state: present
vars:
pack: nginx
5. 命令行传入变量(最高优先级)
使用 -e / --extra-vars,临时覆盖所有地方定义的变量
# 单个变量
ansible-playbook deploy.yml -e "pkg_name=httpd"
# 多个变量
ansible-playbook deploy.yml -e "pkg_name=httpd;port=8080"
# 加载外部变量文件
ansible-playbook deploy.yml -e @var.json
6. Facts 内置自动变量(特殊变量)
当 gather_facts: true ,Ansible 自动采集被控主机信息,存入变量,无需手动定义。 常见 facts:
ansible_os_family:系统系列(RedHat/Debian)ansible_default_ipv4.address:默认网卡 IPansible_memtotal_mb:总内存ansible_processor_vcpus:CPU 核心数
优化:不需要系统信息时
gather_facts: false,减少执行耗时
7.3 变量优先级【重中之重,面试高频】
规则:范围越小、越临时定义,优先级越高;高优先级覆盖低优先级 从低 → 高排序:
- role
defaults/main.yml(最低) - Inventory 组变量
- Inventory 主机变量
- Play 中 vars /vars_files
- role
vars/main.yml - task 内部 vars
- 命令行
-e传入变量(最高)
Facts 不属于上述优先级体系,是系统采集的只读信息,不能直接覆盖。
7.4 特殊变量 hostvars /groups/inventory_hostname
inventory_hostname:当前执行任务的主机在 inventory 里的名称groups['web']:获取 web 组下所有主机列表hostvars['192.168.1.100']['ansible_user']:读取另外一台主机的变量 常用于多主机之间互相引用信息(例如配置集群,获取其他节点 IP)
7.5 变量加密 ansible-vault
变量文件如果存放数据库密码、密钥等敏感信息,明文不安全。
# 加密文件
ansible-vault encrypt secret.yml
# 编辑加密文件
ansible-vault edit secret.yml
# 解密
ansible-vault decrypt secret.yml
# 运行playbook时输入密码
ansible-playbook deploy.yml --ask-vault-pass
7.6 Jinja2 和变量配合
template 模块加载 .j2 模板文件,支持变量渲染、判断、循环 nginx.conf.j2 示例:
worker_processes {{ ansible_processor_vcpus }};
listen {{ listen_port }};
八、条件判断 & 循环
1. when 条件
- name: CentOS安装nginx
yum: name=nginx state=present
when: ansible_os_family == "RedHat"
支持多条件 and / or
2. 循环 with_items(新版推荐 loop)
tasks:
- name: 创建多个目录
file:
path: "{{ item }}"
state: directory
loop:
- /data
- /logs
九、Ansible 常用参数汇总
-i 指定inventory文件
-m 指定模块
-a 模块参数
-b --become sudo提权
-K --ask-become-pass 输入sudo密码
-C --check 模拟运行(干跑)
-v / -vv / -vvv 输出详细日志
-e 传入额外变量
--limit 限定主机 ansible-playbook site.yml --limit 192.168.1.101
十、易混淆知识点总结
- copy vs template copy:原样传输文件;template:Jinja2 渲染变量
- fetch vs copy copy:主控→被控;fetch:被控→主控(仅支持单个文件)
- handlers:只有 notify 触发,且所有任务执行完成后统一执行
- 幂等性:尽量使用官方模块;shell 命令很难做到幂等
- 静态 inventory vs 动态 inventory:静态适合固定服务器,动态适配云环境
十一、完整操作示例:
1.安装
yum install -i ansible
2.编辑inventory清单
[web]
192.168.118.101
192.168.118.102
[web:vars]
env=prod
-
vars.yml(外部变量)
http_port: 80
software: nginx -
nginx.conf.j2 模板
worker_processes {{ ansible_processor_vcpus }};
events {
worker_connections 1024;
}
http {
server {
listen {{ http_port }};
{# 判断环境 #}
{% if env == "prod" %}
server_name prod.test.com;
{% else %}
server_name test.test.com;
{% endif %}
root /usr/share/nginx/html;
}
}
渲染完成后被控端生成效果
worker_processes 2;
events {
worker_connections 1024;
}
http {
server {
listen 80;
server_name prod.test.com;
root /usr/share/nginx/html;
}
}
-
index.html 静态文件
Hello Ansible Demo
-
deploy.yml 主剧本playbook
-
name: 批量部署nginx
hosts: web
become: true
vars_files:- vars.yml
tasks:
-
name: 安装nginx
yum:
name: "{{ software }}"
state: present -
name: 推送nginx模板配置
template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf
mode: '0644'
backup: true
notify: 重启nginx -
name: 推送首页静态文件
copy:
src: index.html
dest: /usr/share/nginx/html/index.html
handlers:
- name: 重启nginx
service:
name: nginx
state: restarted
enabled: yes
-
-
执行命令
模拟运行,不真实修改
ansible-playbook deploy.yml --check
正式执行
ansible-playbook deploy.yml
临时修改变量覆盖配置
ansible-playbook deploy.yml -e "http_port=8080"
-
Ad-hoc 测试连通性(前置验证)
ansible web -m ping