Ansible 自动化运维配置完全指南

Ansible 自动化运维配置完全指南

Someone Lv5

引言

在管理多台 Linux 服务器时,手动登录每台机器执行命令的方式不仅效率低下,而且容易出错。Ansible 作为一款开源的自动化运维工具,凭借其无需 Agent、基于 SSH、声明式语法的三大优势,已成为运维工程师的必备技能。本文将全面介绍 Ansible 的安装配置、核心概念与实战应用。

Ansible 核心架构

Ansible 采用无主从架构(Agentless),通过 SSH 协议直接管理远程主机,核心组件包括:

组件说明
Control Node控制节点,安装 Ansible 的机器(支持 Linux/macOS/WSL)
Managed Node被管理主机,通过 SSH 被控制节点操作
Inventory主机清单,定义被管理主机的列表和分组
Module执行具体任务的模块(如 copy、yum、service)
PlaybookYAML 格式的剧本文件,编排多个任务的执行流程
Role可复用的任务、变量、文件等资源的组织单元

一、Ansible 安装与配置

1.1 控制节点安装

Ubuntu / Debian

1
2
3
4
5
6
7
8
# 启用官方 PPA
sudo apt update
sudo apt install -y software-properties-common
sudo add-apt-repository --yes --update ppa:ansible/ansible
sudo apt install -y ansible

# 验证安装
ansible --version

CentOS / RHEL

1
2
3
4
5
6
# 启用 EPEL 仓库
sudo dnf install -y epel-release
sudo dnf install -y ansible

# 验证安装
ansible --version

使用 pip 安装(跨平台通用)

1
2
3
4
5
6
7
# 推荐使用虚拟环境
python3 -m venv ~/ansible-env
source ~/ansible-env/bin/activate
pip install ansible

# 安装特定版本
pip install ansible==9.5.0

1.2 SSH 免密登录配置

Ansible 通过 SSH 管理远程主机,因此需要配置 SSH 密钥认证:

1
2
3
4
5
6
7
# 生成 Ed25519 密钥对(如果还没有)
ssh-keygen -t ed25519 -f ~/.ssh/ansible_key -N ""

# 将公钥分发到所有被管理主机
ssh-copy-id -i ~/.ssh/ansible_key.pub user@host1
ssh-copy-id -i ~/.ssh/ansible_key.pub user@host2
ssh-copy-id -i ~/.ssh/ansible_key.pub user@host3

配置 SSH Config 简化连接:

1
2
3
4
5
6
7
8
9
10
11
12
# ~/.ssh/config
Host server-*
IdentityFile ~/.ssh/ansible_key
User ubuntu
StrictHostKeyChecking no
UserKnownHostsFile /dev/null

Host server-web
HostName 192.168.1.10

Host server-db
HostName 192.168.1.11

二、主机清单(Inventory)

2.1 静态 Inventory

默认位置 /etc/ansible/hosts 或自定义文件 inventory.ini

1
2
3
4
5
6
7
8
9
10
[webservers]
web1 ansible_host=192.168.1.10 ansible_user=ubuntu
web2 ansible_host=192.168.1.11 ansible_user=ubuntu

[dbservers]
db1 ansible_host=192.168.1.20

[all:vars]
ansible_ssh_private_key_file=~/.ssh/ansible_key
ansible_python_interpreter=/usr/bin/python3

2.2 Inventory 变量定义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# inventory.yml(YAML 格式更清晰)
all:
children:
webservers:
hosts:
web1:
ansible_host: 192.168.1.10
http_port: 80
web2:
ansible_host: 192.168.1.11
http_port: 8080
vars:
ansible_user: ubuntu
nginx_version: 1.26

2.3 动态 Inventory

AWS、GCP、阿里云等云平台提供动态 Inventory 脚本,自动从云 API 获取主机列表:

1
2
3
4
5
6
7
8
9
10
11
12
# 使用 AWS EC2 动态 Inventory
ansible-inventory -i aws_ec2.yaml --list

# aws_ec2.yaml 示例
plugin: aws_ec2
regions:
- ap-northeast-1
filters:
tag:Environment: production
keyed_groups:
- key: tags.Role
prefix: role

三、Ad-Hoc 命令快速上手

在编写 Playbook 之前,先通过 Ad-Hoc 命令熟悉 Ansible 的模块化操作:

3.1 连通性测试

1
2
3
4
5
# Ping 所有主机
ansible all -i inventory.ini -m ping

# 仅测试 webservers 组
ansible webservers -i inventory.yml -m ping

