Day 21-Ansible 进阶与 Zabbix TiDB 迁移学习记录


Ansible:Vault 加密、批量部署与 Zabbix 数据库 TiDB 替换踩坑全记录

这次实操主要啃了三块内容:Ansible Vault 加密敏感变量、用 host_vars/group_vars 做分层变量管理,以及把 Zabbix 的底层数据库从 MariaDB 替换成 TiDB 分布式数据库。前面 Ansible 部分还算顺畅,到 TiDB 对接 Zabbix 初始 SQL 的环节踩了一连串的坑,光触发器兼容问题就折腾了快四个小时,试了 sed、awk、perl 好几种文本处理方式都翻了车,最后用最朴素的强制导入方案才搞定。把完整的操作流程和踩坑细节都整理出来,给大家避避坑。

一、Ansible Vault 加密变量与批量用户创建

1.1 实验目标与前置准备

日常写 Playbook 时,密码、密钥这类敏感信息如果明文写在变量文件里,安全风险很高。Ansible Vault 是官方提供的加密工具,可以将整个变量文件加密,执行时再输入密码解密,非常适合生产环境管理敏感配置。
前置环境:控制端 server1 已完成 Ansible 安装,被管理端主机配置好免密登录与 sudo 权限,inventory 清单中已划分 db、webservers 等主机组。

1.2 Vault 加密变量文件的基础操作

首先创建存放用户列表的变量文件 userlist.yml,写入需要批量创建的用户名与密码,再通过 Vault 对文件进行加密。

userlist:
  - {user: user1, pass: pass1}
  - {user: user2, pass: pass2}
  - {user: user3, pass: pass3}

加密、查看、编辑三个核心命令:

# 加密文件
ansible-vault encrypt userlist.yml

# 查看加密文件内容,输入密码后解密展示
ansible-vault view userlist.yml

# 编辑加密文件,自动完成加解密
ansible-vault edit userlist.yml

执行 view 命令输入密码后即可看到明文内容,效果如下。加密后的文件直接 cat 无法读取任何敏感信息,安全性有保障。
在这里插入图片描述
在这里插入图片描述

1.3 编写批量创建用户的 Playbook

接下来编写 user.yml 剧本,通过 vars_files 加载加密变量文件,配合 loop 循环批量创建用户;密码使用 password_hash 过滤器做 sha512 哈希处理,符合 Linux 系统密码存储规范。

- hosts: db
  gather_facts: no
  vars_files:
    - userlist.yml
  tasks:
    - name: Add the users
      ansible.builtin.user:
        name: "{{ item.user }}"
        password: "{{ item.pass | password_hash('sha512') }}"
        state: present
      loop: "{{ userlist }}"

在这里插入图片描述

1.4 首次执行的两个经典踩坑

写完直接执行剧本,上来就踩了两个坑,报错信息如下:

[WARNING]: Could not match supplied host pattern, ignoring: db
ERROR! Attempting to decrypt but no vault secrets found

第一个警告是 inventory 中没有匹配到 db 主机组,通常是主机组名拼写错误或清单文件路径不对,检查修正即可。
第二个报错是核心问题:使用了加密变量文件,但执行 playbook 时没有传入 Vault 密码,Ansible 无法解密变量。
解决方法:执行时追加 --ask-vault-pass 参数,运行时输入加密密码。

ansible-playbook user.yml --ask-vault-pass

在这里插入图片描述

1.5 进阶:用 host_vars 自动加载加密变量

每次手动编写 vars_files 加载变量略显繁琐,Ansible 支持按主机自动加载对应目录下的变量文件,也就是 host_vars 机制。
在 playbook 同级目录创建 host_vars 目录,再为 node1 主机创建独立子目录,将加密后的 userlist.yml 放入其中。

mkdir -p host_vars/node1
cd host_vars/node1
vim userlist.yml  # 写入变量后执行vault加密

