第8关 k8s架构师课程之持久化存储第二节PV和PVC
参看博客:https://www.bilibili.com/video/BV1M54y187jb?spm_id_from=333.999.0.0
https://www.toutiao.com/a6940963940901945868/?log_from=539f5fa5df11e_1630841897938
第8关 k8s架构师课程之持久化存储第二节PV和PVC
大家好,我是博哥爱运维,k8s持久化存储的第二节,给大家带来 PersistentVolume(PV) & PersistentVolumeClaim(PVC) 的讲解。
现在讲Volume里面在生产中用的最多的PersistentVolume(持久卷,简称PV)和 PersistentVolumeClaim(持久卷消费,简称PVC),通常在企业中,Volume是由存储系统的管理员来维护,他们来提供pv,pv具有持久性,生命周期独立于Pod;Pod则是由应用的开发人员来维护,如果要进行一卷挂载,那么就写一个pvc来消费pv就可以了,K8s会查找并提供满足条件的pv。
有了pvc,我们在K8s进行卷挂载就只需要考虑要多少容量了,而不用关心真正的空间是用什么存储系统做的等一些底层细节信息,pv这些只有存储管理员才应用去关心它。
K8s支持多种类型的pv,我们这里就以生产中常用的NFS来作演示(在云上的话就用NAS),生产中如果对存储要求不是太高的话,建议就用NFS,这样出问题也比较容易解决,如果有性能需求,可以看看rook的ceph,以及Rancher的Longhorn,这些我都在生产中用过,如果有需求的同学可以在评论区留言,我会单独做课程来讲解。
开始部署NFS-SERVER
# 我们这里在10.0.1.201上安装(在生产中,大家要提供作好NFS-SERVER环境的规划)
# yum -y install nfs-utils
# 创建NFS挂载目录
# mkdir /nfs_dir
# chown nobody.nobody /nfs_dir
# 修改NFS-SERVER配置
# echo '/nfs_dir *(rw,sync,no_root_squash)' > /etc/exports
# 重启服务
# systemctl restart rpcbind.service
# systemctl restart nfs-utils.service
# systemctl restart nfs-server.service
# 增加NFS-SERVER开机自启动
# systemctl enable nfs-server.service
Created symlink from /etc/systemd/system/multi-user.target.wants/nfs-server.service to /usr/lib/systemd/system/nfs-server.service.
# 验证NFS-SERVER是否能正常访问
# showmount -e 10.0.1.201
Export list for 10.0.1.201:
/nfs_dir *
创建基于NFS的PV
首先在NFS-SERVER的挂载目录里面创建一个目录
# mkdir /nfs_dir/pv1
接着准备好pv的yaml配置,保存为pv1.yaml
# cat pv1.yaml apiVersion: v1 kind: PersistentVolume metadata: name: pv1 labels: type: test-claim # 这里建议打上一个独有的标签,方便在多个pv的时候方便提供pvc选择挂载 spec: capacity: storage: 1Gi # <---------- 1 accessModes: - ReadWriteOnce # <---------- 2 persistentVolumeReclaimPolicy: Recycle # <---------- 3 storageClassName: nfs # <---------- 4 nfs: path: /nfs_dir/pv1 # <---------- 5 server: 10.0.1.201
注意pv是不需要和namespace命名空间进行绑定的
- capacity 指定 PV 的容量为 1G。
- accessModes 指定访问模式为 ReadWriteOnce,支持的访问模式有: ReadWriteOnce – PV 能以 read-write 模式 mount 到单个节点。 ReadOnlyMany – PV 能以 read-only 模式 mount 到多个节点。 ReadWriteMany – PV 能以 read-write 模式 mount 到多个节点。
- persistentVolumeReclaimPolicy 指定当 PV 的回收策略为 Recycle,支持的策略有: Retain – 需要管理员手工回收。 Recycle – 清除 PV 中的数据,效果相当于执行 rm -rf /thevolume/*。 Delete – 删除 Storage Provider 上的对应存储资源,例如 AWS EBS、GCE PD、Azure Disk、OpenStack Cinder Volume 等。
- storageClassName 指定 PV 的 class 为 nfs。相当于为 PV 设置了一个分类,PVC 可以指定 class 申请相应 class 的 PV。
- 指定 PV 在 NFS 服务器上对应的目录,这里注意,我测试的时候,需要手动先创建好这个目录并授权好,不然后面挂载会提示目录不存在 mkdir /nfsdata/pv1 && chown -R nobody.nogroup /nfsdata 。
创建这个pv
# kubectl apply -f pv1.yaml persistentvolume/pv1 created # STATUS 为 Available,表示 pv1 就绪,可以被 PVC 申请 # kubectl get pv NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE pv1 1Gi RWO Recycle Available nfs 4m45s
这里pv还没有和pvc绑定,所以这里claim是空
第8关 k8s架构师课程之持久化存储第二节PV和PVC
大家好,我是博哥爱运维,k8s持久化存储的第二节,给大家带来 PersistentVolume(PV) & PersistentVolumeClaim(PVC) 的讲解。
现在讲Volume里面在生产中用的最多的PersistentVolume(持久卷,简称PV)和 PersistentVolumeClaim(持久卷消费,简称PVC),通常在企业中,Volume是由存储系统的管理员来维护,他们来提供pv,pv具有持久性,生命周期独立于Pod;Pod则是由应用的开发人员来维护,如果要进行一卷挂载,那么就写一个pvc来消费pv就可以了,K8s会查找并提供满足条件的pv。
有了pvc,我们在K8s进行卷挂载就只需要考虑要多少容量了,而不用关心真正的空间是用什么存储系统做的等一些底层细节信息,pv这些只有存储管理员才应用去关心它。
K8s支持多种类型的pv,我们这里就以生产中常用的NFS来作演示(在云上的话就用NAS),生产中如果对存储要求不是太高的话,建议就用NFS,这样出问题也比较容易解决,如果有性能需求,可以看看rook的ceph,以及Rancher的Longhorn,这些我都在生产中用过,如果有需求的同学可以在评论区留言,我会单独做课程来讲解。
开始部署NFS-SERVER
# 我们这里在10.0.1.201上安装(在生产中,大家要提供作好NFS-SERVER环境的规划)
# yum -y install nfs-utils
# 创建NFS挂载目录
# mkdir /nfs_dir
# chown nobody.nobody /nfs_dir
# 修改NFS-SERVER配置
# echo '/nfs_dir *(rw,sync,no_root_squash)' > /etc/exports
# 重启服务
# systemctl restart rpcbind.service
# systemctl restart nfs-utils.service
# systemctl restart nfs-server.service
# 增加NFS-SERVER开机自启动
# systemctl enable nfs-server.service
Created symlink from /etc/systemd/system/multi-user.target.wants/nfs-server.service to /usr/lib/systemd/system/nfs-server.service.
# 验证NFS-SERVER是否能正常访问
# showmount -e 10.0.1.201
Export list for 10.0.1.201:
/nfs_dir *
创建基于NFS的PV
首先在NFS-SERVER的挂载目录里面创建一个目录
# mkdir /nfs_dir/pv1
接着准备好pv的yaml配置,保存为pv1.yaml
# cat pv1.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv1
labels:
type: test-claim # 这里建议打上一个独有的标签,方便在多个pv的时候方便提供pvc选择挂载
spec:
capacity:
storage: 1Gi # <---------- 1
accessModes:
- ReadWriteOnce # <---------- 2
persistentVolumeReclaimPolicy: Recycle # <---------- 3
storageClassName: nfs # <---------- 4
nfs:
path: /nfs_dir/pv1 # <---------- 5
server: 10.0.1.201
- capacity 指定 PV 的容量为 1G。
- accessModes 指定访问模式为 ReadWriteOnce,支持的访问模式有: ReadWriteOnce – PV 能以 read-write 模式 mount 到单个节点。 ReadOnlyMany – PV 能以 read-only 模式 mount 到多个节点。 ReadWriteMany – PV 能以 read-write 模式 mount 到多个节点。
- persistentVolumeReclaimPolicy 指定当 PV 的回收策略为 Recycle,支持的策略有: Retain – 需要管理员手工回收。 Recycle – 清除 PV 中的数据,效果相当于执行 rm -rf /thevolume/*。 Delete – 删除 Storage Provider 上的对应存储资源,例如 AWS EBS、GCE PD、Azure Disk、OpenStack Cinder Volume 等。
- storageClassName 指定 PV 的 class 为 nfs。相当于为 PV 设置了一个分类,PVC 可以指定 class 申请相应 class 的 PV。
- 指定 PV 在 NFS 服务器上对应的目录,这里注意,我测试的时候,需要手动先创建好这个目录并授权好,不然后面挂载会提示目录不存在 mkdir /nfsdata/pv1 && chown -R nobody.nogroup /nfsdata 。
创建这个pv
# kubectl apply -f pv1.yaml
persistentvolume/pv1 created
# STATUS 为 Available,表示 pv1 就绪,可以被 PVC 申请
# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pv1 1Gi RWO Recycle Available nfs 4m45s
接着准备PVC的yaml,保存为pvc1.yaml
# cat pvc1.yaml kind: PersistentVolumeClaim apiVersion: v1 metadata: name: pvc1 spec: accessModes: - ReadWriteOnce resources: requests: storage: 1Gi storageClassName: nfs selector: matchLabels: type: test-claim
pv是全局的,pvc可以指定namespace。上面没有指定namespace默认就是default。
这个PVC就会和上面的PV进行绑定,为什么呢?它有一些原则:
-
PV和PVC中的spec关键字段要匹配,比如存储(storage)大小。
-
PV和PVC中的storageClassName字段必须一致,这个后面再说
创建这个pvc
# kubectl apply -f pvc1.yaml persistentvolumeclaim/pvc1 created # 看下pvc的STATUS为Bound代表成功挂载到pv了 # kubectl get pvc NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE pvc1 Bound pv1 1Gi RWO nfs 2s # 这个时候再看下pv,STATUS也是Bound了,同时CLAIM提示被default/pvc1消费 # kubectl get pv NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE pv1 1Gi RWO Recycle Bound default/pvc1 nfs
下面我们准备pod服务来挂载这个pvc,这里就以上面最开始演示用的nginx的deployment的yaml配置来作修改
# cat nginx.yaml apiVersion: v1 kind: Service metadata: labels: app: nginx name: nginx spec: ports: - port: 80 protocol: TCP targetPort: 80 selector: app: nginx --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: nginx name: nginx spec: replicas: 1 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - image: nginx name: nginx volumeMounts: # 我们这里将nginx容器默认的页面目录挂载 - name: html-files mountPath: "/usr/share/nginx/html" volumes: - name: html-files persistentVolumeClaim: # 卷类型使用pvc,同时下面名称处填先创建好的pvc1 claimName: pvc1
更新配置
# kubectl apply -f nginx.yaml
service/nginx unchanged
deployment.apps/nginx configured
# 我们看到新pod已经在创建了
# kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx-569546db98-4nmmg 0/1 ContainerCreating 0 5s
nginx-f89759699-6vgr8 1/1 Running 1 23h
web-5bf769fdfc-44p7h 2/2 Running 0 113m
# 我们这里直接用svc地址测试一下
# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.68.0.1 <none> 443/TCP 23h
nginx ClusterIP 10.68.238.54 <none> 80/TCP 23h
web ClusterIP 10.68.229.231 <none> 80/TCP 6h27m
# 咦,这里为什么是显示403了呢,注意,卷挂载后会把当前已经存在这个目录的文件给覆盖掉,这个和传统机器上的磁盘目录挂载道理是一样的
[root@node-1 ~]# curl 10.68.238.54
<html>
<head><title>403 Forbidden</title></head>
<body>
<center><h1>403 Forbidden</h1></center>
<hr><center>nginx/1.19.5</center>
</body>
</html>
# 我们来自己创建一个index.html页面
# echo 'hello, world!' > /nfs_dir/pv1/index.html
# 再请求下看看,已经正常了
# curl 10.68.238.54
hello, world!
# 我们来手动删除这个nginx的pod,看下容器内的修改是否是持久的呢?
# kubectl delete pod nginx-569546db98-4nmmg
pod "nginx-569546db98-4nmmg" deleted
# 等待一会,等新的pod被创建好
# kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx-569546db98-99qpq 1/1 Running 0 45s
# 再测试一下,可以看到,容器内的修改现在已经被持久化了
# curl 10.68.238.54
hello, world!
# 后面我们再想修改有两种方式,一个是exec进到pod内进行修改,还有一个是直接修改挂载在NFS目录下的文件
# echo 111 > /nfs_dir/pv1/index.html
# curl 10.68.238.54
111
下面讲下如何回收PVC以及PV
# 这里删除时会一直卡着,我们按ctrl+c看看怎么回事
# kubectl delete pvc pvc1
persistentvolumeclaim "pvc1" deleted
^C
# 看下pvc发现STATUS是Terminating删除中的状态,我分析是因为服务pod还在占用这个pvc使用中
# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
pvc1 Terminating pv1 1Gi RWO nfs 21m
# 先删除这个pod
# kubectl delete pod nginx-569546db98-99qpq
pod "nginx-569546db98-99qpq" deleted
# 再看先删除的pvc已经没有了
# kubectl get pvc
No resources found in default namespace.
# 根据先前创建pv时的数据回收策略为Recycle – 清除 PV 中的数据,这时果然先创建的index.html已经被删除了,在生产中要尤其注意这里的模式,注意及时备份数据,注意及时备份数据,注意及时备份数据
# ll /nfs_dir/pv1/
total 0
# 虽然此时pv是可以再次被pvc来消费的,但根据生产的经验,建议在删除pvc时,也同时把它消费的pv一并删除,然后再重启创建都是可以的
posted on 2021-09-05 19:55 luzhouxiaoshuai 阅读(255) 评论(0) 编辑 收藏 举报