侧边栏壁纸
  • 累计撰写 51 篇文章
  • 累计创建 23 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

K8s 共享存储3

zhanjie.me
2020-11-18 / 0 评论 / 0 点赞 / 0 阅读 / 0 字

3.1 StorageClass 详解

StorageClass 是用于对存储资源的抽象定义,与 PVC 申请绑定后,就可以屏蔽后端存储的细节,这样也可以减轻管理员手动创建 PV 的过程,交给集群自动创建并绑定 PV。由于这种方式更加方便,所以在实际的生产过程中应用地更加广泛。

示例

下面是一个配置示例:

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata: # StorageClass 的名称为 standard
  name: standard
provisioner: kubernetes.io/aws-ebs # 存储资源提供者
parameters: # 参数
  type: gp2
reclaimPolicy: Retain # 回收策略
allowVolumeExpansion: true # 允许容量扩展
mountOptions: # 挂载选项
  - debug
volumeBindingMode: Immediate # 卷绑定模式

这其中涉及到了比较多的字段选项,下面来一一详解。

provisioner(存储资源提供者)

这是必填的字段,也可以认为这里需要指明的是后端存储驱动。集群支持的存储卷都以 kubernetes.io/ 开头,当然也可以自定义后端存储卷。

parameters(参数)

不同的存储资源提供者,需要设置不同的参数。如果不显性设置参数的话,就会使用这些参数的默认值。

reclaimPolicy(回收策略)

使用这个字段指定回收策略,可选的值有:

  • Delete:删除。如果没有指定回收策略的话,默认为删除。
  • Retain:保留。

allowVolumeExpansion(允许容量扩展)

PV 可以被设置为可扩展的。当设置这个值为 true 时,可以在 PVC 资源对象中调整卷的大小(只能增加,不能减少)。

支持扩展的存储卷有:gcePersistentDisk、awsElasticBlockStore、Cinder、glusterfs、rbd、Azure File、Azure Disk、Portworx、CSI。

mountOptions(挂载选项)

通过这个字段可以指定卷挂载选项。

需要注意的是:如果定义了挂载选项,但是卷插件不支持,那么挂载 PV 将会失败。

volumeBindingMode(卷绑定模式)

这个字段用于设置动态配置和卷绑定的发生时间。有两个可选值:

  • Immediate:立即绑定模式。创建 PVC 以后立刻执行动态配置和卷绑定。但是如果集群中的存储卷不能全局访问所有的 Node 节点,PV 会在不知道 Pod 调度需求的情况下进行绑定,这可能导致 Pod 无法调度。
  • WaitForFirstConsumer:延迟绑定模式。这个模式可以解决上面提到的问题,在这种模式下会延迟 PV 的配置和绑定,直到引用 PVC 的 Pod 被成功创建。

有这些存储插件支持 WaitForFirstConsumer 模式的配置:AWSElasticBlockStore、GCEPersistentDisk、AzureDisk、Local。

allowedTopologies(允许的拓扑)

通常情况下,如果指定了 WaitForFirstConsumer 卷绑定模式,就不需要再限制拓扑结构了。但是在某些特定的情况下依然可以使用这个字段进行限制,配置示例如下:

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: standard
provisioner: kubernetes.io/gce-pd
parameters:
  type: pd-standard
volumeBindingMode: WaitForFirstConsumer
allowedTopologies: # 限定允许的拓扑结构
  - matchLabelExpressions:
      - key: failure-domain.beta.kubernetes.io/zone
        values:
          - us-centrall-a
          - us-centrall-b

3.2 不同存储卷的配置参数

由于不同的存储类需要配置的参数也是不同的,这里简单举例几个不同类型存储卷的参数配置。后续需要使用到的话,也可以再查询相关文档。

Local

Local 卷目前不支持动态配置,但是可以通过创建 StorageClass 来延迟卷绑定直到 Pod 调度。这样可以让 PVC 绑定 PV 时考虑到 Pod 的所有调度约束。

示例如下:

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: local-storage
provisioner: kubernetes.io/no-provisioner
volumeBindingMode: WaitForFirstConsumer

AWS EBS