目录结构效果参考。
在这里插入图片描述

随后修改 user.yml,注释掉 vars_files 部分,无需手动加载变量,Ansible 执行到对应主机时会自动读取 host_vars 下的变量文件。

- hosts: db
  gather_facts: no
  # vars_files:
  #   - userlist.yml
  tasks:
    - name: Add the users
      ansible.builtin.user:
        name: "{{ item.user }}"
        password: "{{ item.pass | password_hash('sha512') }}"
        state: present
      loop: "{{ userlist }}"

修改后的剧本参考。
在这里插入图片描述
在这里插入图片描述

执行时同样携带 --ask-vault-pass 参数,变量会自动加载生效,这种方式在主机数量多、变量差异化大的场景中实用性很强。

二、group_vars 组变量 + Apache 批量部署实战

2.1 group_vars 组变量管理

与 host_vars 对应,group_vars 是面向主机组的变量管理方案,同一组内的所有主机共享一套变量,适合批量部署同类型服务的场景。
创建 webservers 组的变量目录,在其中定义 Apache 监听端口等公共参数。

mkdir -p group_vars/webservers
cd group_vars/webservers
vim vars.yml

在变量文件中定义 http_port: 80,后续剧本中可直接引用该变量。
在这里插入图片描述

2.2 Apache 部署 Playbook

编写 Apache 部署剧本,为每个任务设置不同的 tag,后续可单独执行某一步操作,无需全量运行,大幅提升调试效率。

- hosts: lamp
  become: yes
  vars:
    http_port: 80
  tasks:
    - name: Install the Apache
      ansible.builtin.yum:
        name: httpd
        state: present
      tags: t1

    - name: Start service httpd, if not started
      ansible.builtin.service:
        name: httpd
        state: started
        enabled: yes
      tags: t2

    - name: create index.html
      ansible.builtin.copy:
        content: "{{ ansible_hostname }}\n"
        dest: /var/www/html/index.html
      tags: t3

    - name: Ensure the default Apache port is {{ http_port }}
      ansible.builtin.lineinfile:
        path: /etc/httpd/conf/httpd.conf
        regexp: '^Listen '
        insertafter: '#Listen '
        line: Listen {{ http_port }}
      notify: restart service httpd

  handlers:
    - name: restart service httpd
      ansible.builtin.service:
        name: httpd
        state: restarted

这里使用 lineinfile 模块修改配置文件,配合 handlers 触发器,只有配置文件实际发生修改时才会触发 Apache 重启,比每次执行都重启更加优雅。
如果只需执行安装步骤,可通过 ansible-playbook apache.yml -t t1 单独运行指定标签的任务。
在这里插入图片描述

2.3 本地可用性检测

部署完成后,可以使用 uri 模块在本地执行健康检测,验证服务是否正常返回 200 状态码。

- hosts: localhost
  gather_facts: false
  become: false
  tasks:
    - name: Check that you can connect (GET) to a page and it returns a status 200
      ansible.builtin.uri:
        url: http://192.168.48.162
        return_content: true
      register: result

    - name: Print return information from the previous task
      ansible.builtin.debug:
        var: result.content

这样整个部署+验证流程可以完全自动化,无需手动执行 curl 测试。

三、Ansible 一键部署 Zabbix 服务

3.1 Playbook 整体设计思路

Zabbix 部署步骤多、依赖繁杂,手动安装容易遗漏步骤。我们将整个部署流程封装为完整的 Playbook,从安装依赖、配置源、安装服务、初始化数据库到修改配置实现全自动化。
同时将数据库密码等敏感信息存入 Vault 加密的 secrets.yml 中,通过 vars_files 加载,符合安全规范。

3.2 分步任务拆解

