这是我参与更文挑战的第8天,活动详情查看: 更文挑战
Docker中的数据
保存docker启动容器,只要容器不被删除,其内部的文件不会消失
[root@k8s-node1 ~]# docker run -it -d victor2019/test:v1
e64c2bc31ac04174c1c78f9223e01a2cdec371104c58b74bdfc0a439913bf2d3
复制代码
之后往容器内写点东西,因为我这个测试镜像是nginx,所以写到主页面便于测试
[root@k8s-node1 ~]# docker exec e64c bash -c “echo hello > /usr/share/nginx/html/index.html”
查看一下容器的docker0网段的ip
[root@k8s-node1 ~]# docker inspect e64c | grep 172
"Gateway": "172.17.0.1",
"IPAddress": "172.17.0.2",
"Gateway": "172.17.0.1",
"IPAddress": "172.17.0.2",
复制代码
验证下写进去的内容
[root@k8s-node1 ~]# curl 172.17.0.2
hello
复制代码
然后停掉容器再启动
[root@k8s-node1 ~]# docker kill e64c
e64c
[root@k8s-node1 ~]# docker start e64c
e64c
[root@k8s-node1 ~]# curl 172.17.0.2
hello
复制代码
容器内的文件一直都还在。
所以,直接用docker起容器的话,指定–restart=always,就可以保证容器提供持续服务了。
K8s中的数据保存
但是k8s的机制不一样,每个pod都有自己完整的生命周期,即使没有被人为删除,如果pod因为其中某个容器崩溃重启,不仅pod的ip会变,里面所有容器保存的内容也会全部消失
那么有没有一种办法,可以让k8s的pod可以和docker里面的容器一样,除非是被人为删除,不然即使重启里面保存的东西一直都在。我们这一节要学习的volume就是为了解决这个问题而引入的。
需要注意,docker中也有volume的概念,不过docker中的volume是容器的内容在宿主机磁盘的持久化,即使容器删除也会一直在,和我们下一节要学习的PVC有点像,但是和这里k8s的volume是两个东西,要注意区分
k8s中的volume
volume就是一个可以被pod中所有容器使用的公共文件夹,每个容器可以将这个公共文件夹挂载到本容器内的一个目录(不同容器的目录可以不同),这样pod内容器就可以互相交换数据。volume的生命周期和pod一致,所以不管pod重启多少次volume内的内容和挂载目录都不会改变,但是如果pod被终止volume就会跟着消失。
注意这里的重启是指因为容器崩溃导致的重启,而不是手动删除pod然后因为重启策略而进行的重启
k8s支持很多种volume的类型,官方在官网中给出几十种媒介可供使用。其中的configMap和secret上一节我们已经接触过,这一节我们选其最常用的emptyDir和hostPath再来学习下。
实际操作
以下所有yaml文件托管在我的Github仓库
emptyDir操作
当一个pod被分配到node时,一个emptyDir volume首先被创建,并且其生命周期和pod一样长。正如其名字表示的那样,emptyDir一开始是空的,pod中的所有容器都可以在里面进行读写。如果pod在node上被删除,emptyDir中的数据也会被永久删除。
容器崩溃不会将pod从node上删除,而只是重启,所以emptyDir对容器崩溃来说是安全的
emptyDir通常用于声明一些临时空间,存放一些临时文件,尤其是多容器配合操作的时候。或者是容器从崩溃恢复时候的一些checkpoint。
两个配置字段在pod.spec.volumes.emptyDir中声明
字段 类型 说明
medium string 默认是空字符串表示硬盘,还可以是Memory表示内存
sizeLimit string 默认是nil表示不指定大小
通过下面这个yaml文件test-volume-emptydir.yaml来创建一个Deployment
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: test-volume-emptydir
spec:
replicas: 1
template:
metadata:
labels:
app: test-volume-emptydir
spec:
containers:
- name: mynginx
image: mynginx:v2
ports:
- containerPort: 80
volumeMounts:
- mountPath: /usr/share/nginx/html
name: test-emptydir
- name: myalpine
image: alpine
command: ["ping","8.8.8.8"]
volumeMounts:
- mountPath: /emptydir
name: test-emptydir
volumes:
- name: test-emptydir
emptyDir: {}
复制代码
其中emptyDir: {}表示用默认配置,也就是不声明大小的硬盘空间。
创建成功以后进入myalpine容器,往emptyDir绑定的目录写入文件,之后再访问另一个mynginx容器时被显示
[root@k8s-master volume]# kubectl apply -f test-volume-emptydir.yaml
deployment.extensions/test-volume-emptydir created
[root@k8s-master volume]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
test-volume-emptydir-6bf8d675fc-ds2jx 2/2 Running 0 15m 10.244.1.117 k8s-node1 <none> <none>
[root@k8s-master volume]# kubectl exec test-volume-emptydir-6bf8d675fc-ds2jx -c myalpine -it -- /bin/sh -c "echo hello emptydir > /emptydir/index.html"
[root@k8s-master volume]# curl 10.244.1.117
hello emptydir
复制代码
说明因为emptyDir的引入一个pod内的容器可以共享同一个存储卷。