前置准备

首先配置好K8S,并能保证节点之间的通信,可能需要配置网络插件,例如flannel,确保单机跑多副本的nginx是没问题的。

flannel

总共大约4步:

  1. 配置NFS
  2. helm更换镜像

配置NFS

1
2
3
4
5
6
> sudo apt update && sudo apt install nfs-kernel-server -y
> sudo mkdir -p /mnt/nfs_share # 自定义你要共享的目录
> sudo chown nobody:nogroup /mnt/nfs_share && sudo chmod 777 /mnt/nfs_share # 设置权限
> vim /etc/exports # 编辑配置,添加在文件最后添加 /mnt/nfs_share *(rw,sync,no_subtree_check)
> sudo exportfs -a # 导出配置
> sudo systemctl restart nfs-kernel-server # 重启NFS服务

可以在另一台服务器上测试一下

1
2
3
4
5
6
7
8
9
> sudo apt install nfs-common -y # 安装nfs-common
> showmount -e <NFS_SERVER_IP> # 查看NFS服务器导出的目录
Export list for <NFS_SERVER_IP>:
/mnt/nfs_share *

> sudo mkdir -p /mnt/test_nfs # 在另一台服务器上创建挂载点
> sudo mount -t nfs <NFS_SERVER_IP>:<NFS_SHARE_PATH> /mnt/test_nfs
> sudo mount -t nfs 192.168.71.90:/mnt/nfs_share /mnt/test_nfs # 示例
> df -h /mnt/test_nfs # 查看挂载点内容

image-20250609204429139

然后在/mnt/test_nfs下创建文件、增删内容,在NFS服务器上的目录也会有响应的更改

测试完成后可以卸载NFS共享:sudo umount /mnt/test_nfs

安装nfs-subdir-external-provisioner

nfs-subdir-external-provisioner看起来名字很长,实际上它是用于:根据已有的NFS目录,自动响应PVC请求并动态提供PV。它是开源的项目,官方仓库见:https://github.com/kubernetes-sigs/nfs-subdir-external-provisioner,可以直接用helm安装

1
2
3
4
5
6
7
> helm install nfs-subdir-external-provisioner nfs-subdir-external-provisioner/nfs-subdir-external-provisioner \
--set nfs.server=<YOUR_NFS_SERVER_IP> \
--set nfs.path=<YOUR_NFS_SHARE_PATH> \
--set storageClass.name=nfs-client \
--set storageClass.defaultClass=false \
--namespace kube-system \
--create-namespace

如果网络错误,可以先把包给拉下来:

1
wget https://github.com/kubernetes-sigs/nfs-subdir-external-provisioner/releases/download/nfs-subdir-external-provisioner-4.0.18/nfs-subdir-external-provisioner-4.0.18.tgz

然后把helm install <YOUR_NAME> <YOUR_PATH_TO_PACKAGE>中的PATH改成包文件的路径。

但是这样可能会遇到,在生成的pod中,拉取镜像失败的情况:因为K8S集群是将任务分配给pod,而后pod自行进行pull的

image-20250609205159854

不过在helm安装的时候可以设置镜像,例如https://docker.aityp.com/image/registry.k8s.io/sig-storage/nfs-subdir-external-provisioner:v4.0.2,如下所示

1
helm install nfs-subdir-external-provisioner /home/liuchang/Downloads/nfs-subdir-external-provisioner-4.0.18.tgz   --set nfs.server=192.168.71.90   --set nfs.path=/mnt/nfs_share   --set storageClass.name=nfs-client   --set storageClass.defaultClass=false   --namespace kube-system   --create-namespace   --set image.repository=swr.cn-north-4.myhuaweicloud.com/ddn-k8s/registry.k8s.io/sig-storage/nfs-subdir-external-provisioner   --set image.tag=v4.0.2

上边的命令中,设置了storageClass.name为nfs-client,因此可以在K8S中查看该服务

image-20250609205507824

想带镜像地启动nfs-subdir-external-provisioner的话,得先把原来的给删了,helm uninstall直接就行,加-n用于指定namespace,因为这个服务会在kube-system的namespace中,可以通过kubectl get ns查看所有namespace

image-20250609205903123

#启动主从复制MySQL

helm直接启动,不过可以先把.tgz文件pull下来

1
2
> helm pull oci://registry-1.docker.io/bitnamicharts/mysql --version 12.2.2
> helm install mysql-cluster /root/Downloads/mysql-12.2.2.tgz --set global.storageClass=nfs-client --set architecture=replication --set secondary.replicaCount=2

如果pull不到,可以通过设置网络代理,例如经典的clash

1
2
export https_proxy=http://127.0.0.1:7890
export http_proxy=http://127.0.0.1:7890

但此时的mysql无法被外网访问,需要在helm启动时添加--set primary.service.type=NodePort

不过也不用删了再装,可以用helm upgrade方法,如下所示:

1
helm upgrade mysql-cluster /root/Downloads/mysql-12.2.2.tgz --set global.storageClass=nfs-client --set architecture=replication --set secondary.replicaCount=2 --set primary.service.type=NodePort

验证主从复制

记得用helm安装成功后的这条命令先获取MySQL的root密码:

1
MYSQL_ROOT_PASSWORD=$(kubectl get secret --namespace default mysql-cluster -o jsonpath="{.data.mysql-root-password}" | base64 -d)

image-20250609211618293

执行kubectl get all |grep mysql可以看到primary的service时NodePort类型,pod的3306被映射到32765去了,因此可以通过访问主机的32765来访问MySQL

image-20250609211249911

从datagrip连接进去,直接执行个sql脚本,然后exec到副本secondary的pod,然后再用密码登录进MySQL

image-20250609211646850

这时候随便执行个select语句,你就会发现从MySQL已经从主MySQL中复制了东西过来。

Redis

只要有了nfs-client,Redis和MySQL基本没什么区别,借助ai很容易配置出来。

1
helm install redis-cluster oci://registry-1.docker.io/bitnamicharts/redis --set global.storageClass=nfs-client --set master.service.type=NodePort

上述命令安装的不是redis集群,而是个哨兵模式的redis;不过redis集群再helm中也有提供,以后有时间再尝试了