☰
从 Ansible Role 模板到可用角色:解读 90DaysOfDevOps 中 apache2 角色的标准结构与实战配置
2026/10/11 2:24:11 网站建设 项目流程
  • 文档/教程

【免费下载链接】90DaysOfDevOps

This repository started out as a learning in public project for myself and has now become a structured learning map for many in the community. We have 3 years under our belt covering all things DevOps, including Principles, Processes, Tooling and Use Cases surrounding this vast topic.

项目地址:https://gitcode.com/gh_mirrors/90/90DaysOfDevOps
点击查看免费下载

本篇文章以 90DaysOfDevOps 仓库 2022 年西班牙语版第 68 天配置管理实战中的 apache2 角色 README 为骨架,完整拆解一个 Ansible Role 的标准文件结构(Requirements、Role Variables、Dependencies、Example Playbook、License、Author Information),并结合仓库中ansible-scenario7的真实角色文件、playbook 与全局变量,说明如何把一个ansible-galaxy init生成的模板填充为一个可安装、可配置、可重启、可验证的 Apache HTTP Server 自动化角色。读完本文,你将掌握 Ansible Role 目录规范、变量分层(defaults / vars / group_vars)、任务与处理器(tasks/handlers)的协作方式,以及如何将 MySQL、Nginx 等角色组织进同一套多主机编排。

Role Name:一个角色的"身份证"

ansible-galaxy init roles/apache2生成的角色目录下,README.md 第一小节Role Name看似只是一个标题占位,但在工程实践中,它是角色在 Galaxy 生态与团队文档中的唯一身份标识。角色名应当与目录名、meta/main.yml中的描述保持一致,例如本仓库中的apache2、mysql、nginx、common四个角色,命名即职责:

  • apache2:安装与配置 Apache HTTP Server;
  • mysql:安装 MySQL 并创建数据库与用户;
  • nginx:部署反向代理配置;
  • common:安装各主机通用的基础工具。

角色的标准目录结构(以 ansible-scenario7/roles/apache2 为例)包含:

roles/apache2/ ├── defaults/main.yml # 默认变量(优先级最低,可被覆盖) ├── handlers/main.yml # 处理器:由任务 notify 触发的动作 ├── meta/main.yml # 角色元数据:作者、许可证、依赖、平台 ├── tasks/ │ ├── main.yml # 入口指针,import 具体任务文件 │ └── apache2_install.yml ├── templates/ │ ├── index.html.j2 # Jinja2 模板 │ └── ports.conf.j2 ├── tests/ │ ├── inventory │ └── test.yml └── vars/main.yml # 角色内部变量(优先级高于 defaults)

Requirements:运行角色前需要满足的前提

README 的Requirements小节提示:任何不被 Ansible 自身或角色覆盖的前置条件都应在此说明。以本仓库 MySQL 角色为典型例子——install_mysql.yml 中先通过apt安装python3-pip、mysql-client、python3-mysqldb、libmysqlclient-dev,再通过pip安装PyMySQL模块,然后才安装mysql-server。这正是Requirements要记录的内容:数据库模块依赖 Python 库与系统包,缺一不可。

第 68 天的实战笔记记录了真实教训:首次仅对database标签运行 playbook 时报错,原因是控制端缺少pip3(Python 包管理器),最终通过在 common 角色的任务中补装工具解决。对应证据在 common 角色 install_tools.yml,其中安装了neofetch、tree、figlet等通用工具。由此可见,Requirements 既是文档约定,也是任务文件里隐式执行的前置保障。

Role Variables:变量从哪里来、优先级如何

README 的Role Variables小节要求说明角色可设置的变量,包括defaults/main.yml、vars/main.yml中的变量,以及通过参数传入或从全局作用域(hostvars、group vars)读取的变量。

defaults 与 vars 的优先级

apache2 的 defaults/main.yml 和 vars/main.yml 目前都只有注释占位。在 Ansible 变量优先级体系中,vars/main.yml的优先级高于defaults/main.yml,而defaults是最低优先级,便于被 playbook、inventory、group_vars 或命令行-e覆盖。因此推荐:可变且需被外部定制的参数放 defaults,角色内部强约束的参数放 vars。

