8、kubernetes之 存储卷

第八部分 kubernetes之 存储卷
脱离节点而存在共享存储。
存储卷不属于容器,他属于pod
缓存,宿主机,不具备真正意义上存储,宿主机退役后,存储资源随之丢失,除非宿主机上也挂载独立的卷信息。

容器真正意义上的存储卷类型

emptyDir:pod删除,存储内容也删除,只能当临时存储空间或缓存使用,无真正意义上持久性
hostPath:在宿主机上挂载一个目录,宿主机单点故障,无真正意义上持久性
网络存储:
  传统存储:
    SAN:iSCSI,...
	NAS:nfs、cifs
  分布式存储:
    glusterfs,rbd,cephfs
  云存储:
     EBS、Azure Disk、	 

任何存储服务,关键数据一定要做好异地备份。
存储类别:存储卷级别,存储要求高低分配。
容器怎么使用存储卷:pod上面定义volume(指明挂载哪个存储)->容器上挂载存储卷(volumeMounts)

定义pod容器挂载
1、emptyDir操作
[root@k8s-master ~]# kubectl explain pods.spec.volumes.emptyDir

[root@k8s-master volumes]# cat pod-vol-demo.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod-vol-demo
  namespace: default
  labels:
    app: myapp
    tier: frontend
  annotations:
    k8s.mastet/create-by: "sunny wei"
spec:
  containers:
  - image: ikubernetes/myapp:v1
    name: myapp
    ports:
    - name: http
      containerPort: 80
    volumeMounts:
    - name: html
      mountPath: /usr/share/nginx/html
  - image: busybox:latest
    name: busybox
    volumeMounts:
    - name: html
      mountPath: /data
    command:
    - "/bin/sh"
    - "-c"
    - "while true;do echo $(date) >> /data/index.html;sleep 1;done;"
  nodeSelector:
    disktype: ssd
  volumes:
  - name: html
    emptyDir: {}
pod-vol-demo.yaml

[root@k8s-master volumes]# kubectl create -f pod-vol-demo.yaml
[root@k8s-master volumes]# kubectl get pods pod-vol-demo
[root@k8s-master volumes]# kubectl describe pods pod-vol-demo
Name: pod-vol-demo
Namespace: default
Priority: 0
PriorityClassName: <none>
...
当pod当中有多个容器运行时,需要describe定位是哪个容器,避免不必要的排查异常。

[root@k8s-master volumes]# kubectl get pods pod-vol-demo -owide
NAME           READY   STATUS    RESTARTS   AGE     IP           NODE        NOMINATED NODE   READINESS GATES
pod-vol-demo   2/2     Running   0          2m30s   10.244.1.3   k8s-node1   <none>           <none>
[root@k8s-master volumes]# curl 10.244.1.3                     
Wed Jul 12 14:19:39 UTC 2023
...

进入pod容器内查看,

[root@master volumes]# kubectl exec -it  myapp -c myapp -- /bin/sh
[root@k8s-master volumes]# kubectl exec -it pod-vol-demo -c busybox -- tail -2 /data/index.html 
Wed Jul 12 14:25:23 UTC 2023
Wed Jul 12 14:25:24 UTC 2023
[root@k8s-master volumes]# kubectl exec -it pod-vol-demo -c myapp -- tail -2 /usr/share/nginx/html/index.html
Wed Jul 12 14:19:39 UTC 2023
Wed Jul 12 14:19:40 UTC 2023
这个方式是把存储临时放到docker对应的宿主机上进行存储。登录宿主机查看
[root@k8s-node1 ~]# docker ps |grep k8s_myapp_pod
[root@k8s-node1 ~]# docker inspect cb81760edd07
[root@k8s-node1 ~]# tail -2 /var/lib/kubelet/pods/0dba96e1-20bf-11ee-afb0-000c29250b06/volumes/kubernetes.io~empty-dir/html/index.html
Wed Jul 12 14:32:47 UTC 2023
Wed Jul 12 14:32:48 UTC 2023

上面示例证明,同一个存储卷,可以在同一个pod内多个容器之间使用。