具体可以参考官方文档 Amazon EBS 卷类型

示例如下:

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: slow
provisioner: kubernetes.io/aws-ebs
parameters:
  type: io1
  iopsPerGB: "10"
  fsType: ext4

其中参数代表的含义分别为:

  • type:类型。可选项有:io1、gp2、sc1、st1,默认值为 gp2。
  • iopsPerGB:这个参数只用于 io1 类型的卷,表示每秒每 GiB 的 I/O 操作数量。
  • fsType:kubernetes 支持,默认值为:ext4。
  • encrypted:卷是否加密,可选项为 "true" 或是 "false"。
  • kmsKeyId:加密卷时使用的完整的 Amazon Resource Name。

GCE PD(Google Compute Engine Persistent Disk)

示例如下:

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: slow
provisioner: kubernetes.io/gce-pd
parameters:
  type: pd-standard
  replication-type: none

其中参数代表的含义分别为:

  • type:类型。可选项有:pd-standard 或 pd-ssd。默认值为:pd-standard。
  • replication-type:复制类型。可选项有:none(提供一个普通 PD) 或 regional-pd(提供一个个区域性的 PD,然后使用 zones 字段指定区域)。

GlusterFS

具体可以查看官方文档 GlusterFS DocumentationRESTful based volume management framework for GlusterFS -- Heketi

示例如下:

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: slow
provisioner: kubernetes.io/glusterfs
parameters:
  resturl: "http://127.0.0.1:8081"
  clusterid: "630372ccdc720a92c681fb928f27b53f"
  restauthenabled: "true"
  restuser: "admin"
  secretNamespace: "default"
  secretName: "heketi-secret"
  gidMin: "40000"
  gidMax: "50000"
  volumetype: "replicate:3"

其中参数代表的含义分别为:

  • resturl:Gluster REST 服务(Heketi 服务)的 URL 地址,通常它的格式为 IP 地址:端口号,主要用于自动完成 GlusterFSvolume 的设置。
  • clusterid:集群 ID。Heketi 在配置卷时会使用这个 ID。
  • restauthenabled:是否对 Gluster REST 服务启用安全验证。
  • restuser:访问 Gluster REST 服务的用户名。
  • secretNamespace 和 secretName:标识 Secret 实例。其中保存的是访问 Gluster REST 服务密码的 Secret 资源对象名。
  • gidMin 和 gidMax:StorageClass 的 GID 范围,用于动态资源供应时为 PV 设置 GID。
  • volumetype:设置 GlusterFS 内部的 Volume 类型,有 3 个参数值可选:
  • Replica 类型:replicate:3 表示有 3 份副本。
  • Disperse 类型:disperse:4:2 表示有 4 份数据,其中 2 份属于冗余数据。
  • Distribute 类型:none。

3.3 动态存储管理实例

StatefulSet 是用来部署有状态服务的,通常会使用本地持久存储卷用于保存服务的状态。

整个的流程为:

  • 创建本地持久存储卷
  • 将本地持久存储卷绑定到 Node 上
  • 创建 StatefulSet

创建 local PV,新建 local-storage.yaml 文件,并向其中写入如下代码:

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: local-storage
# provisioner 的值为 kubernetes.io/no-provisioner,因为 local pv 不支持 Dynamic Provisioning,不能在创建 pvc 的时候自动创建 pv
provisioner: kubernetes.io/no-provisioner
# 使用延迟卷绑定功能,将 volume binding 延迟至 pod scheduling 阶段执行
volumeBindingMode: WaitForFirstConsumer

执行创建:

$ kubectl create -f local-storage.yaml
storageclass.storage.k8s.io/local-storage created

然后在每个 Node 上创建一个 PV,新建 local-pv.yaml 文件,并向其中写入如下内容:

---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: local-pv1
spec:
  capacity:
    storage: 1Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: local-storage
  # local.path 指明对应的磁盘路径
  local:
    path: /tmp
  # spec.nodeAffinity 指定对应的 node
  nodeAffinity:
    required:
      nodeSelectorTerms:
        - matchExpressions:
            - key: kubernetes.io/hostname
              operator: In
              values:
                - kubesphere02
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: local-pv2
spec:
  capacity:
    storage: 1Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: local-storage
  local:
    path: /tmp
  nodeAffinity:
    required:
      nodeSelectorTerms:
        - matchExpressions:
            - key: kubernetes.io/hostname
              operator: In
              values:
                - kubesphere03

