2020-03-28 Kubernetes—volume (上)

说起存储卷和docker的存储卷有几分相似的地方,数据不会跟随Pod的停止或删除而消失,从而实现数据的持久性,但是由于K8s的独特,K8s面对的是集群,如果要实现数据的持久性,Pod会分布到各个节点之上,所以引入了外部存储卷。

① · 常见的存储卷类型有:

  • emptyDir :当Pod生命周期结束后,存储卷会被一并删除,这种通常会存放一些临时数据。
  • hostPath:宿主机目录映射
  • 本地的SAN(iSCSI,FC)、NAS(nfs,cifs,http)存储
  • 分布式存储(glusterfs,rbd,cephfs)
  • 云存储(EBS,Azure Disk)
    种类繁多的存储无疑会提高K8s的使用门槛,这意味着你不仅要懂K8s还要懂存储的结构、用法、参数、使用场景等等等...
    所以K8s又引入了一个概念叫做PVC 全称 persistentVolumeClaim -->PVC(存储卷创建申请)
    当你需要一个存储空间的时候,只要进行对应的申请即可,灵魂图: ↓
image.png

在Pod 上定义一个PVC,但该PVC只是一个申请,他需要和PV进行关联,PV是属于存储设备上的一部分空间,so申请之前我们应该创建好对应大小的pv等待使用,那么就造成了每次用户需要存储卷的时候都要想K8s的管理员申请,等管理员建立好他才能进行PVC的申请,这听起来比较麻烦,于是又有了另一个方案。

image.png

不要pv层,把所有存储资源抽象成一个存储类,当用户申请PVC到达存储类的时候,会根据申请大小,自动创建出相应的存储空间,实现动态供给。

emptydir类型示例:

emptydir具体操作步骤: ↓
① · 在Pod层定义volume,并指明关联到哪个存储设备
② · 在容器中层使用 volume mount 进行挂载
emptydir:
是一个临时的空目录,在pod之上的每个容器都可以挂载到相同或不同的目录上,并且共享里面的内容,当Pod因为任何原因被删除时,存储卷会被一并删除,无法保留数据。但是容器崩溃的时候,不会影响数据,因为一个容器崩溃不会导致Pod被删除。
默认情况下emptydir是一个普通磁盘提供的存储空间,但是也可以定义为memory,意为使用node的内存来提供存储功能,因为内存性能强大,但是要注意当node重启的时候,内存内的数据会丢失,emptydir的数据也会随之消失。
清单示例:

apiVersion: v1
kind: Pod
metadata: 
  name: Pod-demo
  namespace: default
  labels:
    app: myapp
    tier: frontend
spec:
  containers:
  - name: myapp
    image: ikubernetes/myapp:v1
    imagePullPolicy: IfNotPresent
    ports:
    - name: http
      containerPort: 80
    volumeMounts:
    - name: html
      mountPath: /usr/share/nginx/html/
  - name: busybox
    image: busybox:latest
    imagePullPolicy: IfNotPresent
    volumeMounts:
    - name: html
      mountPath: /data/
    command: ['/bin/sh','-c','while true;do echo $(date) >> /data/index.html;sleep 2;done']
  volumes:
  - name: html
    emptydir: {}
  

上述清单定义了一个类型为emptydir的存储卷,并且创建了两个容器共同挂载,由后端的busybox不停的向目录中注入内容,通过从前端访问显示内容,实现两个容器之间的存储共享。

[root@k8s-master volumes]# kubectl apply -f pod-vol-demo.yaml 
pod/pod-vol-demo created 
[root@k8s-master volumes]# kubectl get pods
NAME                                 READY     STATUS    RESTARTS   AGE
pod-vol-demo                         2/2       Running   0          27s
[root@k8s-master volumes]# kubectl get pods -o wide
NAME                      READY     STATUS    RESTARTS   AGE       IP            NODE
......
pod-vol-demo              2/2       Running   0          16s       10.244.2.34   k8s-node02
......

[root@k8s-master volumes]# curl 10.244.2.34  #访问验证
Tue Oct 9 03:56:53 UTC 2018
Tue Oct 9 03:56:55 UTC 2018
Tue Oct 9 03:56:57 UTC 2018
Tue Oct 9 03:56:59 UTC 2018
Tue Oct 9 03:57:01 UTC 2018
Tue Oct 9 03:57:03 UTC 2018
Tue Oct 9 03:57:05 UTC 2018
Tue Oct 9 03:57:07 UTC 2018
Tue Oct 9 03:57:09 UTC 2018
Tue Oct 9 03:57:11 UTC 2018
Tue Oct 9 03:57:13 UTC 2018
Tue Oct 9 03:57:15 UTC 2018

