Merge remote-tracking branch 'upstream/main' into feat/base-service-delivery
# Conflicts: # ansible/mysql-deploy.yml # frontend/src/api/delivery.ts # frontend/src/views/service/Catalog.vue # server/.env.example # server/internal/config/config.go # server/internal/handler/task_log.go # server/internal/service/delivery.go
This commit is contained in:
@@ -1,20 +1,53 @@
|
||||
# =============================================================================
|
||||
# XINFRA MySQL 交付实例 Systemd 模板单元
|
||||
# =============================================================================
|
||||
# 这是 systemd 的模板单元(template unit),文件名中的 @ 是模板标识
|
||||
# 使用方式:systemctl start mysql-delivery@{实例名}.service
|
||||
# 例如:mysql-delivery@db01.service、mysql-delivery@db02.service
|
||||
#
|
||||
# %i 参数会被 systemd 自动替换为 @ 后面的实例名
|
||||
# 这样同一台主机可以运行多个 MySQL 实例,彼此隔离
|
||||
# =============================================================================
|
||||
|
||||
[Unit]
|
||||
# 服务描述,%i 会被替换为实际实例名
|
||||
Description=XINFRA MySQL delivery instance %i
|
||||
# 依赖:等待网络在线后再启动(MySQL 需要绑定网络端口)
|
||||
After=network-online.target
|
||||
Wants=network-online.target
|
||||
|
||||
[Service]
|
||||
# Type=notify:mysqld 启动完成后会通过 sd_notify 通知 systemd
|
||||
# 比 Type=simple 更可靠,systemd 能准确知道服务何时真正就绪
|
||||
Type=notify
|
||||
|
||||
# 以 mysql 用户/组身份运行(最小权限原则)
|
||||
User=mysql
|
||||
Group=mysql
|
||||
|
||||
# 创建运行时目录 /run/mysql-delivery-{实例名}/
|
||||
# 用于存放 socket 和 pid 文件,放在 tmpfs(内存文件系统)上,重启自动清理
|
||||
RuntimeDirectory=mysql-delivery-%i
|
||||
RuntimeDirectoryMode=0755
|
||||
|
||||
# 启动命令:使用实例专属配置文件
|
||||
# %i 被替换为实例名,指向 /etc/mysql/mysql-delivery/{实例名}.cnf
|
||||
ExecStart=/usr/sbin/mysqld --defaults-file=/etc/mysql/mysql-delivery/%i.cnf
|
||||
|
||||
# 故障自动重启:崩溃后 5 秒自动重启
|
||||
Restart=on-failure
|
||||
RestartSec=5s
|
||||
|
||||
# 启动超时:120 秒内未完成启动则判定为失败
|
||||
TimeoutStartSec=120s
|
||||
|
||||
# 最大打开文件数:MySQL 需要大量文件描述符(连接、临时表等)
|
||||
LimitNOFILE=65535
|
||||
|
||||
# OOM 评分调整:-200 表示被 OOM Killer 杀掉的优先级较低
|
||||
# MySQL 是数据库服务,被误杀影响较大,尽量保护
|
||||
OOMScoreAdjust=-200
|
||||
|
||||
[Install]
|
||||
# 开机自启:加入 multi-user.target(多用户模式,即正常启动完成后)
|
||||
WantedBy=multi-user.target
|
||||
|
||||
@@ -1,11 +1,35 @@
|
||||
# =============================================================================
|
||||
# Ansible Inventory 示例文件
|
||||
# =============================================================================
|
||||
# Inventory 定义了要管理的主机列表和分组
|
||||
# 实际使用时,平台会动态生成 inventory 并传入变量
|
||||
#
|
||||
# 使用方式:
|
||||
# ansible-playbook -i inventory.example.yml mysql-deploy.yml \
|
||||
# -e "target_hosts=mysql_hosts" \
|
||||
# -e "instance_name=db01" \
|
||||
# -e "topology=mgr_3" \
|
||||
# -e "mysql_version=8.0" \
|
||||
# -e "memory_mb=8192" \
|
||||
# -e "storage_gb=100"
|
||||
# =============================================================================
|
||||
|
||||
all:
|
||||
children:
|
||||
# --- MySQL 主机组 ---
|
||||
# 按拓扑需求选择对应数量的主机:
|
||||
# standalone = 1 台
|
||||
# primary_replica = 2 台(一主一从)
|
||||
# mgr_3 = 3 台(三节点组复制)
|
||||
mysql_hosts:
|
||||
hosts:
|
||||
# 格式:主机名: { ansible_host: IP地址 }
|
||||
k8s-server-01: { ansible_host: 192.168.1.4 }
|
||||
k8s-server-02: { ansible_host: 192.168.1.5 }
|
||||
k8s-server-03: { ansible_host: 192.168.1.2 }
|
||||
k8s-worker-01: { ansible_host: 192.168.1.3 }
|
||||
|
||||
# --- 全局变量 ---
|
||||
vars:
|
||||
ansible_user: root
|
||||
ansible_python_interpreter: /usr/bin/python3
|
||||
ansible_user: root # SSH 登录用户(需要 root 权限执行系统级操作)
|
||||
ansible_python_interpreter: /usr/bin/python3 # Python 解释器路径(Ubuntu 默认位置)
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
---
|
||||
- name: Roll back native MySQL delivery instance
|
||||
hosts: "{{ target_hosts }}"
|
||||
become: true
|
||||
gather_facts: false
|
||||
any_errors_fatal: true
|
||||
vars:
|
||||
mysql_instance: "{{ instance_name }}"
|
||||
mysql_data_disk: "{{ data_disk }}"
|
||||
mysql_base_dir: "{{ mysql_data_disk }}/mysql-delivery/{{ mysql_instance }}"
|
||||
mysql_install_dir: "/opt/mysql-delivery/{{ mysql_instance }}"
|
||||
mysql_config_file: "/etc/mysql/mysql-delivery/{{ mysql_instance }}.cnf"
|
||||
mysql_run_dir: "/run/mysql-delivery-{{ mysql_instance }}"
|
||||
|
||||
pre_tasks:
|
||||
- name: Validate rollback target
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- mysql_instance is match('^[a-z0-9][a-z0-9-]{0,62}$')
|
||||
- mysql_data_disk is match('^/')
|
||||
- mysql_data_disk != '/'
|
||||
- "'..' not in mysql_data_disk"
|
||||
fail_msg: "Rollback target is outside the native MySQL delivery layout"
|
||||
quiet: true
|
||||
|
||||
tasks:
|
||||
- name: Stop the delivery instance when present
|
||||
ansible.builtin.systemd_service:
|
||||
name: "mysql-delivery@{{ mysql_instance }}.service"
|
||||
state: stopped
|
||||
enabled: false
|
||||
register: mysql_stop_result
|
||||
failed_when: false
|
||||
|
||||
- name: Remove the instance systemd failure state
|
||||
ansible.builtin.command:
|
||||
argv:
|
||||
- systemctl
|
||||
- reset-failed
|
||||
- "mysql-delivery@{{ mysql_instance }}.service"
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
|
||||
- name: Remove the instance configuration
|
||||
ansible.builtin.file:
|
||||
path: "{{ mysql_config_file }}"
|
||||
state: absent
|
||||
|
||||
- name: Remove instance-local binary links
|
||||
ansible.builtin.file:
|
||||
path: "{{ mysql_install_dir }}"
|
||||
state: absent
|
||||
|
||||
- name: Remove the instance data and log tree
|
||||
ansible.builtin.file:
|
||||
path: "{{ mysql_base_dir }}"
|
||||
state: absent
|
||||
|
||||
- name: Remove the instance runtime directory
|
||||
ansible.builtin.file:
|
||||
path: "{{ mysql_run_dir }}"
|
||||
state: absent
|
||||
|
||||
- name: Confirm the instance artifacts are gone
|
||||
ansible.builtin.stat:
|
||||
path: "{{ item }}"
|
||||
loop:
|
||||
- "{{ mysql_config_file }}"
|
||||
- "{{ mysql_install_dir }}"
|
||||
- "{{ mysql_base_dir }}"
|
||||
- "{{ mysql_run_dir }}"
|
||||
register: mysql_rollback_artifacts
|
||||
|
||||
- name: Assert that all instance artifacts are gone
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- mysql_rollback_artifacts.results | selectattr('stat.exists') | list | length == 0
|
||||
fail_msg: "One or more MySQL delivery artifacts remain after rollback"
|
||||
quiet: true
|
||||
@@ -1,82 +1,134 @@
|
||||
# Managed by XINFRA MySQL delivery - generated, do not edit by hand
|
||||
# instance={{ mysql_instance }} version={{ mysql_version_value }} topology={{ topology }}
|
||||
# =============================================================================
|
||||
# XINFRA MySQL 实例配置文件(Jinja2 模板)
|
||||
# =============================================================================
|
||||
# 此文件由 Playbook 自动生成,禁止手动编辑
|
||||
# 修改配置请通过平台参数传递,重新部署即可
|
||||
# =============================================================================
|
||||
|
||||
# 客户端连接配置(mysql 命令行工具使用)
|
||||
[client]
|
||||
socket={{ mysql_run_dir }}/mysql.sock
|
||||
port={{ mysql_port_value }}
|
||||
socket={{ mysql_run_dir }}/mysql.sock # Unix socket 连接路径(本地连接更快)
|
||||
port={{ mysql_port_value }} # TCP 端口(远程连接使用)
|
||||
|
||||
# =============================================================================
|
||||
# MySQL 服务端核心配置
|
||||
# =============================================================================
|
||||
[mysqld]
|
||||
user=mysql
|
||||
basedir=/usr
|
||||
datadir={{ mysql_data_dir }}
|
||||
tmpdir={{ mysql_tmp_dir }}
|
||||
socket={{ mysql_run_dir }}/mysql.sock
|
||||
pid-file={{ mysql_run_dir }}/mysql.pid
|
||||
port={{ mysql_port_value }}
|
||||
bind-address=0.0.0.0
|
||||
skip-name-resolve=ON
|
||||
server-id={{ mysql_server_id_value }}
|
||||
local-infile=OFF
|
||||
# --- 基础运行参数 ---
|
||||
user=mysql # 运行用户(与 systemd 单元一致)
|
||||
basedir=/usr # MySQL 安装根目录(Ubuntu apt 安装位置)
|
||||
datadir={{ mysql_data_dir }} # 数据目录(所有表、索引、数据文件)
|
||||
tmpdir={{ mysql_tmp_dir }} # 临时文件目录(排序、临时表等)
|
||||
socket={{ mysql_run_dir }}/mysql.sock # Unix socket 路径(本地客户端连接)
|
||||
pid-file={{ mysql_run_dir }}/mysql.pid # 进程 PID 文件路径
|
||||
port={{ mysql_port_value }} # 监听端口
|
||||
bind-address=0.0.0.0 # 监听所有网络接口(允许远程连接)
|
||||
skip-name-resolve=ON # 跳过 DNS 解析(提升连接速度,授权时需用 IP)
|
||||
server-id={{ mysql_server_id_value }} # 服务器唯一 ID(复制必须,全机唯一)
|
||||
local-infile=OFF # 禁用 LOAD DATA LOCAL(安全考虑,防止读取客户端文件)
|
||||
|
||||
# --- charset / collation / timezone / identifier case ---
|
||||
character-set-server={{ mysql_character_set }}
|
||||
collation-server={{ mysql_collation }}
|
||||
default-time-zone={{ mysql_timezone }}
|
||||
lower-case-table-names={{ mysql_lower_case_table_names }}
|
||||
# --- 字符集 / 排序规则 / 时区 / 标识符大小写 ---
|
||||
character-set-server={{ mysql_character_set }} # 服务端字符集,默认 utf8mb4
|
||||
collation-server={{ mysql_collation }} # 排序规则,默认 utf8mb4_general_ci
|
||||
default-time-zone={{ mysql_timezone }} # 默认时区,东八区
|
||||
lower-case-table-names={{ mysql_lower_case_table_names }} # 表名大小写敏感:1=不敏感(Linux 推荐)
|
||||
|
||||
# --- error / slow log ---
|
||||
log-error={{ mysql_log_dir }}/error.log
|
||||
slow-query-log=ON
|
||||
slow-query-log-file={{ mysql_log_dir }}/slow.log
|
||||
long-query-time={{ mysql_long_query_time }}
|
||||
# --- 错误日志 / 慢查询日志 ---
|
||||
log-error={{ mysql_log_dir }}/error.log # 错误日志路径
|
||||
slow-query-log=ON # 启用慢查询日志
|
||||
slow-query-log-file={{ mysql_log_dir }}/slow.log # 慢查询日志路径
|
||||
long-query-time={{ mysql_long_query_time }} # 慢查询阈值(秒),超过此时间记录
|
||||
|
||||
# --- binlog (PITR + replication base) ---
|
||||
log-bin={{ mysql_binlog_dir }}/binlog
|
||||
binlog-format=ROW
|
||||
sync-binlog={{ mysql_sync_binlog }}
|
||||
max-binlog-size={{ mysql_max_binlog_size }}
|
||||
binlog-expire-logs-seconds={{ mysql_binlog_expire_logs_seconds }}
|
||||
# =============================================================================
|
||||
# Binlog 配置(用于数据恢复 PITR + 复制基础)
|
||||
# =============================================================================
|
||||
log-bin={{ mysql_binlog_dir }}/binlog # binlog 文件前缀(二进制日志)
|
||||
binlog-format=ROW # 格式:ROW(行变更),复制最安全
|
||||
sync-binlog={{ mysql_sync_binlog }} # 每次提交同步 binlog 到磁盘,1=最安全
|
||||
max-binlog-size={{ mysql_max_binlog_size }} # 单个 binlog 文件最大大小
|
||||
binlog-expire-logs-seconds={{ mysql_binlog_expire_logs_seconds }} # binlog 过期时间(秒),默认 7 天
|
||||
|
||||
# --- 非 standalone 拓扑才启用的复制参数 ---
|
||||
{% if topology != 'standalone' %}
|
||||
gtid-mode=ON
|
||||
enforce-gtid-consistency=ON
|
||||
relay-log={{ mysql_binlog_dir }}/relay-bin
|
||||
gtid-mode=ON # 启用 GTID(全局事务标识符)
|
||||
enforce-gtid-consistency=ON # 强制 GTID 一致性(确保复制安全)
|
||||
relay-log={{ mysql_binlog_dir }}/relay-bin # 中继日志路径(从库重放 binlog 使用)
|
||||
{% endif %}
|
||||
|
||||
# --- InnoDB core ---
|
||||
# =============================================================================
|
||||
# InnoDB 存储引擎核心配置
|
||||
# =============================================================================
|
||||
# 缓冲池大小:分配内存的 55%(MySQL 官方推荐 50%-75%)
|
||||
innodb-buffer-pool-size={{ ((mysql_memory_mb_value | int) * 55 / 100) | int }}M
|
||||
|
||||
# 刷盘方式:O_DIRECT 绕过操作系统缓存,直接写磁盘
|
||||
# 避免双重缓存,适合有电池保护写缓存的 RAID 控制器
|
||||
innodb-flush-method=O_DIRECT
|
||||
|
||||
# 事务提交时刷日志到磁盘:1=每次提交都刷(最安全,性能最低)
|
||||
innodb-flush-log-at-trx-commit={{ mysql_flush_log_at_trx_commit }}
|
||||
|
||||
# InnoDB I/O 能力:告诉 InnoDB 磁盘的 IOPS 能力
|
||||
# 2000 适合 SSD,HDD 建议 200-400
|
||||
innodb-io-capacity={{ mysql_io_capacity }}
|
||||
|
||||
# 最大连接数(按内存梯度计算,默认值见 Playbook)
|
||||
max-connections={{ mysql_max_connections }}
|
||||
|
||||
# --- redo log (version-sensitive) ---
|
||||
innodb-log-group-home-dir={{ mysql_redo_dir }}
|
||||
# =============================================================================
|
||||
# Redo Log 配置(InnoDB 崩溃恢复必需)
|
||||
# =============================================================================
|
||||
innodb-log-group-home-dir={{ mysql_redo_dir }} # redo log 目录
|
||||
|
||||
# MySQL 8.0.30+ 使用 innodb-redo-log-capacity 控制 redo log 总大小
|
||||
# 旧版本使用 innodb-log-file-size 控制单个文件大小
|
||||
{% if mysql_version_value in ['8.0', '8.4'] %}
|
||||
innodb-redo-log-capacity={{ mysql_redo_capacity }}
|
||||
{% else %}
|
||||
innodb-log-file-size={{ mysql_redo_capacity }}
|
||||
{% endif %}
|
||||
|
||||
# --- X Protocol disabled (version-sensitive) ---
|
||||
# =============================================================================
|
||||
# X Protocol 禁用(版本相关)
|
||||
# =============================================================================
|
||||
# X Protocol 是 MySQL 的 NoSQL 部分,我们不需要,禁用节省资源
|
||||
{% if mysql_version_value in ['8.0', '8.4'] %}
|
||||
mysqlx=0
|
||||
mysqlx=0 # 8.0/8.4 直接禁用
|
||||
{% elif mysql_version_value == '5.7' %}
|
||||
loose-mysqlx=0
|
||||
loose-mysqlx=0 # 5.7 使用 loose 前缀(参数可能不存在)
|
||||
{% endif %}
|
||||
|
||||
# =============================================================================
|
||||
# Group Replication 配置(仅 mgr_3 拓扑)
|
||||
# =============================================================================
|
||||
# 注意:这里只做配置就绪,实际启动组复制需要平台侧执行 START GROUP_REPLICATION
|
||||
{% if topology == 'mgr_3' %}
|
||||
# --- Group Replication (config-ready; runtime bootstrap handled out-of-band) ---
|
||||
# 加载 Group Replication 插件
|
||||
plugin-load-add=group_replication.so
|
||||
|
||||
# MySQL 8.0.26 之前需要设置事务写集提取(8.4 已移除此参数)
|
||||
{% if mysql_version_value != '8.4' %}
|
||||
{# deprecated since 8.0.26 and removed in 8.3+; only inject for older series #}
|
||||
transaction-write-set-extraction=XXHASH64
|
||||
transaction-write-set-extraction=XXHASH64 # 使用 XXHASH64 算法提取写集
|
||||
{% endif %}
|
||||
|
||||
# GR 组 UUID(所有节点必须相同)
|
||||
loose-group-replication-group-name={{ mgr_group_name }}
|
||||
|
||||
# 不在启动时自动加入组(由平台侧手动控制加入时机)
|
||||
loose-group-replication-start-on-boot=OFF
|
||||
|
||||
# 本节点用于 GR 通信的地址和端口
|
||||
loose-group-replication-local-address={{ ansible_host | default(inventory_hostname) }}:{{ mysql_gr_port_value }}
|
||||
|
||||
# 组内所有节点的种子列表(用于新节点发现和连接)
|
||||
loose-group-replication-group-seeds={% for host in ansible_play_hosts_all %}{{ hostvars[host].ansible_host | default(host) }}:{{ mysql_gr_port_value }}{% if not loop.last %},{% endif %}{% endfor %}
|
||||
|
||||
# IP 白名单:只允许组内节点 IP 加入(安全限制)
|
||||
loose-group-replication-ip-allowlist={% for host in ansible_play_hosts_all %}{{ hostvars[host].ansible_host | default(host) }}{% if not loop.last %},{% endif %}{% endfor %}
|
||||
|
||||
# 单主模式:只有 primary 节点可写,replica 只读(推荐生产使用)
|
||||
loose-group-replication-single-primary-mode=ON
|
||||
|
||||
# 关闭强制更新检查:单主模式下不需要(多主模式才需要)
|
||||
loose-group-replication-enforce-update-everywhere-checks=OFF
|
||||
{% endif %}
|
||||
|
||||
Reference in New Issue
Block a user