一.Volumes
Volumes:官方文档 https://kubernetes.io/docs/concepts/storage/volumes/
Volumes:中文文档 https://kubernetes.io/zh/docs/concepts/storage/volumes/
Redis-Cluster:nodes.conf
1.emptyDir
- 和上述volume不同的是,如果删除Pod,emptyDir卷中的数据也将被删除,一般emptyDir卷用于Pod中的不同Container共享数据。它可以被挂载到相同或不同的路径上。
- 默认情况下,emptyDir卷支持节点上的任何介质,可能是SSD、磁盘或网络存储,具体取决于自身的环境。可以将emptyDir.medium字段设置为Memory,让Kubernetes使用tmpfs(内存支持的文件系统),虽然tmpfs非常快,但是tmpfs在节点重启时,数据同样会被清除,并且设置的大小会被计入到Container的内存限制当中。
使用emptyDir卷的示例,直接指定emptyDir为{}即可:
[root@k8s-master01 volumes]# vim nginx-deploy.yaml //编辑一个deployment
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
deployment.kubernetes.io/revision: "1"
creationTimestamp: "2020-09-19T02:41:11Z"
generation: 1
labels:
app: nginx
name: nginx
namespace: default
spec:
progressDeadlineSeconds: 600
replicas: 2
revisionHistoryLimit: 10
selector:
matchLabels:
app: nginx
strategy:
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
type: RollingUpdate
template:
metadata:
creationTimestamp: null
labels:
app: nginx
spec:
containers:
- image: nginx:1.15.2
imagePullPolicy: IfNotPresent
name: nginx //nginx1
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
volumeMounts:
- mountPath: /opt //挂载的路径/opt
name: share-volume //调用emptyDir的名称
- image: nginx:1.15.2
imagePullPolicy: IfNotPresent
name: nginx2 //nginx2
command: //预防同POD端口冲突,设置睡眠
- sh
- -c
- sleep 3600
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
volumeMounts:
- mountPath: /mnt //挂载的路径/mnt
name: share-volume //调用emptyDir的名称
dnsPolicy: ClusterFirst
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
terminationGracePeriodSeconds: 30
volumes: //设置volumes:
- name: share-volume //设置emptyDir的名称
emptyDir: {} //设置emptyDir,指定 {}即可
#medium: Memory //可以使用内存做存储,根据实际情况是否启用
[root@k8s-master01 volumes]# kubectl create -f nginx-deploy.yaml //启动
deployment.apps/nginx created
[root@k8s-master01 volumes]# kubectl get pod //查看成功启动
NAME READY STATUS RESTARTS AGE
dp-cm-6f98c85ff5-pxhbc 1/1 Running 2 43h
nginx-67948c7d6b-djwgx 2/2 Running 0 33s
nginx-67948c7d6b-xg29c 2/2 Running 0 33s
验证:先从1pod中的nginx1容器里面挂载的/opt里面写入数据,然后进入nginx2容器挂载的/mnt目录下查看文件是否存在。
[root@k8s-master01 volumes]# kubectl exec -it nginx-67948c7d6b-djwgx -c nginx -- bash //进入nginx1 root@nginx-67948c7d6b-djwgx:/# cd /opt/ root@nginx-67948c7d6b-djwgx:/opt# echo '1234qwe' > test.txt root@nginx-67948c7d6b-djwgx:/opt# exit exit [root@k8s-master01 volumes]# kubectl exec -it nginx-67948c7d6b-djwgx -c nginx2 -- bash //进入nginx2 root@nginx-67948c7d6b-djwgx:/# cd /mnt && cat test.txt 1234qwe
2.hostPath
- hostPath卷可将节点上的文件或目录挂载到Pod上,用于Pod自定义日志输出或访问Docker内部的容器等。
使用hostPath卷的示例。将主机的/data目录挂载到Pod的/test-pd目录:
[root@k8s-master01 volumes]# vim nginx-deploy.yaml
.......... //省略,和上述一致
volumeMounts:
- mountPath: /mnt
name: share-volume
- mountPath: /etc/timezone //挂载pod的路径,只设置挂载到nginx2的路径,nginx1没挂载
name: timezone //调用hostPath的名称
dnsPolicy: ClusterFirst
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
terminationGracePeriodSeconds: 30
volumes:
- name: share-volume
emptyDir: {}
#medium: Memory
- name: timezone //设置hostPath名称
hostPath:
path: /etc/timezone //设置宿主机的文件
type: File //类型,File表示文件
验证:nginx1原文件,nginx2为挂载的路径
[root@k8s-master01 volumes]# kubectl replace -f nginx-deploy.yaml deployment.apps/nginx replaced [root@k8s-master01 volumes]# kubectl exec nginx-78bcb8886d-rfb69 -c nginx -- cat /etc/timezone //nginx1原文件 Etc/UTC [root@k8s-master01 volumes]# kubectl exec nginx-78bcb8886d-rfb69 -c nginx2 -- cat /etc/timezone //nginx2为挂载的路径 Asia/Shanghai
hostPath卷常用的type(类型)如下:
- type为空字符串:默认选项,意味着挂载hostPath卷之前不会执行任何检查。
- DirectoryOrCreate:如果给定的path不存在任何东西,那么将根据需要创建一个权限为0755的空目录,和Kubelet具有相同的组和权限。
- Directory:目录必须存在于给定的路径下。
- FileOrCreate:如果给定的路径不存储任何内容,则会根据需要创建一个空文件,权限设置为0644,和Kubelet具有相同的组和所有权。
- File:文件,必须存在于给定路径中。
- Socket:UNIX套接字,必须存在于给定路径中。
- CharDevice:字符设备,必须存在于给定路径中。
- BlockDevice:块设备,必须存在于给定路径中。
3.nfs挂载
这边测试挂载到nfs上,如果生产环境推荐用云平台的NAS等高性能存储,nfs受性能影响比较大。
安装nfs服务器:node01
安装nfs安装包:其他所有节点,挂载nfs需要识别NFS,装安装包即可,无需配置
所有节点:
[root@k8s-node01 ~]# yum -y install nfs-utils //安装nfs
node01节点:
[root@k8s-master01 ~]# mkdir -p /data/nfs/test 创建共享路径 [root@k8s-node01 ~]# systemctl enable --now nfs-server //开机启动+启动 [root@k8s-node01 nfs]# vim /etc/exports //修改配置文件添加其他节点访问权限 /data/nfs/ 192.168.1.0/24(rw,sync,no_subtree_check,no_root_squash) [root@k8s-node01 ~]# systemctl restart nfs-server //重启服务 回到master01 [root@k8s-master01 volumes]# mount -t nfs 192.168.1.103:/data/nfs /mnt //挂载测试 [root@k8s-master01 mnt]# df -h [root@k8s-master01 volumes]# cd /mnt/ && touch 123 //测试正常 [root@k8s-master01 mnt]#cd ~ && umount /mnt //测试正常后,退出目录取消挂载
然后挂载到deployment
[root@k8s-master01 volumes]# vim nginx-deploy.yaml
................ //参考上面yaml,省略
- image: nginx:1.15.2
imagePullPolicy: IfNotPresent
name: nginx2
command:
- sh
- -c
- sleep 3600
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
volumeMounts:
- mountPath: /mnt
name: share-volume
- mountPath: /opt //添加挂载到/opt
name: nfs-volume //调用挂载nfs的名称nfs-volume
dnsPolicy: ClusterFirst
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
terminationGracePeriodSeconds: 30
volumes:
- name: share-volume
emptyDir: {}
#medium: Memory
- name: timezone
hostPath:
path: /etc/timezone
type: File
- name: nfs-volume //设置nfs名称
nfs:
server: 192.168.0.204 //设置挂载的IP路径
path: /data/nfs/test-dp //设置挂载的源路径
验证:更新deployment后,进容器查看挂载是否成功,再写入文件测试。
[root@k8s-master01 volumes]# kubectl replace -f nginx-deploy.yaml deployment.apps/nginx replaced [root@k8s-master01 volumes]# kubectl exec -it nginx-ddd4487f8-5jdkw -c nginx2 -- bash root@nginx-ddd4487f8-5jdkw:/# df -h //已挂载了 Filesystem Size Used Avail Use% Mounted on overlay 17G 3.8G 14G 23% / tmpfs 64M 0 64M 0% /dev tmpfs 978M 0 978M 0% /sys/fs/cgroup /dev/mapper/centos-root 17G 3.8G 14G 23% /mnt 192.168.1.103:/data/nfs/test 17G 3.3G 14G 20% /opt root@nginx-ddd4487f8-5jdkw:/# cd /opt/ root@nginx-ddd4487f8-5jdkw:/opt# touch 123 回到node01查看文件,能正常使用 [root@k8s-node01 nfs]# cd test/ [root@k8s-node01 test]# ls 123
二.Pv&Pvc
volume无法解决的问题
- 当某个数据卷不再被挂载使用时,里面数据不好处理。
- 实现不了设置权限挂载,比如只读挂载。
- 实现不了只能一个POD挂载。
- 设置挂载的空间大小
官方文档:https://kubernetes.io/docs/concepts/storage/persistent-volumes/
PV:PersistentVolume,简称PV,是由Kubernetes管理员设置的存储,可以配置Ceph、NFS、GlusterFS等常用存储配置,相对于Volume配置,提供了更多的功能,比如生命周期的管理、大小的限制。PV分为静态和动态。
PVC:PersistentVolumeClaim,简称PVC,是对存储PV的请求,表示需要什么类型的PV,需要存储的技术人员只需要配置PVC即可使用存储,或者Volume配置PVC的名称即可。

