[Workshops]K3s–mysql+nfs持久存储

k3s部署项目也需要进行持久化存储。但是不希望在节点上进行localpath 的存储。不大优雅且和节点有强相关不利于HA的设计。

所以就需要使用 nfs 的方式来进行持久化的存储。 这里我使用群晖来提供nfs服务偷个懒。使用自建的nfs server 也是可以的。

Workshops

节点准备

需要先在节点上安装nfs-common来提供nfs 的客户端从而有挂载的能力

sudo apt install nfs-common

存储准备

在存储的管理上有两种方法,一个是安装 CSI 使用 NFS 的存储类来进行NFS 的持久化管理。还有一个一种是NFS类型的PV来实现。两种都可以实现NFS挂载为POD 的持久卷。但是第一个种方式对NFS 进行了抽象。不需要在进行更多的配置以及额外的管理。把存储层更加抽象也更符合我们的K8S的思想。这里两种部署的方式都记录一下。

使用存储类(Storagecalss)来进行持久化管理

NFS 的CSI 驱动安装

安装过程十分的简单,参考下面的指引文档

Install NFS CSI driver v4.5.0 version on a kubernetes cluster

直接使用 yaml apply 来进行安装,

curl -skSL https://raw.githubusercontent.com/kubernetes-csi/csi-driver-nfs/v4.5.0/deploy/install-driver.sh | bash -s v4.5.0 --
######
kubectl -n kube-system get pod -o wide -l app=csi-nfs-controller
kubectl -n kube-system get pod -o wide -l app=csi-nfs-node
NAME                                 READY   STATUS    RESTARTS      AGE     IP             NODE           NOMINATED NODE   READINESS GATES
csi-nfs-controller-6f5f9cb8f-7n974   4/4     Running   12 (9h ago)   4d10h   192.168.3.10   k3s-worker-0   <none>           <none>
NAME                 READY   STATUS    RESTARTS     AGE     IP             NODE           NOMINATED NODE   READINESS GATES
csi-nfs-node-bz8gl   3/3     Running   0            4d10h   192.168.3.9    k3s-master     <none>           <none>
csi-nfs-node-xh2pm   3/3     Running   6 (9h ago)   4d10h   192.168.3.10   k3s-worker-0   <none>           <none>

这里应该算是K8s系统的优雅之处的体现了。应用软件甚至系统功能就可以通过 配置文件来进行管理。

Storage Class 注册

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: nfs-csi
provisioner: nfs.csi.k8s.io
parameters:
  onDelete: retain
  share: /volume1/vm_nfs
  server: nas-vm.local
reclaimPolicy: Delete
volumeBindingMode: Immediate
mountOptions:
  - nfsvers=4

声明PVC

---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mysql-nfs-pvc
  namespace: database-common
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi
  storageClassName: nas-nfs
  volumeMode: Filesystem

使用NFS PVC 来直接使用

PV是支持Nfs类型的,所以也可以直接在PV里面来对Nfs 的连接选项来进行配置。这样的方式需要自己手动的对NFS 的目录来进行管理。整体性上不如上面。但是也是一个可用的方法。

apiVersion: v1
kind: PersistentVolume
metadata:
  name: mysql-pv
spec:
  accessModes:
    - ReadWriteOnce
  capacity:
    storage: 10Gi
  nfs:
    path: /volume1/vm_nfs/data0/
    server: nas-vm.local
  persistentVolumeReclaimPolicy: Retain
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  namespace: database-common
  name: mysql-pvc
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi
  volumeName: mysql-pv
  storageClassName: vm-nfs

ConfigMaps 配置

使用Config来进行Mysql 的配置管理,可以方便配置的变更。下面是 mysql.cnf 文件中的内容。

[mysqld]
skip_name_resolve
character-set-server=utf8mb4
collation-server=utf8mb4_general_ci

[client]
default-character-set=utf8mb4

写入Secret文件,

echo -n MYSQL_ROOT_PASSWORD > mysql-root-password.txt

创建Configmaps

kubectl create -n database-common secret generic mysql-root-password --from-file=password=./mysql-root-password.txt
kubectl create -n database-common configmap mysql-config --from-file=./mysql.cnf 

StatefulSet 工作负载部署

有了前面的资源铺垫,后面的mysql的部署就比较简单了,通过statefulset模板来创建mysql。

其中三个地方的挂载

  1. secret 挂载mysql 初始化的root密码
  2. 第二个是我们的nfs pvc 用来存储mysql 的DB文件
  3. 第三个是公开的configmap 的配置
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  namespace: database-common
  name: mysql
spec:
  serviceName: mysql
  replicas: 1
  selector:
    matchLabels:
      app: mysql
  updateStrategy:
    type: RollingUpdate
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
        - name: mysql
          image: mysql:8
          env:
            - name: MYSQL_ROOT_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: mysql-root-password
                  key: password
          ports:
            - containerPort: 3306
          livenessProbe:
            exec:
              command: ["mysqladmin", "ping"]
          volumeMounts:
            - name: mysql-pvc
              mountPath: /var/lib/mysql
            - name: mysql-conf
              mountPath: /etc/mysql/conf.d
      securityContext:
        runAsUser: 1000
        fsGroup: 1000
      volumes:
        - name: mysql-pvc
          persistentVolumeClaim:
            claimName: mysql-nfs-pvc
        - name: mysql-conf
          configMap:
            name: mysql-config

这里有一点需要注意的是,securityContext 这里的配置,强制指定了容器中的mysql进程的用户ID。否在在读写nfs时候有权限问题。

服务端口暴露

这里就不过多讲解了,使用一个 Nodeport的service 来对mysql 的服务进行暴露,这样我们就可以直接使用 节点的IP来进行mysql 的连接和管理。

---
apiVersion: v1
kind: Service
metadata:
  name: mysql
  namespace: database-common
  labels:
    app: mysql
spec:
  type: NodePort
  ports:
    - port: 3306
      protocol: TCP
  selector:
    app: mysql

通过这个Workshop 搞懂了PVC/PV 和 StorageClass 之间的设计关系。通过StorageClass 来对基础的存储过程进行抽象,的确是其设计的精妙之处。

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注