3.2 常用 Ad-Hoc 命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 远程执行命令
ansible all -m shell -a "uptime && free -h"

# 复制文件
ansible webservers -m copy -a "src=/etc/nginx/nginx.conf dest=/etc/nginx/nginx.conf backup=yes"

# 安装软件包
ansible webservers -m apt -a "name=nginx state=present" -b

# 启停服务
ansible webservers -m service -a "name=nginx state=restarted enabled=yes" -b

# 收集系统信息
ansible all -m setup -a "filter=ansible_distribution*"

3.3 常用模块速查

模块功能常用参数
command/shell执行命令cmd (shell 支持管道重定向)
copy复制文件src, dest, owner, mode, backup
templateJinja2 模板src, dest, vars
file文件/目录管理path, state (directory/touch/link/absent)
apt/yum/dnf包管理name, state (present/latest/absent)
service/systemd服务管理name, state (started/stopped/restarted), enabled
user用户管理name, groups, shell, state
lineinfile行编辑path, line, regexp, insertafter
firewalld/iptables防火墙规则service, port, permanent, state
docker_containerDocker 容器name, image, state, ports, env

四、编写 Playbook

Playbook 是 Ansible 的核心,使用 YAML 格式定义任务编排。

4.1 基础 Playbook 结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
---
- name: 配置 Nginx Web 服务器
hosts: webservers
become: yes
vars:
nginx_port: 80
server_name: example.com

tasks:
- name: 更新 apt 缓存
apt:
update_cache: yes
cache_valid_time: 3600

- name: 安装 Nginx
apt:
name: nginx
state: present

- name: 配置 Nginx 站点
template:
src: nginx.conf.j2
dest: /etc/nginx/sites-available/{{ server_name }}
notify: restart nginx

- name: 启用站点
file:
src: /etc/nginx/sites-available/{{ server_name }}
dest: /etc/nginx/sites-enabled/{{ server_name }}
state: link
notify: restart nginx

- name: 开放防火墙端口
ufw:
rule: allow
port: "{{ nginx_port }}"
proto: tcp

handlers:
- name: restart nginx
service:
name: nginx
state: restarted

4.2 执行 Playbook

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 基本执行
ansible-playbook -i inventory.yml nginx-setup.yml

# 检查模式(Dry Run)
ansible-playbook -i inventory.yml nginx-setup.yml --check

# 详细输出
ansible-playbook -i inventory.yml nginx-setup.yml -vvv

# 指定 SSH 用户
ansible-playbook -i inventory.yml nginx-setup.yml -u ubuntu

# 从特定任务开始执行
ansible-playbook -i inventory.yml nginx-setup.yml --start-at-task="配置 Nginx 站点"

# 语法检查
ansible-playbook -i inventory.yml nginx-setup.yml --syntax-check

4.3 条件判断与循环

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
- name: 根据发行版安装不同包
apt:
name: "{{ item }}"
state: present
when: ansible_facts['os_family'] == "Debian"
loop:
- nginx
- python3-pip
- htop

- name: 创建多个用户
user:
name: "{{ item.username }}"
groups: "{{ item.groups | default('users') }}"
shell: /bin/bash
loop:
- { username: "alice", groups: "sudo" }
- { username: "bob", groups: "docker" }
- { username: "carol" }

4.4 文件模板(Jinja2)

