一.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