gitRepo仓库,将数据存储在仓库,对应宿主机需要有git操作能力。本质上也是emptyDir方式。
仓库有数据更新,pod运行过程中不会主动去同步仓库数据,只在拉取镜像数据过程会同步数据。
为解决难点,可以借助运行两个容灾,一个主,一个辅助(定时更新仓库镜像)容器。
还有,他不能把修改的内容及时推到仓库,pod重建后,会丢失。

2、hostPath存储卷
hostPath:pod删除重建后,宿主机上数据依然存在,pod也会获取到。
不足的是,节点宿主机宕机,数据会丢失。
[root@k8s-master ~]# kubectl explain pod.spec.volumes.hostPath
每个节点创建目录和文件
[root@k8s-node1 ~]# mkdir -p /data/pod/volume1 &&echo "node1.mage.com">/data/pod/volume1/index.html
[root@k8s-node2 ~]# mkdir -p /data/pod/volume1 &&echo "node2.mage.com">/data/pod/volume1/index.html

[root@k8s-master volumes]# cat pod-hostpath-demo.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: pod-vol-hostpath
  namespace: default
spec:
  containers:
  - image: ikubernetes/myapp:v1
    name: myapp
    volumeMounts:
    - name: html
      mountPath: /usr/share/nginx/html
  volumes:
  - name: html
    hostPath:
      path: /data/pod/volume1
      type: DirectoryOrCreate

[root@k8s-master volumes]# kubectl create -f pod-hostpath-demo.yaml
pod/pod-vol-hostpath created
[root@k8s-master volumes]# kubectl get pods pod-vol-hostpath -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod-vol-hostpath 1/1 Running 0 26s 10.244.1.5 k8s-node1 <none> <none>
[root@k8s-master volumes]# curl 10.244.1.5
node1.mage.com
[root@k8s-master volumes]# kubectl delete -f pod-hostpath-demo.yaml # 删除重建后,数据没有丢失
[root@k8s-master volumes]# kubectl create -f pod-hostpath-demo.yaml
[root@k8s-master volumes]# kubectl get pods pod-vol-hostpath -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod-vol-hostpath 1/1 Running 0 48s 10.244.2.42 k8s-node2 <none> <none>
[root@k8s-master volumes]# curl 10.244.2.42
node2.mage.com
自此,完成hostpath主机共享存储,主机down之后,数据丢失

3、采用nfs存储,实现存储共享。
各节点确保有mount命令,都需要安装相关命令
部署nfs存储服务
[root@stor ~]# mkdir -p /data/volumes
[root@stor ~]# yum install nfs-utils -y
[root@stor ~]# echo "<h1>NFS stor01</h1>">/data/volumes/index.html
[root@stor ~]# echo "/data/volumes 192.168.1.0/24(rw,no_root_squash)" >>/etc/exports
[root@stor ~]# systemctl restart nfs
[root@stor ~]# showmount -e 127.0.0.1
Export list for 127.0.0.1:
/data/volumes 192.168.1.0/24
客户端查看可挂载情况
[root@k8s-node2 ~]# showmount -e 192.168.1.203
Export list for 192.168.1.203:
/data/volumes 192.168.1.0/24

容器部署nfs卷服务

[root@k8s-master volumes]# cat pod-nfs-demo.yaml  
apiVersion: v1
kind: Pod
metadata:
  name: pod-nfs-demo
  namespace: default
spec:
  containers:
  - image: ikubernetes/myapp:v1
    imagePullPolicy: IfNotPresent
    name: myapp
    volumeMounts:
    - name: html
      mountPath: /usr/share/nginx/html
  volumes:
  - name: html
    nfs:
      path: /data/volumes
      server: 192.168.1.203
pod-nfs-demo.yaml

[root@k8s-master volumes]# kubectl create -f pod-nfs-demo.yaml
[root@k8s-master volumes]# kubectl get pod pod-nfs-demo -owide
[root@k8s-master volumes]# curl 10.244.1.6
<h1>NFS stor01</h1>
删除pod重建也可以正常访问。
验证nfs使用情况:Mount挂载,容器服务检测,挂载有效。
使用nfs存储需要将存储信息和目录固定指定,不能动态创建存储结构。

4、pvc存储卷
生产和消费模型:如吃芹菜,不需要自己去种,想吃的时候直接去购买即可。
如下图形架构,

pvc跟pv上面的数据绑定,