模板文件使用 .j2 扩展名,存放在 templates/ 目录下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
{# templates/nginx.conf.j2 #}
server {
listen {{ nginx_port }};
server_name {{ server_name }};

root /var/www/{{ server_name }};
index index.html;

location / {
try_files $uri $uri/ =404;
}

location /api {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}

五、Roles 角色编排

当 Playbook 变得复杂时,使用 Role 将任务、变量、模板和文件组织为可复用的单元。

5.1 Role 目录结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
site.yml                  # 主 Playbook
roles/
common/ # 通用角色
tasks/main.yml # 主任务列表
handlers/main.yml # 处理器
templates/ # Jinja2 模板
files/ # 静态文件
vars/main.yml # 角色变量
defaults/main.yml # 默认变量(优先级最低)
meta/main.yml # 角色依赖
nginx/ # Nginx 角色
tasks/main.yml
templates/nginx.conf.j2
vars/main.yml
postgresql/ # PostgreSQL 角色
tasks/main.yml
vars/main.yml

5.2 编写 Role 任务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# roles/nginx/tasks/main.yml
---
- name: 确保 Nginx 已安装
apt:
name: nginx
state: "{{ nginx_state | default('present') }}"

- name: 创建站点目录
file:
path: "/var/www/{{ nginx_server_name }}"
state: directory
mode: '0755'

- name: 部署 Nginx 配置
template:
src: nginx.conf.j2
dest: "/etc/nginx/sites-available/{{ nginx_server_name }}"
notify: restart nginx

- name: 启用站点
file:
src: "/etc/nginx/sites-available/{{ nginx_server_name }}"
dest: "/etc/nginx/sites-enabled/{{ nginx_server_name }}"
state: link
notify: restart nginx

- name: 部署 index.html
copy:
src: index.html
dest: "/var/www/{{ nginx_server_name }}/index.html"
mode: '0644'

5.3 主 Playbook 引用 Roles

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# site.yml
---
- name: 所有服务器通用配置
hosts: all
roles:
- common

- name: Web 服务器配置
hosts: webservers
roles:
- role: nginx
vars:
nginx_server_name: "example.com"
nginx_port: 443

- name: 数据库服务器配置
hosts: dbservers
roles:
- role: postgresql
vars:
postgresql_version: 16
postgresql_max_connections: 200

5.4 Role 依赖与 Galaxy

1
2
3
4
5
6
7
8
# roles/postgresql/meta/main.yml
---
dependencies:
- role: common
- role: geerlingguy.security
vars:
security_ssh_permit_root_login: "no"
security_fail2ban_enabled: true

使用 Ansible Galaxy 下载社区 Role:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 搜索 Role
ansible-galaxy search nginx

# 安装 Role
ansible-galaxy install geerlingguy.nginx
ansible-galaxy install geerlingguy.postgresql

# 安装 requirements.yml 中定义的 Role
cat << 'EOF' > requirements.yml
---
roles:
- name: geerlingguy.nginx
version: 3.2.0
- name: geerlingguy.postgresql
version: 3.5.0
- name: geerlingguy.security
version: 2.3.0
EOF

ansible-galaxy install -r requirements.yml

六、Ansible Vault 加密敏感数据

保护密码、密钥等敏感信息:

6.1 加密与解密

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 创建加密文件
ansible-vault create secrets.yml

# 编辑加密文件
ansible-vault edit secrets.yml

# 加密已有文件
ansible-vault encrypt group_vars/all/vault.yml

# 解密
ansible-vault decrypt secrets.yml

# 更改密码
ansible-vault rekey secrets.yml

6.2 使用加密变量

1
2
3
4
5
6
7
# group_vars/all/vault.yml(加密文件)
vault_db_password: "MySecureP@ssw0rd!2026"
vault_api_key: "sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

# group_vars/all/main.yml(引用加密变量)
db_password: "{{ vault_db_password }}"
api_key: "{{ vault_api_key }}"

6.3 执行时提供密码

1
2
3
4
5
6
7
8
9
10
# 交互式输入密码
ansible-playbook site.yml --ask-vault-pass

# 使用密码文件
echo "my-vault-password" > .vault_pass
chmod 600 .vault_pass
ansible-playbook site.yml --vault-password-file .vault_pass

# 使用环境变量
ANSIBLE_VAULT_PASSWORD_FILE=.vault_pass ansible-playbook site.yml

七、Ansible 配置优化

7.1 主配置文件 ansible.cfg

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
[defaults]
# Inventory 文件路径
inventory = inventory.yml

# 并行执行数量
forks = 20

# SSH 连接超时
timeout = 30

# 主机密钥检查(生产环境建议开启)
host_key_checking = False

# 日志路径
log_path = /var/log/ansible.log

# 模块缓存
gathering = smart
fact_caching = jsonfile
fact_caching_connection = /tmp/ansible_facts
fact_caching_timeout = 3600

# 默认 Python 解释器
interpreter_python = /usr/bin/python3

[ssh_connection]
# SSH 复用加速
pipelining = True
ssh_args = -o ControlMaster=auto -o ControlPersist=60s

7.2 性能优化技巧

1
2
3
4
5
6
7
8
9
10
11
# 关闭 fact gathering(如果不需要)
ansible-playbook site.yml --gathering=explicit

# 限制执行范围
ansible-playbook site.yml --limit web1

# 跳过特定标签
ansible-playbook site.yml --skip-tags "firewall"

# 仅执行特定标签
ansible-playbook site.yml --tags "deploy"

八、实战案例:完整部署 LEMP 栈

综合运用上述知识,编写完整 Playbook 部署 LEMP 栈(Nginx + MariaDB + PHP):

8.1 目录结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
lemp-deployment/
├── ansible.cfg
├── inventory.yml
├── site.yml
├── requirements.yml
├── group_vars/
│ └── all/
│ └── main.yml
├── roles/
│ ├── common/
│ │ └── tasks/main.yml
│ ├── nginx/
│ │ ├── tasks/main.yml
│ │ └── templates/nginx.conf.j2
│ ├── mariadb/
│ │ ├── tasks/main.yml
│ │ ├── vars/main.yml
│ │ └── templates/my.cnf.j2
│ └── php/
│ ├── tasks/main.yml
│ └── templates/www.conf.j2
└── vault.yml

8.2 部署命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 安装外部 Role
ansible-galaxy install -r requirements.yml

# 语法检查
ansible-playbook site.yml --syntax-check

# 试运行
ansible-playbook site.yml --check -v

# 正式部署
ansible-playbook site.yml -v

# 验证结果
ansible all -m shell -a "curl -sI http://localhost | head -5"

8.3 部署后验证脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# 独立的验证 Playbook
- name: 验证 LEMP 部署
hosts: all
tasks:
- name: 检查 Nginx 进程
shell: "pgrep -c nginx"
register: nginx_count
failed_when: nginx_count.stdout | int == 0

- name: 检查 MariaDB 进程
shell: "pgrep -c mariadbd"
register: mariadb_count
failed_when: mariadb_count.stdout | int == 0

- name: 检查 PHP-FPM 进程
shell: "pgrep -c php-fpm"
register: php_count
failed_when: php_count.stdout | int == 0

- name: 测试 Nginx 响应
uri:
url: http://localhost/health.php
return_content: yes
register: health
failed_when: "'OK' not in health.content"

- name: 输出部署摘要
debug:
msg:
- "Nginx 进程数: {{ nginx_count.stdout }}"
- "MariaDB 进程数: {{ mariadb_count.stdout }}"
- "PHP-FPM 进程数: {{ php_count.stdout }}"
- "Web 健康检查: {{ '通过' if health.status == 200 else '失败' }}"

九、常见问题排查

问题可能原因解决方案
SSH 连接超时防火墙规则、SSH 配置检查 ssh-T user@host 连通性;确认 ControlPath 文件无冲突
权限被拒绝become 未启用或密码错误添加 -b/-K 参数;检查 /etc/sudoers 配置
Python 解释器错误远程主机无 Python3设置 ansible_python_interpreter=/usr/bin/python3
事实(Fact)超时网络延迟或主机负载高启用 fact_caching;减少 for 数量
幂等性失败任务设计未考虑幂等性使用声明式模块而非 shell/command
依赖 Role 冲突多个 Role 修改同一文件使用 lineinfile 替代文件覆盖;明确 Role 执行顺序
模板语法错误Jinja2 变量未定义使用 default() 过滤器;--syntax-check 提前检查
并发写入冲突多节点同时操作使用 serial 限制并行度;throttle 控制并发

十、最佳实践总结

  1. 目录结构规范化:严格遵循 Role 目录结构,Playbook 和 Role 分离
  2. 变量分离:加密变量放 vault,默认值放 defaults,环境特化变量放 group_vars
  3. 幂等性优先:优先使用声明式模块,避免 shell/command 模块
  4. 版本控制:所有 Playbook、Role 和配置文件纳入 Git 管理
  5. 标签管理:通过 tags 精确控制 Playbook 执行范围
  6. 测试先行:使用 --check--diff 预览变更影响
  7. 日志记录:开启 ansible.log,便于故障追溯
  8. 定期验证:通过 cron 定时执行验证 Playbook 确保配置一致性

总结

Ansible 以其简洁的 YAML 语法、无 Agent 的架构设计和强大的模块生态,大大降低了服务器批量管理的学习门槛。从单条 Ad-Hoc 命令到复杂的多 Role 编排,Ansible 能够满足从小型项目到大规模集群的自动化运维需求。掌握 Inventory 清单管理、Playbook 编写、Role 复用和 Vault 加密等核心技能,是每一位运维工程师迈向高效自动化管理的关键一步。

本文由AI辅助生成,内容仅供参考

  • 标题: Ansible 自动化运维配置完全指南
  • 作者: Someone
  • 创建于 : 2026-06-16 17:13:00
  • 更新于 : 2026-06-18 08:39:57
  • 链接: https://demo-blog.qusite.cn/2026-06-16-ansible-automation-guide/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。