引言
在运维工作中,你是否曾被重复的部署步骤折磨?一台台SSH登录、执行同样的命令、复制相同的配置文件------不仅效率低下,还极易出错。随着服务器数量增长,手动运维已成为不可能完成的任务。Ansible作为一款简单、强大、无代理的自动化运维工具,正成为DevOps工程师的"瑞士军刀"。
本文将通过一个完整的实战项目,带你从零开始使用Ansible,在3台CentOS服务器上批量部署Nginx并上线静态网站。你将掌握Inventory清单、Playbook剧本、变量模板等核心知识,并能直接将示例代码用于生产环境。
一、Ansible核心概念速览
在动手之前,先理解几个关键概念:
- 控制节点(Control Node):安装Ansible的机器,负责下发任务。可以是你的笔记本或一台跳板机。
- 受管节点(Managed Nodes):被管理的服务器,只需开启SSH和Python即可,无需安装任何Agent。
- Inventory(清单) :定义受管节点的文件,可分组、定义变量。默认路径
/etc/ansible/hosts,也支持自定义。 - Module(模块) :Ansible执行任务的单元,比如
yum用于安装软件,copy用于复制文件,service用于管理服务。 - Task(任务):调用模块执行的一个具体操作。
- Playbook(剧本):YAML格式文件,定义了一系列Task的执行计划,是Ansible的核心。
- Roles(角色):组织Playbook的目录结构,实现代码复用。本文实战中会简单涉及。
Ansible的工作流程非常简单:控制节点通过SSH连接到受管节点,将Python脚本传送过去并执行,最终返回结果。整个过程幂等,多次执行结果一致,不会产生副作用。
二、实战场景与准备
目标环境
| 主机名 | IP地址 | 角色 | 操作系统 |
|---|---|---|---|
| ansible | 192.168.56.10 | 控制节点 | CentOS 7/8 |
| web01 | 192.168.56.11 | Web服务器 | CentOS 7/8 |
| web02 | 192.168.56.12 | Web服务器 | CentOS 7/8 |
我们将用Ansible在web01和web02上完成以下操作:
- 更新系统并安装Nginx
- 部署自定义静态网站(HTML+CSS)
- 配置防火墙放行HTTP/HTTPS
- 启动Nginx并设为开机自启
提前准备
- 控制节点安装Ansible(版本≥2.9)
- 控制节点能通过SSH密钥免密登录所有web节点
- 所有节点网络互通
bash
# 在控制节点生成SSH密钥(如果已有可跳过)
ssh-keygen -t rsa -b 4096
# 将公钥复制到web节点
ssh-copy-id root@192.168.56.11
ssh-copy-id root@192.168.56.12
三、安装Ansible及创建项目结构
安装Ansible
控制节点执行:
bash
# CentOS 7 需要先安装EPEL源
yum install epel-release -y
yum install ansible -y
# 验证安装
ansible --version
项目目录结构
我们将采用符合最佳实践的Roles结构(即使不复杂,也方便扩展):
bash
mkdir -p ansible-nginx-project/roles/nginx/{tasks,handlers,templates,files,vars}
mkdir -p ansible-nginx-project/inventory
cd ansible-nginx-project
最终结构:
.
├── inventory
│ └── hosts # 主机清单
├── roles
│ └── nginx
│ ├── tasks
│ │ └── main.yml # 任务列表
│ ├── handlers
│ │ └── main.yml # 触发器,如重启服务
│ ├── templates
│ │ └── index.html.j2 # 网站模板
│ ├── files
│ │ └── style.css # 静态CSS文件
│ └── vars
│ └── main.yml # 角色变量
└── deploy.yml # 主Playbook
四、编写详细配置
1. Inventory清单文件
创建 inventory/hosts:
ini
[webservers]
web01 ansible_host=192.168.56.11 ansible_user=root
web02 ansible_host=192.168.56.12 ansible_user=root
[webservers:vars]
ansible_python_interpreter=/usr/bin/python3
使用分组webservers,并定义了连接参数。如果您的受管节点默认Python是2,请指定Python3解释器路径(CentOS 8已默认为3)。
2. 角色变量
roles/nginx/vars/main.yml定义变量,便于统一修改:
yaml
---
# Nginx相关变量
nginx_port: 80
website_title: "Ansible自动化运维实战"
website_welcome: "恭喜!您的网站已通过Ansible部署成功。"
3. 任务列表
roles/nginx/tasks/main.yml是核心执行步骤:
yaml
---
# 任务1:安装EPEL源(CentOS 7需要,8可略过,但保留也不报错)
- name: Install EPEL repo for CentOS 7
yum:
name: epel-release
state: present
when: ansible_distribution_major_version == "7"
# 任务2:安装Nginx
- name: Install Nginx
yum:
name: nginx
state: latest
notify: restart nginx # 如有变更,触发handler重启
# 任务3:配置防火墙,放行HTTP/HTTPS
- name: Configure firewalld
firewalld:
service: "{{ item }}"
permanent: yes
state: enabled
immediate: yes
loop:
- http
- https
# 任务4:部署静态网站文件
- name: Deploy index.html from template
template:
src: index.html.j2
dest: /usr/share/nginx/html/index.html
owner: root
group: root
mode: 0644
notify: restart nginx
- name: Deploy CSS file
copy:
src: style.css
dest: /usr/share/nginx/html/style.css
owner: root
group: root
mode: 0644
# 任务5:确保Nginx启动并开机自启
- name: Start and enable Nginx
service:
name: nginx
state: started
enabled: yes
关键点解释 :
-
notify: restart nginx通知Handler,当配置文件变更时自动重启服务。 -
template模块渲染Jinja2模板,可将变量动态插入。 -
copy模块直接复制文件。 -
firewalld使用immediate: yes使规则立即生效。
4. 触发器Handlers
roles/nginx/handlers/main.yml:
yaml
---
- name: restart nginx
service:
name: nginx
state: restarted
Handlers只在被notify时执行,且所有任务完成后再统一运行,避免多次重启。
5. 网站模板文件
roles/nginx/templates/index.html.j2:
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>{{ website_title }}</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<h1>{{ website_welcome }}</h1>
<p>当前服务器主机名:{{ ansible_hostname }}</p>
<p>系统发行版:{{ ansible_distribution }} {{ ansible_distribution_version }}</p>
</body>
</html>
通过{``{ ansible_hostname }}等fact变量,展示每台服务器的差异信息,验证负载均衡效果。
6. 静态CSS文件
roles/nginx/files/style.css:
css
body {
font-family: Arial, sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
text-align: center;
padding: 100px;
}
h1 {
font-size: 3em;
margin-bottom: 20px;
}
7. 主Playbook
项目根目录下deploy.yml:
yaml
---
- name: Deploy Nginx and static website on webservers
hosts: webservers
gather_facts: yes # 收集主机信息,如hostname等
become: yes # 以root权限执行
roles:
- nginx
说明 :
-
hosts: webservers引用清单中的组。 -
gather_facts: yes会收集系统信息,可在模板中使用。 -
become: yes提权执行。
五、运行与验证
第一步:检查语法
bash
ansible-playbook -i inventory/hosts deploy.yml --syntax-check
输出应显示 playbook: deploy.yml 无报错。
第二步:列出任务(不执行)
bash
ansible-playbook -i inventory/hosts deploy.yml --list-tasks
确认任务列表。
第三步:执行部署
bash
ansible-playbook -i inventory/hosts deploy.yml
首次执行会看到大量changed状态。再次运行会显示ok,证明幂等性。
输出示例:
PLAY [Deploy Nginx and static website on webservers] **********************************
TASK [Gathering Facts] ***************************************************************
ok: [web01]
ok: [web02]
TASK [nginx : Install EPEL repo for CentOS 7] ****************************************
skipping: [web01] # 因为CentOS 8跳过
skipping: [web02]
TASK [nginx : Install Nginx] *********************************************************
changed: [web01]
changed: [web02]
...
第四步:验证网站
浏览器访问 http://192.168.56.11 和 http://192.168.56.12,应该看到渐变色背景的欢迎页,并显示正确的服务器主机名。
六、常见问题与注意事项
1. SSH连接失败
- 确认控制节点能免密连接:
ssh root@192.168.56.11。 - 检查防火墙是否允许SSH(通常22端口)。
- 如果使用非root用户,需在Inventory中配置
ansible_become=yes和ansible_become_pass(或在Playbook里设定)。
2. Python解释器问题
CentOS 8及以上默认Python3,CentOS 7需安装Python3或指定ansible_python_interpreter=/usr/bin/python2。建议统一安装Python3,并在清单中指定。
3. 防火墙模块差异
本文使用firewalld模块,如果你的系统用ufw(Ubuntu),请替换为:
yaml
- name: Allow HTTP in ufw
ufw:
rule: allow
port: '80'
proto: tcp
4. 幂等性与变更检测
Ansible模块会检测目标状态,避免重复操作。但自定义脚本需要自行保证幂等。使用creates或when条件可提升安全性。
5. 调试方法
- 增加输出详细度:
-v、-vv、-vvv。 - 仅执行指定任务:
--start-at-task="Task Name"。 - 使用
debug模块打印变量:
```yaml - debug:
var: ansible_hostname
```
6. 生产环境建议
- 将敏感信息(密码、密钥)放入Ansible Vault加密。
- 使用
ansible-lint检查Playbook是否符合最佳实践。 - 配合Git进行版本管理。
- 正式部署前在测试环境充分验证。
七、总结
通过本文的实战,你已掌握Ansible的核心工作流:定义Inventory → 编写Playbook和Roles → 执行部署。示例虽然简单,但覆盖了日常运维中90%的场景,稍加修改即可用于批量安装数据库、配置监控、更新应用等。
Ansible的优势在于简洁性、无代理架构和丰富的模块生态。随着业务的增长,你可以逐步学习动态Inventory、Ansible Tower/AWX、自定义模块等高级特性,打造一套自动化运维体系。
希望本文能成为你自动化之旅的坚实起点。把重复工作交给机器,留出时间思考更有价值的事!
完整项目代码已开源,欢迎克隆实践
GitHub示例仓库(伪链接):https://github.com/yourname/ansible-nginx-demo
如果文章对你有帮助,请点赞、收藏,你的支持是我持续输出的动力!