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: {}
[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
[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
[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
[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做测试,看数据是否丢失。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 通过 API 将Deepseek响应流式内容输出到前端
· AI Agent开发,如何调用三方的API Function,是通过提示词来发起调用的吗