2. 部署mysql服务并监控mysql

一、环境清单

1. 节点信息
机器名称 机器 IP 操作系统 角色
k8s-master 10.132.47.60 Centos7.9 Master
k8s-node1 10.132.47.61 Centos7.9 Worker
k8s-node2 10.132.47.62 Centos7.9 Worker
2. 验证集群环境
bash 复制代码
# 检查集群节点状态(所有节点应为 Ready 状态)
kubectl get nodes

# 检查prometheus 组件状态
kubectl get pod -n monitoring 

# 检查pod网络(确保calico/flannel等网络插件正常)
kubectl get pods -n kube-system -o wide

# 检查存储类(确认nfs-client存在且可用)
kubectl get sc

二、部署mysql服务

1. 部署MySQL
shell 复制代码
vim mysql.yaml
yaml 复制代码
# ============== 第一部分:创建独立的mysql命名空间 ==============
apiVersion: v1
kind: Namespace
metadata:
  name: mysql-test         # 命名空间名称,所有mysql相关资源都归属此命名空间
  labels:
    app: mysql        # 命名空间的标签,用于标识和筛选,非必需但规范统一
---
# ============== 第二部分:创建Secret 安全存储mysql的所有敏感密码 ==============
apiVersion: v1
kind: Secret
metadata:
  name: mysql         # Secret的名称,后续pod读取密码时会关联此名称
  namespace: mysql-test    # 归属mysql命名空间,与业务资源保持一致
type: Opaque          # Secret的存储类型,Opaque为通用型密文存储,最常用,存储键值对格式
data:                 # data字段:要求填写【base64加密后的密文】,区别于stringData(填明文自动加密)
  # 明文原始密码:Shyshy521521!  | 加密后的密文:U2h5c2h5NTIxNTIxIQ==
  root-password: U2h5c2h5NTIxNTIxIQ==
---
# ============== 第三部分: 创建ConfigMap 存储mysql的核心配置文件 ==============
apiVersion: v1
kind: ConfigMap
metadata:
  name: mysql-config  # ConfigMap名称,后续pod挂载配置时关联此名称
  namespace: mysql-test    # ✅ 修复:改为正确的命名空间mysql-test
data:
  mysql.cnf: |        # 存储的配置文件名称:mysql.cnf,mysql的标准配置文件名
    [mysqld]          # mysql服务端的核心配置段,所有mysql服务相关配置都写在此段内
    character-set-server=utf8mb4         # 数据库默认字符集,utf8mb4是utf8的超集,支持emoji表情/生僻字,生产必配
    collation-server=utf8mb4_unicode_ci  # 字符集校对规则,排序更精准,搭配utf8mb4使用
    max_connections=1000                  # mysql最大连接数,默认151,根据业务并发量调整,避免连接数不足报错
    skip-name-resolve                     # 关闭mysql的DNS反向解析,解决连接慢、超时问题,生产必开
    default-storage-engine=InnoDB         # 默认存储引擎,InnoDB支持事务/行锁/外键,mysql8默认就是此引擎
    log-bin=mysql-bin                     # 开启二进制日志,核心作用:主从复制的日志同步依赖binlog、数据备份/恢复
    binlog-format=ROW                     # binlog日志格式:ROW为行级日志,记录每行数据的修改,主从复制最稳定的格式,生产必配
    log-slave-updates=1                   # 开启从库日志更新,若后续搭建多级主从,该配置必须开启
    expire-logs-days=7                    # binlog日志自动过期清理时间,保留7天,避免日志占满磁盘
    innodb_flush_log_at_trx_commit=1      # 事务安全级别最高配置,每次事务提交立即刷日志到磁盘,防止宕机丢数据,生产必配
    sync_binlog=1                         # 每次binlog写入立即刷盘,和上一项搭配,实现双1配置,极致数据安全
    server-id=1                           # mysql主从复制的唯一服务ID,主库必须配置且唯一,从库需改为2/3等其他值,不能重复
    lower_case_table_names=1              # 忽略表名大小写,避免Linux环境下表名大小写问题导致的查询失败,生产必备
    innodb_buffer_pool_size=512M          # InnoDB核心内存缓存池,缓存表数据/索引,提升查询性能,建议配置为物理内存的50%-70%
---
# ============== 第四部分:创建PVC 持久化存储卷声明 (适配 csi-rbd-sc 存储类) ==============
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mysql-pvc     # PVC名称,后续pod挂载存储时关联此名称
  namespace: mysql-test    # 归属mysql命名空间
  labels:
    app: mysql        # PVC标签,用于筛选和标识
spec:
  accessModes:        # 存储访问模式,核心配置
    - ReadWriteOnce   # ✅ 修复:改为ReadWriteOnce,更适配MySQL单实例场景
  storageClassName: nfs-client  # 存储类名称,指定使用集群内的nfs-client存储类
  resources:
    requests:
      storage: 1Gi    # 申请的存储容量,5GB,可根据业务数据量调整
---
# ============== 第五部分:MySQL 主库 Deployment 核心控制器配置 (主从集群的主库节点) ==============
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mysql         # Deployment的名称,唯一标识该控制器
  namespace: mysql-test    # 归属mysql命名空间
  labels:
    app: mysql        # Deployment标签,用于筛选和标识
