当前位置: 首页 > 工具软件 > K8STARS > 使用案例 >

【云原生 | Kubernetes 实战】13、K8s 常见的存储方案及具体应用场景分析(下)

冯星剑
2023-12-01

目录

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 


k8s 存储类:storageclass

        前面文章介绍的 PV 和 PVC 模式都是需要先创建好 PV,然后定义好 PVC 和 pv 进行一对一的 Bond,但是如果 PVC 请求成千上万,那么就需要创建成千上万的 PV,对于运维人员来说维护成本很高。Kubernetes 提供一种自动创建 PV 的机制,叫 StorageClass,它的作用就是创建 PV的模板。k8s 集群管理员通过创建 storageclass 可以动态生成一个存储卷 pv 供 k8s pvc 使用。

        每个 StorageClass 都包含 provisionerparameters 和 reclaimPolicy 字段, 这些字段会在 StorageClass 需要动态制备 PersistentVolume 时会使用到。 

具体来说,StorageClass 会定义以下两部分:

  1. PV 的属性 ,比如存储的大小、类型等;
  2. 创建这种 PV 需要使用到的存储插件,比如 Ceph、NFS 等。

        有了这两部分信息,Kubernetes 就能够根据用户提交的 PVC,找到对应的 StorageClass,然后 Kubernetes 就会调用 StorageClass 声明的存储插件,创建出需要的 PV。 

1.1 存储制备器 

        每个 StorageClass 都有一个制备器或者也叫供应商(Provisioner),用来决定使用哪个卷插件制备 PV。 该字段必须指定。

        storageclass 需要有一个供应者,用来确定我们使用什么样的存储来创建 pv,常见的provisioner 如下:(“ √ ” 为内部供应商,“ - ” 为外部供应商)

卷插件内置制备器配置例子
AWSElasticBlockStoreAWS EBS
AzureFileAzure File
AzureDiskAzure Disk
CephFS--
CinderOpenStack Cinder
FC--
FlexVolume--
GCEPersistentDiskGCE PD
GlusterfsGlusterfs
iSCSI--
NFS-NFS
RBDCeph RBD
VsphereVolumevSphere
PortworxVolumePortworx 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 

1.2 回收策略 

        由 StorageClass 动态创建的 PersistentVolume 会在类的 reclaimPolicy 字段中指定回收策略,可以是 Delete 或者 Retain。如果 StorageClass 对象被创建时没有指定 reclaimPolicy,它将默认为 Delete

通过 StorageClass 手动创建并管理的 PersistentVolume 会使用它们被创建时指定的回收策略。

1.3 允许卷扩展 

PersistentVolume 可以配置为可扩展。将此功能设置为 true 时,允许用户通过编辑相应的 PVC 对象来调整卷大小。

当下层 StorageClass 的 allowVolumeExpansion 字段设置为 true 时,以下类型的卷支持卷扩展:

卷类型Kubernetes 版本要求
gcePersistentDisk1.11
awsElasticBlockStore1.11
Cinder1.11
glusterfs1.11
rbd1.11
Azure File1.11
Azure Disk1.11
Portworx1.11
FlexVolume1.13
CSI1.14 (alpha), 1.16 (beta)

说明:此功能仅可用于扩容卷,不能用于缩小卷。

二、安装 nfs provisioner 用于配合存储类动态生成 pv 

Kubernetes 不包含内部 NFS 驱动。你需要使用外部驱动为 NFS 创建 StorageClass。 这里有些例子:

本次使用 NFS subdir 外部驱动为例。

nfs-subdir-external-provisioner.tar.gz 文件下载地址:https://download.csdn.net/download/weixin_46560589/87315292

2.1 把 nfs-subdir-external-provisioner.tar.gz 上传到 node2 和 node1 上,手动解压。 

[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

2.2 创建运行 nfs-provisioner 需要的 sa 账号 

[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 就有了我们指定的账户的权限了。

2.3 对 sa 授权

[root@k8s-master01 volumes]# kubectl create clusterrolebinding nfs-provisioner-clusterrolebinding --clusterrole=cluster-admin --serviceaccount=default:nfs-provisioner

2.4 安装 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   <none>           <none>

三、创建 storageclass 动态供给 pv

[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

四、创建 pvc 通过 storageclass 动态生成 pv 

[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 自动生成的。

步骤总结:

  1. 创建供应商:创建一个 nfs provisioner
  2. 创建 storageclass,storageclass 指定刚才创建的供应商
  3. 创建 pvc,这个 pvc 指定 storageclass

五、创建 pod 挂载 storageclass 动态生成的 pvc:test-claim1 

[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博客

 类似资料: