一、介绍
Percona Server for MySQL 是任何 MySQL 数据库的免费,完全兼容,增强和开源的直接替代品。通过在 Kubernetes 环境中使用 Percona Distribution for MySQL Operator,您可以确保 MySQL 数据库的数据可用性,同时使用 Kubernetes 配置文件简化复杂的部署。本指南解释了如何使用 Vultr Kubernetes Engine 部署、配置和备份高可用性 MySQL 集群。备份单独存储在 Vultr 对象存储中,并且能够通过时间点恢复进行恢复。
二、准备工作
在开始之前,您应该:
- 部署至少具有三个节点的 Vultr Kubernetes 集群。
- 配置和在您的计算机中。
kubectl
git
- 创建 Vultr 对象存储。
- 为对象存储准备访问密钥和私有密钥
三、 为 MySQL 运算符安装 Percona 发行版
使用 Kubectl 安装 Percona Distribution for MySQL Operator 版本 1.10.0:
$ kubectl apply -f https://raw.githubusercontent.com/percona/percona-xtradb-cluster-operator/v1.10.0/deploy/bundle.yaml
四、创建 MySQL 集群
- 第 1 步:下载本指南的源代码。
$ git clone -b v1.10.0 https://github.com/quanhua92/k8s-mysql-cluster
- 步骤 2:使用以下命令部署数据库集群:
$ kubectl apply -f 001_cr_minimal.yaml
数据库集群的 CR 规范文件在 中定义。001_cr_minimal.yaml
apiVersion: pxc.percona.com/v1-10-0
kind: PerconaXtraDBCluster
metadata:
name: db-cluster
spec:
crVersion: 1.10.0
secretsName: db-cluster-secrets
allowUnsafeConfigurations: true
upgradeOptions:
apply: 8.0-recommended
schedule: "0 4 * * *"
pxc:
size: 3
image: percona/percona-xtradb-cluster:8.0.23-14.1
volumeSpec:
persistentVolumeClaim:
storageClassName: vultr-block-storage
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 15G
haproxy:
enabled: true
size: 3
image: percona/percona-xtradb-cluster-operator:1.10.0-haproxy
#serviceType: LoadBalancer
#replicasServiceType: LoadBalancer
logcollector:
enabled: true
image: percona/percona-xtradb-cluster-operator:1.10.0-logcollector
它是专门为 Vultr Kubernetes Engine 设计的。001_cr_minimal.yaml
默认情况下,此规范文件会创建一个集群,其中 03 个 Pod 用于 MySQL 实例,03 个 HAProxy Pod 以实现高可用性。Vultr块存储用作每个 MySQL 实例的数据存储。db-cluster
跑步的结果也类似:kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
db-cluster-haproxy-0 2/2 Running 0 5m7s 10.244.80.197 node-1f0f02fd5303 <none> <none>
db-cluster-haproxy-1 2/2 Running 0 3m16s 10.244.19.131 node-1e43b600d18b <none> <none>
db-cluster-haproxy-2 2/2 Running 0 2m56s 10.244.182.4 node-a2ed9ec0ccf8 <none> <none>
db-cluster-pxc-0 3/3 Running 0 5m7s 10.244.182.3 node-a2ed9ec0ccf8 <none> <none>
db-cluster-pxc-1 3/3 Running 0 3m23s 10.244.80.198 node-1f0f02fd5303 <none> <none>
db-cluster-pxc-2 3/3 Running 0 100s 10.244.19.132 node-1e43b600d18b <none> <none>
percona-xtradb-cluster-operator-566848cf48-tl4fh 1/1 Running 0 5m25s 10.244.80.196 node-1f0f02fd5303 <none> <none>
四、访问 MySQL 服务
- 步骤1:获取 root 密码以访问名为.的密钥下的 MySQL 服务。
db-cluster-secrets
$ kubectl get secret db-cluster-secrets -o yaml
输出应如下所示:
apiVersion: v1
data:
clustercheck: MjFuTUZmblMyVTRJeW11Ng==
monitor: bnJLUFNrVmgxcE9NTFd6ZVI=
operator: N3p3M0hqbVYyUlVuZ1dSZzEycA==
proxyadmin: dGducHllSnZPdXM2cDhYY1Y=
replication: ZXhrS0tidEJ3N29QZE5kRHA=
root: MUVtTnBDVkdJeWI4cVlraGVY
xtrabackup: RFBJQ0FWRkIyazJCTmFONEM=
kind: Secret
metadata:
creationTimestamp: "2022-01-09T13:23:42Z"
name: db-cluster-secrets
namespace: default
resourceVersion: "1011"
uid: 5e05580e-cab7-4b3d-bf18-f978614d73dd
type: Opaque
以根身份获取 base64 编码的密码。在此示例示例中。MUVtTnBDVkdJeWI4cVlraGVY
- 步骤 2:使用以下命令解码 root 密码的值:
$ echo 'MUVtTnBDVkdJeWI4cVlraGVY' | base64 --decode
- 第 3 步:在 Kubernetes 集群中创建一个 pod,用于访问 MySQL 服务。
$ kubectl run -it --rm percona-client --image=percona:8.0 -* bash
- 第 4 步:使用 mysql 工具登录,如下所示(将<root_password>替换为上一步中解码的密码):
$ mysql -h db-cluster-haproxy -uroot -p<root_password>
五、(可选)使用负载均衡器公开 MySQL 服务以供外部使用
在 CR YAML 规范中添加 haproxy 下的 serviceType,以便为 Kubernetes 之外的应用程序公开 MySQL 服务
haproxy:
serviceType: LoadBalancer
replicasServiceType: LoadBalancer
安装提供的规范以启用负载均衡器。此命令在您的账户中创建 Vultr 负载均衡器。002_cr_load_balancer.yaml
$ kubectl apply -f 002_cr_load_balancer.yaml
六、第 2 天操作
本节介绍如何管理备份和还原,以便使用 3-2-1 备份策略制定良好的灾难恢复计划。
3-2-1 备份策略意味着在两个不同的介质上至少拥有三个数据拷贝(一个生产数据和两个备份拷贝),以及一个异地备份。
为简单起见,本指南利用定时备份功能自动归档数据的三个副本:
- 生产数据:Vultr块存储。
- Vultr 对象存储:第一个备份位置。
- 异地 S3 兼容对象存储:Vultr 对象存储或任何 S3 兼容存储。
6.1、设置 Vultr 对象存储
获取 Vultr 对象存储的访问 ID 和访问密钥。
- 步骤 1:将访问密钥和私有密钥存储为名为 的密钥。
vultr-s3-secret
下面是作为示例的文件。003_vultr_s3_secrets.yaml
apiVersion: v1
kind: Secret
metadata:
name: vultr-s3-secret
type: Opaque
stringData:
AWS_ACCESS_KEY_ID: "4hrVSwKAYtfcjFu92r"
AWS_SECRET_ACCESS_KEY: "sIgPx!z#%9V&l65TRV"
- 第 2 步:将密钥保存到 Kubernetes
$ kubectl apply -f 003_vultr_s3_secrets.yaml
- 步骤 3:在 Vultr 对象存储中创建具有该名称的存储桶。此存储桶用于在后面的部分中存储备份数据。
db-cluster-backup
6.2、设置 S3 兼容对象存储
创建另一个 Vultr 对象存储或使用任何与 S3 兼容的对象存储。
- 步骤 1:将访问密钥和私有密钥存储为名为
offsite-s3-secret
这是示例规范,004_offsite_s3_secrets.yaml
apiVersion: v1
kind: Secret
metadata:
name: offsite-s3-secret
type: Opaque
stringData:
AWS_ACCESS_KEY_ID: "4hrVSwKAYtfcjFu92r"
AWS_SECRET_ACCESS_KEY: "sIgPx!z#%9V&l65TRV"
- 第 2 步:将密钥保存到 Kubernetes
$ kubectl apply -f 004_offsite_s3_secrets.yaml
- 步骤 3:在对象存储中创建具有该名称的存储桶。此存储桶用于在后面的部分中存储备份数据。
db-cluster-offsite-backup
6.3、设置自动备份
该文件包含一个新部分,其中包含上一步中的机密。005_cr_with_backup_s3.yaml
backup
backup:
image: perconalab/percona-xtradb-cluster-operator:main-pxc8.0-backup
pitr:
enabled: true
storageName: s3-vultr
timeBetweenUploads: 30
storages:
s3-vultr:
type: s3
s3:
bucket: db-cluster-backup
credentialsSecret: vultr-s3-secret
endpointUrl: https://<insert_vultr_s3_endpoint_here>
s3-offsite:
type: s3
s3:
bucket: db-cluster-backup
credentialsSecret: offsite-s3-secret
endpointUrl: https://<insert_offsite_s3_endpoint_here>
schedule:
- name: "daily-backup-vultr"
schedule: "0 0 * * *"
keep: 10
storageName: s3-vultr
- name: "daily-backup-offsite"
schedule: "0 0 * * *"
keep: 10
storageName: s3-offsite
在上述规范中,计划备份每天运行,存储中最多有 10 个副本。启用时间点恢复功能,使您能够还原到任何特定日期和时间。
- 步骤1:确保 正确,并使用以下命令应用更改:
bucket
endpointUrl
$ kubectl apply -f 005_cr_with_backup_s3.yaml
跑步的结果也类似:kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
db-cluster-haproxy-0 2/2 Running 0 7m52s 10.244.80.197 node-1f0f02fd5303 <none> <none>
db-cluster-haproxy-1 2/2 Running 0 6m1s 10.244.19.131 node-1e43b600d18b <none> <none>
db-cluster-haproxy-2 2/2 Running 0 5m41s 10.244.182.4 node-a2ed9ec0ccf8 <none> <none>
db-cluster-pitr-6cfb7549f7-bgsr5 1/1 Running 0 16s 10.244.182.6 node-a2ed9ec0ccf8 <none> <none>
db-cluster-pxc-0 3/3 Running 0 7m52s 10.244.182.3 node-a2ed9ec0ccf8 <none> <none>
db-cluster-pxc-1 3/3 Running 0 6m8s 10.244.80.198 node-1f0f02fd5303 <none> <none>
db-cluster-pxc-2 3/3 Running 0 4m25s 10.244.19.132 node-1e43b600d18b <none> <none>
percona-client 1/1 Running 0 98s 10.244.182.5 node-a2ed9ec0ccf8 <none> <none>
percona-xtradb-cluster-operator-566848cf48-tl4fh 1/1 Running 0 8m10s 10.244.80.196 node-1f0f02fd5303 <none> <none>
- 步骤二:使用以下命令检查备份容器PITR的日志。您需要将容器名称更改为相应的容器名称。
$ kubectl logs db-cluster-pitr-6cfb7549f7-bgsr5
结果显示二进制日志已成功写入 S3。这些是时间点恢复功能的备份。
2022/01/09 13:30:08 run binlog collector
2022/01/09 13:30:10 Reading binlogs from pxc with hostname= db-cluster-pxc-0.db-cluster-pxc.default.svc.cluster.local
2022/01/09 13:30:10 Starting to process binlog with name binlog.000003
2022/01/09 13:30:10 Successfully written binlog file binlog.000003 to s3 with name binlog_1641594293_733acbcaf56c45ed9cb41518b6b90cc0
2022/01/09 13:30:10 Starting to process binlog with name binlog.000004
2022/01/09 13:30:11 Successfully written binlog file binlog.000004 to s3 with name binlog_1641595077_bf4ecf614e5dc157128e7495cb590d4a
2022/01/09 13:30:11 Starting to process binlog with name binlog.000012
2022/01/09 13:30:13 Successfully written binlog file binlog.000012 to s3 with name binlog_1641595331_c4261dced1631cc839d4ef97b4b60931
- 第 3 步:转到 Vultr 对象存储以浏览文件。
6.4、创建手动备份
- 步骤 1:创建新的等级库文件 ,进行手动备份
006_manual_backup.yaml
apiVersion: pxc.percona.com/v1 kind: PerconaXtraDBClusterBackup metadata: finalizers: - delete-s3-backup name: backup-001 spec: pxcCluster: db-cluster storageName: s3-vultr
- 步骤2:运行命令以执行备份:
$ kubectl apply -f 006_manual_backup.yaml
- 步骤三:执行以下命令,查看备份进度。
$ kubectl get pxc-backup -w
结果应类似于:
NAME CLUSTER STORAGE DESTINATION STATUS COMPLETED AGE
backup-001 db-cluster s3-vultr s3://db-cluster-backup/db-cluster-2022-01-09-13:32:16-full Running 9s
backup-001 db-cluster s3-vultr s3://db-cluster-backup/db-cluster-2022-01-09-13:32:16-full Succeeded 4s 35s
- 步骤4:状态变为 后,您可以前往 Vultr 对象存储浏览文件。
Succeeded
6.5、 向数据库添加数据
- 步骤 1:创建 Pod 以访问数据库。(将<root_password>替换为上一步中解码的密码)
$ kubectl run -it --rm percona-client --image=percona:8.0 -- bash $ mysql -h db-cluster-haproxy -uroot -p<root_password>
- 步骤 2:通过运行以下 MYSQL 命令创建新的数据库和表
mysql> create database data; mysql> use data; mysql> create table first_table(id INT PRIMARY KEY);
- 步骤 3:向数据库表添加几行
mysql> insert into data.first_table values (1), (2), (3); mysql> select * from data.first_table;
- 步骤 4:在删除数据库之前,请确保二进制日志已上传到 Vultr 对象存储
- 步骤 5:删除数据库以进行测试
mysql> drop database data;
6.6、恢复
- 步骤 1:在执行任何还原之前禁用 PITR,即使备份不是使用时间点恢复进行的。将属性设置为 CR YAML 文件中。
spec.backup.pitr.enabled
false
- 第 2 步:使用以下命令应用文件:
007_cr_disable_pitr.yaml
$ kubectl apply -f 007_cr_disable_pitr.yaml
- 步骤 3:准备还原规范文件,以便在删除数据库后立即还原到时间。这是我的恢复规范文件。您需要更改日期时间以匹配您的设置。
008_restore.yaml
apiVersion: pxc.percona.com/v1 kind: PerconaXtraDBClusterRestore metadata: name: restore-001 spec: pxcCluster: db-cluster backupName: backup-001 pitr: type: date date: "2022-01-09 13:36:00" backupSource: storageName: s3-vultr
- 步骤4:使用以下命令执行恢复:
$ kubectl apply -f .\008_restore.yaml
- 步骤5:运行以下命令以查看进度:
$ kubectl get pxc-restore -w
结果应类似于:
NAME CLUSTER STATUS COMPLETED AGE
restore-001 db-cluster Stopping Cluster 4s
restore-001 db-cluster Restoring 72s
restore-001 db-cluster Starting Cluster 101s
restore-001 db-cluster Point-in-time recovering 2m13s
restore-001 db-cluster Succeeded 0s 5m46s
- 步骤6:状态更改为 后,执行查询以检查数据库
Succeeded
$ kubectl run -it --rm percona-client --image=percona:8.0 -- bash $ mysql -h db-cluster-haproxy -uroot -p<root_password> mysql> show databases; mysql> select * from data.first_table;
- 步骤 7:通过将 设置为 .运行以下命令:
spec.backup.pitr.enabled
true
$ kubectl apply -f .\010_cr_enable_pitr.yaml
6.7、快速提示
™如果在运行 或 时在状态下未看到任何更改,请尝试重置 Percona 操作员 pod,如下所示:kubectl get pxc-restore
kubectl get pxc-backup
- 获取 Percona 运算符的 pod 名称
$ kubectl get pod -l app.kubernetes.io/instance=percona-xtradb-cluster-operator
- 删除容器。(将<pod_name>替换为容器名称):
$ kubectl delete pod <pod_name>
七、使用系统 bench 对您的 MySQL 服务进行基准测试
- 创建一个 Pod 来运行基准测试。将<root_password>替换为上一步中解码的密码。
sysbench
$ kubectl run -it --rm sysbench-client --image=perconalab/sysbench:latest -- bash
- 创建名为
sbtest
$ mysql -h db-cluster-haproxy -uroot -p<root_password> mysql> create database sbtest; mysql> exit;
- 准备数据表
$ sysbench oltp_read_write --mysql-user=root --mysql-password=<root_password> --db-driver=mysql --tables=10 --table-size=100000 --mysql-host=db-cluster-haproxy --mysql-port=3306 prepare
- 执行读写测试
$ sysbench oltp_read_write --mysql-user=root --mysql-password=<root_password> --db-driver=mysql --tables=10 --table-size=100000 --mysql-host=db-cluster-haproxy --mysql-port=3306 --time=30 --threads=100 run
- 执行只读测试
$ sysbench oltp_read_only --mysql-user=root --mysql-password=<root_password> --db-driver=mysql --tables=10 --table-size=100000 --mysql-host=db-cluster-haproxy --mysql-port=3306 --time=30 --threads=100 run
- 执行只写测试
$ sysbench oltp_write_only --mysql-user=root --mysql-password=<root_password> --db-driver=mysql --tables=10 --table-size=100000 --mysql-host=db-cluster-haproxy --mysql-port=3306 --time=30 --threads=100 run
- 执行选择随机点测试
$ sysbench select_random_points --mysql-user=root --mysql-password=<root_password> --db-driver=mysql --tables=10 --table-size=1000 --mysql-host=db-cluster-haproxy --mysql-port=3306 --threads=100 --rand-type=uniform --time=30 run
- 清理测试数据
$ sysbench oltp_read_write --mysql-user=root --mysql-password=<root_password> --db-driver=mysql --tables=10 --table-size=100000 --mysql-host=db-cluster-haproxy --mysql-port=3306 cleanup
八、清理
卸载本指南中的所有内容,如下所示:
- 删除集群:
$ kubectl delete -f .\010_cr_enable_pitr.yaml $ kubectl delete deployment.apps/db-cluster-pitr
- 删除 PXC 备份
$ kubectl delete pxc-backup backup-001
- 删除 PXC 还原
$ kubectl delete pxc-restore restore-001 $ kubectl delete pxc-restore restore-002
- 删除永久性卷声明
$ kubectl delete pvc datadir-db-cluster-pxc-0 $ kubectl delete pvc datadir-db-cluster-pxc-1 $ kubectl delete pvc datadir-db-cluster-pxc-2
- 删除机密
$ kubectl delete secret db-cluster-secrets $ kubectl delete secret internal-db-cluster $ kubectl delete secret vultr-s3-secret $ kubectl delete secret offsite-s3-secret
- 删除 MySQL 运算符的 Percona 发行版
$ kubectl delete -f https://raw.githubusercontent.com/percona/percona-xtradb-cluster-operator/v1.10.0/deploy/bundle.yaml
- 删除对象存储中的文件