问题原因

在k8s中使用nfs作为持久存储方式,根据不同环境对应不同名称空间的pod使用的存储类/存储卷 相对应,发现mysql8.0.23 在启动时挂载NFS会卡住的情况:

问题复现

这里在某台宿主机上面创建了一个本地目录,然后按照默认方式:

1
mount -t nfs   10.10.10.142:/data/bbb /tmp/cc

将nfs挂载到本地,然后映射到容器中去,所以这里跟k8s环境没多大联系,主要是nfs挂载问题:

初始化一直卡着,而且在挂载目录发现只有这个文件:

问题排查

检查一下nfs挂载的参数情况:

1
2
3
4
5
mount -v  | grep nfs

10.10.10.137:/data/nfs_share_137 on /tmp/fans type nfs (rw,relatime,vers=3,rsize=1048576,wsize=1048576,namlen=255,hard,proto=tcp,timeo=600,retrans=2,sec=sys,mountaddr=10.10.10.137,mountvers=3,mo=udp,local_lock=none,addr=10.10.10.137)

10.10.10.142:/data/bbb on /tmp/cc type nfs (rw,relatime,vers=3,rsize=1048576,wsize=1048576,namlen=255,hard,proto=tcp,timeo=600,retrans=2,sec=sys,mountaddr=10.10.10.142,mountvers=3,mountport=569lock=none,addr=10.10.10.142)

如上可以看出我们如果使用默认的方式直接挂载,它会有一些默认参数

后面也是通过该容器运行的宿主机上的内核日志才发现,这个问题:

问题处理

这个错误提示实际上是NFS客户端无法获得文件锁定,而不是无法与NFS服务器建立联系。当NFS客户端无法获得文件锁定时,它会尝试向NFS服务器发送锁定请求,并等待服务器响应。如果NFS服务器没有响应,则可能会出现类似的错误提示。可能造成这个错误的原因如下:

  1. 检查NFS服务器的负载情况,如果负载过高,则可能需要优化服务器配置或增加服务器数量。
  2. 检查NFS客户端与服务器之间的网络连接,如果存在网络故障,则可能需要修复网络问题或更改网络配置。
  3. 考虑使用NFS挂载选项来优化NFS客户端的行为,例如使用soft选项而不是hard选项,或者使用intr选项允许中断NFS操作。
  4. 如果NFS客户端和服务器在不同的时区中运行,则可能需要使用noac选项来禁用NFS客户端的属性缓存,以确保文件锁定请求和响应的时间戳是正确的。
  5. 如果您的NFS客户端和服务器运行的是不同的操作系统,则可能需要使用适当的挂载选项来确保文件锁定机制得到正确支持,例如使用nolock选项来禁用文件锁定机制。

因为我们使用了kuboard, 无法全局对这个存储类做暂时不能影响业务,不能所有变更:


这里只是单独这个mysql服务没有办法挂在使用,是由需要添加挂载参数:

找到我们在页面上新建的pv:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
 kubectl edit pv -n testnet pvc-b0de2c7f-49de-4e16-83cc-492de8292e5f



# Please edit the object below. Lines beginning with a '#' will be ignored,
# and an empty file will abort the edit. If an error occurs while saving this file will be
# reopened with the relevant failures.
#
apiVersion: v1
kind: PersistentVolume
metadata:
annotations:
pv.kubernetes.io/provisioned-by: nfs-testnet
creationTimestamp: "2023-07-20T16:29:30Z"
finalizers:
- kubernetes.io/pv-protection
name: pvc-b0de2c7f-49de-4e16-83cc-492de8292e5f
resourceVersion: "147600146"
uid: e9f111ac-2932-46a0-b6bc-876275dfa02f
spec:
accessModes:
- ReadWriteOnce
capacity:
storage: 2G
claimRef:
apiVersion: v1
kind: PersistentVolumeClaim
name: dassssssssssssssss
namespace: testnet
resourceVersion: "147600141"
uid: b0de2c7f-49de-4e16-83cc-492de8292e5f
nfs:
path: /data/testnet-dassssssssssssssss-pvc-b0de2c7f-49de-4e16-83cc-492de8292e5f
server: 10.10.10.142
persistentVolumeReclaimPolicy: Retain
storageClassName: testnet
volumeMode: Filesystem
status:
phase: Bound

然后我们在volumeMode同级 就可以定义挂载参数(具体参数:https://poe.com/s/FyTCOkthr3VREHU3mByA):

1
2
3
4
5
mountOptions:
- nolock
- timeo=120
- intr
- retrans=10

这样我们单独为MySQL服务创建的这个pvc就拥有了这些挂载参数,初始化,运行正常:

在这个pod运行的宿主机上 查看结果,可以看到我们修改pv后的参数已经生效,并且在nfs服务端可以看到我们的MySQL初始化文件已经生成:


最终该挂载问题完美解决。

对于特殊,不同的deployment 可能需要特殊处理,这里按照mysql的部署,记录一下顺序

  1. 创建pvc
  2. 修改默认pvc配置,增加nfs挂载参数
  3. 启动pod
  4. 检查挂载目录数据是否正常生成
  5. 检查挂载选项是否已经增加

By the way:
谁说的K8S不能跑MySQL, 我嫩死TA 🔪🔪🔪