Ansible自动化运维实战:从零部署高可用Nginx+静态网站集群

引言

在运维工作中,你是否曾被重复的部署步骤折磨?一台台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在web01web02上完成以下操作:

  1. 更新系统并安装Nginx
  2. 部署自定义静态网站(HTML+CSS)
  3. 配置防火墙放行HTTP/HTTPS
  4. 启动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.11http://192.168.56.12,应该看到渐变色背景的欢迎页,并显示正确的服务器主机名。

六、常见问题与注意事项

1. SSH连接失败

  • 确认控制节点能免密连接:ssh root@192.168.56.11
  • 检查防火墙是否允许SSH(通常22端口)。
  • 如果使用非root用户,需在Inventory中配置ansible_become=yesansible_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模块会检测目标状态,避免重复操作。但自定义脚本需要自行保证幂等。使用createswhen条件可提升安全性。

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

如果文章对你有帮助,请点赞、收藏,你的支持是我持续输出的动力!

相关推荐
阿牛哥_GX1 天前
Word/PDF 文档处理:模板填充与格式转换
人工智能·自动化运维
增量星球1 天前
《持续交付2.0系列六》业务需求协作管理
java·运维·自动化·devops·持续部署·持续集成
砍材农夫1 天前
运维|devops|nginx|基本配置拆解
运维·nginx·devops
love530love2 天前
ComfyUI 插件发布 GitHub Release + Comfy Registry (官方节点商店)完整复盘教程(从零开始)
人工智能·windows·github·devops
John Song3 天前
ansible-playbook常用的检查命令
windows·ansible
龙智DevSecOps解决方案3 天前
Perforce Intelligence 三大平台全新发布:当自动化升级为“自主化”,AI 时代的工作流该如何编排?
软件测试·人工智能·devops·perforce
小林ixn4 天前
会议纪要自动化:用 Claude Skill 把重复工作“卷”成一行命令
agent·自动化运维
Geek-Chow4 天前
04 Touring the Stack: One Checkout, Traced Through Every Container
devops
增量星球5 天前
《持续交付2.0系列一》从技术交付到业务引领
java·docker·容器·devops