资讯动态

90DaysOfDevOps 第 68 天:Ansible 标签、变量、Inventory 与数据库服务器配置实战

发布时间:2026/10/3 13:37:16 来源:尧图企业网站定制
文档/教程【免费下载链接】90DaysOfDevOpsThis 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 天的内容对应 2022/Days/day68.md聚焦 Ansible 自动化运维中的四个关键实战主题用标签Tags精细控制 playbook 的执行范围、用用户自定义变量与 Ansible Facts 让配置模板动态化、用独立 Inventory 文件管理多环境主机清单以及最终通过一个全新的 mysql 角色把数据库服务器 db01 接入自动化体系。读完本文你将掌握--tags、--list-tags、setup模块、group_vars/host_vars目录约定与 MySQL 角色的完整落地方法并能在自己的 Ansible 环境中直接复现整套多主机编排。回顾我们正在搭建的多节点环境前几天的内容已经在本地通过 Vagrant 建起了一组虚拟机web01、web02、loadbalancer 与 db01其定义位于 2022/Days/Configmgmt/Vagrantfile。从该文件中可以看到db01192.168.169.130、web01192.168.169.131、web02192.168.169.132、loadbalancer192.168.169.134四台机器均使用bento/ubuntu-21.10镜像每台机器把宿主机的 22 端口分别映射为 2210、2211、2212、2213方便控制节点逐个 SSH 访问每台虚拟机分配 2048MB 内存并接入桥接网络。控制节点本地主机通过/etc/ansible/hosts默认 Inventory 文件管理这些主机将其划分为webservers、proxy与database三个组。本文将基于这个环境逐步完成“标签化执行 → 变量外置 → 动态模板 → 数据库角色部署”的完整链路。Tags让大 playbook 按需分片执行在昨天Day 67留下的 playbook 中webservers与proxy两组 play 会顺序执行到结束。当 playbook 变得又长又大时这种“全量执行”并不高效——此时标签Tags可以把任务分组按需只跑其中一部分。本部分使用的示例文件为 ansible-scenario5/playbook5.yml- hosts: webservers become: yes vars: http_port: 8000 https_port: 4443 html_welcome_msg: Hello 90DaysOfDevOps - Welcome to Day 66! roles: - common - apache2 tags: web - hosts: proxy become: yes roles: - common - nginx tags: proxy这里的要点是tags既可以写在 play 级别如上例也可以写到任务task级别从而在单个 play 内部实现更细粒度的控制。例如为安装、配置、卸载类任务分别打上不同的标签。查看与筛选标签的常用命令ansible-playbook playbook5.yml --list-tags不实际执行只列出该 playbook 中已定义的全部标签便于在运行前确认标签结构ansible-playbook playbook5.yml --tags proxy只执行带有proxy标签的 play 或任务其余跳过ansible-playbook playbook5.yml --tags proxy,web同时执行带proxy与web标签的内容多个标签可以捆绑使用一个 play 或任务也可以同时声明多个标签ansible-playbook playbook5.yml --skip-tags tag反选跳过指定标签。特殊的always标签文档中还强调了一个非常实用的标签值——tag: always。任何被打上always的 play 或任务无论你在命令行使用哪个--tags它都会被执行。这非常适合放置那些每次都必须运行的公共步骤例如基础环境检查、事实收集或安全加固任务避免被--tags过滤掉。变量体系Ansible Facts 与用户自定义变量Ansible 的变量主要分为两大类用户自定义变量User created variables由我们自己在 playbook、vars段或变量文件中定义Ansible Facts事实每次运行 playbook 时自动收集的目标主机信息对应任务名为“Gathering facts”。Ansible Facts用 setup 模块洞察目标主机每一次ansible-playbook执行时默认都会先执行一个我们没有显式定义的任务——“Gathering facts”它把目标主机的系统信息以 JSON 形式带回控制节点。我们可以单独用 setup 模块查看这些数据ansible proxy -m setup输出内容非常庞大建议重定向到文件再研究ansible proxy -m setup facts.json仓库中保存了一份真实运行结果 ansible-scenario5/facts.json展开后可以看到ansible_all_ipv4_addressesIP 地址、ansible_architecture架构如 x86_64、ansible_bios_versionBIOS 版本等成百上千个键值。这些字段可以直接在 playbook 与模板中以ansible_facts[xxx]的形式引用。用 Facts 循环模板实现负载均衡动态配置在 Day 66/67 中nginx 负载均衡模板 ansible-scenario4/roles/nginx/templates/mysite.j2 里硬编码了两个 web 服务器的 IPupstream webservers { server 192.168.169.131:8000; server 192.168.169.132:8000; }现在借助 Facts 与 Jinja2 的for循环可以遍历groups[webservers]组并动态生成 upstream 配置见 ansible-scenario5/mysite.j2#Dynamic Config for server {{ ansible_facts[nodename] }} upstream webservers { {% for host in groups[webservers] %} server {{ hostvars[host][ansible_facts][nodename] }}:8000; {% endfor %} } server { listen 80; location / { proxy_pass http://webservers; } }这段模板的关键点groups[webservers]是 Inventory 中的主机组Ansible 在模板上下文里自动提供hostvars[host]用于从控制节点侧读取其他主机而不是当前主机的事实其中nodename即目标主机的节点名前提条件目标环境必须配置好名称解析DNS 或/etc/hosts因为这里使用的是主机名而非 IP 地址。这样一来将来新增或下线 web 服务器时无需再手工编辑负载均衡配置——重跑 playbook 即可让 upstream 自动增减成员这正是“配置即代码”的体现。用户自定义变量从 playbook 内联到 group_vars 外置用户自定义变量最初直接写在 playbook 的vars:段见上文的 playbook5.yml。为了让 playbook 更清爽、变量可复用Ansible 支持按目录约定把变量外置到独立文件。本部分的实战目录是 ansible-scenario6具体做法如下在ansible-scenario6根目录创建group_vars/all/文件夹all表示所有主机组都会获得这些变量在group_vars/all/下创建 common_variables.yml把 playbook 中的变量整体搬进去http_port: 8000 https_port: 4443 html_welcome_msg: Hello 90DaysOfDevOps - Welcome to Day 68!从 playbook 中删除vars:段及其变量定义得到干净的 playbook6.yml- hosts: webservers become: yes roles: - common - apache2 tags: web - hosts: proxy become: yes roles: - common - nginx tags: proxy由于这些变量对所有组生效全局性质还可以顺手把 NTP、DNS 服务器等公共配置也放进来。变量生效范围由目录结构决定group_vars/all/面向全部主机group_vars/组名/面向某个主机组而host_vars/主机名.yml则面向单台主机——例如可以创建host_vars/web01.yml让某台 web 服务器显示专属欢迎语。外置后的变量在模板中的引用方式不变。nginx 模板 ansible-scenario7/roles/nginx/templates/mysite.j2 直接用{{ http_port }}替换了硬编码端口#Dynamic Config for server {{ ansible_facts[nodename] }} upstream webservers { {% for host in groups[webservers] %} server {{ hostvars[host][ansible_facts][nodename] }}:{{ http_port }}; {% endfor %} } server { listen 80; location / { proxy_pass http://webservers; } }apache2 的首页模板 ansible-scenario6/roles/apache2/templates/index.html.j2 则同时使用用户变量与 Facts让访问者一眼看出当前请求落到了哪台 web 服务器html h1{{ html_welcome_msg }}! Im webserver {{ ansible_facts[nodename] }} /h1 /html运行ansible-playbook playbook6.yml后反复刷新负载均衡地址即可看到请求在 web01/web02 之间切换页面标题会随之变化——这验证了动态模板与 Facts 引用的正确性。Inventory 文件按环境拆分主机清单到目前为止我们一直使用默认的/etc/ansible/hosts作为 Inventory。但在真实环境中生产、预发布staging、开发往往需要不同的主机清单。解决方案是把 Inventory 拆成多个独立文件并通过-i参数指定ansible-playbook -i dev playbook.yml例如创建dev、staging、production三个 Inventory 文件内容各自包含对应环境的主机与组。Inventory 文件内部同样可以定义变量这些变量随后能在 playbook 或模板中直接引用——在文档所参考的课程示例中就是把“环境名”变量定义在 hosts 文件里再输出到负载均衡的网页模板让页面上显示当前所处的环境如 dev/staging/production。这是“Inventory 不只是主机列表也是变量来源”的典型用法。实战用 mysql 角色部署数据库服务器 db01最后一块拼图是尚未通电配置的db01。本部分工作目录为 ansible-scenario7。第一步启动虚拟机并打通 SSH在 Vagrantfile 所在目录执行vagrant up db01机器启动并可访问后先把控制节点的 SSH 公钥拷贝过去保证后续 Ansible 能免密连接ssh-copy-id db01第二步用 ansible-galaxy 初始化 mysql 角色ansible-galaxy init roles/mysql该命令会在roles/mysql下自动生成一套标准角色目录tasks/、handlers/、templates/、defaults/、vars/、meta/、tests/、README.md等。仓库中的成品结构可见 ansible-scenario7/roles/mysql。第三步在 playbook 中追加 database play在 playbook7.yml 中新增数据库组的 play应用common与新建的mysql角色并打上database标签- 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: databasedatabase组已存在于/etc/ansible/hosts中对应 Vagrantfile 里的 db01 机器。得益于标签机制后续我们可以只针对数据库组部署而不必重跑全部 play。第四步填充角色内容Handlers—— handlers/main.yml 定义 MySQL 服务重启动作供模板变更后通过notify触发--- # handlers file for roles/mysql - name: restart mysql service: name: mysql state: restartedTasks 入口—— tasks/main.yml 是指针文件按顺序引入两个任务文件--- # tasks file for roles/mysql - import_tasks: install_mysql.yml - import_tasks: setup_mysql.ymlTasks安装与启动—— tasks/install_mysql.yml 负责安装依赖包、MySQL 服务端与 PyMySQL 模块并确保服务启动- name: Install Common packages apt: name{{ item }} statelatest with_items: - python3-pip - mysql-client - python3-mysqldb - libmysqlclient-dev - name: Ensure mysql-server is installed latest version apt: namemysql-server statelatest - name: Installing python module MySQL-python pip: name: PyMySQL - name: Ensure mysql-server is running service: name: mysql state: startedTasks建库与建用户—— tasks/setup_mysql.yml 先渲染 MySQL 配置模板并通知重启再通过community.mysql.mysql_user与mysql_db模块创建用户与数据库- name: Create my.cnf configuration file template: srctemplates/my.cnf.j2 dest/etc/mysql/conf.d/mysql.cnf notify: restart mysql - name: Create database user with name devops and password DevOps90 with all database privileges community.mysql.mysql_user: login_unix_socket: /var/run/mysqld/mysqld.sock login_user: {{ mysql_user_name }} login_password: {{ mysql_user_password }} name: {{db_user}} password: {{db_pass}} priv: *.*:ALL,GRANT host: % state: present - name: Create a new database with name 90daysofdevops mysql_db: login_user: {{ db_user }} login_password: {{ db_pass }} name: {{ db_name }} state: present - name: Enable remote login to mysql lineinfile: path: /etc/mysql/mysql.conf.d/mysqld.cnf regexp: ^bind-address line: bind-address 0.0.0.0 backup: yes notify: - Restart mysql几点值得注意的实践细节均来自仓库中的真实文件login_unix_socket: /var/run/mysqld/mysqld.sock这一行是原作者在实战中发现并补充的当 root 账号在本机通过 Unix Socket 认证时Ansible 需要显式指定 socket 路径才能成功连接 MySQL 实例仓库版本中mysql_db任务使用db_user/db_pass连接而非 root并且额外增加了一个lineinfile任务把bind-address改为0.0.0.0以支持远程登录对应模板中开放监听地址的意图模板文件 templates/my.cnf.j2 内容如下[mysql] bind-address 0.0.0.0 [client] userroot passwordvagrant它被渲染到目标机器的/etc/mysql/conf.d/mysql.cnf其中[client]段提供默认连接账号bind-address 0.0.0.0让 MySQL 监听所有接口。变量集中管理—— 上述任务中引用的用户名、密码、数据库名都来自 group_vars/all/common_variables.ymlhttp_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注意把明文口令写入版本库是演示环境下的简化做法生产环境应改用 Ansible Vault 等加密机制。第五步执行 playbook 并排障完整部署全部机器ansible-playbook playbook7.yml也可以只针对数据库组ansible-playbook playbook7.yml --tags database文档记录了一个真实排障过程仅对database标签执行时报错提示缺少pip3Python。解决办法是把python3-pip加进公共角色common的任务中安装——仓库里 common 角色的 install_tools.yml 展示了这类公共工具任务的形态该文件安装了 neofetch、tree、figlet而 mysql 角色的 install_mysql.yml 则已包含python3-pip、mysql-client、python3-mysqldb、libmysqlclient-dev等依赖。补齐依赖后重新运行部署即成功。第六步在 db01 上验证结果从控制节点登录ssh db01连接 MySQLroot 使用 vagrant 密码sudo /usr/bin/mysql -u root -p依次确认用户与数据库是否创建成功select user, host from mysql.user; SHOW DATABASES;预期能看到devops用户以及90DaysOfDevOps数据库。此外还可以用应用账号验证连接方式sudo /usr/bin/mysql -u devops -p # 密码为 DevOps90至此四台虚拟机web01、web02、loadbalancer、db01已全部纳入 Ansible 自动化管理一个包含 Web 应用、负载均衡与数据库的最小化 DevOps 环境闭环完成。小结Day 68 的核心收获可以浓缩为四条可复用的经验标签让大 playbook 可分片执行--tags/--list-tags/--skip-tags组合使用always标签保障公共步骤不被过滤Facts 是现成的机器情报ansible host -m setup导出的 JSON见 facts.json配合 Jinja2 循环可把硬编码配置升级为动态配置变量外置符合“约定优于配置”group_vars/all、group_vars/组、host_vars/主机三级目录约定配合-i多 Inventory 文件即可支撑多环境角色化是模块复用的抓手ansible-galaxy init生成标准骨架install_mysql.yml管安装、setup_mysql.yml管建库建用户、my.cnf.j2管配置handlers notify 保证配置变更后自动重启服务。如果你希望继续沿着这条路线前进下一步Day 69将在本环境基础上做进一步扩展完整学习路径可参考仓库根目录的 2022/Days/day69.md。赞分享文档/教程【免费下载链接】90DaysOfDevOpsThis 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 Day 68Ansible Tags、变量分层、Inventory 与 MySQL 数据库服务器部署实战90DaysOfDevOps Day 68Ansible Tags、变量分层、Inventory 与 MySQL 数据库服务器部署实战 导读 本文是 90Da文档/教程90DaysOfDevOps 第 65 天用 Ansible Playbook 声明式配置你的服务器群90DaysOfDevOps 第 65 天用 Ansible Playbook 声明式配置你的服务器群 导读 本文是 90DaysOfDevOps 学习路线图文档/教程90DaysOfDevOps 第 64 天Ansible 入门实战——控制节点安装、模块命令与 Inventory 主机清单配置90DaysOfDevOps 第 64 天Ansible 入门实战——控制节点安装、模块命令与 Inventory 主机清单配置 本文是 90DaysOfDe文档/教程上一篇Full Page Screen CaptureChrome浏览器终极完整网页截图工具下一篇手机号转QQ号查询工具一键实现社交账号关联功能创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