全局变量:group_vars

在本场景中,变量被集中到了全局作用域 group_vars/all/common_variables.yml:

http_port: 8000 https_port: 4443 html_welcome_msg: "Hello 90DaysOfDevOps - Welcome to Day 68!" mysql_user_name: root mysql_user_password: vagrant db_user: devops db_pass: DevOps90 db_name: 90DaysOfDevOps

由于放在group_vars/all/下,所有主机组(webservers、proxy、database)都能读取这些变量。这正是 README 中"从全局作用域读取变量"的真实落点——http_port被 apache2 的ports.conf.j2模板消费,同时被 nginx 的mysite.j2动态代理配置消费;mysql_*、db_*系列变量则被 mysql 角色的用户与数据库创建任务引用。

模板中的变量与事实(facts)

ports.conf.j2 使用Listen {{ http_port }}与Listen {{ https_port }}两个变量渲染监听端口,且仅在启用ssl_module或mod_gnutls.c模块时监听 HTTPS 端口:

Listen {{ http_port }} <IfModule ssl_module> Listen {{ https_port }} </IfModule> <IfModule mod_gnutls.c> Listen {{ https_port }} </IfModule>

index.html.j2 则同时使用了用户变量与 Ansible 自动收集的"事实":

<html> <h1>{{ html_welcome_msg }}! I'm webserver {{ ansible_facts['nodename'] }} </h1> </html>

ansible_facts['nodename']来自每次执行 playbook 前默认触发的"收集事实(gathering facts)"阶段,无需我们显式定义。你可以用ansible <host> -m setup查看完整事实数据,本仓库将输出重定向保存为 ansible-scenario5/facts.json 供查阅——其中包含 IP 地址、架构、BIOS 版本等大量可复用信息。这就是 README 提示"变量可来自 hostvars / group vars / facts"的完整写照。

Dependencies:角色依赖的声明方式

README 的Dependencies小节要求列出托管于 Galaxy 的其他角色及其参数。对应实现位于 meta/main.yml:

galaxy_info: author: your name description: your role description company: your company (optional) license: license (GPL-2.0-or-later, MIT, etc) min_ansible_version: 2.1 galaxy_tags: [] dependencies: []

dependencies: []表示当前角色没有声明对其他角色的硬依赖——依赖关系通过 playbook 的roles:列表以编排顺序表达(例如每个主机组都先跑common再跑业务角色),而不是在角色内部耦合。min_ansible_version: 2.1声明了最低 Ansible 版本门槛。值得注意的是,README 末尾声明许可证为 BSD,而meta/main.yml中 license 字段仍为占位符(SPDX 建议值如 BSD-3-Clause、MIT、GPL-2.0-or-later、Apache-2.0 等),正式发布前应统一二者。

Example Playbook:如何引用该角色

README 的Example Playbook给出了标准的角色引用语法:

- hosts: servers roles: - { role: username.rolename, x: 42 }

仓库中 playbook7.yml 给出了本场景的真实多主机编排:

- hosts: webservers become: yes roles: - common - apache2 tags: web - hosts: proxy become: yes roles: - common - nginx tags: proxy - hosts: database become: yes roles: - common - mysql tags: database

要点解读:

  • 三个 play 分别针对webservers(web01、web02)、proxy(loadbalancer)、database(db01)主机组,均使用become: yes提权;
  • 每个主机组先应用common(通用工具),再应用各自业务角色;
  • tags让运维可以按需定点执行:ansible-playbook playbook7.yml --tags web只跑 Web 相关任务,--tags database只配置数据库,而--tags proxy,web可组合执行;
  • 若某任务标记tag: always,则无论--tags传什么都会执行。

主机组定义在控制端的/etc/ansible/hosts(inventory)中,虚拟机清单可参考仓库根部的 Vagrantfile——它定义了db01(192.168.169.130)、web01(192.168.169.131)、web02(192.168.169.132)、loadbalancer(192.168.169.134)四台基于bento/ubuntu-21.10的机器。

Tasks 与 Handlers:安装、模板渲染与重启联动

apache2 角色通过 tasks/main.yml 作为指针文件引入 apache2_install.yml,形成完整的状态闭环:

- name: ensure apache is at the latest version apt: name=apache2 state=latest - name: write the apache2 ports.conf config file template: src=templates/ports.conf.j2 dest=/etc/apache2/ports.conf notify: restart apache - name: write a basic index.html file template: src: templates/index.html.j2 dest: /var/www/html/index.html notify: - restart apache - name: ensure apache is running service: name: apache2 state: started

四个任务职责清晰:

  1. 安装:apt: name=apache2 state=latest确保 Apache 为最新版本(幂等);
  2. 渲染监听端口:把ports.conf.j2写入/etc/apache2/ports.conf,配置变更时notify: restart apache;
  3. 渲染首页:把index.html.j2写入/var/www/html/index.html,同样在变更时通知重启;
  4. 保证运行:service模块确保apache2服务处于 started 状态。

处理器(handler)定义在 handlers/main.yml:

- name: restart apache service: name: apache2 state: restarted

关键机制:handler 仅在任务实际发生变更(changed)时由notify触发,且在所有任务结束后执行。这意味着只有端口配置或首页内容真正变化才重启 Apache,避免了无谓的服务中断——这是 Ansible 幂等设计在服务管理上的核心体现。

同样的模式贯穿于其他角色:mysql 的 handlers/main.yml 定义restart mysql;nginx 的 configure_nginx.yml 渲染mysite.j2到/etc/nginx/sites-enabled/mysite并notify: restart nginx,同时移除默认站点配置。

角色自测:tests 目录与 inventory

README 虽未单独列出测试小节,但角色目录规范中包含tests/。tests/test.yml 针对localhost执行角色:

- hosts: localhost remote_user: root roles: - roles/apache2

配合 tests/inventory(内容为localhost),可用于在开发机上快速冒烟验证角色是否可运行。发布到 Galaxy 前,建议为tests/补全针对各变量的验证断言。

运行与验证:端到端效果

在 db01 虚拟机启动并ssh-copy-id db01完成密钥分发后,从ansible-scenario7目录执行:

ansible-playbook playbook7.yml

若只想配置数据库,可只跑 database 标签:

ansible-playbook playbook7.yml --tags database

执行成功后,登录 db01 验证:

ssh db01 sudo /usr/bin/mysql -u root -p # 密码:vagrant select user, host from mysql.user; # 应看到 devops 用户 SHOW DATABASES; # 应看到 90DaysOfDevOps 数据库

同样可以用sudo /usr/bin/mysql -u devops -p(密码DevOps90)登录。实战笔记还记录了一个关键排错点:在 setup_mysql.yml 中创建用户时必须显式指定login_unix_socket: /var/run/mysqld/mysqld.sock,才能正确连接 db01 上的 MySQL 实例——这是本地套接字认证环境下的常见适配。

从整体链路看,common + apache2 + nginx + mysql四个角色通过 playbook7.yml 被编排到三组主机,变量统一收敛于 group_vars/all/common_variables.yml,nginx 的 mysite.j2 借助groups['webservers']与hostvars[host]['ansible_facts']['nodename']动态生成 upstream 列表,实现负载均衡配置随 Web 主机增减而自动伸缩。

小结

这份 apache2 角色的 README 虽然只是ansible-galaxy init生成的模板占位,但它精确勾勒了 Ansible Role 的"契约骨架"。对照 90DaysOfDevOps 仓库ansible-scenario7的真实实现可以看到:Requirements 对应任务中的系统包与 Python 模块安装,Role Variables 对应 defaults/vars/group_vars 的分层取值,Dependencies 对应 meta 中的声明与 playbook 的编排,Example Playbook 对应多主机组的 tags 化执行,License 与 Author Information 对应 meta/main.yml 的元数据。理解这套骨架,你就能把任意一个ansible-galaxy init生成的空角色,快速填充成可复用、可测试、可发布的生产级自动化组件。

  • 文档/教程

【免费下载链接】90DaysOfDevOps

This repository started out as a learning in public project for myself and has now become a structured learning map for many in the community. We have 3 years under our belt covering all things DevOps, including Principles, Processes, Tooling and Use Cases surrounding this vast topic.

项目地址:https://gitcode.com/gh_mirrors/90/90DaysOfDevOps
点击查看免费下载

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询