spec:
  replicas: 1         # 副本数:主从复制架构中,主库只能部署1个副本,绝对不能多副本,否则会出现多主冲突
  selector:           # 标签选择器:Deployment的核心配置,通过该标签精准找到要管理的pod
    matchLabels:      # Deployment必须用matchLabels包裹标签
      app: mysql      # 必须和下方pod模板中的metadata.labels完全一致,否则控制器无法管理pod
  strategy:
    type: Recreate    # 更新策略:重建更新(先删除旧pod,再创建新pod),有状态服务必备配置!
                      # 注意:默认是RollingUpdate滚动更新,滚动更新会创建新pod再删旧pod,会导致mysql同时有2个实例挂载同一份PVC,触发文件锁冲突、数据损坏,生产必改为Recreate
  template:           # Pod模板:定义要创建的mysql pod的所有核心配置,控制器基于此模板创建pod
    metadata:
      labels:
        app: mysql    # pod的标签,和上方selector.matchLabels保持一致,关联控制器与pod
    spec:
      restartPolicy: Always  # pod重启策略:总是重启,当容器异常退出时,kubelet会自动重启容器,保证服务可用性,默认就是Always,显式声明更规范
      containers:           # 容器列表:一个pod中运行的容器,此处只有1个mysql业务容器
      - name: mysql         # 容器名称,pod内唯一即可
        # mysql镜像地址:阿里云个人镜像仓库的mysql8.0.32版本,稳定版,生产推荐8.0+系列
        image: crpi-vdf183p7g8m4zpud.cn-hangzhou.personal.cr.aliyuncs.com/shy_my/mysql:8.0.32
        imagePullPolicy: Always  # 镜像拉取策略:总是拉取最新镜像,生产环境推荐配置,避免使用本地旧镜像;可选值:IfNotPresent(本地有则用本地)、Never(只用本地)
        ports:                   # 容器暴露的端口
        - containerPort: 3306    # mysql的默认服务端口,固定3306
        env:                     # 容器的环境变量配置,给mysql容器传递启动参数/配置项
        # 环境变量1:设置mysql的root管理员密码,从上面创建的Secret中读取,而非明文写死,安全合规
        - name: MYSQL_ROOT_PASSWORD
          valueFrom:
            secretKeyRef:        # 从Secret中读取指定key的value
              name: mysql        # 指定关联的Secret名称
              key: root-password # 指定读取Secret中的root-password这个key对应的密码
        # 环境变量2:初始化时跳过时区表加载,解决mysql容器启动时因时区表缺失导致的初始化失败问题,mysql8.0常见坑点,必配
        - name: MYSQL_INITDB_SKIP_TZINFO
          value: "1"
        # 容器的卷挂载配置:将外部的ConfigMap/PVC挂载到容器内部指定目录,核心配置段
        volumeMounts:
        # 挂载1:将ConfigMap中的mysql.cnf配置文件挂载到mysql容器内
        - name: mysql-config-volume  # 卷的名称,必须和下方volumes中定义的名称一致
          mountPath: /etc/mysql/conf.d/mysql.cnf # 容器内的挂载路径,mysql会自动加载/etc/mysql/conf.d目录下的所有.cnf配置文件,优先级高于默认配置
          subPath: mysql.cnf  # 精准挂载:只挂载ConfigMap中的mysql.cnf文件,而非整个ConfigMap,避免覆盖容器原有文件,必配!
        # 挂载2:将PVC的持久化存储挂载到mysql的数据目录,实现数据持久化
        - name: mysql-data    # 卷的名称,必须和下方volumes中定义的名称一致
          mountPath: /var/lib/mysql # mysql的默认数据存储目录,所有库/表数据都存在这里,挂载PVC后数据永久保存
        # 健康检查-存活探针:检测mysql容器是否「存活运行」,保障服务自愈能力
        livenessProbe:
          tcpSocket:          # 探测方式:TCP端口探测,检测3306端口是否能连通,比httpGet更适合mysql这类TCP服务
            port: 3306
          initialDelaySeconds: 120 # 容器启动后,延迟120秒再开始第一次探测,mysql启动较慢,需给足初始化时间,太短会误判容器异常
          periodSeconds: 10   # 探测频率:每10秒探测一次,探测失败3次则判定容器异常,触发重启
        # 健康检查-就绪探针:检测mysql容器是否「就绪可用」,即是否能正常提供数据库服务
        readinessProbe:
          tcpSocket:
            port: 3306
          initialDelaySeconds: 60 # 延迟60秒开始探测,比存活探针短,快速感知服务就绪状态
          periodSeconds: 5    # 探测频率:每5秒探测一次,探测失败则将pod标记为未就绪,剔除service流量
        # 容器资源限制:为mysql容器分配CPU和内存资源,防止容器占用过多集群资源导致节点资源耗尽,生产必配
        resources:
          limits:             # 资源上限:容器能使用的最大CPU和内存,超过则会被kubelet限流/驱逐
            cpu: 500m        # CPU上限:1000毫核 = 1核
            memory: 512Mi      # 内存上限:1GB
          requests:           # 资源申请:容器启动时kubelet为其分配的保底资源,调度器根据此值选择合适的节点部署pod
            cpu: 250m         # 申请500毫核CPU
            memory: 128Mi     # 申请512MB内存
      # 定义pod需要挂载的所有卷:关联ConfigMap和PVC,是volumeMounts的前置配置,一一对应
      volumes:
      # 卷1:关联ConfigMap,提供mysql的配置文件
      - name: mysql-config-volume
        configMap:
          name: mysql-config  # 指定关联的ConfigMap名称
      # 卷2:关联PVC,提供mysql的持久化存储
      - name: mysql-data
        persistentVolumeClaim:
          claimName: mysql-pvc # 指定关联的PVC名称
---
# ============== 第六部分:创建MySQL的Service服务,提供固定访问入口 ==============
apiVersion: v1
kind: Service
metadata:
  name: mysql         # Service名称,集群内访问时的域名就是 mysql.mysql-test.svc
  namespace: mysql-test    # 归属mysql命名空间
  labels:
    app: mysql        # Service标签,用于筛选和关联