1.Pv的回收策略
- 1.Retain:保留,该策略允许手动回收资源,当删除PVC时,PV仍然存在,PV被视为已释放,管理员可以手动回收卷。
- 2.Recycle:回收,如果Volume插件支持,Recycle策略会对卷执行rm -rf清理该PV,并使其可用于下一个新的PVC,但是本策略将来会被弃用,目前只有NFS和HostPath支持该策略。
- 3.Delete:删除,如果Volume插件支持,删除PVC时会同时删除PV,动态卷默认为Delete,目前支持Delete的存储后端包括AWS EBS, GCE PD, Azure Disk, or OpenStack Cinder等。
- 可以通过persistentVolumeReclaimPolicy: Recycle字段配置
2.Pv的访问策略
官方文档:https://kubernetes.io/docs/concepts/storage/persistent-volumes/#access-modes
- ReadWriteOnce:可以被单节点以读写模式挂载,命令行中可以被缩写为RWO。
- ReadOnlyMany:可以被多个节点以只读模式挂载,命令行中可以被缩写为ROX。
- ReadWriteMany:可以被多个节点以读写模式挂载,命令行中可以被缩写为RWX。

3.创建NFS(NAS)类型和HostPath类型的PV
按照上述volume的NFS挂载,node01装好nfs,设置好挂载目录,确保其他节点能挂载到NFS服务器。
yaml配置详解:
capacity:容量配置
[root@k8s-master01 pv]# vim pv-nfs.yaml
apiVersion: v1
kind: PersistentVolume //简称PV
metadata:
name: pv-nfs //pv的资源名称
spec:
capacity:
storage: 5Gi
volumeMode: Filesystem //卷的模式,文件系统和块
accessModes:
- ReadWriteOnce //pv的访问模式
persistentVolumeReclaimPolicy: Recycle //pv的回收策略
storageClassName: nfs-slow //存储类的名称,PVC绑定pv的名称
mountOptions:
- hard
- nfsvers=4.1
nfs: //pv的类型
path: /data/nfs/test //nfs的共享目录
server: 192.168.1.103 //nfs的IP地址
[root@k8s-master01 pv]# kubectl create -f pv-nfs.yaml
[root@k8s-master01 pv]# kubectl get pv //查看pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pv-nfs 5Gi RWO Recycle Available nfs-slow 8s
HostPath类型:把宿主机的目录挂载到PV中。
[root@k8s-master01 pv]# vim pv-hostpath.yaml
kind: PersistentVolume
apiVersion: v1
metadata:
name: task-pv-volume
labels:
type: local
spec:
storageClassName: hostpath
capacity:
storage: 10Gi
accessModes:
- ReadWriteOnce
hostPath:
path: "/mnt/test"
[root@k8s-master01 pv]# kubectl create -f pv-hostpath.yaml //创建
persistentvolume/task-pv-volume created
[root@k8s-master01 pv]# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pv-nfs 5Gi RWO Recycle Available nfs-slow 32m
task-pv-volume 10Gi RWO Retain Available hostpath 5s
4.pv的状态
5.pcv绑定到pv
a.创建一个PVC,绑定到POD中
[root@k8s-master01 pv]# vim pvc-nfs.yaml
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: task-pvc-claim
spec:
storageClassName: nfs-slow //引用pv的storageClassName名称
accessModes:
- ReadWriteOnce //与PV的访问策略一致
resources:
requests:
storage: 3Gi //小于PV的容量
[root@k8s-master01 pv]# kubectl create -f pvc-nfs.yaml //创建PVC
persistentvolumeclaim/task-pvc-claim created
[root@k8s-master01 pv]# kubectl get pvc //查看PVC
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
task-pvc-claim Bound pv-nfs 5Gi RWO nfs-slow 5s
[root@k8s-master01 pv]# kubectl get pv //查看PVC绑定到了PV
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pv-nfs 5Gi RWO Recycle Bound default/task-pvc-claim nfs-slow 4d22h
task-pv-volume 10Gi RWO Retain Available hostpath 4d21h
创建一个挂载的POD
[root@k8s-master01 pv]# vim pvc-nfs-pod.yaml //创建挂载pod的pvc
kind: Pod
apiVersion: v1
metadata:
name: task-pv-pod
spec:
volumes:
- name: task-pv-storage //volume的名称
persistentVolumeClaim: //pvc
claimName: task-pvc-claim //调用pvc的名称
containers:
- name: task-pv-container
image: nginx
ports:
- containerPort: 80
name: "http-server"
volumeMounts:
- mountPath: "/usr/share/nginx/html" //挂载的路径
name: task-pv-storage //上volume的名称
[root@k8s-master01 pv]# kubectl create -f pvc-nfs-pod.yaml
pod/task-pv-pod created
[root@k8s-master01 pv]# kubectl exec -it task-pv-pod -- bash
root@task-pv-pod:/# df -Th //进容器查看挂载
Filesystem Type Size Used Avail Use% Mounted on
192.168.1.103:/data/nfs/test nfs4 17G 3.5G 14G 21% /usr/share/nginx/html
[root@k8s-node01 test]# echo '123' > index.html //nfs的源挂载路径创建index文件测试
root@task-pv-pod:/usr/share/nginx/html# ls //回到pod中,发现已经创建
123 index.html
b.绑定pvc到deployment中
绑定PVC到POD和绑定pvc到deployment类似
一个是定义spec下的volumes,一个是定义containers下的volumeMounts。
首先定义挂载pvc的deploy的yaml
[root@k8s-master01 pv]# vim pvc-nfs-deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: nginx
name: nginx
namespace: default
spec:
replicas: 2
revisionHistoryLimit: 10
selector:
matchLabels:
app: nginx
strategy:
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
type: RollingUpdate
template:
metadata:
creationTimestamp: null
labels:
app: nginx
spec:
volumes:
- name: task-pv-storage //volume名称
persistentVolumeClaim: //pvc
claimName: task-pvc-claim //pvc的名称
containers:
- env:
- name: TZ
value: Asia/Shanghai
- name: LANG
value: C.UTF-8
image: nginx
imagePullPolicy: IfNotPresent
name: nginx
volumeMounts:
- mountPath: "/usr/share/nginx/html" //挂载路径
name: task-pv-storage //pvc的名称
创建deployment,并进入pod验证挂载是否共享。
[root@k8s-master01 pv]# kubectl create -f pvc-nfs-deploy.yaml deployment.apps/nginx created [root@k8s-master01 pv]# kubectl get pod NAME READY STATUS RESTARTS AGE nginx-66cfc7f7d5-jkmvh 1/1 Running 0 4s nginx-66cfc7f7d5-zdk4r 1/1 Running 0 4s [root@k8s-master01 pv]# kubectl exec -it nginx-66cfc7f7d5-jkmvh -- bash //进入第一个pod root@nginx-66cfc7f7d5-jkmvh:/# df -Th //查看挂载 192.168.1.103:/data/nfs/test nfs4 17G 3.5G 14G 21% /usr/share/nginx/html root@nginx-66cfc7f7d5-jkmvh:/# cd /usr/share/nginx/html/ root@nginx-66cfc7f7d5-jkmvh:/usr/share/nginx/html# echo 'dp-123' > index.html //修改index.html root@nginx-66cfc7f7d5-jkmvh:/usr/share/nginx/html# exit //退出 exit [root@k8s-master01 pv]# kubectl exec -it nginx-66cfc7f7d5-zdk4r -- bash //进入第二个Pod root@nginx-66cfc7f7d5-zdk4r:/# cd /usr/share/nginx/html/ root@nginx-66cfc7f7d5-zdk4r:/usr/share/nginx/html# cat index.html //查看再第一个pod修改的文件,说明目录已经共享 dp-123