Kubernetes学习总结(15)—— Kubernetes 实战之部署 Mysql 集群
发布日期:2025-04-03 06:08:30 浏览次数:8 分类:精选文章

本文共 6419 字,大约阅读时间需要 21 分钟。

Kubernetes StatefulSet 实现 MySQL 主从集群——基于本地存储的状态管理实践

引言

在 Kubernetes 环境中,管理有状态服务(StatefulSet)是一个复杂但关键的任务。与无状态服务(ReplicaSet)不同,StatefulSet 有状态的 pods 需要保持特定的网络标识符和唯一的网络接口。通过本地存储解决方案,我们可以避免服务漂移导致的数据丢失问题。本文通过一个 MySQL 主从集群的案例,探讨如何利用 Kubernetes 的 StatefulSet 实现状态管理。


本地存储原理

为了快速搭建测试环境,我们采用本地存储策略,即将存储固定在特定节点上。这种方法的关键在于容器级别的持久化存储(PersistentVolume),ensure each pod can mount a stable volume. 但是,由于本地存储不支持动态供给(Dynamic Provisioning),因此我们需要手动预先创建 PersistentVolume(PVs)。

为了实现动态配置,我们使用了以下方法:

  • StorageClass:定义一个存储类,使其支持延迟绑定(LazyBinding),具体配置如下:
kind: StorageClassapiVersion: storage.k8s.io/v1metadata:  name: local-storage  provider: kubernetes.io/no-provisionervolumeBindingMode: WaitForFirstConsumer

通过这种方式,我们确保 PersistentVolume 在第一次消费时创建。


实验步骤

一、本地节点预先创建 PersistentVolumes

apiVersion: v1kind: PersistentVolumemetadata:  name: example-mysql-pvspec:  capacity: 15Gi  volumeMode: Filesystem  accessModes: [ReadWriteOnce]  persistentVolumeReclaimPolicy: Delete  storageClassName: local-storage  local: path: /data/svr/projects/mysql  nodeAffinity: required: hostname: 172.31.170.51

手动创建 3 个 PersistentVolumes 为实验准备,并确保它们绑定在特定节点。

二、创建 StorageClass

kind: StorageClassapiVersion: storage.k8s.io/v1metadata:  name: local-storage  provider: kubernetes.io/no-provisionervolumeBindingMode: WaitForFirstConsumer

确保 StorageClass 已创建,并支持延迟绑定。

三、创建 Namespace

apiVersion: v1kind: Namespacemetadata:  name: mysql  labels:    app: mysql

为 MySQL 集群创建一个 isolated 的 Namespace。

四、使用 ConfigMap 分配配置

apiVersion: v1kind: ConfigMapmetadata:  name: mysql  namespace: mysql  labels:    app: mysqldata:  master.cnf: |    [mysqld]    log-bin=mysqllog    skip-name-resolve    slave.cnf: |    [mysqld]    super-read-only    skip-name-resolve    log-bin=mysql-bin    replicate-ignore-db=mysql

为主节点和从节点分别配置不同的 MySQL 配置文件。

五、创建 MySQL 密码 Secret

apiVersion: v1kind: Secretmetadata:  name: mysql-secret  namespace: mysql  labels:    app: mysqltype: Opaquedata:  password: MTIzNDU2

创建一个 Secret 提供 MySQL 密码。


StatefulSet 实现 MySQL 主从集群

YAML 模板

以下是 StatefulSet 的配置文件:

