Ansible部署、核心概念与操作指南
一、Ansible 简介
Ansible 是一款开源的自动化运维工具,基于 Python 开发,无需在受管节点安装客户端,通过 SSH 协议实现远程控制。其核心优势包括:
- 无代理架构:受管节点无需部署额外软件
- 模块化设计:通过丰富的模块实现各类运维任务
- 支持 declarative 语法:Playbook 采用 YAML 格式,易读易写
- 幂等性:重复执行同一操作不会产生意外结果
二、Ansible 部署过程
2.1 环境要求
- 控制节点(Ansible 主机):Python 3.6+、SSH 客户端
- 受管节点:SSH 服务开启、Python 2.7 或 3.5+、sudo 权限(可选)
- 网络:控制节点与受管节点网络互通,支持 SSH 连接
2.2 控制节点安装(以 CentOS 为例)
方式 1:YUM 安装(推荐)
bash
# 安装 EPEL 源(CentOS 默认无 Ansible 仓库)
sudo yum install -y epel-release
# 安装 Ansible
sudo yum install -y ansible
# 验证安装
ansible --version
方式 2:pip 安装
bash
# 安装 pip
sudo yum install -y python3-pip
# 安装 Ansible
pip3 install ansible
# 添加环境变量(若未自动添加)
echo "export PATH=\$PATH:/usr/local/bin" >> ~/.bashrc
source ~/.bashrc
# 验证安装
ansible --version
2.3 免密登录配置(可选但推荐)
Ansible 默认使用 SSH 连接受管节点,配置免密登录可避免重复输入密码:
bash
# 控制节点生成 SSH 密钥对(若已存在可跳过)
ssh-keygen -t rsa -b 2048 -N "" -f ~/.ssh/id_rsa
# 分发公钥到受管节点(替换为实际主机名/IP)
ssh-copy-id root@node1
ssh-copy-id root@node2
2.4 目录结构说明
安装完成后,Ansible 核心目录如下:
bash
# 查看 Ansible 安装文件分布
rpm -ql ansible
关键目录说明:
/etc/ansible/:主配置目录(默认配置文件、主机清单)/usr/bin/:执行文件(ansible、ansible-playbook 等)/usr/lib/pythonX.X/site-packages/ansible/:依赖库与模块/usr/share/ansible/plugins/:插件目录/usr/share/doc/ansible/:帮助文档
三、核心概念
3.1 主机清单(Inventory)
定义 Ansible 管理的主机集合,支持静态清单(文本文件)和动态清单(脚本生成)。
3.1.1 静态清单格式(INI 格式)
创建清单文件 inventory:
ini
# 单个主机(IP 或主机名)
web1.example.com
192.0.2.42
# 主机组定义
[webservers]
web1.example.com
web2.example.com
192.168.3.7
[dbservers]
db1.example.com
db2.example.com
192.0.2.42
192.0.2.43
# 地理位置分组
[eastdc]
web1.example.com
db1.example.com
[westdc]
web2.example.com
db2.example.com
# 组嵌套(子组必须已定义)
[dc:children]
eastdc
westdc
# 范围简写(支持数字/字母范围)
[priv]
192.168.[4:7].[0:255] # 192.168.4.0-192.168.7.255
[hosts]
host[01:20].example.com # host01 ~ host20
[servers]
server[a:c].example.com # servera ~ serverc
3.1.2 内置主机组
all:包含所有主机ungrouped:未归属任何组的主机
3.1.3 清单验证命令
bash
# 查看单个主机
ansible --list-hosts -i inventory web1.example.com
# 查看主机组
ansible --list-hosts -i inventory webservers
# 查看所有主机
ansible --list-hosts -i inventory all
# 树形结构显示清单
ansible-inventory -i inventory --graph
# YAML 格式导出清单
ansible-inventory -i inventory --list -y
3.2 配置文件(ansible.cfg)
控制 Ansible 行为的配置文件,支持多级别优先级(从高到低):
- 环境变量
ANSIBLE_CONFIG指定的文件 - 当前目录下的
./ansible.cfg - 用户家目录下的
~/.ansible.cfg - 系统默认配置
/etc/ansible/ansible.cfg
常用配置示例(./ansible.cfg)
ini
[defaults]
# 清单文件路径
inventory = ./inventory
# 远程登录用户
remote_user = laogao
# 并发执行主机数
forks = 10
# 禁用 SSH 主机密钥检查
host_key_checking = False
# 日志文件路径
log_path = /var/log/ansible.log
# 默认模块
module_name = command
[privilege_escalation]
# 启用权限提升(sudo)
become = True
# 提升到 root 用户
become_user = root
# 提权方式
become_method = sudo
# 不提示输入 sudo 密码
become_ask_pass = False
配置验证命令
bash
# 查看当前生效的配置文件
ansible --version | grep 'config file'
# 查看所有配置项
ansible-config list
# 查看生效的配置
ansible-config dump
# 查看配置文件内容
ansible-config view
3.3 模块(Modules)
Ansible 的最小功能单元,用于执行具体任务(如文件操作、软件安装、服务管理等)。
常用模块分类
| 模块类型 | 代表模块 | 功能描述 |
|---|---|---|
| 文件操作 | copy、file、lineinfile | 复制文件、设置文件属性、修改文件内容 |
| 软件包 | yum、apt、pip | 管理系统软件包 |
| 服务管理 | service、systemd | 启动 / 停止 / 重启服务 |
| 系统管理 | user、group、reboot | 管理用户组、重启系统 |
| 命令执行 | command、shell、raw | 执行命令(command 不支持管道 / 重定向) |
模块文档查询
bash
# 查看模块列表
ansible-doc -l
# 查看指定模块详情(如 copy 模块)
ansible-doc copy
# 查看模块使用示例
ansible-doc -s copy
3.4 Ad-Hoc 命令
临时执行的单个任务命令,无需编写 Playbook,适用于快速测试或简单操作。
命令语法
bash
ansible <host-pattern> -m <module> [-a <module-arguments>] [-i <inventory>]
<host-pattern>:主机 / 主机组(如all、webservers)-m:指定模块(默认command模块)-a:模块参数-i:指定清单文件
常用示例
bash
# 1. 查看所有受管节点主机名(默认 command 模块)
ansible all -a "hostname"
# 2. 检查操作系统版本
ansible all -a "cat /etc/os-release"
# 3. 查看内存使用情况
ansible all -a "free -h"
# 4. 统计 /etc 目录文件数(需 shell 模块支持管道)
ansible all -m shell -a "ls -l /etc | wc -l"
# 5. 安装 httpd 软件(yum 模块)
ansible webservers -m yum -a "name=httpd state=present"
# 6. 启动并设置 httpd 开机自启(service 模块)
ansible webservers -m service -a "name=httpd state=started enabled=yes"
# 7. 复制本地文件到远程(copy 模块)
ansible all -m copy -a "src=/tmp/local.txt dest=/opt/remote.txt mode=0644"
# 8. 创建用户(user 模块)
ansible all -m user -a "name=newuser uid=1001 state=present"
执行结果颜色说明
- 绿色:目标主机已为预期状态,无需修改
- 黄色:命令执行后状态变更,已设置为预期状态
- 红色:执行过程出错,任务中止
3.5 Playbook
Ansible 的核心功能,用于编排多个任务,支持复杂的运维流程自动化。Playbook 采用 YAML 格式,具有可读性强、可复用的特点。
YAML 语法规则
- 缩进敏感:同一级别元素缩进一致(推荐 2 个空格)
- 键值对:
key: value(冒号后必须加空格) - 列表:用
-开头表示 - 注释:
#开头 - 字符串:可不用引号,特殊字符(如空格、换行)需用引号包裹
- 多行字符串:
|保留换行,>折叠换行
Playbook 基本结构
yaml
# 示例:部署 Web 服务
- name: 部署 HTTP 服务 # Play 名称
hosts: webservers # 目标主机组
become: True # 启用权限提升
tasks: # 任务列表
- name: 安装 httpd 和 firewalld # 任务 1 名称
yum: # 模块名
name: # 模块参数
- httpd
- firewalld
state: latest # 确保为最新版本
- name: 创建测试页面 # 任务 2 名称
copy:
content: "Welcome to Ansible Web!\n"
dest: /var/www/html/index.html
- name: 启动 firewalld 并放行 HTTP 服务 # 任务 3 名称
firewalld:
service: http
permanent: yes
state: enabled
immediate: yes
- name: 启动 httpd 并设置开机自启 # 任务 4 名称
service:
name: httpd
state: started
enabled: yes
Playbook 执行命令
bash
# 1. 直接执行
ansible-playbook playbook.yaml
# 2. 语法检查(不执行任务)
ansible-playbook --syntax-check playbook.yaml
# 3. 空运行(模拟执行,不修改系统)
ansible-playbook -C playbook.yaml
# 4. 提高输出详细程度(-v 到 -vvvv)
ansible-playbook -v playbook.yaml
# 5. 指定清单文件
ansible-playbook -i inventory playbook.yaml
3.6 变量(Variables)
用于存储可复用数据,简化 Playbook 维护。变量支持多级别定义,优先级从高到低为:
- 命令行变量(
-e参数) - Playbook 任务级变量
- Playbook Play 级变量
- 主机变量(host_vars)
- 主机组变量(group_vars)
- 清单文件变量
变量定义方式
方式 1:命令行定义
bash
# 传递变量 package=httpd 并安装
ansible all -e "package=httpd" -m yum -a "name={{ package }} state=present"
方式 2:Play 级变量(vars 关键字)
yaml
- name: 测试变量
hosts: node1
vars:
user: joe
home_dir: /home/joe
tasks:
- name: 创建用户 {{ user }}
user:
name: "{{ user }}"
home: "{{ home_dir }}"
state: present
方式 3:变量文件(vars_files 关键字)
创建变量文件 vars/user.yaml:
yaml
user: laowang
home_dir: /home/laowang
在 Playbook 中引用:
yaml
- name: 测试变量文件
hosts: node1
vars_files:
- vars/user.yaml
tasks:
- name: 创建用户 {{ user }}
user:
name: "{{ user }}"
home: "{{ home_dir }}"
state: present
方式 4:主机 / 组变量(目录结构)
推荐方式,在项目目录下创建 host_vars 和 group_vars 目录:
plaintext
project/
├── ansible.cfg
├── inventory
├── group_vars/
│ └── webservers.yaml # 主机组变量
├── host_vars/
│ └── node1.yaml # 主机变量
└── playbook.yaml
group_vars/webservers.yaml:
yaml
package: httpd
service: httpd
host_vars/node1.yaml:
yaml
package: mariadb-server # 覆盖组变量
变量引用规则
-
变量用
{``{ 变量名 }}引用 -
若变量作为值的第一个元素,需用引号包裹:
yaml# 错误示例 name: {{ user }} # 正确示例 name: "{{ user }}"
数组变量
yaml
- name: 测试数组变量
hosts: node1
vars:
users:
- name: joe
uid: 1001
home: /home/joe
- name: jane
uid: 1002
home: /home/jane
tasks:
- name: 创建用户 {{ item.name }}
user:
name: "{{ item.name }}"
uid: "{{ item.uid }}"
home: "{{ item.home }}"
state: present
loop: "{{ users }}" # 循环数组
3.7 事实(Facts)
Ansible 自动从受管节点收集的系统信息(如主机名、IP 地址、内核版本等),可作为变量直接使用。
查看 Facts
bash
# 查看所有 Facts
ansible node1 -m setup
# 过滤特定 Facts(如默认 IPv4 地址)
ansible node1 -m setup -a "filter=ansible_default_ipv4"
常用 Facts 示例
| Facts 变量 | 描述 |
|---|---|
ansible_facts['hostname'] |
短主机名 |
ansible_facts['fqdn'] |
完全限定域名 |
ansible_facts['default_ipv4']['address'] |
默认 IPv4 地址 |
ansible_facts['kernel'] |
内核版本 |
ansible_facts['memory_mb']['total'] |
总内存(MB) |
ansible_facts['distribution'] |
操作系统发行版 |
在 Playbook 中使用 Facts
yaml
- name: 使用 Facts 配置 Nginx
hosts: webservers
tasks:
- name: 配置 Nginx 监听地址
lineinfile:
path: /etc/nginx/nginx.conf
regexp: '^listen'
line: "listen {{ ansible_facts['default_ipv4']['address'] }}:80;"
关闭 Facts 收集(加快执行速度)
yaml
- name: 关闭 Facts 收集
hosts: webservers
gather_facts: no # 关闭自动收集
tasks:
# 手动收集特定 Facts(如需)
- name: 收集网络相关 Facts
setup:
gather_subset: network
3.8 敏感数据管理(Ansible Vault)
用于加密存储敏感数据(如密码、API 密钥),避免明文泄露。
常用命令
bash
# 1. 创建加密文件
ansible-vault create secret.yaml
# 输入密码后,编辑文件内容(YAML 格式):
# password: Huawei@123
# db_user: root
# 2. 查看加密文件
ansible-vault view secret.yaml
# 或通过密码文件自动输入密码
ansible-vault view --vault-password-file=pass.txt secret.yaml
# 3. 编辑加密文件
ansible-vault edit secret.yaml
# 4. 加密现有文件
ansible-vault encrypt plain.yaml
# 5. 解密文件
ansible-vault decrypt secret.yaml
# 6. 修改加密文件密码
ansible-vault rekey secret.yaml
在 Playbook 中使用加密文件
yaml
- name: 部署数据库并配置密码
hosts: dbservers
vars_files:
- secret.yaml # 引用加密文件
tasks:
- name: 安装 mariadb-server
yum:
name: mariadb-server
state: present
- name: 设置数据库 root 密码
mysql_user:
name: root
password: "{{ password }}" # 引用加密变量
host: '%'
priv: '*.*:ALL'
state: present
执行带加密文件的 Playbook
bash
# 交互输入密码
ansible-playbook playbook.yaml --ask-vault-pass
# 通过密码文件输入
ansible-playbook playbook.yaml --vault-password-file=pass.txt
# 在 ansible.cfg 中配置密码文件路径(永久生效)
echo "vault_password_file = ./pass.txt" >> ansible.cfg
ansible-playbook playbook.yaml
四、常用文件操作模块实战
4.1 file 模块(文件 / 目录管理)
yaml
- name: 文件操作示例
hosts: all
tasks:
# 1. 创建文件并设置权限
- name: 创建测试文件
file:
path: /tmp/testfile
owner: root
group: root
mode: 0644 # 权限(必须带前导 0)
state: touch
# 2. 创建目录(递归)
- name: 创建 /webdev 目录
file:
path: /webdev
owner: apache
group: apache
mode: 0755
state: directory
# 3. 删除文件
- name: 删除测试文件
file:
path: /tmp/testfile
state: absent
4.2 copy 模块(文件复制)
yaml
- name: 复制文件示例
hosts: webservers
tasks:
# 1. 复制本地文件到远程
- name: 复制 Nginx 配置文件
copy:
src: /etc/nginx/nginx.conf # 本地文件路径
dest: /etc/nginx/nginx.conf # 远程文件路径
owner: root
group: root
mode: 0644
backup: yes # 覆盖前备份原文件(后缀为时间戳)
# 2. 直接写入内容到远程文件
- name: 创建自定义 index.html
copy:
content: |
<html>
<head><title>Ansible Test</title></head>
<body><h1>Hello from {{ ansible_facts['hostname'] }}</h1></body>
</html>
dest: /var/www/html/index.html
4.3 lineinfile 模块(单行文本修改)
yaml
- name: 单行文本操作示例
hosts: webservers
tasks:
# 1. 确保文件中存在特定行
- name: 添加时区配置
lineinfile:
path: /etc/profile
line: "export TZ=Asia/Shanghai"
state: present
# 2. 在指定行前插入
- name: 在 Listen 80 前插入 Listen 8080
lineinfile:
path: /etc/httpd/conf/httpd.conf
line: "Listen 8080"
insertbefore: '^Listen 80'
state: present
# 3. 替换匹配的行
- name: 注释掉 Listen 80
lineinfile:
path: /etc/httpd/conf/httpd.conf
regexp: '^Listen 80'
line: '#Listen 80'
state: present
4.4 blockinfile 模块(多行文本块操作)
yaml
- name: 多行文本操作示例
hosts: webservers
tasks:
# 1. 向文件添加多行文本块
- name: 配置 Apache 虚拟主机
blockinfile:
path: /etc/httpd/conf/httpd.conf
block: |
<VirtualHost *:80>
ServerName web.example.com
DocumentRoot /var/www/example
ErrorLog /var/log/httpd/example_error.log
CustomLog /var/log/httpd/example_access.log combined
</VirtualHost>
state: present
marker: "# {mark} ANSIBLE MANAGED BLOCK - VirtualHost" # 标记注释
4.5 fetch 模块(从远程获取文件)
yaml
- name: 从远程获取文件示例
hosts: dbservers
tasks:
# 收集远程主机的日志文件到控制节点
- name: 获取 MariaDB 日志
fetch:
src: /var/log/mariadb/mariadb.log # 远程文件路径(必须是文件)
dest: /tmp/backup/ # 控制节点存储路径(会自动创建主机名子目录)
flat: no # 保留目录结构(默认 no)