spec:
  type: NodePort      # Service类型:NodePort,核心特性:在集群的每个节点上暴露一个固定端口,实现「集群外部访问集群内的mysql服务」
                      # Service的4种类型:ClusterIP(仅集群内访问,默认)、NodePort(集群内+集群外访问)、LoadBalancer(云厂商负载均衡)、ExternalName(域名映射)
  selector:           # 标签选择器:Service通过该标签找到要代理的mysql pod,必须和pod的metadata.labels一致
    app: mysql        # Service直接写标签,无matchLabels
  ports:              # 端口映射配置,TCP协议默认,mysql是TCP服务
  - port: 3306        # Service的集群内访问端口,集群内其他服务访问mysql时用该端口
    targetPort: 3306  # 目标端口:pod/容器的实际端口,必须和容器的containerPort一致
    nodePort: 30337   # 节点端口:集群外部访问的端口,范围固定 30000-32767,手动指定固定值,方便外部访问
    protocol: TCP     # 协议类型:TCP,mysql基于TCP协议通信,固定配置
2. 验证服务
bash 复制代码
kubectl apply -f mysql.yaml

# 验证Secret创建成功
kubectl get secrets -n mysql-test

# 验证ConfigMap创建成功
kubectl get configmaps -n mysql-test 

# 验证PVC状态(应为 Bound 状态,说明动态存储已分配PV)
kubectl get pvc -n mysql-test 

# 验证Pod状态
kubectl get pods -n mysql-test 

# 验证Service创建成功(查看NodePort端口)
kubectl get svc -n mysql-test 

# 外部机器访问(替换为集群节点IP)
mysql -uroot -pShyshy521521! -h 10.132.47.60 -P 30306
3. 创建监控账号并授权
bash 复制代码
# 进入主库容器
kubectl exec -it -n mysql-test $(kubectl get pods -n mysql-test -l app=mysql -o jsonpath='{.items[0].metadata.name}') -- /bin/bash


# 登录MySQL(使用root密码)
mysql -uroot -p$(echo "U2h5c2h5NTIxNTIxIQ==" | base64 -d)

#执行复制权限配置 SQL
-- 创建账号(允许集群内任意地址访问,密码建议复杂)
CREATE USER 'mysql_exporter'@'%' IDENTIFIED BY 'Shyshy521521!';

-- 授予监控必要权限(最小权限原则)
GRANT PROCESS, REPLICATION CLIENT, SELECT ON *.* TO 'mysql_exporter'@'%';

-- 刷新权限
FLUSH PRIVILEGES;

-- 验证权限(可选)
SHOW GRANTS FOR 'mysql_exporter'@'%';

-- 退出MySQL
exit;

-- 退出pod
exit

三、创建mysql监控服务

1.创建文件
复制代码
vim mysql-exporter.yaml
yaml 复制代码
# 1. 替换为ConfigMap挂载认证信息(替代原Secret)
apiVersion: v1
kind: ConfigMap
metadata:
  name: mysql-exporter-cm
  namespace: monitoring
data:
  .my.cnf: |-
    [client]
    user = mysql_exporter
    password = Shyshy521521!
---
# 2. 修改exporter Deployment(使用ConfigMap挂载 + 节点IP+NodePort访问)
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mysql-exporter
  namespace: monitoring
  labels:
    app: mysql-exporter
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mysql-exporter
  template:
    metadata:
      labels:
        app: mysql-exporter
    spec:
      volumes:
      - name: mysql-config
        configMap:
          name: mysql-exporter-cm
          items:
          - key: .my.cnf
            path: .my.cnf
      containers:
      - name: mysql-exporter
        image: swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/prom/mysqld-exporter:v0.15.0
        command:
        - mysqld_exporter
        - --config.my-cnf=/etc/mysql/.my.cnf  # 挂载路径
        - --mysqld.address=10.132.47.60:30337  # 节点IP+NodePort
        securityContext:
          runAsUser: 0  # 避免权限问题
        ports:
        - containerPort: 9104
          name: metrics  # 新增端口名称,方便ServiceMonitor匹配
        volumeMounts:
        - name: mysql-config
          mountPath: /etc/mysql/.my.cnf
          subPath: .my.cnf
        resources:
          limits:
            cpu: 100m
            memory: 128Mi
          requests:
            cpu: 50m
            memory: 64Mi
---
# 3. 修改Service(添加端口名称)
apiVersion: v1
kind: Service
metadata:
  name: mysql-exporter
  namespace: monitoring
  labels:
    app: mysql-exporter
spec:
  selector:
    app: mysql-exporter
  ports:
  - name: metrics  # 端口名称,ServiceMonitor匹配用
    port: 9104
    targetPort: 9104
  type: ClusterIP
---
# 4. 修改ServiceMonitor(用端口名称匹配)
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: mysql-exporter
  namespace: monitoring
  labels:
    app: mysql-exporter
spec:
  selector:
    matchLabels:
      app: mysql-exporter
  namespaceSelector:
    matchNames:
    - monitoring
  endpoints:
  - port: metrics  # 匹配Service的端口名称
    interval: 15s
    path: /metrics
2. 验证资源创建
shell 复制代码
kubectl apply -f mysql-exporter.yaml

# 验证secret
kubectl get secret mysql-exporter-cnf -n mysql

# 验证pod+svc
kubectl get pod,svc -n mysql -l app=mysql-exporter

# 验证servicemonitor
kubectl get servicemonitor mysql-exporter -n mysql

#验证
#先获取mysql-exporter的Service集群IP
MYSQL_EXPORTER_IP=$(kubectl get svc mysql-exporter -n monitoring -o jsonpath='{.spec.clusterIP}')
#查看获取到的 ClusterIP
echo $MYSQL_EXPORTER_IP
#访问 metrics 接口,查看 mysql_up(核心验证)
curl -s http://${MYSQL_EXPORTER_IP}:9104/metrics | grep mysql_up
返回mysql_up 1成功
3. 访问 Prometheus Web UI