apiVersion: apps/v1kind: StatefulSetmetadata:  name: mysql  namespace: mysql  labels:    app: mysqlspec:  selector:    matchLabels:      app: mysql  serviceName: mysql  replicas: 2  template:    metadata:      labels:        app: mysql    spec:      initContainers:        - name: init-mysql          image: mysql:5.7          env:            - name: MYSQL_ROOT_PASSWORD              valueFrom: secretKeyRef: mysql-secret, password          command: [bash]            -c: |              set -ex              [[ $(hostname) =~ -([-9]+) ]] || exit 1              ordinal=${BASH_REMATCH[1]}              echo "[mysqld]" > /mnt/conf.d/server-id.cnf              echo "server-id=$((100 + $ordinal))" >> /mnt/conf.d/server-id.cnf              if [ $(hostname) == "mysql-0.mysql" ]; then                cp /mnt/config-map/master.cnf /mnt/conf.d              else                cp /mnt/config-map/slave.cnf /mnt/conf.d              fi          volumeMounts:          - name: conf            mountPath: /mnt/conf.d          - name: config-map            mountPath: /mnt/config-map        - name: clone-mysql          image: gcr.io/google-samples/xtrabackup:1.0          env:            - name: MYSQL_ROOT_PASSWORD              valueFrom: secretKeyRef: mysql-secret, password          volumeMounts:          - name: data            mountPath: /var/lib/mysql            subPath: mysql          - name: conf            mountPath: /etc/mysql/conf.d          - name: config-map            configMap: name: mysql            volumeClaimTemplate:              metadata: name: data              spec: accessModes: [ReadWriteOnce]              storageClassName: local-storage              resources: storage: 3Gi        - name: xtrabackup          image: gcr.io/google-samples/xtrabackup:1.0          ports:          - containerPort: 3307          env:            - name: MYSQL_ROOT_PASSWORD              valueFrom: secretKeyRef: mysql-secret, password          command: [bash]            -c: |              set -ex              cd /var/lib/mysql              if [ -f xtrabackup_slave_info ]; then                mv xtrabackup_slave_info change_master_to.sql.in                echo "CHANGE MASTER TO" > change_master_to.sql.in                mysql -h 127.0.0.1 -uroot -p$(MYSQL_ROOT_PASSWORD) < change_master_to.sql.in                mv change_master_to.sql.in change_master_to.sql.orig                mysql -h 127.0.0.1 -uroot -p$(MYSQL_ROOT_PASSWORD) < change_master_to.sql.orig > /dev/null              elif [ -f xtrabackup_binlog_info ]; then                mysql -h 127.0.0.1 -uroot -p$(MYSQL_ROOT_PASSWORD) < xtrabackup_binlog_info                rm -f xtrabackup_binlog_info                echo "CHANGE MASTER TO ..." > change_master_to.sql.in                mysql -h 127.0.0.1 -uroot -p$(MYSQL_ROOT_PASSWORD) < change_master_to.sql.in                mv change_master_to.sql.in change_master_to.sql.orig                mysql -h 127.0.0.1 -uroot -p$(MYSQL_ROOT_PASSWORD) < change_master_to.sql.orig > /dev/null              fi              if [ -f change_master_to.sql.in ]; then                echo "Waiting for mysqld to be ready..."                until mysql -h 127.0.0.1 -uroot -p$(MYSQL_ROOT_PASSWORD) -e "SELECT 1"; do sleep 1; done                echo "Initializing replication from clone position..."                mv change_master_to.sql.in change_master_to.sql.orig                mysql -h 127.0.0.1 -uroot -p$(MYSQL_ROOT_PASSWORD) < change_master_to.sql.orig > /dev/null              fi              ncat --listen --keep-open --send-only --max-conns=1 3307 -c "xtrabackup --backup --slave-info --stream=xbstream --host=127.0.0.1 --user=root --password=$(MYSQL_ROOT_PASSWORD)"

操作步骤

kubectl apply -f 07-mysql-statefulset.yaml

创建 StatefulSet 后,可以通过以下命令验证其状态:

kubectl get po -n mysql

随后,可以通过以下命令执行 SQL 操作:

kubectl -n mysql exec mysql-0 sh -c "mysql -uroot -p123456 -e 'create database test; use test; create table counter (c int); insert into counter values(123)'"
kubectl -n mysql exec mysql-1 sh -c "mysql -uroot -p123456 -e 'use test; select * from counter'"

此时,您应该看到主节点和从节点同步正常的状态。


扩展节点

StatefulSet 的一个重要优势是支持动态扩展。比如,如果您需要扩展节点数量,可以执行以下命令:

kubectl scale statefulset mysql --replicas=3

扩展后,可以通过 kubectl get po -n mysql 检查新节点的状态,并验证其数据同步情况。通过严格控制主节点的写操作和从节点的读操作,确保主从集群的高可用性和数据一致性。


通过以上步骤,我们成功利用 Kubernetes 的 StatefulSet 和本地存储策略,搭建了一个 MySQL 主从集群,实现了状态管理的关键功能。这一解决方案突破了传统 Kubernetes 集群存储的局限,为高可用性和状态管理提供了强有力的支持。

上一篇:Kubernetes学习总结(16)—— Kubernetes 实战之部署 Redis 集群
下一篇:Kubernetes学习总结(14)—— Kubernetes 实用命令总结

发表评论

最新留言

路过按个爪印,很不错,赞一个!
[***.219.124.196]2025年04月29日 07时20分30秒