目录
k8s 存储类:storageclass
1.1 存储制备器
1.2 回收策略
1.3 允许卷扩展
二、安装 nfs provisioner 用于配合存储类动态生成 pv
2.1 把 nfs-subdir-external-provisioner.tar.gz 上传到 node2 和 node1 上,手动解压。
2.2 创建运行 nfs-provisioner 需要的 sa 账号
2.3 对 sa 授权
2.4 安装 nfs-provisioner 程序
三、创建 storageclass 动态供给 pv
四、创建 pvc 通过 storageclass 动态生成 pv
步骤总结:
五、创建 pod 挂载 storageclass 动态生成的 pvc:test-claim1
前面文章介绍的 PV 和 PVC 模式都是需要先创建好 PV,然后定义好 PVC 和 pv 进行一对一的 Bond,但是如果 PVC 请求成千上万,那么就需要创建成千上万的 PV,对于运维人员来说维护成本很高。Kubernetes 提供一种自动创建 PV 的机制,叫 StorageClass,它的作用就是创建 PV的模板。k8s 集群管理员通过创建 storageclass 可以动态生成一个存储卷 pv 供 k8s pvc 使用。
每个 StorageClass 都包含 provisioner
、parameters
和 reclaimPolicy
字段, 这些字段会在 StorageClass 需要动态制备 PersistentVolume 时会使用到。
具体来说,StorageClass 会定义以下两部分:
有了这两部分信息,Kubernetes 就能够根据用户提交的 PVC,找到对应的 StorageClass,然后 Kubernetes 就会调用 StorageClass 声明的存储插件,创建出需要的 PV。
每个 StorageClass 都有一个制备器或者也叫供应商(Provisioner),用来决定使用哪个卷插件制备 PV。 该字段必须指定。
storageclass 需要有一个供应者,用来确定我们使用什么样的存储来创建 pv,常见的provisioner 如下:(“ √ ” 为内部供应商,“ - ” 为外部供应商)
卷插件 | 内置制备器 | 配置例子 |
---|---|---|
AWSElasticBlockStore | ✓ | AWS EBS |
AzureFile | ✓ | Azure File |
AzureDisk | ✓ | Azure Disk |
CephFS | - | - |
Cinder | ✓ | OpenStack Cinder |
FC | - | - |
FlexVolume | - | - |
GCEPersistentDisk | ✓ | GCE PD |
Glusterfs | ✓ | Glusterfs |
iSCSI | - | - |
NFS | - | NFS |
RBD | ✓ | Ceph RBD |
VsphereVolume | ✓ | vSphere |
PortworxVolume | ✓ | Portworx Volume |
Local | - | Local |
provisioner 既可以由内部供应商提供,也可以由外部供应商提供,如果是外部供应商可以参考代码仓库 kubernetes-sigs/sig-storage-lib-external-provisioner 包含一个用于为外部制备器编写功能实现的类库。你可以访问代码仓库 kubernetes-sigs/sig-storage-lib-external-provisioner 了解外部驱动列表。
例如,NFS 没有内部制备器,但可以使用外部制备器。 也有第三方存储供应商提供自己的外部制备器。要想使用 NFS,我们需要一个 nfs-client 的自动装载程序,称之为 provisioner,这个程序会使用我们已经配置好的 NFS 服务器自动创建持久卷,也就是自动帮我们创建 PV。
存储制备器官方参考文档:存储类 | Kubernetes
由 StorageClass 动态创建的 PersistentVolume 会在类的 reclaimPolicy
字段中指定回收策略,可以是 Delete
或者 Retain
。如果 StorageClass 对象被创建时没有指定 reclaimPolicy
,它将默认为 Delete
。
通过 StorageClass 手动创建并管理的 PersistentVolume 会使用它们被创建时指定的回收策略。
PersistentVolume 可以配置为可扩展。将此功能设置为 true
时,允许用户通过编辑相应的 PVC 对象来调整卷大小。
当下层 StorageClass 的 allowVolumeExpansion
字段设置为 true 时,以下类型的卷支持卷扩展:
卷类型 | Kubernetes 版本要求 |
---|---|
gcePersistentDisk | 1.11 |
awsElasticBlockStore | 1.11 |
Cinder | 1.11 |
glusterfs | 1.11 |
rbd | 1.11 |
Azure File | 1.11 |
Azure Disk | 1.11 |
Portworx | 1.11 |
FlexVolume | 1.13 |
CSI | 1.14 (alpha), 1.16 (beta) |
说明:此功能仅可用于扩容卷,不能用于缩小卷。
Kubernetes 不包含内部 NFS 驱动。你需要使用外部驱动为 NFS 创建 StorageClass。 这里有些例子:
本次使用 NFS subdir 外部驱动为例。
nfs-subdir-external-provisioner.tar.gz 文件下载地址:https://download.csdn.net/download/weixin_46560589/87315292
[root@k8s-node1 ~]# ctr -n=k8s.io images import nfs-subdir-external-provisioner.tar.gz
[root@k8s-node2 ~]# ctr -n=k8s.io images import nfs-subdir-external-provisioner.tar.gz
[root@k8s-master01 volumes]# vim serviceaccount.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: nfs-provisioner
[root@k8s-master01 volumes]# kubectl apply -f serviceaccount.yaml
serviceaccount/nfs-provisioner created
[root@k8s-master01 volumes]# kubectl get sa
NAME SECRETS AGE
default 0 56d
nfs-provisioner 0 13s
扩展:什么是 sa?(后面文章会讲到)
sa 的全称是 serviceaccount。serviceaccount 是为了方便 Pod 里面的进程调用 Kubernetes API 或其他外部服务而设计的。指定了 serviceaccount 之后,我们把 pod 创建出来了,我们在使用这个pod 时,这个 pod 就有了我们指定的账户的权限了。
[root@k8s-master01 volumes]# kubectl create clusterrolebinding nfs-provisioner-clusterrolebinding --clusterrole=cluster-admin --serviceaccount=default:nfs-provisioner
# 创建目录
[root@k8s-master01 volumes]# mkdir /data/nfs_pro -pv
# 把 /data/nfs_pro 变成 nfs 共享的目录
[root@k8s-master01 volumes]# vim /etc/exports
/data/nfs_pro *(rw,no_root_squash)
# 使其生效
[root@k8s-master01 volumes]# exportfs -arv
exporting *:/data/nfs_pro
# 创建 deployment 资源文件
[root@k8s-master01 volumes]# vim nfs-deployment.yaml
kind: Deployment
apiVersion: apps/v1
metadata:
name: nfs-provisioner
spec:
selector:
matchLabels:
app: nfs-provisioner
replicas: 1
strategy:
type: Recreate
template:
metadata:
labels:
app: nfs-provisioner
spec:
serviceAccount: nfs-provisioner
containers:
- name: nfs-provisioner
image: registry.cn-beijing.aliyuncs.com/mydlq/nfs-subdir-external-provisioner:v4.0.0
imagePullPolicy: IfNotPresent
volumeMounts:
- name: nfs-client-root
mountPath: /persistentvolumes
env:
- name: PROVISIONER_NAME
value: example.com/nfs
- name: NFS_SERVER
value: 192.168.78.133
- name: NFS_PATH
value: /data/nfs_pro
volumes:
- name: nfs-client-root
nfs:
server: 192.168.78.133 # NFS 服务器的主机名或 IP 地址。
path: /data/nfs_pro # NFS 服务器导出的路径。
# 更新资源清单文件
[root@k8s-master01 volumes]# kubectl apply -f nfs-deployment.yaml
deployment.apps/nfs-provisioner created
# 查看 nfs-provisioner 是否正常运行
[root@k8s-master01 volumes]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nfs-provisioner-6fc44b8b68-k8qpm 1/1 Running 0 7s 10.244.169.173 k8s-node2
[root@k8s-master01 volumes]# vim nfs-storageclass.yaml
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
name: nfs
provisioner: example.com/nfs
[root@k8s-master01 volumes]# kubectl apply -f nfs-storageclass.yaml
storageclass.storage.k8s.io/nfs created
[root@k8s-master01 volumes]# kubectl get storageclass
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
nfs example.com/nfs Delete Immediate false 17s
显示内容如上,说明 storageclass 创建成功了。
注意:provisioner 处写的 example.com/nfs 应该跟安装 nfs provisioner 时候的 env下的PROVISIONER_NAME 的 value 值保持一致,如下:
env:
- name: PROVISIONER_NAME
value: example.com/nfs
[root@k8s-master01 volumes]# vim claim.yaml
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: test-claim1
spec:
accessModes: ["ReadWriteMany"]
resources:
requests:
storage: 1Gi
storageClassName: nfs
[root@k8s-master01 volumes]# kubectl apply -f claim.yaml
persistentvolumeclaim/test-claim1 created
# 查看是否动态生成了 pv,pvc 是否创建成功,并和 pv 绑定
[root@k8s-master01 volumes]# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
test-claim1 Bound pvc-a7571e3f-7017-40fa-8e3f-7d96a106450a 1Gi RWX nfs 12s
[root@k8s-master01 volumes]# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pvc-a7571e3f-7017-40fa-8e3f-7d96a106450a 1Gi RWX Delete Bound default/test-claim1 nfs 2m28s
# 宿主机挂载的目录下也自动生成了一个新的目录
[root@k8s-master01 volumes]# ls /data/nfs_pro/
default-test-claim1-pvc-a7571e3f-7017-40fa-8e3f-7d96a106450a
通过上面可以看到 test-claim1 的 pvc 已经成功创建了,绑定的 pv 是 pvc-a7571e3f-7017-40fa-8e3f-7d96a106450a,这个 pv 是由 storageclass 调用 nfs provisioner 自动生成的。
[root@k8s-master01 volumes]# vim read-pod.yaml
kind: Pod
apiVersion: v1
metadata:
name: read-pod
spec:
containers:
- name: read-pod
image: nginx
imagePullPolicy: IfNotPresent
volumeMounts:
- name: nfs-pvc
mountPath: /usr/share/nginx/html
restartPolicy: "Never"
volumes:
- name: nfs-pvc
persistentVolumeClaim:
claimName: test-claim1
[root@k8s-master01 volumes]# kubectl apply -f read-pod.yaml
pod/read-pod created
[root@k8s-master01 volumes]# kubectl get pods | grep read
read-pod 1/1 Running 0 9s
# 进入挂载目录下,创建文件
[root@k8s-master01 volumes]# cd /data/nfs_pro/default-test-claim1-pvc-a7571e3f-7017-40fa-8e3f-7d96a106450a/
[root@k8s-master01 default-test-claim1-pvc-a7571e3f-7017-40fa-8e3f-7d96a106450a]# touch 1.txt
# 进入容器内部查看文件是否同步
[root@k8s-master01 default-test-claim1-pvc-a7571e3f-7017-40fa-8e3f-7d96a106450a]# kubectl exec -it read-pod -- bash
root@read-pod:/# ls /usr/share/nginx/html/
1.txt
上一篇文章:【云原生 | Kubernetes 实战】13、K8s 常见的存储方案及具体应用场景分析(中)_Stars.Sky的博客-CSDN博客
下一篇文章:【云原生 | Kubernetes 实战】14、K8s 控制器 Statefulset 入门到企业实战应用_Stars.Sky的博客-CSDN博客