存储管理员配置共享存储
[root@stor ~]# mkdir -pv /data/volumes/{v1,v2,v3,v4,v5}
[root@stor ~]# cat /etc/exports
/data/volumes 192.168.1.0/24(rw,no_root_squash)
/data/volumes/v1 192.168.1.0/24(rw,no_root_squash)
/data/volumes/v2 192.168.1.0/24(rw,no_root_squash)
/data/volumes/v3 192.168.1.0/24(rw,no_root_squash)
/data/volumes/v4 192.168.1.0/24(rw,no_root_squash)
/data/volumes/v5 192.168.1.0/24(rw,no_root_squash)
[root@stor ~]# systemctl restart nfs
[root@stableor ~]# showmount -e 192.168.1.203
Nfs服务部署完毕,以此作为存储,在其上部署PV。

创建pv服务
[root@k8s-master volumes]# cat pv-nfs.yaml

[root@k8s-master volumes]# cat pv-nfs.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv001
  labels:
    app: pv001
spec:
  nfs:
    path: /data/volumes/v1
    server: stor.test.com
  accessModes: ["ReadWriteMany","ReadWriteOnce"]
  capacity:
    storage: 2Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv002
  labels:
    app: pv002
spec:
  nfs:
    path: /data/volumes/v2
    server: stor.test.com
  accessModes: ["ReadWriteOnce"]
  capacity:
    storage: 5Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv003
  labels:
    app: pv003
spec:
  nfs:
    path: /data/volumes/v3
    server: stor.test.com
  accessModes: ["ReadWriteMany","ReadWriteOnce"]
  capacity:
    storage: 20Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv004
  labels:
    app: pv004
spec:
  nfs:
    path: /data/volumes/v4
    server: stor.test.com
  accessModes: ["ReadWriteMany","ReadWriteOnce"]
  capacity:
    storage: 10Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv005
  labels:
    app: pv005
spec:
  nfs:
    path: /data/volumes/v5
    server: stor.test.com
  accessModes: ["ReadWriteMany","ReadWriteOnce"]
  capacity:
    storage: 10Gi
pv-nfs.yaml

[root@k8s-master volumes]# kubectl create -f pv-nfs.yaml
persistentvolume/pv001 created
...
[root@k8s-master volumes]# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pv001 2Gi RWO,RWX Retain Available 16s
pv002 5Gi RWO Retain Available 15s
pv003 20Gi RWO,RWX Retain Available 15s
pv004 10Gi RWO,RWX Retain Available 15s
pv005 10Gi RWO,RWX Retain Available 15s

自此,三个PV完成部署,创建一个PVC服务。
[root@k8s-master volumes]# cat pod-vol-pvc.yaml

[root@k8s-master volumes]# cat pod-vol-pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mypvc
  namespace: default
spec:
  accessModes: ["ReadWriteMany"]
  resources:
    requests:
      storage: 6Gi
---
apiVersion: v1
kind: Pod
metadata:
  name: pod-vol-pvc
  namespace: default
spec:
  containers:
  - image: ikubernetes/myapp:v1
    imagePullPolicy: IfNotPresent
    name: myapp
    volumeMounts:
    - name: html
      mountPath: /usr/share/nginx/html
  volumes:
  - name: html
    persistentVolumeClaim:
      claimName: mypvc
pod-vol-pvc.yaml

[root@k8s-master volumes]# kubectl create -f pod-vol-pvc.yaml
[root@k8s-master volumes]# kubectl get pv
[root@k8s-master volumes]# kubectl get pvc
[root@k8s-master ~]# kubectl describe pods pod-vol-pvc

一般删除pod,不会删除pvc删除,pvc不属于节点,他是标准的k8s资源,在etcd上运行。
只要etcd正常,pvc就没有问题,只有pod在节点上运行,其他资源数据都保存在etcd里面。不要主动删除pvc,删除pvc,pv里面的数据取决于pvc回收策略。

早期版本k8s有bug,可以直接删除pv,新版本不能直接删除pv,只要有绑定的pvc,就不支持删除pv。
建议使用有状态存储的pod做测试,看数据是否丢失。

posted @ 2023-07-13 11:29  wang_wei123  阅读(30)  评论(0编辑  收藏  举报