上面的配置会在 kubesphere02 和 kubesphere03 两个 Node 上分别创建一个 PV。其中,存储类 spec.storageClassName 用的是前面启用的 local-storage, spec.capacity.storage 指定了容量为 1G,挂载路径 spec.local.path 为 /tmp(该路径需要在 Node 上存在)。

执行创建:

$ kubectl create -f local-pv.yaml
persistentvolume/local-pv1 created
persistentvolume/local-pv2 created

$ kubectl get pv
NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM        STORAGECLASS    REASON   AGE
local-pv1                                  1Gi        RWO            Retain           Available                local-storage            17s
local-pv2                                  1Gi        RWO            Retain           Available                local-storage            17s

可以看到两个 PV 都已创建成功,其状态为可用(Available),底层资源提供者为 local-storage。

创建有状态集合,新建 web.yaml 文件,并向其中写入如下代码:

apiVersion: v1
kind: Service
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  ports:
    - port: 80
      name: web
  clusterIP: None
  selector:
    app: nginx
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: web
spec:
  serviceName: "nginx"
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: mirrorgooglecontainers/nginx-slim:0.8
          ports:
            - containerPort: 80
              name: web
          volumeMounts:
            - name: www
              mountPath: /usr/share/nginx/html
  volumeClaimTemplates:
    - metadata:
        name: www
      spec:
        accessModes:
          - ReadWriteOnce
        storageClassName: local-storage
        resources:
          requests:
            storage: 10Mi

其中 Service 的 clusterIP 指定为 None,表示它是一个 Headless Service,集群不用为它分配 IP。StatefulSet 包含 2 个 Pod 副本,它们的名字分别为 web-0 和 web-1,并且都挂载了一个 PV。不管 Pod 被重新调度到哪个节点,Pod 的名字和挂载的 PV 都将跟之前保持一致。

在执行创建之前可以监听 Pod 的创建过程,在一个新的终端执行如下命令:

$ kubectl get pods -w -l app=nginx

然后执行创建:

$ kubectl create -f web.yaml
service/nginx created
statefulset.apps/web created

这个时候可以看到整个的创建过程:

$ kubectl get pods -w -l app=nginx
NAME    READY   STATUS    RESTARTS   AGE
web-0   0/1     Pending   0          0s
web-0   0/1     Pending   0          1s
web-0   0/1     ContainerCreating   0          1s
web-0   0/1     ContainerCreating   0          2s
web-0   1/1     Running             0          14s
web-1   0/1     Pending             0          0s
web-1   0/1     Pending             0          1s
web-1   0/1     ContainerCreating   0          1s
web-1   0/1     ContainerCreating   0          1s
web-1   1/1     Running             0          11s

查看创建的 Headless Service 和 StatefulSet:

$ kubectl get service nginx
NAME    TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
nginx   ClusterIP   None         <none>        80/TCP    100s
$ kubectl get statefulset web
NAME   READY   AGE
web    2/2     108s

查看根据 volumeClaimTemplates 自动创建 PVC:

# PVC 名称的格式为:$(volumeClainTemplates.name)-(pod_name),这里 volumeClainTemplates.name 为 www,pod_name 为 web-[0-1]
$ kubectl get pvc
NAME        STATUS   VOLUME      CAPACITY   ACCESS MODES   STORAGECLASS    AGE
www-web-0   Bound    local-pv2   1Gi        RWO            local-storage   2m43s
www-web-1   Bound    local-pv1   1Gi        RWO            local-storage   2m29s

查看创建的 Pod,它们都是有序的:

# Pod 名称的格式为:$(StatefulSet 名称)-$(序号),这里为:web-0、web-1
$ kubectl get pods -l app=nginx
NAME    READY   STATUS    RESTARTS   AGE
web-0   1/1     Running   0          3m43s
web-1   1/1     Running   0          3m29s
0

评论区