查看 mysql-exporter 的 Target 状态(核心验证)

  1. 进入 UI 后,点击左侧菜单栏的 StatusTargets

  2. 在页面右上角的搜索框输入 mysql-exporter,过滤出目标;

  3. 重点看 State列:

    • UP:说明 Prometheus 已成功发现并采集 mysql-exporter 的指标(监控链路完全打通);

    • Down:采集失败(鼠标悬停在红色的 Down 上,会显示具体错误原因,比如端口不通、超时等);

    • 📶 无此条目:极少数情况,可重新应用 ServiceMonitor 配置:

      复制代码
      kubectl apply -f mysql-exporter.yaml -n monitoring
4. 导入 MySQL 监控面板

Grafana 官方有成熟的 MySQL 监控面板,推荐导入 ID 为7362(MySQL Overview)或9628(MySQL Detailed)的面板。

****:覆盖连接数、QPS、InnoDB 状态、慢查询等核心指标,适配 Prometheus + mysqld_exporter。

(1)导入面板步骤:
  1. 点击左侧菜单DashboardsNewImport
  2. Import via grafana.com输入框中输入7362,点击Load
  3. 选择 Prometheus 数据源(需确保 Grafana 已配置 Prometheus 数据源)。
  4. 点击Import完成导入。

我用的:14057

四、Prometheus指标查询语句

bash 复制代码
#2.1 检查 MySQL exporter 是否正常运行(实例级)
mysql_up{job="mysql-exporter"}
#2.2 MySQL 连接数(适配 v0.15.0,补充缺失时的默认值)
#若 mysql_connections 无数据,用 global_status_Threads_connected 替代(v0.15.0 兼容)
mysql_connections{job="mysql-exporter"} OR mysql_global_status_threads_connected{job="mysql-exporter"}
#2.3 MySQL 最大连接数(适配 v0.15.0)
mysql_max_connections{job="mysql-exporter"} OR mysql_global_variables_max_connections{job="mysql-exporter"}
#2.4 MySQL 查询总数(适配 v0.15.0,处理无数值的情况)
mysql_global_status_queries{job="mysql-exporter"} > 0
#2.5 MySQL 连接使用率(适配 v0.15.0)
(mysql_global_status_threads_connected{job="mysql-exporter"} / mysql_global_variables_max_connections{job="mysql-exporter"}) * 100
#2.6 MySQL QPS(适配 v0.15.0,5 分钟滑动窗口)
rate(mysql_global_status_queries{job="mysql-exporter"}[5m])
#2.7 MySQL TPS(适配 v0.15.0,5 分钟滑动窗口)
rate(mysql_global_status_questions{job="mysql-exporter"}[5m])
#2.8 MySQL 慢查询数(适配 v0.15.0)
mysql_global_status_slow_queries{job="mysql-exporter"}
#2.9 InnoDB 缓冲池命中率(适配 v0.15.0)
(mysql_global_status_innodb_buffer_pool_read_requests{job="mysql-exporter"} / (mysql_global_status_innodb_buffer_pool_read_requests{job="mysql-exporter"} + mysql_global_status_innodb_buffer_pool_reads{job="mysql-exporter"})) * 100
#2.10 MySQL 锁等待数(适配 v0.15.0)
mysql_global_status_innodb_row_lock_waits{job="mysql-exporter"}
#2.11 MySQL InnoDB 读 IO 数(适配 v0.15.0)
mysql_global_status_innodb_data_reads{job="mysql-exporter"}
#2.12 MySQL InnoDB 写 IO 数(适配 v0.15.0)
mysql_global_status_innodb_data_writes{job="mysql-exporter"}
#2.13 MySQL 表缓存命中率(适配 v0.15.0)
(mysql_global_status_open_tables{job="mysql-exporter"} / mysql_global_status_opened_tables{job="mysql-exporter"}) * 100
#2.14 MySQL 运行线程数(适配 v0.15.0)
mysql_global_status_threads_running{job="mysql-exporter"}

五、添加mysql告警规则

bash 复制代码
vim mysql-rules.yaml
yaml 复制代码
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
  name: mysql-rules
  namespace: monitoring
  labels:
    custom-rule: "true"  # 专属标签,用于筛选
    prometheus: k8s
    role: alert-rules
