[FAQ] 修改configmap后,使用subPath的Pod异常
Pod状态异常,挂载configmap显示no such file or directory
$ kubectl get pod -o wide
test-7695dc7fb9-rjxlq 0/1 CrashLoopBackOff 13 17h 192.168.100.20 node1 <none>
CrashLoopBackOff
状态需要查看pod的日志,通过kubectl logs
可以查看到具体的错误信息。
$ kubectl logs -n test-7695dc7fb9-rjxlq
container_linux.go:345: starting container process caused "process_linux.go:430: container init caused \"rootfs_linux.go:58: mounting \\\"/var/lib/kubelet/pods/ed1b799a-d3a5-11e9-add6-0894ef725f6e/volume-subpaths/test-cm/app-conf/1\\\" to rootfs \\\"/var/lib/docker/overlay/23a69e27f79f84a14b50fbee1e4840836487f8c740423291c2f785da1e7a6820/merged\\\" at \\\"/var/lib/docker/overlay/23a69e27f79f84a14b50fbee1e4840836487f8c740423291c2f785da1e7a6820/merged/etc/app/app.conf\\\" caused \\\"no such file or directory\\\"\""
查看日志发现是挂载的configmap有问题。
猜测原因:该pod采用subPath的方式挂载configmap,怀疑是configmap修改后,未重建pod导致,因此会出现上述no such file or directory
的错误。
排查问题
查看异常pod的uid,通过下述的命令我们可以看到当前pod在2019-09-10T08:35:21Z
的时间创建,并且uid为ed1b799a-d3a5-11e9-add6-0894ef725f6e
。
$ kubectl get pod test-7695dc7fb9-rjxlq -o json | jq .metadata
{
"creationTimestamp": "2019-09-10T08:35:21Z",
"generateName": "test-7695dc7fb9-",
"labels": {
"application": "test",
"pod-template-hash": "3251873965"
},
"name": "test-7695dc7fb9-rjxlq",
"namespace": "openstack",
"ownerReferences": [
{
"apiVersion": "apps/v1",
"blockOwnerDeletion": true,
"controller": true,
"kind": "ReplicaSet",
"name": "test-7695dc7fb9",
"uid": "ece58508-d3a5-11e9-add6-0894ef725f6e"
}
],
"resourceVersion": "1762165",
"selfLink": "/api/v1/namespaces/default/pods/test-7695dc7fb9-rjxlq",
"uid": "ed1b799a-d3a5-11e9-add6-0894ef725f6e"
}
接下来就需要登录到pod所在的节点进行查看。
查看node1
节点的kubelet工作目录下该pod的configmap保存路径,路径为/var/lib/kubelet/pods/<uid>/volumes/kubernetes.io~configmap
。
针对当前的pod该路径为/var/lib/kubelet/pods/ed1b799a-d3a5-11e9-add6-0894ef725f6e/volumes/kubernetes.io~configmap
,在这个目录下我们看到有目录为test-cm
,该目录即为需要挂载的configmap的内容。因为日志显示为test-cm
挂载有问题,因此我们进入该目录下,并查看该目录下所有文件的最后修改时间。
$ cd test-cm/
$ ll -at
total 0
drwxrwxrwx 3 root root 325 Sep 10 16:37 .
drwxr-xr-x 2 root root 272 Sep 10 16:37 ..2019_09_10_08_37_48.156264351
lrwxrwxrwx 1 root root 31 Sep 10 16:37 ..data -> ..2019_09_10_08_37_48.156264351
drwxr-xr-x 4 root root 38 Sep 10 16:35 ..
lrwxrwxrwx 1 root root 27 Sep 10 16:35 app.conf -> ..data/app.conf
我们可以看到在9.10号16:37分的时候,kubelet更新configmap到该目录下,但是容器挂载的是16:35的文件,因此符合我们的猜想,即configmap修改后,未重建整个pod,在pod里的某个容器重启新建的时候,就会有上述no such file or directory
。
但是目前环境上的问题,是pod在最开始新建的时候,状态就为CrashLoopBackOff
,因此怀疑在pod里的容器新建之前,有其他操作导致test
这个容器创建的时间在configmap更新之后。
正常的pod新建流程,会由kubelet先把configmap更新到该目录下,然后挂载到容器内,而这个时间很短,在pod第一次启动的时候应该是可以正常Running才对,因此需要进一步排查问题。
我们查看下该pod的内容,发现该pod还有initContainer的操作,我们通过下述命令发现该initContainer的处理时间为2019-09-10T08:35:31Z
到2019-09-10T08:37:47Z
。这个和我们上面看到的configmap时间与猜想是符合的,因为这个说明pod是在第一次configmap创建的时候生成,而test
这个容器是在configmap更新之后才创建,而subPath的方式挂载configmap需要在configmap更新后重建整个pod,但是目前环境没有该操作。
$ kubectl get pod test-7695dc7fb9-rjxlq -o json | jq .status.initContainerStatuses
[
{
"containerID": "docker://3aaab80f5a4b5349a1444cfb483b2877416cbe877693d62cbae78434ddd48c6f",
"image": "docker.cloud/pytimer/kubernetes-entrypoint:v0.3.1",
"imageID": "docker-pullable://docker.cloud/pytimer/kubernetes-entrypoint@sha256:2cad635d9079ee130f7f288b2ffb9c65c90fc7711364dcf438973ddf579b7fed",
"lastState": {},
"name": "init",
"ready": true,
"restartCount": 0,
"state": {
"terminated": {
"containerID": "docker://3aaab80f5a4b5349a1444cfb483b2877416cbe877693d62cbae78434ddd48c6f",
"exitCode": 0,
"finishedAt": "2019-09-10T08:37:47Z",
"reason": "Completed",
"startedAt": "2019-09-10T08:35:31Z"
}
}
}
]
通过操作日志记录,发现在16:35:15这个时间点,创建了test这个pod相关的资源,包括configmap。而在16:36:55的时候更新了configmap。我们上面看到这个异常的pod的创建时间在16:35:21,configmap最后更新的时间为16:37分(kubelet会有10s左右的时间延迟更新),因此从kubelet的相关信息和日志操作时间对比,时间点是吻合的,因此确认了该问题确实是因为更新了configmap未重建pod,而pod里的容器又是在configmap更新后新建的,因此会出现状态为CrashLoopBackOff
,并且日志为no such file or directory
。
结论
该现象的发生是由于configmap更新,但是未重建整个pod导致。