背景:使用dockerhub官方的mongodb 3.6部署了3副本的workload,但是每次重启pod,都会发现原本该pod写入持久卷的数据丢失,经过排查,找到了问题所在。
问题复现
用户使用如下yaml文件创建了workload
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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
|
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: mongo
namespace: default
spec:
podManagementPolicy: OrderedReady
replicas: 3
revisionHistoryLimit: 10
selector:
matchLabels:
k8s-app: mongo
serviceName: mongo
template:
metadata:
labels:
k8s-app: mongo
spec:
containers:
- command:
- mongod
- --bind_ip
- 0.0.0.0
- --replSet
- config
- --configsvr
image: mongo:3.6
imagePullPolicy: IfNotPresent
name: mongo
resources: {}
securityContext:
privileged: false
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
volumeMounts:
- mountPath: /data
name: mongo-pvc
dnsPolicy: ClusterFirst
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
terminationGracePeriodSeconds: 30
updateStrategy:
rollingUpdate:
partition: 0
type: RollingUpdate
volumeClaimTemplates:
- apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mongo-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
storageClassName: cbs
volumeMode: Filesystem
|
因根据dockerhub页面所描述,默认存放db数据的路径为/data/db:
故将数据卷挂载至pod内的/data目录看似并无问题,创建后也正常启动,并写入数据,一切看似都再正常不过。
但是当pod发生重启后,pod内的数据就会全部丢失。
原因分析
通过findmnt
命令查询,发现/data/db
和/data/configdb
并未出现在所挂载pvc对应的/data
下,而是被挂载至了/dev/vda1
这就是问题的关键了,那么是什么原因造成此问题的呢?
通过docker history --no-trunc mongo:3.6
查看镜像的构建历史发现,此dockerfile在构建时有使用VOLUME命令,手工挂载了/data/db
和/data/configdb
dockerfile构建后的镜像中,VOLUME中的操作并不会被kubernetes忽略,而是会继续挂载,如需要将其覆盖,必须要手工指定pvc的挂载点同名,将其覆盖,类似这样
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
spec:
template:
spec:
volumeMounts:
- mountPath: /data/db
name: mongo-pvc
volumeClaimTemplates:
- apiVersion: v1
kind: PersistentVolumeClaim
metadata:
creationTimestamp: null
name: mongo-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
storageClassName: cbs
volumeMode: Filesystem
|
调整挂载点为/data/db
和/data/configdb
后,再次测试,数据丢失的问题已经消失。
问题反思
为什么之前通过df -h命令,并没有看到/data/db和/data/configdb呢?而只有/data?
在这里,我们还发现了一个看似奇怪的挂载点/etc/hosts
经查询,此为引用了docker中的bind-mount特性,结合了multimount,所以,他的真实情况是这样的:
每一行有多个数据,其中TARGET和SOURCE是我们这次需要关注的,正是这里的multimount,导致了此前被我们忽略的问题
参考文档
What is the meaning of mounting /dev/sda1 to /etc/hosts in Docker container
Use bind mounts