kubernetes创建的pod默认都是无状态的,换句话说删除以后不会保留任何数据。
所以对于mysql这种有状态的应用,必须使用持久化存储作为支撑,才能部署成有状态的stateful.
最简单的方法就是使用nfs作为网络存储,因为nfs存储很容易被所有节点所共享。
首先安装nfs
安装nfs非常简单。一条命令就可以完成
yum install nfs-utils
nfs-utils必须在所有节点都安装,因为除了nfs-server, 其他node节点需要nfs客户端才能访问nfs存储。
然后创建nfs共享的目录,比如/nfs-mysql
mkdir /nfs-mysql
接着配置/etc/exports把上面的目录写进去, vim /etc/exports
/nfs-mysql 192.168.10.0/24(rw,no_root_squash)
备注:
192.168.10.0/24表示nfs存储共享的ip段,
rw表示可读写,
no_root_squash表示允许nfs客户端保留跟它原来客户端主机上一样的身份权限,这么说有点拗口,简单说:就是nfs客户端可以通过chown命令切换/nfs-mysql目录的身份和权限
为什么要这样设置: 因为nfs默认会将nfs客户端的身份映射为匿名用户,这样一来像mysql一旦chown切换身份就会失败。
man exports就可以看到root_squash和no_root_squash的作用
然后启动nfs-server,这样nfs存储就搞好了
systemctl start nfs-server
nfs增加共享资源,使其生效的命令是:
exportfs -fr
nfs客户端通过showmount -e ${nfs服务器ip} 就可以查看到远程nfs服务器共享的资源:
然后下面讲重点,怎么利用nfs创建pvc存储。
首先第一步创建pv存储卷:
# 创建pv存储卷apiVersion: v1
kind: PersistentVolume
metadata:
name: nfs-pv-mysql
spec:
capacity:
storage: 1Gi
volumeMode: Filesystem
accessModes:
- ReadWriteMany
persistentVolumeReclaimPolicy: Retain
storageClassName: "nfs-mysql"
nfs:
path: /nfs-mysql # nfs服务器上定义的挂载地址, 也就是/etc/exports里面定义的
server: 192.168.10.20 # nfs服务器的地址
第二步: 向上面创建的pv存储卷申请存储空间
# 向pv申请空间
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: nfs-pvc-mysql # 这个pvc的名称就是后面stateful要使用到的,非常重要
spec:
accessModes:
- ReadWriteMany
storageClassName: "nfs-mysql"
resources:
requests:
storage: 1Gi
注意: 上面两个storageClassName的值必须是一样的。
然后pv和pvc就创建好了。
上面pvc状态显示Bound,表示pvc跟pv已经绑定成功。
你可以理解为pv就是一个存储池, 而pvc就是从里面拿出来的存储资源
mysql就是使用这个创建好的pvc来做持久化存储的。
kind: StatefulSet
apiVersion: apps/v1
metadata:
name: mysql-db-deploy
namespace: default
labels:
k8s-app: mysql-db-app
spec:
replicas: 1
serviceName: mysql-db-app-service #此字段必须有,stateful规定的
selector:
matchLabels:
k8s-app: mysql-db-app
template:
metadata:
labels:
k8s-app: mysql-db-app
name: mysql-db-app
spec:
containers:
- image: registry.myharbor.com/library/mysql:5.7
name: mysql-db-app
ports:
- name: admin
containerPort: 3306
env:
- name: MYSQL_ROOT_PASSWORD
value: "123456"
volumeMounts:
- name: data-pv
mountPath: /var/lib/mysqlvolumes:
- name: data-pv
persistentVolumeClaim:
claimName: nfs-pvc-mysql # 使用已存在的 PVC 的名称---
kind: Service
apiVersion: v1
metadata:
name: mysql-db-svc
namespace: default
spec:
selector:
k8s-app: mysql-db-app
ports:
- protocol: TCP
port: 3306
name: admin
nodePort: 30306
type: NodePort
重点在我标红的地方: 主要就是volumeMounts和volumes配置这两个地方
claimName的值就是上面已经创建好的pvc的名字
volumeMounts选项是containers二级子配置
volumes跟containers字段是同级关系
serviceName字段必须有
这样mysql stateful就配好了,你可以测试一下: 就是删除了mysql pod,然后重新自动创建mysql pod, mysql的数据也不会丢失, 这就是stateful的作用
注意点:
1. 创建pv时,nfs下path必须是提前存在的,而且是远程nfs设置的挂载路径
否则会报错:
mounting xxx:/nfs_share failed, reason given by server: No such file or directory
2. mysql stateful配置中volumes.persistentVolumeClaim.claimName字段的值必须是已创建pvc的名称,不能是pv的名称, 否则会报错: MountVolume.SetUp failed for volume "nfs-pv" : mount failed
3. nfs exports中的配置必须要有no_root_squash选项,否则创建mysql pod就会报错:
chown: changing ownership of '/var/lib/mysql/': Operation not permitted
4. mysql所使用的pvc的挂载目录必须是空的,否则mysql pod会报错:
[ERROR] --initialize specified but the data directory has files in it. Aborting.