spec:
  groups:
  - name: mysql.rules
    rules:
    # === P0级(严重,立即处理)===
    # MySQL宕机
    - alert: MySQL服务不可用
      expr: mysql_up == 0
      for: 1m
      labels:
        severity: critical
        level: P0
      annotations:
        summary: "MySQL服务不可用"
        description: "MySQL实例 {{ $labels.instance }} 无法连接 (状态码: {{ $value }})"
        runbook: |
          【K8s环境】
          1. 检查MySQL Pod状态: kubectl get pods -n {{ $labels.namespace }} | grep mysql
          2. 查看MySQL容器日志: kubectl logs -n {{ $labels.namespace }} {{ $labels.pod }}
          3. 测试容器网络: kubectl exec -it -n {{ $labels.namespace }} {{ $labels.pod }} -- ping {{ $labels.instance }}
          4. 重启MySQL Pod: kubectl delete pod -n {{ $labels.namespace }} {{ $labels.pod }}
          【Linux原生环境】
          1. 检查MySQL进程状态: ps -ef | grep mysqld
          2. 查看MySQL日志: cat /var/log/mysqld.log (或 /data/mysql/error.log)
          3. 测试网络连通性: telnet {{ $labels.instance }} 3306
          4. 重启MySQL服务: systemctl restart mysqld (或 service mysqld restart)

    # MySQL连接数耗尽
    - alert: MySQL连接数即将耗尽
      expr: mysql_connections / mysql_max_connections > 0.95
      for: 1m
      labels:
        severity: critical
        level: P0
      annotations:
        summary: "MySQL连接数即将耗尽"
        description: "MySQL实例 {{ $labels.instance }} 当前连接数占最大连接数的{{ $value | humanizePercentage }} (超过95%)"
        runbook: |
          【K8s环境】
          1. 进入MySQL容器: kubectl exec -it -n {{ $labels.namespace }} {{ $labels.pod }} -- mysql -uroot -p
          2. 紧急调整连接数: set global max_connections=2000;
          3. 长期优化: 修改MySQL ConfigMap中的max_connections配置并重启Pod
          【Linux原生环境】
          1. 登录MySQL: mysql -h {{ $labels.instance }} -uroot -p
          2. 紧急调整连接数: set global max_connections=2000;
          3. 查杀空闲连接: kill id1,id2,...; (id从show processlist获取)
          4. 长期优化: 修改my.cnf中max_connections参数并重启mysqld

    # MySQL主从复制中断
    - alert: MySQL主从复制中断
      expr: mysql_slave_status_slave_io_running != 1 or mysql_slave_status_slave_sql_running != 1
      for: 1m
      labels:
        severity: critical
        level: P0
      annotations:
        summary: "MySQL主从复制中断"
        description: "MySQL实例 {{ $labels.instance }} 复制异常: IO线程={{ $labels.slave_io_running }}, SQL线程={{ $labels.slave_sql_running }}"
        runbook: |
          【K8s环境】
          1. 进入从库容器: kubectl exec -it -n {{ $labels.namespace }} {{ $labels.pod }} -- mysql -uroot -p
          2. 查看复制错误: show slave status\G;
          3. 修复复制错误: stop slave; set global sql_slave_skip_counter=1; start slave;
          4. 检查主库binlog: kubectl exec -it -n {{ $labels.namespace }} 主库Pod名称 -- mysql -uroot -p -e "show binary logs;"
          【Linux原生环境】
          1. 登录从库MySQL: mysql -h {{ $labels.instance }} -uroot -p
          2. 查看复制错误: show slave status\G;
          3. 修复复制错误: stop slave; set global sql_slave_skip_counter=1; start slave;
          4. 检查主库binlog: mysql -h 主库IP -uroot -p -e "show binary logs;"

    # MySQL数据目录磁盘空间耗尽
    - alert: MySQL数据目录磁盘空间耗尽
      expr: mysql_disk_space_used_bytes{mountpoint=~"/var/lib/mysql|/data/mysql"} / mysql_disk_space_total_bytes{mountpoint=~"/var/lib/mysql|/data/mysql"} > 0.95
      for: 1m
      labels:
        severity: critical
        level: P0
      annotations:
        summary: "MySQL数据目录磁盘空间耗尽"
        description: "MySQL实例 {{ $labels.instance }} 数据目录 {{ $labels.mountpoint }} 使用率: {{ $value | humanizePercentage }} (超过95%)"
        runbook: |
          【K8s环境】
          1. 查看PVC空间: kubectl get pvc -n {{ $labels.namespace }} | grep mysql
          2. 进入容器清理日志: kubectl exec -it -n {{ $labels.namespace }} {{ $labels.pod }} -- rm -rf /var/log/mysql/*.log
          3. 清理binlog: kubectl exec -it -n {{ $labels.namespace }} {{ $labels.pod }} -- mysql -uroot -p -e "PURGE BINARY LOGS BEFORE DATE_SUB(NOW(), INTERVAL 7 DAY);"
          4. 扩容PVC: kubectl edit pvc -n {{ $labels.namespace }} mysql-pvc名称
          【Linux原生环境】
          1. 检查磁盘空间: df -h {{ $labels.mountpoint }}
          2. 清理日志文件: rm -rf /var/log/mysqld/*.log (或数据目录下的无用日志)
          3. 登录MySQL清理binlog: mysql -h {{ $labels.instance }} -uroot -p -e "PURGE BINARY LOGS BEFORE DATE_SUB(NOW(), INTERVAL 7 DAY);"
          4. 扩容磁盘: 通过fdisk/lsblk扩容挂载分区

    # === P1级(警告,重点关注)===
    # MySQL连接数过高
    - alert: MySQL连接数过高
      expr: mysql_connections / mysql_max_connections > 0.8
      for: 5m
      labels:
        severity: warning
        level: P1
      annotations:
        summary: "MySQL连接数过高"
        description: "MySQL实例 {{ $labels.instance }} 当前连接数占最大连接数的{{ $value | humanizePercentage }} (超过80%)"
        runbook: |
          【K8s环境】
          1. 进入MySQL容器: kubectl exec -it -n {{ $labels.namespace }} {{ $labels.pod }} -- mysql -uroot -p
          2. 查看连接详情: show full processlist;
          3. 调整连接数配置: 修改ConfigMap中max_connections并重启Pod
          【Linux原生环境】
          1. 登录MySQL: mysql -h {{ $labels.instance }} -u root -p
          2. 查看连接详情: show full processlist;
          3. 临时调整连接数: set global max_connections=1500;
          4. 长期优化: 修改my.cnf中max_connections参数并重启mysqld

    # MySQL慢查询增多
    - alert: MySQL慢查询增多
      expr: rate(mysql_global_status_slow_queries[5m]) > 10
      for: 5m
      labels:
        severity: warning
        level: P1
      annotations:
        summary: "MySQL慢查询增多"
        description: "MySQL实例 {{ $labels.instance }} 5分钟内慢查询数: {{ $value | humanize }}"
        runbook: |
          【K8s环境】
          1. 进入容器开启慢查询日志: kubectl exec -it -n {{ $labels.namespace }} {{ $labels.pod }} -- mysql -uroot -p -e "set global slow_query_log=1; set global long_query_time=1;"
          2. 查看慢查询: kubectl exec -it -n {{ $labels.namespace }} {{ $labels.pod }} -- mysql -uroot -p -e "select * from mysql.slow_log;"
          3. 分析慢SQL: kubectl exec -it -n {{ $labels.namespace }} {{ $labels.pod }} -- mysql -uroot -p -e "explain 慢SQL语句;"
          【Linux原生环境】
          1. 登录MySQL开启慢查询: mysql -h {{ $labels.instance }} -uroot -p -e "set global slow_query_log=1; set global long_query_time=1;"
          2. 查看慢查询日志: cat /var/log/mysql/slow.log (或show slow logs;)
          3. 分析慢SQL: mysql -h {{ $labels.instance }} -uroot -p -e "explain 慢SQL语句;"

    # InnoDB缓冲池命中率低
    - alert: MySQLInnoDB缓冲池命中率低
      expr: sum(mysql_global_status_innodb_buffer_pool_read_requests) / (sum(mysql_global_status_innodb_buffer_pool_read_requests) + sum(mysql_global_status_innodb_buffer_pool_reads)) < 0.95
      for: 5m
      labels:
        severity: warning
        level: P1
      annotations:
        summary: "MySQL InnoDB缓冲池命中率低"
        description: "MySQL实例 {{ $labels.instance }} 命中率: {{ $value | humanizePercentage }} (低于95%)"
        runbook: |
          【K8s环境】
          1. 进入容器调整缓冲池: kubectl exec -it -n {{ $labels.namespace }} {{ $labels.pod }} -- mysql -uroot -p -e "set global innodb_buffer_pool_size=4G;" (根据实际内存调整)
          2. 长期优化: 修改ConfigMap中innodb_buffer_pool_size并重启Pod
          【Linux原生环境】
          1. 登录MySQL调整缓冲池: mysql -h {{ $labels.instance }} -uroot -p -e "set global innodb_buffer_pool_size=4G;"
          2. 长期优化: 修改my.cnf中innodb_buffer_pool_size参数并重启mysqld
          3. 优化SQL减少磁盘读取: 给高频查询表加索引

    # MySQL锁等待过多
    - alert: MySQLInnoDB行锁等待过多
      expr: rate(mysql_global_status_innodb_row_lock_waits[5m]) > 10
      for: 5m
      labels:
        severity: warning
        level: P1
      annotations:
        summary: "MySQL InnoDB行锁等待过多"
        description: "MySQL实例 {{ $labels.instance }} 5分钟内锁等待数: {{ $value | humanize }}"
        runbook: |
          【K8s环境】
          1. 进入容器查看锁等待: kubectl exec -it -n {{ $labels.namespace }} {{ $labels.pod }} -- mysql -uroot -p -e "show engine innodb status\G;"
          2. 查看当前事务: kubectl exec -it -n {{ $labels.namespace }} {{ $labels.pod }} -- mysql -uroot -p -e "select * from information_schema.innodb_trx;"
          【Linux原生环境】
          1. 登录MySQL查看锁等待: mysql -h {{ $labels.instance }} -uroot -p -e "show engine innodb status\G;"
          2. 查看阻塞事务: mysql -h {{ $labels.instance }} -uroot -p -e "select * from information_schema.innodb_locks;"
          3. 优化事务SQL: 缩短事务执行时间、减少锁冲突

    # MySQL主从复制延迟过高
    - alert: MySQL主从复制延迟过高
      expr: mysql_slave_status_seconds_behind_master > 30
      for: 5m
      labels:
        severity: warning
        level: P1
      annotations:
        summary: "MySQL主从复制延迟过高"
        description: "MySQL实例 {{ $labels.instance }} 复制延迟: {{ $value }} 秒 (阈值30秒)"
        runbook: |
          【K8s环境】
          1. 进入从库容器查看延迟: kubectl exec -it -n {{ $labels.namespace }} {{ $labels.pod }} -- mysql -uroot -p -e "show slave status\G;"
          2. 检查从库资源: kubectl top pod -n {{ $labels.namespace }} {{ $labels.pod }}
          3. 优化主库大事务: 拆分长事务、避免批量更新
          【Linux原生环境】
          1. 登录从库查看延迟: mysql -h {{ $labels.instance }} -uroot -p -e "show slave status\G;"
          2. 检查从库CPU/IO: top -p `pidof mysqld`; iostat -x 1
          3. 临时提升从库优先级: set global slave_parallel_workers=8; (MySQL8.0+)
          4. 优化主库大事务: 拆分长事务

    # MySQL磁盘临时表占比过高
    - alert: MySQL磁盘临时表占比过高
      expr: rate(mysql_global_status_created_tmp_disk_tables[5m]) / rate(mysql_global_status_created_tmp_tables[5m]) > 0.2
      for: 5m
      labels:
        severity: warning
        level: P1
      annotations:
        summary: "MySQL磁盘临时表占比过高"
        description: "MySQL实例 {{ $labels.instance }} 磁盘临时表占比: {{ $value | humanizePercentage }} (超过20%)"
        runbook: |
          【K8s环境】
          1. 进入容器调整临时表大小: kubectl exec -it -n {{ $labels.namespace }} {{ $labels.pod }} -- mysql -uroot -p -e "set global tmp_table_size=64M; set global max_heap_table_size=64M;"
          2. 长期优化: 修改ConfigMap中相关参数并重启Pod
          【Linux原生环境】
          1. 登录MySQL调整参数: mysql -h {{ $labels.instance }} -uroot -p -e "set global tmp_table_size=64M; set global max_heap_table_size=64M;"
          2. 长期优化: 修改my.cnf中tmp_table_size和max_heap_table_size
          3. 优化SQL: 补充缺失索引、避免ORDER BY/RAND()等产生临时表的操作

    # MySQL连接失败数激增
    - alert: MySQL连接失败数激增
      expr: rate(mysql_global_status_aborted_connects[5m]) > 5
      for: 5m
      labels:
        severity: warning
        level: P1
      annotations:
        summary: "MySQL连接失败数激增"
        description: "MySQL实例 {{ $labels.instance }} 5分钟内连接失败数: {{ $value | humanize }}"
        runbook: |
          【K8s环境】
          1. 检查MySQL服务是否正常: kubectl exec -it -n {{ $labels.namespace }} {{ $labels.pod }} -- mysql -uroot -p -e "select 1;"
          2. 检查权限配置: kubectl exec -it -n {{ $labels.namespace }} {{ $labels.pod }} -- mysql -uroot -p -e "select user,host from mysql.user;"
          3. 检查网络策略: kubectl get networkpolicy -n {{ $labels.namespace }}
          【Linux原生环境】
          1. 检查MySQL用户权限: mysql -h {{ $labels.instance }} -uroot -p -e "select user,host from mysql.user;"
          2. 检查防火墙/安全组: firewall-cmd --list-ports | grep 3306 (或iptables -L)
          3. 检查max_connections: mysql -h {{ $labels.instance }} -uroot -p -e "show variables like 'max_connections';"
          4. 查看连接失败日志: grep "Access denied" /var/log/mysqld.log

    # MySQL死锁次数增多
    - alert: MySQL死锁次数增多
      expr: rate(mysql_global_status_innodb_deadlocks[5m]) > 1
      for: 5m
      labels:
        severity: warning
        level: P1
      annotations:
        summary: "MySQL死锁次数增多"
        description: "MySQL实例 {{ $labels.instance }} 5分钟内死锁数: {{ $value | humanize }}"
        runbook: |
          【K8s环境】
          1. 进入容器查看死锁日志: kubectl exec -it -n {{ $labels.namespace }} {{ $labels.pod }} -- mysql -uroot -p -e "show engine innodb status\G;"
          2. 导出死锁日志分析: kubectl exec -it -n {{ $labels.namespace }} {{ $labels.pod }} -- mysql -uroot -p -e "show engine innodb status\G;" > deadlock.log
          【Linux原生环境】
          1. 登录MySQL查看死锁日志: mysql -h {{ $labels.instance }} -uroot -p -e "show engine innodb status\G;"
          2. 开启死锁监控: set global innodb_print_all_deadlocks=1;
          3. 优化方案: 调整事务执行顺序、缩小锁粒度(行锁替代表锁)、缩短事务时长

    # === P2级(提示,按需处理)===
    # MySQL QPS突增
    - alert: MySQLQPS突增
      expr: rate(mysql_global_status_queries[5m]) > 2 * rate(mysql_global_status_queries[30m])
      for: 5m
      labels:
        severity: warning
        level: P2
      annotations:
        summary: "MySQL QPS突增"
        description: "MySQL实例 {{ $labels.instance }} QPS突增(当前值超过基线2倍)"
        runbook: |
          【K8s环境】
          1. 进入容器查看QPS: kubectl exec -it -n {{ $labels.namespace }} {{ $labels.pod }} -- mysql -uroot -p -e "show global status like 'Queries';"
          2. 查看慢查询日志: kubectl exec -it -n {{ $labels.namespace }} {{ $labels.pod }} -- cat /var/log/mysql/slow.log
          3. 限流异常请求: 结合K8s NetworkPolicy限制高频IP
          【Linux原生环境】
          1. 登录MySQL查看QPS: mysql -h {{ $labels.instance }} -uroot -p -e "show global status like 'Queries';"
          2. 查看慢查询日志: cat /var/log/mysql/slow.log
          3. 检查异常访问: netstat -an | grep 3306 | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -nr
          4. 优化高频SQL: 给高频查询加索引、使用缓存

    # MySQL表缓存命中率低
    - alert: MySQL表缓存命中率低
      expr: (mysql_global_status_open_tables / mysql_global_status_opened_tables) * 100 < 90
      for: 5m
      labels:
        severity: warning
        level: P2
      annotations:
        summary: "MySQL表缓存命中率低"
        description: "MySQL实例 {{ $labels.instance }} 表缓存命中率: {{ $value | humanizePercentage }} (阈值90%)"
        runbook: |
          【K8s环境】
          1. 进入容器调整表缓存: kubectl exec -it -n {{ $labels.namespace }} {{ $labels.pod }} -- mysql -uroot -p -e "set global table_open_cache=2000;"
          2. 长期优化: 修改ConfigMap中table_open_cache并重启Pod
          【Linux原生环境】
          1. 登录MySQL调整参数: mysql -h {{ $labels.instance }} -uroot -p -e "set global table_open_cache=2000;"
          2. 长期优化: 修改my.cnf中table_open_cache和table_definition_cache
          3. 优化连接复用: 调整应用连接池的min_idle/max_active参数

    # MySQL运行线程数过高
    - alert: MySQL运行线程数过高
      expr: mysql_global_status_threads_running > 100
      for: 5m
      labels:
        severity: warning
        level: P2
      annotations:
        summary: "MySQL运行线程数过高"
        description: "MySQL实例 {{ $labels.instance }} 运行线程数: {{ $value | humanize }} (阈值100)"
        runbook: |
          【K8s环境】
          1. 进入容器查看线程: kubectl exec -it -n {{ $labels.namespace }} {{ $labels.pod }} -- mysql -uroot -p -e "show processlist;"
          2. 终止慢线程: kubectl exec -it -n {{ $labels.namespace }} {{ $labels.pod }} -- mysql -uroot -p -e "kill 线程ID;"
          3. 扩容Pod资源: kubectl edit statefulset -n {{ $labels.namespace }} mysql名称
          【Linux原生环境】
          1. 登录MySQL查看线程: mysql -h {{ $labels.instance }} -uroot -p -e "show full processlist;"
          2. 终止慢线程: mysql -h {{ $labels.instance }} -uroot -p -e "kill 线程ID;"
          3. 优化线程配置: set global thread_cache_size=64; (减少线程创建开销)

    # MySQL全表扫描占比过高
    - alert: MySQL全表扫描占比过高
      expr: rate(mysql_global_status_select_scan[5m]) / rate(mysql_global_status_com_select[5m]) > 0.3
      for: 10m
      labels:
        severity: warning
        level: P2
      annotations:
        summary: "MySQL全表扫描占比过高"
        description: "MySQL实例 {{ $labels.instance }} 全表扫描占SELECT比例: {{ $value | humanizePercentage }} (超过30%)"
        runbook: |
          【K8s环境】
          1. 导出慢查询分析: kubectl exec -it -n {{ $labels.namespace }} {{ $labels.pod }} -- mysqldumpslow -s r /var/log/mysql/slow.log
          2. 分析无索引SQL: kubectl exec -it -n {{ $labels.namespace }} {{ $labels.pod }} -- mysql -uroot -p -e "explain SELECT * FROM 表名 WHERE 条件;"
          【Linux原生环境】
          1. 分析慢查询: mysqldumpslow -s r /var/log/mysql/slow.log
          2. 检查缺失索引: mysql -h {{ $labels.instance }} -uroot -p -e "show indexes from 表名;"
          3. 补充索引: mysql -h {{ $labels.instance }} -uroot -p -e "ALTER TABLE 表名 ADD INDEX idx_字段名 (字段名);"
          4. 优化WHERE条件: 避免使用NULL/OR/like %xxx等无法走索引的条件

    # MySQL Binlog日志过多
    - alert: MySQLBinlog日志过多
      expr: mysql_binlog_files_count > 30 or mysql_binlog_disk_size / 1024 / 1024 / 1024 > 10
      for: 1h
      labels:
        severity: warning
        level: P2
      annotations:
        summary: "MySQL Binlog日志过多/过大"
        description: "MySQL实例 {{ $labels.instance }} Binlog文件数/大小超过阈值"
        runbook: |
          【K8s环境】
          1. 进入容器配置自动清理: kubectl exec -it -n {{ $labels.namespace }} {{ $labels.pod }} -- mysql -uroot -p -e "set global expire_logs_days=7;"
          2. 手动清理旧日志: kubectl exec -it -n {{ $labels.namespace }} {{ $labels.pod }} -- mysql -uroot -p -e "PURGE BINARY LOGS BEFORE '2024-01-01 00:00:00';"
          3. 长期优化: 修改ConfigMap中expire_logs_days参数
          【Linux原生环境】
          1. 登录MySQL配置自动清理: mysql -h {{ $labels.instance }} -uroot -p -e "set global expire_logs_days=7;"
          2. 手动清理指定日期前的日志: mysql -h {{ $labels.instance }} -uroot -p -e "PURGE BINARY LOGS BEFORE '2024-01-01 00:00:00';"
          3. 长期优化: 修改my.cnf中expire_logs_days=7

    # MySQL表碎片率过高
    - alert: MySQL表碎片率过高
      expr: mysql_table_fragmentation > 0.3
      for: 12h
      labels:
        severity: warning
        level: P2
      annotations:
        summary: "MySQL表碎片率过高"
        description: "MySQL实例 {{ $labels.instance }} 表 {{ $labels.table }} 碎片率: {{ $value | humanizePercentage }} (超过30%)"
        runbook: |
          【K8s环境】
          1. 进入容器优化表: kubectl exec -it -n {{ $labels.namespace }} {{ $labels.pod }} -- mysql -uroot -p -e "OPTIMIZE TABLE {{ $labels.table }};"
          2. 定期清理历史数据: 编写定时任务清理过期数据(避免业务低峰期执行)
          【Linux原生环境】
          1. 优化碎片表: mysql -h {{ $labels.instance }} -uroot -p -e "OPTIMIZE TABLE {{ $labels.table }};" (InnoDB需开启innodb_file_per_table)
          2. 清理历史数据: DELETE FROM {{ $labels.table }} WHERE create_time < '2024-01-01';
          3. 重建表(大表推荐): CREATE TABLE new_table LIKE {{ $labels.table }}; INSERT INTO new_table SELECT * FROM {{ $labels.table }}; RENAME TABLE {{ $labels.table }} TO old_table, new_table TO {{ $labels.table }};
验证规则生效
1.用 kubectl 验证 PrometheusRule 资源是否被正确创建
bash 复制代码
kubectl get prometheusrules -n monitoring | grep "mysql-rules"

#看到:
NAME               AGE
mysql-rules        2m11s
2.Prometheus UI

打开 Prometheus UI( http://:30883)点击菜单:

Status → Rules

你应该能看到你创建的 rule groups:

  • mysql-rules

如果这些 groups 都存在,说明 Prometheus 已经成功加载你的规则。

3. Grafana 导入告警规则面板

推荐适配 postgres_exporter 的中文面板:

  • **模板 ID:14858(k8s - alert);

导入步骤:

  1. Grafana → + → Import;
  2. 输入模板 ID(如14858);
  3. 选择 Prometheus 数据源;
相关推荐
聪明人2 小时前
macOS安装Redis
数据库·redis·macos
北漂Zachary2 小时前
Mysql中使用sql语句生成雪花算法Id
sql·mysql·算法
weixin_505154462 小时前
Bowell Studio:重塑工业互联网时代的装配制造与运维检修
运维·数据库·人工智能·制造·数字孪生·3d产品配置器·3d交互展示
sa100272 小时前
淘宝商品详情 API 接口开发实战:item_detail 调用、参数与 Python 示例
linux·数据库·python
小光学长3 小时前
基于ssm的膳食健康管理系统e6whl4q7(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
java·开发语言·数据库·学习·ssm
一个天蝎座 白勺 程序猿3 小时前
KingbaseES融合数据库:一库多能,企业数据管理新思路
数据库·性能优化·kingbasees·金仓数据库
橘颂TA3 小时前
【MySQL】解锁表的 N 种牵手方式:SQL 连接与子查询漫游(复合查询)
数据库·mysql
数据知道3 小时前
MongoDB基于角色的访问控制(RBAC):精细化权限管理的实用方法
数据库·mongodb
代码派3 小时前
NineData社区版:免费+本地化部署,满足数据库DevOps、数据复制与一致性对比的数据库管理平台
运维·数据库·database·devops·数据库管理工具·ninedata·数据库迁移