另外一种比较特殊类型的存储类型叫做gitrepo,就是利用github仓库作为外部持久存储,但是他的基础仍然是emptydir来实现的,并且要确保node之上有Git工具,因为这是通过node 来驱动的git,具体实现方式就是通过sidecar容器将gitrepo clone到容器上,然后不停的往GitHub之上push数据来实现。

hostPath类型示例:

hostPath是将宿主机上的某个目录与Pod中的容器建立关联关系,数据不属于container,所以当Pod生命周期结束的时候,数据不会丢失。但是当node节点发生故障的时候,数据也会丢失。

apiVersion: v1
kind: Pod
metadata:
  name: pod-hostPath
  namespace: default
spec:
  containers:
  - name: myapp
    image: ikubernetes/myapp:v1
    imagePullPolicy: IfNotPresent
    volumeMonts: 
    - name: html
      mountPath: /usr/share/nginx/html
  volumes:
  - name: html
    hostPath:
      path: /data/pod/volume1
      type: DirectoryOrCreate

# type:
#DirectoryOrCreate  宿主机上不存在创建此目录  
#Directory 必须存在挂载目录  
#FileOrCreate 宿主机上不存在挂载文件就创建  
#File 必须存在文件  

在node节点上创建挂载目录
[root@k8s-node01 ~]# mkdir -p /data/pod/volume1
[root@k8s-node01 ~]# vim /data/pod/volume1/index.html
node01.magedu.com
[root@k8s-node02 ~]# mkdir -p /data/pod/volume1
[root@k8s-node02 ~]# vim /data/pod/volume1/index.html
node02.magedu.com
[root@k8s-master volumes]# kubectl apply -f pod-hostpath-vol.yaml 
pod/pod-vol-hostpath created

(4)访问测试
[root@k8s-master volumes]# kubectl get pods -o wide
NAME                                 READY     STATUS    RESTARTS   AGE       IP            NODE
......
pod-vol-hostpath                     1/1       Running   0          37s       10.244.2.35   k8s-node02
......
[root@k8s-master volumes]# curl 10.244.2.35
node02.magedu.com
[root@k8s-master volumes]# kubectl delete -f pod-hostpath-vol.yaml  #删除pod,再重建,验证是否依旧可以访问原来的内容
[root@k8s-master volumes]# kubectl apply -f pod-hostpath-vol.yaml 
pod/pod-vol-hostpath created
[root@k8s-master volumes]# curl  10.244.2.37 
node02.magedu.com

NFS类型示例:

NFS挂载是在其中一个node之上将共享的目录发布出来,并且在各个node之上都安装好nfs-utils工具,只要在创建Pod的时候指定要挂载的文件系统为nfs,和挂载点、权限即可自动完成挂载操作,并且能实现数据同步。
在创建Pod之前要做好nfs的配置

在stor01节点上安装nfs,并配置nfs服务
[root@stor01 ~]# yum install -y nfs-utils                 ##  192.168.56.14
[root@stor01 ~]# mkdir /data/volumes -pv
[root@stor01 ~]# vim /etc/exports
/data/volumes 192.168.56.0/24(rw,no_root_squash)
[root@stor01 ~]# systemctl start nfs
[root@stor01 ~]# showmount -e
Export list for stor01:
/data/volumes 192.168.56.0/24
在node2上测试连接,成功后即可创建Pod

[root@k8s-node02 ~]# yum install -y nfs-utils
[root@k8s-node02 ~]# mount -t nfs stor01:/data/volumes /mnt
[root@k8s-node02 ~]# mount
......
stor01:/data/volumes on /mnt type nfs4 (rw,relatime,vers=4.1,rsize=131072,wsize=131072,namlen=255,hard,proto=tcp,port=0,timeo=600,retrans=2,sec=sys,clientaddr=192.168.56.13,local_lock=none,addr=192.168.56.14)
[root@k8s-node02 ~]# umount /mnt/

清单示例:

apiVersion: v1
kind: Pod
metadata: 
  name: Pod-nfs
  namespace: default
spec:
  containers:
  - name: myapp
    image: ikubernetes/myapp:v1
    imagePullPolicy: IfNotPresent
    volumeMounts:
    - name: html
      mountPath: /usr/share/nginx/html
  volumes:
  - name: html
    nfs:
      path: /data/volumes  # 共享出来的目录
      server: stor01   #要提前做好解析

你可能感兴趣的:(2020-03-28 Kubernetes—volume (上))