PV的全称是:
PersistentVolume (持久化卷),是对底层的共享存储的一种抽象,PV由管理员进行创建和配置,它和具体的底层的共享存储技术的实现方式有关,比如Ceph、GlusterFS、NFS等,都是通过插件机制完成与共享存储的对接
PVC的全称是:
PersistenVolumeClaim (持久化卷声明),PVC是用户存储的一种声明,PVC和Pod比较类型,Pod是消耗节点,PVC消耗的是PV资源,Pod可以请求CPU的内存,而PVC可以请求特定的存储空间和访问模式。对于真正存储的用户不需要关心底层的存储实现细节,只需要直接使用PVC即可
PV和PVC的生命周期
PV可以看作可用的存储资源,PVC则是对存储资源的需求,
1、资源供应 (Provisioning)
Kubernetes支持两种资源的供应模式:静态模式(Staic)和动态模式(Dynamic)。资源供应的结果就是创建好的PV。
- 静态模式:集群管理员手工创建许多PV,在定义PV时需要将后端存储的特性进行设置
- 动态模式:集群管理员无须手工创建PV,而是通过StorageClass的设置对后端存储进行描述,标记为某种 "类型(Class)"。此时要求PVC对存储的类型进行声明,系统将自动完成PV的创建及PVC的绑定。PVC可以声明Class为"",说明该PVC禁止使用动态模式
2、资源绑定 (Binding)
在用户定义好PVC后,系统将根据PVC对存储资源的请求 (存储空间和访问模式)在已存在的PV中选择一个满足PVC要求的PV,一旦找到,就将该PV与用户定义的PVC进行绑定,然后用户的应用就可以使用这个PVC了。如果系统中没有满足PVC要求的PV,PVC则会无限期处于Pending状态,直到等到系统管理员创建了一个符合要求的PV。PV一旦绑定在某个PVC上,就被这个PVC独占,不能再与其他PVC进行绑定了。在这种情况下,当PVC申请的存储空间比PV的少时,整个PV的空间都能够为PVC所用,可能会造成资源的浪费。如果资源供应使用的是动态模式,则系统在PVC找到合适的StorageClass后,将会自动创建PV并完成PVC的绑定
3、资源使用 (Using)
Pod 使用volume的定义,将PVC挂载到容器内的某个路径进行使用。
volume的类型为persistentVoulumeClaim,在容器应用挂载了一个PVC后,就能被持续独占使用。
不过,多个Pod可以挂载同一个PVC,应用程序需要考虑多个实例共同访问一块存储空间的问题
4、资源释放 (Releasing)
当用户对存储资源使用哪个完毕后,用户可以删除PVC,与该PVC绑定的PV将会被标记为已释放,但还不能立刻与其他PVC进行绑定。通过之前PVC写入的数据可能还留在存储设备上,只有在清除之后该PV才能继续使用
5、资源回收 (Reclaiming)
对于PV,管理员可以设定回收策略(Reclaim Policy)用于设置与之绑定的PVC释放资源之后,对于遗留数据如何处理。只有PV的存储空间完成回收,才能供新的PVC绑定和使用。
5.1、静态资源下,通过PV和PVC完成绑定,并供Pod使用的存储管理机制
5.2、动态资源下,通过StorageClass和PVC完成资源动态绑定 (系统自动生成PV,并供Pod使用的存储管理机制)
一:实际上顺便使用一台服务器安装nfs都可以 (建议和kubernetes集群分开,找单独一台机器)
[root@nfs ~]# yum install nfs-utils -y rpcbind
#接下来设置nfs存储目录
[root@yunwei ~]# mkdir /data1/k8s-volume
[root@yunwei ~]# chmod 755 /data1/k8s-volume/
#编辑nfs配置文件
[root@yunwei ~]# cat /etc/exports
/data/volumes/pv01 10.4.7.0/24(rw,sync,no_root_squash)
/data/volumes/pv02 10.4.7.0/24(rw,sync,no_root_squash)
/data/volumes/pv03 10.4.7.0/24(rw,sync,no_root_squash)
/data/volumes/pv04 10.4.7.0/24(rw,sync,no_root_squash)
/data/volumes/pv05 10.4.7.0/24(rw,sync,no_root_squash)
存储目录,允许10.4.7.0/24网段的主机连接
rw :读写权限
sync : 文件同时写入硬盘及内存
no_root_squash : 使用者root用户自动修改为普通用户
#由于nfs需要向rpcbind进行注册,所以我们需要优先启动rpcbind
[root@yunwei ~]# systemctl start rpcbind
[root@yunwei ~]# systemctl enable rpcbind
[root@yunwei ~]# systemctl status rpcbind
#启动NFS
[root@yunwei ~]# systemctl restart nfs
[root@yunwei ~]# systemctl enable nfs
[root@yunwei ~]# systemctl status nfs
#检查rpcbind及nfs是否正常
[root@nfs ~]# rpcinfo |grep nfs
#查看nfs挂载信息
[root@yunwei ~]# exportfs -arv
exporting 10.4.7.0/24:/data/volumes/pv05
exporting 10.4.7.0/24:/data/volumes/pv04
exporting 10.4.7.0/24:/data/volumes/pv03
exporting 10.4.7.0/24:/data/volumes/pv02
exporting 10.4.7.0/24:/data/volumes/pv01
[root@yunwei volumes]# showmount -e localhost
Export list for localhost:
/data/volumes/pv05 10.4.7.0/24
/data/volumes/pv04 10.4.7.0/24
/data/volumes/pv03 10.4.7.0/24
/data/volumes/pv02 10.4.7.0/24
/data/volumes/pv01 10.4.7.0/24
二.客户端安装 接下来在所有需要nfs挂载的集群节点安装以下
[root@node01 ~]# yum install -y nfs-utils rpcbind
[root@node01 ~]# systemctl start rpcbind
[root@node01 ~]# systemctl enable rpcbind
[root@node01 ~]# systemctl start nfs
[root@node01 ~]# systemctl enable nfs
#现在进行节点挂载
[root@node01 ~]# mount -t nfs yunwei.host.com:/data/volumes/pv01 /mnt/
#卸载
[root@node01 ~]# umount /mnt/
挂在完成后我们使用df -h 就可以看到挂载点
[root@node01 ~]# df -h |grep yunwei.host.com
yunwei.host.com:/data/volumes/pv01 50G 7.6G 43G 16% /mnt
#所有需要nfs节点这样挂载就可以
三.pv创建,
注意:pv,pvc,pod,deployment需要在同一个名称空间。否则pvc无法绑定pv,pod,deployment无法选择同一个名称空间pvc。
# 有了我们NFS共享存储,下面就可以来使用PV和PVC。
PV作为存储资源,主要包括存储能力、访问模式、存储类型、回收策略等关键信息。
这里使用nfs类型的后端存储,1g存储空间,访问模式为ReadWriteOnce,保留策略为Retain,对应文件如下
[root@master01 pv]# cat pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv01 #pv名称
spec:
capacity: #存储能力,一个pv对象都要指定一个存储能力,目前仅支持存储空间的设置
storage: 5Gi #存储空间
accessModes:
- ReadWriteOnce #访问模式
persistentVolumeReclaimPolicy: Retain #保留策略
nfs: #服务模式 (nfs、ceph、hostpath等)
path: /data/volumes/pv01 #共享数据目录挂载点
server: yunwei.host.com #nfs服务器地址
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv02
spec:
capacity:
storage: 4Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
nfs:
path: /data/volumes/pv02
server: yunwei.host.com
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv03
spec:
capacity:
storage: 5Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
nfs:
path: /data/volumes/pv03
server: yunwei.host.com
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv04
labels:
pvname: pv04 #定义pv04一个标签,后面pvc如果要指定这个pv04的pv,可以通过选择器选择这个标签。
spec:
capacity:
storage: 6Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
nfs:
path: /data/volumes/pv04
server: yunwei.host.com
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv05
spec:
capacity:
storage: 2Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
nfs:
path: /data/volumes/pv05
server: yunwei.host.com
---
## 创建pv
[root@master01 pv]# kubectl apply -f pv.yaml
persistentvolume/pv01 created
persistentvolume/pv02 created
persistentvolume/pv03 created
persistentvolume/pv04 created
persistentvolume/pv05 created
[root@master01 pv]# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pv01 5Gi RWO Retain Available 8m29s
pv02 4Gi RWO Retain Available 8m28s
pv03 5Gi RWO Retain Available 8m28s
pv04 6Gi RWO Retain Available 8m27s
pv05 2Gi RWO Retain Available 8m27s
# 参数解释
pv1 名称
1Gi 代表存储空间大小
RWO 访问模式(ReadWriteOnce缩写)
Recycle 回收策略
Available PV状态
capacity: 属性来设置存储空间,目前仅支持storage=数据大小,未来可能会加入IOPS、吞吐量等指标配置
AccessModes : 访问模式
AccessModes : 是用来对PV进行访问模式的设置,用于描述用户应用对存储资源的访问权限
ReadWriteOnce (RWO): 读写权限,但是只能被单个节点挂载
ReadOnlyMany (ROX): 只读权限,可能被多个节点挂载
ReadWriteMany (RWX): 读写权限,可以被多个节点挂载
注意:一些PV可能支持多种访问模式,但挂载的时候只可以使用一种访问模式,多种访问模式不会生效
常用的Volume插件支持的访问模式(需要根据我们配置的类型进行选择对应的访问模式)
persistentVolumeReclaimPolicy : 回收策略
Retain : (保留) 保留数据,需要管理员手动清理
Recycle : (回收) 清除PV中的数据,效果相当于执行删除命令
Delete (删除) 与PV相连的后端存储完成volume的删除操作,常见于云服务商的存储服务
注意: 目前只有NFS和HostPath两类支持回收策略,一般设置Retain比较保险
状态
1.Available (可用): 表示可用状态,还未被任何PVC绑定
2.Bound (已绑定):已经绑定到某个PVC
3.Released (已释放):对应的PVC已经删除,但资源还没有被集群收回
4.Failed : PV自动回收失败
四.创建pvc,
注意,当我们pvc申请的容量小于我们pv的容量是可以进行绑定的,当我们申请pvc的容量大于pv的容量是无法进行绑定的。 这里需要注意
[root@master01 pv]# cat pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc01 #pvc名称
spec:
accessModes:
- ReadWriteOnce #访问模式
resources:
requests:
storage: 5Gi #创建的pvc容量要求5G,下面选择的pv,一定要大于5G的存储量。否则会报错,
selector:
matchLabels:
pvname: pv04 #pvc01选择了有定义labels为:pvname: pv04 的pv
---
#查看创建的pvc01绑定了pv04这个pv,说明配置没问题。
[root@master01 pv]# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
pvc01 Bound pv04 6Gi RWO 5m15s
4.Deployment引用pvc
[root@master01 pv]# cat nginx-dp-service-pvc.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-pvc
spec:
replicas: 2
selector:
matchLabels:
app: nginx-pvc
template:
metadata:
labels:
app: nginx-pvc
spec:
containers:
- name: myapp
image: harbor.od.com/kubeadm/myapp:v1
image:ikubernetes:myapp:v1
ports:
- containerPort: 80
volumeMounts: #挂载,首先添加需要挂载的目录
- name: pvc-nginx #挂载存储卷pvc01到容器目录
mountPath: /usr/share/nginx/html #挂载容器里的路径
volumes: #指定pvc的volumes
- name: pvc-nginx #指定存储卷的名称
persistentVolumeClaim: #将镜像中的nginx目录挂载到下面名称的pvc中
claimName: pvc01 #绑定pvc名称为:pvc01
---
apiVersion: v1
kind: Service
metadata:
name: nginx-pvc-service
labels:
app: nginx-pvc-service #被后面ingress选择器选择这个labels
spec:
type: NodePort
ports:
- port: 80
targetPort: 80
selector:
app: nginx-pvc
[root@master01 pv]# kubectl apply -f nginx-dp-service-pvc.yaml
[root@master01 pv]# kubectl get pods|grep nginx-pvc
nginx-pvc-5fdd4f6c8f-rpwp7 1/1 Running 0 10m
nginx-pvc-5fdd4f6c8f-snfkf 1/1 Running 0 10m
[root@master01 pv]# kubectl get svc|grep nginx-pvc
nginx-pvc-service NodePort 10.111.232.28 <none> 80:32357/TCP 7m10s
#由于nfs的pv04的目录挂载容器/usr/share/nginx/html目录下,是没有任何文件的。容器也不会自动产生文件,所以只能手动产生
yunwei主机操作
[root@yunwei ~]# cd /data/volumes/pv04
[root@yunwei pv04]# echo "10.4.7.51" > index.html
[root@yunwei pv04]# cat index.html
10.4.7.51
#master节点操作
[root@master01 pv]# kubectl get svc|grep nginx-pvc
nginx-pvc-service NodePort 10.111.232.28 <none> 80:32357/TCP 7m10s
[root@master01 pv]# curl 10.4.7.49:32357
10.4.7.51
[root@master01 pv]# curl 10.111.232.28:80
10.4.7.51
五:同时配置ingress,查看secret,使用tls
1.自签证书,创建私钥
[root@master01 tls]# openssl genrsa -out tls.key 2048
Generating RSA private key, 2048 bit long modulus
....................................................................................................................+++
......+++
e is 65537 (0x10001)
#通过私钥生成tomcat.od.com这个域名的证书,有效期设置10年。
[root@master01 tls]# openssl req -new -x509 -days 3650 -key tls.key -out nginxpvc.crt -subj /C=CN/ST=Beijing/O=DevOps/CN=nginxpvc.od.com
[root@master01 ssl]# ll
total 8
-rw-r--r-- 1 root root 1237 Dec 16 13:26 tls.crt
-rw-r--r-- 1 root root 1675 Dec 16 12:26 tls.key
#查看证书有效期
[root@master01 ssl]# openssl x509 -noout -text -in tls.crt
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
ac:97:46:33:e0:d1:6c:46
Signature Algorithm: sha256WithRSAEncryption
Issuer: C=CN, ST=Beijing, O=DevOps, CN=tomcat.od.com
Validity
Not Before: Dec 16 05:26:22 2021 GMT
Not After : Dec 14 05:26:22 2031 GMT
Subject: C=CN, ST=Beijing, O=DevOps, CN=tomcat.od.com
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
#创建secret对象,把这些证书添加到ingress对象里,默认是default名称空间。
[root@master01 tls]# kubectl create secret tls nginx-ingress-secret --cert=nginxpvc.crt --key=tls.key
secret/nginx-ingress-secret created
[root@master01 tls]# kubectl get secret |grep nginx-ingress-secret
NAME TYPE DATA AGE
nginx-ingress-secret kubernetes.io/tls 2 9s
[root@master01 tls]# kubectl describe secret nginx-ingress-secret
Name: nginx-ingress-secret
Namespace: default #secret跟pod,deployment,service最好同一个名称空间
Labels: <none>
Annotations: <none>
Type: kubernetes.io/tls
Data
====
tls.crt: 1237 bytes
tls.key: 1675 bytes
[root@master01 pv]# cat nginx-pvc-ingress.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: nginx-tls-ingress
namespace: default
annotations:
kubernets.io/ingress.class: "nginx"
spec:
tls:
- hosts:
- nginxpvc.od.com
secretName: nginx-ingress-secret
rules:
- host: nginxpvc.od.com
http:
paths:
- path: /
backend:
serviceName: nginx-pvc-service #选择同一名称空间servie资源的名字或者labels,
servicePort: 80
[root@master01 pv]#
[root@master01 pv]# kubectl apply -f nginx-pvc-ingress.yaml
ingress.extensions/nginx-tls-ingress created
[root@master01 pv]# kubectl get ingress
NAME CLASS HOSTS ADDRESS PORTS AGE
nginx-tls-ingress <none> nginxpvc.od.com 10.99.155.170 80, 443 89s
#nginxpvc.od.com域名解析
[root@master01 tls]# cat /var/named/od.com.zone
nginxpvc A 10.4.7.51
[root@master01 tls]# systemctl restart named
#访问命令行或者浏览器: https://nginxpvc.od.com/
[root@master01 tls]# curl -k https://nginxpvc.od.com/
10.4.7.51
#pv信息,pv04这个pv被pvc01绑定
[root@master01 pki]# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pv01 5Gi RWO Retain Available 4h23m
pv02 4Gi RWO Retain Available 4h23m
pv03 5Gi RWO Retain Available 4h23m
pv04 6Gi RWO Retain Bound default/pvc01 4h23m
pv05 2Gi RWO Retain Available 4h23m