使用Ansible角色源码编译部署nginx服务
实践项目背景:
随着云计算和自动化运维技术的发展,传统的手动部署软件方式已无法满足高效、标准化、规模化的运维需求。Ansible 作为一款轻量级的自动化运维工具,凭借无代理、基于 SSH 协议、配置简单等优势,被广泛应用于服务器配置管理、应用部署等场景。
Nginx 是高性能的 HTTP 和反向代理服务器,在生产环境中常需通过源码编译的方式部署,以满足自定义编译参数(如添加特定模块、指定用户 / 组、自定义安装路径)、适配特定系统环境、优化性能等需求。本实验基于前期 Ansible 部署 Httpd 的基础,通过 Ansible 角色(Role)模块化的方式实现 Nginx 的源码编译部署,旨在解决手动编译部署 Nginx 过程中步骤繁琐、易出错、环境一致性难以保障的问题,同时强化 Ansible 角色化、模块化的运维思想。
我们在上一个使用Ansible部署Httpd的案例的基础上,在httpd1 项目目录下创建 nginx 角色
1.环境架构配置
1.1创建roles角色
bash
[root@ansible-controller httpd1]# cd ~
[root@ansible-controller ~]# cd httpd1/roles
[root@ansible-controller roles]# ansible-galaxy role init nginx
- Role nginx was created successfully
[root@ansible-controller roles]# ls
httpd nginx
1.2修改playbook.yaml文件
bash
[root@ansible-controller roles]# vim ../playbook.yaml
[root@ansible-controller roles]# cat ../playbook.yaml
---
- name: Install httpd playbook
hosts: server
roles:
#- role: roles/httpd
- role: roles/nginx
将新创建的 nginx 角色添加到据本文件中。
2.创建角色目录结构
2.1编写tasks/main.yaml顺序配置清单文件
bash
[root@ansible-controller roles]# cd nginx/
[root@ansible-controller nginx]# cd tasks/
[root@ansible-controller tasks]# ls
main.yml
[root@ansible-controller tasks]# vim main.yml
[root@ansible-controller tasks]# cat main.yml
---
- include: install_nginx_compile.yaml
- include: install_nginx_dependency.yaml
- include: nginx_package_unzip.yaml
- include: compile_nginx.yaml
- include: config_nginx.yaml
- include: index_nginx.yaml
- include: service_nginx.yaml
2.2编写tasks/install_nginx_compile.yaml 安装编译工具模块
bash
[root@ansible-controller tasks]# vim install_nginx_compile.yaml
[root@ansible-controller tasks]# cat install_nginx_compile.yaml
---
- name: install compile
ansible.builtin.dnf:
name:
- gcc
- gcc-c++
state: installed
2.3编写tasks/install_nginx_dependency.yaml 安装nginx的依赖库模块
bash
[root@ansible-controller tasks]# vim install_nginx_dependency.yaml
[root@ansible-controller tasks]# cat install_nginx_dependency.yaml
---
- name: install nginx depenency
ansible.builtin.dnf:
name: "{{ item }}"
state: installed
loop:
- openssl
- openssl-devel
- zlib
- zlib-devel
- pcre
- pcre-devel
2.4编写tasks/nginx_package_unzip.yaml 解压nginx源码包模块
此实验需提前获取nginx-1.23.3.tar.gz压缩包,存放至roles/nginx/files目录下
bash
[root@ansible-controller tasks]# vim nginx_package_unzip.yaml
[root@ansible-controller tasks]# cat nginx_package_unzip.yaml
---
- name: unzip nginx package
unarchive:
src: "{{ src_nginx }}"
dest: "{{ nginx_unzip_dir }}"
2.5编写tasks/compile_nginx.yaml 创建用户,编译安装nginx模块
bash
[root@ansible-controller tasks]# vim compile_nginx.yaml
[root@ansible-controller tasks]# cat compile_nginx.yaml
---
- name: create nginx user
ansible.builtin.shell: |
user_name=`cat /etc/passwd|grep nginx|wc -l`
[ ${user_name} -eq 0 ] && useradd -s /sbin/nologin nginx || break
- name: compile and configue nginx
ansible.builtin.shell: |
cd {{ nginx_unzip_dir }}
cd {{ nginx_unzip_name }}
./configure --user=nginx --group=nginx --prefix={{ nginx_install_dir }} --with-http_stub_status_module --with-http_ssl_module
make
make install
2.6编写tasks/config_nginx.yaml 推送主配置+虚拟主机配置模块
bash
[root@ansible-controller tasks]# vim config_nginx.yaml
[root@ansible-controller tasks]# cat config_nginx.yaml
---
- name: config nginx
ansible.builtin.copy:
src: "{{ src_nginx_conf }}"
dest: "{{ dest_nginx_conf }}"
notify: restart nginx
- name: create nginx include conf
ansible.builtin.shell: |
cd {{ nginx_install_dir }}
[ ! -d conf/vhost ] && mkdir conf/vhost || break
- name: include conf
ansible.builtin.copy:
src: "{{ src_nginx_include_conf }}"
dest: "{{ dest_nginx_include_conf }}"
notify: restart nginx
2.7编写tasks/index_nginx.yaml 推送测试页面模块
bash
[root@ansible-controller tasks]# vim index_nginx.yaml
[root@ansible-controller tasks]# cat index_nginx.yaml
---
- name: index nginx
ansible.builtin.copy:
src: "{{ src_nginx_index }}"
dest: "{{ dest_nginx_index }}"
在roles/nginx/files目录下创建index.html文件,并写入页面
[root@harbor files]# vim index.html
[root@harbor files]# cat index.html
<!DOCTYPE html>
<html>
<head>
<title>Nginx Test Page</title>
</head>
<body>
<h1>Hello Nginx!</h1>
<p>Source compile success!</p>
</body>
</html>
2.8编写tasks/service_nginx.yaml 启动nginx模块
bash
[root@ansible-controller tasks]# vim service_nginx.yaml
[root@ansible-controller tasks]# cat service_nginx.yaml
---
- name: start nginx
ansible.builtin.shell: /usr/local/nginx/sbin/nginx
2.9编写handlers/main.yaml,在这个文件中定义任务处理器
bash
[root@ansible-controller tasks]# cd ../handlers/
[root@ansible-controller handlers]# vim main.yml
[root@ansible-controller handlers]# cat main.yml
---
- name: restart nginx
ansible.builtin.shell: |
pkill nginx
/usr/local/nginx/sbin/nginx
杀死现有nginx进程和重启nginx
3.变量定义
3.1编写vars/main.yaml 文件,在这个文件中定义所用到的变量
bash
[root@ansible-controller vars]# vim main.yml
[root@ansible-controller vars]# cat main.yml
---
src_nginx: "nginx-1.23.3.tar.gz" # 源码包名(控制器files目录)
nginx_unzip_dir: "/usr/local" # 源码解压目录
nginx_install_dir: "/usr/local/nginx" # Nginx安装目录
nginx_unzip_name: "nginx-1.23.3" # 解压后的源码目录名
src_nginx_conf: "nginx.conf" # 主配置文件名(控制器files目录)
src_nginx_include_conf: "www.test.com.conf" # 虚拟主机配置名
dest_nginx_conf: "/usr/local/nginx/conf/nginx.conf" # 主配置目标路径
dest_nginx_include_conf: "/usr/local/nginx/conf/vhost/www.test.com.conf" # 虚拟主机目标路径
src_nginx_index: "index.html" # 测试页面名(控制器files目录)
dest_nginx_index: "/usr/local/nginx/html/" # 测试页面目标路径
3.2编写files/nginx.conf 主配置文件
bash
[root@ansible-controller files]# vim nginx.conf
[root@ansible-controller files]# cat nginx.conf
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet.stream;
include /usr/local/nginx/conf/vhost/*.conf;
sendfile on;
keepalive_timeout 65;
}
3.3编写files/www.test.com.conf 虚拟机主配置文件
bash
[root@ansible-controller files]# vim www.test.com.conf
[root@ansible-controller files]# cat www.test.com.conf
server {
listen 80;
server_name www.test.com;
location / {
root html;
index index.html index.htm
}
}
4.运行和测试
4.1运行playbook
bash
[root@ansible-controller files]# cd ..
[root@ansible-controller nginx]# cd ..
[root@ansible-controller roles]# cd ..
[root@ansible-controller httpd1]# ansible-playbook playbook.yaml
bash
[root@harbor httpd1]# ansible-playbook playbook.yaml
[DEPRECATION WARNING]: "include" is deprecated, use include_tasks/import_tasks instead. See
https://docs.ansible.com/ansible-core/2.14/user_guide/playbooks_reuse_includes.html for details. This
feature will be removed in version 2.16. Deprecation warnings can be disabled by setting
deprecation_warnings=False in ansible.cfg.
PLAY [install nginx] **************************************************************************************
TASK [Gathering Facts] ************************************************************************************
ok: [192.168.110.150]
ok: [192.168.110.151]
TASK [roles/nginx : install compile] **********************************************************************
ok: [192.168.110.151]
ok: [192.168.110.150]
TASK [roles/nginx : install nginx depenency] **************************************************************
ok: [192.168.110.151] => (item=openssl)
ok: [192.168.110.150] => (item=openssl)
ok: [192.168.110.151] => (item=openssl-devel)
ok: [192.168.110.150] => (item=openssl-devel)
ok: [192.168.110.151] => (item=zlib)
ok: [192.168.110.151] => (item=zlib-devel)
ok: [192.168.110.150] => (item=zlib)
ok: [192.168.110.151] => (item=pcre)
ok: [192.168.110.150] => (item=zlib-devel)
ok: [192.168.110.151] => (item=pcre-devel)
ok: [192.168.110.150] => (item=pcre)
ok: [192.168.110.150] => (item=pcre-devel)
TASK [roles/nginx : unzip nginx package] ******************************************************************
ok: [192.168.110.151]
ok: [192.168.110.150]
TASK [roles/nginx : create nginx user] ********************************************************************
changed: [192.168.110.151]
changed: [192.168.110.150]
TASK [roles/nginx : compile and configue nginx] ***********************************************************
changed: [192.168.110.151]
changed: [192.168.110.150]
TASK [roles/nginx : config nginx] *************************************************************************
ok: [192.168.110.151]
ok: [192.168.110.150]
TASK [roles/nginx : create nginx include conf] ************************************************************
changed: [192.168.110.150]
changed: [192.168.110.151]
TASK [roles/nginx : include conf] *************************************************************************
changed: [192.168.110.150]
changed: [192.168.110.151]
TASK [roles/nginx : index nginx] **************************************************************************
ok: [192.168.110.150]
ok: [192.168.110.151]
TASK [roles/nginx : start nginx] **************************************************************************
changed: [192.168.110.150]
changed: [192.168.110.151]
RUNNING HANDLER [roles/nginx : restart nginx] *************************************************************
changed: [192.168.110.150]
changed: [192.168.110.151]
PLAY RECAP ************************************************************************************************
192.168.110.150 : ok=12 changed=6 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
192.168.110.151 : ok=12 changed=6 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
可以看到,安装和编译程序均无报错提示,nginx被成功编译安装在节点机上,接下来进行可用测试;
4.2节点测试
在主控节点上测试nginx访问:
bash
[root@harbor httpd1]# curl localhost:80
<!DOCTYPE html>
<html>
<head>
<title>Nginx Test Page</title>
</head>
<body>
<h1>Hello Nginx!</h1>
<p>Source compile success!</p>
</body>
</html>
[root@harbor httpd1]
在被控节点测试nginx访问:
[root@worker2 ~]# curl localhost:80
<!DOCTYPE html>
<html>
<head>
<title>Nginx Test Page</title>
</head>
<body>
<h1>Hello Nginx!</h1>
<p>Source compile success!</p>
</body>
</html>
[root@worker2 ~]#
验证可知,两个节点均被源码编译的方式成功部署nginx
5.实验总结:
本实验以 Ansible 控制器为核心,面向被控服务器节点,通过角色化的方式完成 Nginx 源码编译部署的全流程:
- 角色初始化 :使用
ansible-galaxy role init nginx创建标准化的 Nginx 角色目录结构,将部署逻辑与主 Playbook 解耦; - Playbook 配置:修改主 Playbook 文件,将 nginx 角色纳入执行流程,指定部署目标主机组;
- 任务模块化编写 :将 Nginx 部署拆解为编译工具安装、依赖库安装、源码包解压、用户创建、编译安装、配置文件推送、测试页面部署、服务启动、配置变更重启等子任务,每个子任务对应独立的 YAML 文件,通过
include(虽有弃用提示,但可适配为include_tasks)整合到tasks/main.yml; - 变量统一管理 :在
vars/main.yml中定义源码包名、解压目录、安装路径、配置文件路径等变量,提升部署脚本的可维护性和复用性; - 配置文件与测试资源准备 :在
files目录存放 Nginx 主配置文件、虚拟主机配置文件、测试页面文件,通过copy模块推送到目标节点指定路径; - 处理器定义 :在
handlers/main.yml中定义 Nginx 重启处理器,实现配置文件变更时自动重启服务; - 执行与验证 :运行
ansible-playbook playbook.yaml执行部署,通过curl命令在控制器和被控节点验证 Nginx 服务正常访问,最终所有目标节点均成功完成 Nginx 源码编译部署,无报错且访问测试页面正常。
6.实验意义与收获:
(一)实验意义
- 运维效率层面:将手动、重复性的 Nginx 源码编译部署工作自动化,大幅降低多节点部署的时间成本,提升运维效率,同时降低人为操作失误的概率;
- 标准化与规范化层面:通过 Ansible 角色的标准化目录结构和模块化任务设计,建立了可复用、可扩展的服务部署规范,为企业级批量运维提供了可落地的模板;
- 技术适配层面:满足了 Nginx 源码编译部署的个性化需求(如自定义模块、安装路径),相比二进制包安装更灵活,适配生产环境中多样化的业务场景;
- 自动化体系建设层面:强化了 "基础设施即代码(IaC)" 的理念,将运维操作转化为可版本控制、可追溯的代码,便于团队协作和运维经验沉淀。
(二)实验收获
- 技术能力提升:熟练掌握 Ansible 角色(Role)的创建、目录结构及核心功能(tasks/handlers/vars/files)的使用,理解模块化运维的核心思想;掌握 Nginx 源码编译部署的完整流程,包括编译依赖安装、编译参数配置、服务启停与配置管理;学会使用 Ansible 循环(loop)、处理器(handlers)、文件操作(copy/unarchive)、命令执行(shell)等模块解决实际运维问题,理解变量统一管理对脚本复用的重要性。
- 运维思维培养:建立 "自动化替代手动" 的运维思维,能够将复杂的运维任务拆解为标准化、可自动化的子任务;强化 "环境一致性" 和 "可复用性" 的运维理念,避免碎片化的手动操作,提升运维工作的规范性和可维护性;理解自动化部署脚本的容错性和可扩展性设计(如用户创建前的存在性判断、目录创建前的校验),提升脚本的健壮性设计能力。