整个剧本按执行顺序拆分为 8 个标签任务,便于分步调试:

  1. 安装 pymysql 依赖,为后续 MySQL 模块提供运行支持
  2. 添加 Zabbix 官方 yum 软件源
  3. 安装 Zabbix 服务端、Web 端、Agent 等全套组件
  4. 安装 MariaDB 数据库
  5. 启动数据库并设置开机自启
  6. 创建 zabbix 数据库,设置 utf8mb4 字符集
  7. 创建 zabbix 数据库用户并授权
  8. 导入初始 SQL 脚本、配置服务端密码、启动服务

核心任务代码参考:

- name: import zabbix initial sql
  ansible.builtin.shell:
    zcat /usr/share/zabbix-sql-scripts/mysql/server.sql.gz | mysql -uzabbix -pzabbix@123 zabbix
  args:
    creates: /var/lib/mysql/zabbix/hosts.ibd
  tags: t7_import_sql

这里使用 creates 参数实现幂等判断,只要数据库文件已存在就不会重复导入,多次执行剧本也不会报错。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.3 结合 Vault 加密敏感配置

将数据库密码放入加密的 secrets.yml 中,剧本通过 vars_files 加载,配置项使用变量引用,避免明文泄露。

- hosts: zabbix_server
  become: yes
  vars_files:
    - secrets.yml
  tasks:
    ...
    - name: config zabbix server db password
      ansible.builtin.lineinfile:
        path: /etc/zabbix/zabbix_server.conf
        regexp: '#DBPassword='
        line: "DBPassword={{ zabbix_db_password }}"
      tags: t8_config_server

执行时携带 --ask-vault-pass 输入解密密码即可;生产环境也可以使用 vault 密码文件的方式实现自动化执行。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

四、核心实战:Zabbix 数据库替换为 TiDB

这部分是本次实操最折腾的环节,也是踩坑最多的部分。我们要将 Zabbix 原本的 MariaDB 数据库替换为 TiDB 分布式数据库,验证二者的兼容性。

4.1 TiDB 单机集群快速部署

TiDB 官方提供了 tiup 工具,一行命令即可快速拉起一套单机测试集群,非常便捷。
首先安装 tiup:

curl --proto '=https' --tlsv1.2 -sSf https://tiup-mirrors.pingcap.com/install.sh | sh
source ~/.bash_profile

安装成功后验证版本【图20】,随后启动 v6.5.0 版本的单机 playground 集群:

export TIUP_TIMEOUT=120
tiup playground v6.5.0 --db 1 --kv 1 --pd 1 --host 0.0.0.0

首次启动会自动下载各个组件,等待数分钟即可启动完成。启动后默认通过 4000 端口提供 MySQL 协议服务,root 用户默认无密码。
在这里插入图片描述

4.2 导入 Zabbix 初始 SQL 的连环踩坑

原本以为直接将 SQL 导入 TiDB 即可,结果一执行就报错,开启了长达两小时的排坑之路。

坑1:TiDB 不支持数据库触发器

第一次直接导入原始 SQL,直接抛出 1064 语法错误,定位到 create trigger 开头的语句。

ERROR 1064 (42000) at line 2124: You have an error in your SQL syntax; check the manual that corresponds to your TiDB version for the right syntax to use line 1 column 14 near "trigger hosts_name_upper_insert"

查阅官方文档后得知,TiDB 目前不支持数据库触发器语法,而 Zabbix 初始 SQL 末尾附带了多个触发器,用于自动更新 name_upper 字段。
最初的思路是从 SQL 文件中删除触发器部分,于是开启了文本处理的翻车之路。

坑2:sed 范围匹配失效

最开始使用 sed '/CREATE TRIGGER/,/END;/d' 进行删除,结果导入后依然报错。排查后发现两个问题:

  • Zabbix 的 SQL 中触发器为小写 create trigger,sed 默认区分大小写,无法匹配
  • 触发器结尾不是 END;,而是修改了分隔符的 END //,范围结束标记不匹配
    即使添加忽略大小写参数依然无效,受多行结构和分隔符影响,范围匹配总会遗漏内容。
