Pvc持久卷
PVC存储:
存储卷工作原理:
- 一个pod创建时,同时创建存储卷,根据类型访问定义好的存储类型
- 存储卷需提前手动创建出来

使用原理:
- pod中创建存储卷
- 容器绑定使用同一pod内的存储卷
- pvc创建申请pv请求
- 按工作逻辑,划分空间
存储类:
根据各种存储进行分类,如nfs分类为网络存储,硬盘分类为物理存储
存储类是对pv进行自动管理,无需再手动创建pv和pvc绑定,当pod申请pvc时,如果存储类空间满足,会通过存储类创建pv并绑定pvc
存储类只能在创建时设置类的名称和其他参数,创建后不能再更新。可以为不请求绑定任何特定存储类的 PVC 指定默认sc
文档: https://kubernetes.io/docs/concepts/storage/storage-classes/
配置语法:
kubectl explain sc
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: standard
provisioner: #制备器(Provisioner),用来决定使用哪个卷插件制 PV。 该字段必须指定,每个不同的插件,参数可能不同
#example.com/external-nfs,nfs存储插件,由于没有内置nfs插件,需额外部署使用:nfs-ganesha-server-and-external-provisioner插件,文档:https://github.com/kubernetes-sigs/nfs-ganesha-server-and-external-provisioner
#nfs.csi.k8s.io,nfs-csi驱动提供,github安装:https://github.com/kubernetes-csi/csi-driver-nfs
#kubernetes.io/gce-pd,GCE PD存储插件
#kubernetes.io/aws-ebs,aws存储插件
#kubernetes.io/cinder,openstack
#kubernetes.io/rbd
#kubernetes.io/no-provisioner,本地卷不支持动态配置,但可以实现延迟pvc绑定,WaitForFirstConsumer卷绑定模式时才能使用
parameters: #provisioner可以接受不同的参数
---aws
type: gp2 #硬盘类型,gp2和gp3为通用固态硬盘,默认为gp2,更多了解aws文档:https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/EBSVolumeTypes.html
#io1
#gp2
#sc1
#st1
iopsPerGB: "i/o操作数" #仅适用于io1卷。每GiB每秒的I/O操作数。 AWS卷插件将此乘以请求卷的大小以计算卷的 IOPS并将其上限为20000 IOPS(AWS 支持的最大值,请参阅 AWS 文档)。字符串类型:"10"
fsType: 文件系统 #默认ext4,必须是当前系统支持的
encrypted: 布尔值字符串 #是否进行加密,字符串类型:"true"
---nfs---
server: nfs主机
path: 共享路径
readOnly: "true" #默认false只读挂载
---openstack
availability: nova
---ceph-rbd
monitors: ip:6789,ip2:port #Ceph 监视器字符串,多个用","分隔
adminId: admin #可在存储池中创建图像的Ceph管理员
adminSecretName: ceph-admin-secret #secret名称。此参数是必需的。提供的秘密必须具有类“kubernetes.io/rbd”
adminSecretNamespace: ceph #adminSecretName的命名空间。默认为“默认”
pool: k8s-rbd #Ceph RBD 池。默认为“rbd”
userId: k8s-user #ceph普通用户,客户端挂载使用此
userSecretName: ceph-user #secret名称
userSecretNamespace: default
fsType: ext4 #文件系统类型,默认ext4
imageFormat: "2" #Ceph RBD 镜像格式,“1”或“2”。默认值为“2”
imageFeatures: "layering" #rbd启用新特性,参数可选,仅当将imageFormat设置为“2”时才使用。目前仅支持有 layering 。默认为“”,不开启任何功能
reclaimPolicy: 回收策略
#Retain,保留
#Delete,删除
allowVolumeExpansion: 布尔值 #true时,允许用户通过编辑相应的 PVC 对象来调整卷的大小,只能增大,不能缩小
mountOptions: #指定pv选项,挂载选项无效会导致挂载失败
- debug
volumeBindingMode: 模式 #控制何时应该进行卷绑定和动态配置。未设置时,默认使用立即配置模式
#Immediate,表示一旦创建pvc就进行卷绑定和动态配置。对于拓扑受限且无法从集群中的所有节点全局访问的存储后端,PersistentVolumes将在不知道Pod的调度要求的情况下被绑定或配置。这可能会导致不可调度的Pod
#WaitForFirstConsumer,可解决上面问题,延迟pv的绑定和配置,直到有pod要使用pvc时再创建创建。pv将根据Pod的调度约束指定的拓扑来选择或配置。这些包括但不限于资源要求、节点选择器、pod亲和力和反亲和力以及污点和容忍度
这些插件支持该模式动态配置:
AWSElasticBlockStore AWSElasticBlockStore
GCEPersistentDisk
AzureDisk
静态配置(创建时就指定):
Local
上面所有
allowedTopologies: #WaitForFirstConsumer卷绑定模式时的额外配置,可选项
- matchLabelExpressions: #如配置标签选择器
注意:如果卷绑定模式使用 WaitForFirstConsumer ,不能在pod定义中使用 nodeName 来指定节点亲和性。会导致调度器将被绕过,PVC 将保持在 pending 状态,应该使用节点选择器来实现类似的功能
apiVersion: v1
kind: Pod
spec:
nodeSelector:
kubernetes.io/hostname: kube-01
pvc资源:
pvc是不属于集群资源,只能在namespace中使用
pvc动态空集:
- pod创建时,指定要用的空间,pvc去存储类中申请空间,存储类根据pod需要的pvc大小自动分配其刚好满足条件的pv(空间)
- 存储类是一个抽象层,是存储设备的抽象化,把所有存储放在存储类中定义
- pvc对存储和使用进行了解耦,pvc在pod中定义,pv在pod外用于绑定存储,存储是自己准备,如硬盘、nfs等。访问时pv自动根据pvc的需求创建空间,不在关注存储,只需关注pvc容量(类似lvm,只需关注lvm,不用关注vg)
- 动态pvc对存储有很高的要求,glusterfs、ceph等支持
pvc与pv的关系:
- pvc使用一个pv时,pv就处于绑定状态,不能再提供给其他pvc使用
- 但一个pvc可以为多个pod提供使用
配置语法:
kubectl explain pvc.spec
kind: persistentvolumeclaims
spec:
accessModes <[]string> #访问模型,必须能先满足pv的访问模型
dataSource <Object>
resources <Object> #资源限制,最少使用多少
requests: #需要的最小资源
storage: 大小 #数据卷的大小
selector #对pv的标签选择器
matchExpressions: #正则匹配
matchLabels: #用于匹配pv的标签
name: value
...
storageClassName <string> #存储类名称
volumeMode <string> #存储卷的模式,允许使用哪些类型的卷
volumeName <string> #存储卷名称,精确匹配,允许使用哪些卷
pv资源:
pv的定义与普通存储卷是一样的,包括大部分方法
pv属于集群资源,可以给所有资源使用,所以不能定义在namespace中
创建方式:
- 静态,手动创建pv,绑定pvc
- 动态,通过定义存储类,自动创建pv
pv不同存储支持的访问模型:
https://kubernetes.io/docs/concepts/storage/persistent-volumes/#access-modes
pv数据回收策略:
- 保留(Retain),pod删除,数据保留
- 回收(Recycle),数据清空,保持空闲状态
- 删除(Delete),pv删除
配置语法:
kubectl explain pv.spec
kind: persistentvolumes
spec:
accessModes <[]string> #pv访问模型
#ReadWriteOnce,简写:RWO,单节点读写
#ReadOnlyMany,简写:ROX,多节点只读
#ReadWriteMany,简写:RWX,多节点读写
#ReadWriteOncePod,简写:RWOP,单pod读写,仅支持CSI接口和k8s-1.22版本以上
capacity <map[string]string> #pv大小
storage: 大小
#单位Ki、Mi、Gi、Ti、Pi、Ei按1024计算
#单位m、k、M、G、T、P、E按1000计算
persistentVolumeReclaimPolicy: 回收策略 #前提条件是,底层存储支持这些策略:https://kubernetes.io/docs/concepts/storage/persistent-volumes#reclaiming
#Retain,手动创建的pv,不再用时默认用此
#Delete,动态配置的pv,不再用时默认用此
案例:
例1: 基于nfs,创建pv、pvc
1)安装nfs,配置nfs
yum install -y nfs-utils
mkdir -p /data/nfs
echo '/data/nfs 2.2.0.0/16(rw,no_root_squash)' >> /etc/exports
exportfs -av
2)添加nfs到pv
apiVersion: v1
kind: PersistentVolume
metadata:
name: nfs-pv
labels:
pv: nfs-pv
spec:
nfs:
server: 2.2.2.10
path: /data/nfs
accessModes:
- ReadWriteMany
- ReadOnlyMany
capacity:
storage: 1Gi
3)创建pvc,pod中挂载pvc
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: nfs-pvc
labels:
pvc: nfs-pvc
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 100Mi
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: ngx-dep
spec:
replicas: 2
selector:
matchLabels:
app: ngx-dep
template:
metadata:
labels:
app: ngx-dep
spec:
volumes:
- name: web
persistentVolumeClaim:
claimName: nfs-pvc
containers:
- name: ngx
image: nginx
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
volumeMounts:
- name: web
mountPath: /usr/share/nginx/html
例2: 基于nfs,用deployment控制器部署zk集群
1)准备nfs
mkdir -p /data/nfs/zk-{1..3}
echo '/data/nfs 2.2.0.0/16(rw,no_root_squash)' > /etc/exports
systemctl enable --now nfs
showmount -e 127.0.0.1
2)创建pv
apiVersion: v1
kind: PersistentVolume
metadata:
name: zk-pv-1
spec:
capacity:
storage: 2Gi
accessModes:
- ReadWriteOnce
nfs:
path: /data/nfs/zk-1
server: 2.2.2.30
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: zk-pv-2
spec:
capacity:
storage: 2Gi
accessModes:
- ReadWriteOnce
nfs:
path: /data/nfs/zk-2
server: 2.2.2.30
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: zk-pv-3
spec:
capacity:
storage: 2Gi
accessModes:
- ReadWriteOnce
nfs:
path: /data/nfs/zk-3
server: 2.2.2.30
3)创建pvc
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: zk-pvc-1
spec:
volumeName: zk-pv-1
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 2Gi
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: zk-pvc-2
spec:
volumeName: zk-pv-2
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 2Gi
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: zk-pvc-3
spec:
volumeName: zk-pv-3
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 2Gi
4)创建svc
apiVersion: v1
kind: Service
metadata:
name: zk-svc-1
spec:
selector:
app: zk
server-id: "1"
type: NodePort
ports:
- name: client
port: 2181
nodePort: 31000
- name: followers
port: 2888
nodePort: 31001
- name: election
port: 3888
nodePort: 31002
- name: admin
port: 8080
nodePort: 31003
---
apiVersion: v1
kind: Service
metadata:
name: zk-svc-2
spec:
selector:
app: zk
server-id: "2"
type: NodePort
ports:
- name: client
port: 2181
nodePort: 32000
- name: followers
port: 2888
nodePort: 32001
- name: election
port: 3888
nodePort: 32002
- name: admin
port: 8080
nodePort: 32003
---
apiVersion: v1
kind: Service
metadata:
name: zk-svc-3
spec:
selector:
app: zk
server-id: "3"
type: NodePort
ports:
- name: client
port: 2181
nodePort: 33000
- name: followers
port: 2888
nodePort: 33001
- name: election
port: 3888
nodePort: 33002
- name: admin
port: 8080
nodePort: 33003
5)使用deploy控制器创建zk集群
apiVersion: apps/v1
kind: Deployment
metadata:
name: zk-1
spec:
replicas: 1
selector:
matchLabels:
app: zk
template:
metadata:
labels:
app: zk
server-id: "1"
spec:
volumes:
- name: wal
emptyDir:
medium: Memory
- name: zk-pvc-data
persistentVolumeClaim:
claimName: zk-pvc-1
containers:
- name: zk
image: zookeeper:3.4.14
imagePullPolicy: IfNotPresent
ports:
- containerPort: 2181
- containerPort: 2888
- containerPort: 3888
- containerPort: 8080
env:
- name: ZOO_MY_ID
value: "1"
- name: ZOO_SERVERS
value: "server.1=0.0.0.0:2888:3888 server.2=zk-svc-2:2888:3888 server.3=zk-svc-3:2888:3888"
- name: JVMFLAGS
value: "-Xmx300M"
volumeMounts:
- name: zk-pvc-data
mountPath: /data
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: zk-2
spec:
replicas: 1
selector:
matchLabels:
app: zk
template:
metadata:
labels:
app: zk
server-id: "2"
spec:
volumes:
- name: wal
emptyDir:
medium: Memory
- name: zk-pvc-data
persistentVolumeClaim:
claimName: zk-pvc-2
containers:
- name: zk
image: zookeeper:3.4.14
imagePullPolicy: IfNotPresent
ports:
- containerPort: 2181
- containerPort: 2888
- containerPort: 3888
- containerPort: 8080
env:
- name: ZOO_MY_ID
value: "2"
- name: ZOO_SERVERS
value: "server.1=zk-svc-1:2888:3888 server.2=0.0.0.0:2888:3888 server.3=zk-svc-3:2888:3888"
- name: JVMFLAGS
value: "-Xmx300M"
volumeMounts:
- name: zk-pvc-data
mountPath: /data
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: zk-3
spec:
replicas: 1
selector:
matchLabels:
app: zk
template:
metadata:
labels:
app: zk
server-id: "3"
spec:
volumes:
- name: wal
emptyDir:
medium: Memory
- name: zk-pvc-data
persistentVolumeClaim:
claimName: zk-pvc-3
containers:
- name: zk
image: zookeeper:3.4.14
imagePullPolicy: IfNotPresent
ports:
- containerPort: 2181
- containerPort: 2888
- containerPort: 3888
- containerPort: 8080
env:
- name: ZOO_MY_ID
value: "3"
- name: ZOO_SERVERS
value: "server.1=zk-svc-1:2888:3888 server.2=zk-svc-2:2888:3888 server.3=0.0.0.0:2888:3888"
- name: JVMFLAGS
value: "-Xmx300M"
volumeMounts:
- name: zk-pvc-data
mountPath: /data

浙公网安备 33010602011771号