前
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。
其中三个地方的挂载
- secret 挂载mysql 初始化的root密码
- 第二个是我们的nfs pvc 用来存储mysql 的DB文件
- 第三个是公开的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 来对基础的存储过程进行抽象,的确是其设计的精妙之处。