作者 | 江小南
来源 | 江小南和他的小伙伴们
引言
前两天,公司有个同事跑过来问我一件事:我在制作镜像的时候明明把文件已经放到镜像里面去了,为什么kubernetes部署应用的时候文件没有了?听完这话,我看了看Dockerfile是这么写的(不是原文内容,但是意思一样)。
FROM nginx
MAINTAINER jiangxiaonan<xxc113206@163.com>
ENV MYPATH /usr/local
ADD test.tar /nfs/data/01
WORKDIR $MYPATH
EXPOSE 80
CMD /bin/bash
通过Dockerfile可以看出,它是把本地的test.tar包复制并解压到了容器的/nfs/data/01
。确实写的没毛病,本地也有相应的tar包。
[root@k8s-master test]# pwd
/root/test
[root@k8s-master test]# ll
total 28
-rw-r--r-- 1 root root 587 Jul 9 18:06 deployment.yaml
-rw-r--r-- 1 root root 142 Jul 9 17:41 Dockerfile
-rw-r--r-- 1 root root 0 Jul 9 16:25 file1.txt
-rw-r--r-- 1 root root 0 Jul 9 16:25 file2.txt
-rw-r--r-- 1 root root 184 Jul 9 16:54 pvc.yaml
-rw-r--r-- 1 root root 212 Jul 9 16:53 pv.yaml
-rw-r--r-- 1 root root 10240 Jul 9 16:26 test.tar
[root@k8s-master test]#
那问题出在了哪里呢?看了一眼yaml,我说你把挂载去掉吧。他去掉挂载重新测试,文件有了。给他讲解了一番,同事连连拍手叫好。
为什么挂载了存储,文件就没有了,而去掉挂载文件又有了?今天就将关于挂载存储的这个小细节讲解给大家。
环境准备
首先我们需要有kubernetes集群。
[root@k8s-master ~]# kubectl get node
NAME STATUS ROLES AGE VERSION
k8s-master Ready control-plane,master 3m52s v1.20.9
k8s-worker1 Ready <none> 2m8s v1.20.9
k8s-worker2 Ready <none> 2m3s v1.20.9
[root@k8s-master ~]#
并且安装了存储,我这里使用NFS文件系统。
[root@k8s-master ~]# exportfs
/nfs/data <world>
[root@k8s-master ~]#
使用上面的Dockerfile制作好镜像。(有Harbor仓库的话也可以使用,如果没有,需要在每个节点制作镜像,防止拉取镜像失败的情况。)
docker build -f ./Dockerfile -t mynginx:1.0 .
由于我们使用的是PV&PVC,所以这里也进行了创建。
# pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:name: pv01-10m
spec:capacity:storage: 1GiaccessModes:- ReadWriteManystorageClassName: nfsnfs:path: /nfs/data/01server: 172.31.0.2
# pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:name: nginx-pvc
spec:accessModes:- ReadWriteManyresources:requests:storage: 500MistorageClassName: nfs
[root@k8s-master test]# kubectl get pv,pvc
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
persistentvolume/pv01-10m 1Gi RWX Retain Bound default/nginx-pvc nfs 13sNAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
persistentvolumeclaim/nginx-pvc Bound pv01-10m 1Gi RWX nfs 7s
[root@k8s-master test]#
测试
有挂载的情况
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:labels:app: nginx-deployname: nginx-deploy
spec:replicas: 2selector:matchLabels:app: nginx-deploytemplate:metadata:labels:app: nginx-deployspec:containers:- image: mynginx:1.0imagePullPolicy: Nevercommand: [ "/bin/bash", "-ce", "tail -f /dev/null" ]name: mynginxvolumeMounts:- name: testmountPath: /nfs/data/01volumes:- name: testpersistentVolumeClaim:claimName: nginx-pvc
通过yaml可以看出,将容器的/nfs/data/01
目录进行了挂载。
[root@k8s-master test]# kubectl apply -f deployment.yaml
deployment.apps/nginx-deploy created
[root@k8s-master test]# kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx-deploy-86477c464b-x5jkd 1/1 Running 0 4s
nginx-deploy-86477c464b-xzqsx 1/1 Running 0 4s
[root@k8s-master test]#
# 成功部署了2个pod,我们进入到pod中一探究竟。
[root@k8s-master test]# kubectl exec -it nginx-deploy-86477c464b-x5jkd -c mynginx -- /bin/bash
root@nginx-deploy-86477c464b-x5jkd:/usr/local# cd /nfs/data/01
root@nginx-deploy-86477c464b-x5jkd:/nfs/data/01# ls
root@nginx-deploy-86477c464b-x5jkd:/nfs/data/01#
按照Dockerfile的编写,/nfs/data/01下应该会有file1.txt和file2.txt两个文件才对,现在并没有。
why?
没有挂载的情况。
修改我们的yaml,将挂载去掉。
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:labels:app: nginx-deployname: nginx-deploy
spec:replicas: 2selector:matchLabels:app: nginx-deploytemplate:metadata:labels:app: nginx-deployspec:containers:- image: mynginx:1.0imagePullPolicy: Nevercommand: [ "/bin/bash", "-ce", "tail -f /dev/null" ]name: mynginx
[root@k8s-master test]# kubectl apply -f deployment.yaml
deployment.apps/nginx-deploy created
[root@k8s-master test]# kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx-deploy-67cd67ff86-dbdbp 1/1 Running 0 5s
nginx-deploy-67cd67ff86-w4wgx 1/1 Running 0 5s
[root@k8s-master test]#
# 成功部署了2个pod,我们进入到pod中一探究竟。
[root@k8s-master test]# kubectl exec -it nginx-deploy-67cd67ff86-dbdbp -c mynginx -- /bin/bash
root@nginx-deploy-67cd67ff86-dbdbp:/usr/local# cd /nfs/data/01
root@nginx-deploy-67cd67ff86-dbdbp:/nfs/data/01# ls
file1.txt file2.txt
root@nginx-deploy-67cd67ff86-dbdbp:/nfs/data/01#
确实在没有挂载的情况下有了file1.txt和file2.txt。
探究
为了搞清楚这个问题,我们去NFS文件系统中寻找答案。
[root@k8s-master 01]# pwd
/nfs/data/01
[root@k8s-master 01]# ls
[root@k8s-master 01]#
发现文件系统的/nfs/data/01
也是空的。这时我们创建文件nfs.txt。
[root@k8s-master 01]# touch nfs.txt
[root@k8s-master 01]# ls
nfs.txt
[root@k8s-master 01]#
然后使用有挂载的deployment.yaml进行测试。
[root@k8s-master test]# kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx-deploy-86477c464b-5mhw4 1/1 Running 0 23s
nginx-deploy-86477c464b-wxc8q 1/1 Running 0 21s
[root@k8s-master test]#
# 成功部署了2个pod,我们进入到pod中一探究竟。
[root@k8s-master test]# kubectl exec -it nginx-deploy-86477c464b-5mhw4 -c mynginx -- /bin/bash
root@nginx-deploy-86477c464b-5mhw4:/usr/local# cd /nfs/data/01
root@nginx-deploy-86477c464b-5mhw4:/nfs/data/01# ls
nfs.txt
root@nginx-deploy-86477c464b-5mhw4:/nfs/data/01#
发现我们在NFS中创建的文件被同步到了pod中。而file1.txt和file2.txt并没有出现。
分析总结
我们知道NFS作为持久化的存储,会和容器内的挂载目录进行同步。NFS本身存在的文件会在pod中显示,镜像本身存在的文件却不能显示。
一个容器挂载了存储,那么这个目录空间并不属于容器,而是属于存储,容器的目录相当于是对存储空间的引用。
搞清楚了这一点,对于同事的问题就很好解释了,file1.txt和file2.txt存在于容器中,而不存在于存储中,挂载部署的情况下当然是看不到的了,除非这两个文件先在存储中。
往期推荐
Redis 内存优化神技,小内存保存大数据
使用 nginx 轻松管理 kubernetes 资源文件
Redis 内存满了怎么办?这样置才正确!
实战 Kubectl 创建 Deployment 部署应用
点分享
点收藏
点点赞
点在看