坑3:awk/perl 处理生成空文件

换成 awk 状态机和 perl 多行匹配的写法,结果要么触发器没删干净,要么直接把整个文件处理成 0 字节的空文件,导入后一张表都没有,非常影响心态。
中间还尝试过按行号截断,结果匹配到了表名中包含 trigger 的行,把大半表结构都截断了,同样翻车。

最终方案:–force 强制导入跳过错误

折腾到最后突然反应过来,MySQL 客户端有个 --force 参数,遇到 SQL 错误会自动跳过并继续执行后续语句。触发器都集中在文件末尾,前面的建表语句和初始数据完全正常,直接强制导入跳过触发器报错即可。

zcat /usr/share/zabbix-sql-scripts/mysql/server.sql.gz | mysql -h127.0.0.1 -P4000 -uroot --force zabbix

执行过程中会闪过几条触发器的报错,无需理会;命令运行结束后,所有业务表和初始数据都完整导入。最终查表数量为 174 张,与原生 MariaDB 导入的数量一致,完全可用。
真的是绕了一大圈,最朴素的方法反而最管用。
在这里插入图片描述

4.3 Zabbix 配置修改

数据库导入完成后,修改 Zabbix 服务端配置文件,将数据库端口改为 TiDB 的 4000 端口,地址修改为对应 IP:

DBHost=127.0.0.1
DBPort=4000
DBName=zabbix
DBUser=zabbix
DBPassword=zabbix@123

在这里插入图片描述
在这里插入图片描述

随后修改 Web 端的 PHP 配置文件 /etc/zabbix/web/zabbix.conf.php,同步更新为 TiDB 的连接信息:

<?php
global $DB;

$DB['TYPE']     = 'MYSQL';
$DB['SERVER']   = '127.0.0.1';
$DB['PORT']     = '4000';
$DB['DATABASE'] = 'zabbix';
$DB['USER']     = 'zabbix';
$DB['PASSWORD'] = 'zabbix@123';

$DB['SCHEMA'] = '';

$ZBX_SERVER      = '127.0.0.1';
$ZBX_SERVER_PORT = '10051';
$ZBX_SERVER_NAME = 'Zabbix Server';

$IMAGE_FORMAT_DEFAULT = IMAGE_FORMAT_PNG;

修改完成后为配置文件设置正确权限,否则 Web 页面会抛出权限错误:

chown apache:apache /etc/zabbix/web/zabbix.conf.php
chmod 644 /etc/zabbix/web/zabbix.conf.php

4.4 重启所有服务

全部配置修改完成后,重启 Zabbix 服务端、Apache 和 PHP-FPM:

systemctl restart zabbix-server httpd php-fpm
systemctl status zabbix-server

看到服务显示 active (running) 即说明启动成功。
在这里插入图片描述

五、最终效果验证

5.1 服务与数据库连通性验证

首先查看 Zabbix 服务日志,确认无数据库连接报错,服务正常启动。
随后验证数据库内的数据,查询 hosts 表的记录数:

mysql -h127.0.0.1 -P4000 -uzabbix -pzabbix@123 zabbix -e "select count(*) from hosts;"

返回 431 条记录,说明初始数据完整,服务端可以正常读写 TiDB。

在这里插入图片描述

5.2 Web 端登录验证

浏览器访问 http://server2的IP/zabbix,使用默认账号 Admin / zabbix 登录,成功进入仪表盘。
可以看到主机、模板、监控项、触发器的数量均正常显示,Zabbix server 状态显示运行中,整个 Web 界面无任何数据库报错。
在这里插入图片描述

5.3 功能可用性验证

进入「配置-主机」可以看到默认的 Zabbix server 主机状态正常;「监测-最新数据」中可以看到持续更新的监控数据,说明数据采集、入库、展示全链路均无问题。
执行配置重载命令也可以正常响应:

zabbix_server -R config_cache_reload
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值