k8s教程(Volume篇)-动态存储管理案例(GlusterFS)

本文涉及的产品
容器服务 Serverless 版 ACK Serverless,317元额度 多规格
容器服务 Serverless 版 ACK Serverless,952元额度 多规格
简介: k8s教程(Volume篇)-动态存储管理案例(GlusterFS)

01 引言

声明:本文为《Kubernetes权威指南:从Docker到Kubernetes实践全接触(第5版)》的读书笔记

通过前面的博客,大致知道了k8s里面Volume存储的一些概念了,有兴趣的童鞋可以参考下:

本文结合之前的知识,从定义StorageClass、创建 GlusterFSHeketi服务、 用户申请PVC到创建Pod使用存储资源,对StorageClass和动态资源分配进行详细说明。

02 准备工作

首先在各 Node上安装 GlusterFS客户端:

yum install glusterfs glusterfs-fuse

GlusterFS管理服务容器 需要以特权模式运行,在kube-apiserver的启动参数中增加:

--allow-privileged=true

给要部署GlusterFS管理服务的节点打上storagenode=glusterfs标签,是为了GlusterFS容器定向部署到安装了GlusterFS的 Node:

$ kubectl label node k8s-node-1 storagenode=glusterfs 
$ kubectl label node k8s-node-2 storagenode=glusterfs 
$ kubectl label node k8s-node-3 storagenode=glusterfs

03 创建GlusterFS管理服务容器集群

GlusterFS管理服务容器以DaemonSet的方式进行部署,确保在每个Node上都运行—个GlusterFS管理服务

glusterfs-daemonset.yaml的内容如下:

apiVersion: apps/v1 
kind: DaemonSet
metadata:
  name: glusterfs 
    labels:
    glusterfs: daemonset 
  annotations:
    description: GlusterFS Daenonset
    tags: glusterfs
spec:
  template:
    metadata:
      name: glusterfs 
      labels:
        glusterfs-node: pod 
    spec:
      nodeSelector:
        storagenode: glusterfs
      hostNetwork: true 
      containers:
      - image: gluster/gluster-centos:latest 
        name: glusterfs 
        volumeMounts:
        - name: glusterfs-heketi
                mountPath: "/var/lib/heketi" 
              - name: glusterfs-run
                mountPath: "/run"
              - name: glusterfs-lvm
                mount Path: "/run/1vm"
              - name: glusterfs-etc
                mountPath: "/etc/glusterfs" 
              - name: glusterfs-1ogs
                mountPath: "/var/log /glusterfs" 
              - name: glusterfs-config
                mountPath: "/var/lib/glusterd" 
              - name: glusterfs-dev
                mountPath: "/dev"
              - name: glusterfs-misc
                mountPath: "/var/lio/misc/glusterfsd" 
              - name: glusterfs-cgroup
                mountPath: "/sys/fs/cgroup" 
                readonly: true
              - name: glusterfs-ss1
                mountPath: "/etc/ssl"
                readonly: true 
              securityContext:
          capabilities: {}
        privileged: true 
        readinessProbe:
          timeoutSeconds: 3
        initialDelaySeconds: 60 
        exec:
          command:
          - "/bin/bash"
          - "-c"
          - systemctl status glusterd.service 
        livenessProbe:
          timeoutSeconds: 3
        initialDelaySeconds: 60 
        exec:
          command:
          - "/bin/bash"
          - "-c"
          - systemctl status glusterd.service
      volumes:
      - name: glusterfs-heketi 
        hostPath:
        path: "/var/lib/heketi"
      - name: glusterfs-run
      - name: qlusterfs-1vn 
        hostPath:
          path: " /run/1vm"
      - name: glusterfs-etc 
        hostPath:
          path: "/etc/glusterfs"
      - name: glusterfs-1ogs 
        hostPath:
          path:"/var/log/glusterfs"
      - name: glusterfs-config 
        hostPath: 
          path:"/var/lib/glusterd"
      - name: glusterfs-dev 
        hostPath:
          path: "/dev"
      - name: glusterfs-nise 
        hostPath:
          path: "/var/1ib/misc/glusterfsd" 
      - name: glusterfs-cgroup 
        hostPath:
        path: "/sys/fs/cgroup"
      - name: glusterfs-ssl 
        hostPath:
        path: "/etc/ssl"

创建:

$ kubectl create -f glusterfs-daemonset.yaml
daemonset.apps/glusterfs created

查询pod:

$ kubect1 get po
NAME        READY   STATUS     RESTARTS   AGE
glusterfs-k2src   1/1   Running     0     1m
glusterfs-q32z2   1/1   Running     0     1m

04 创建Heketi服务

Heketi是一个 提供RESTful API管理GlusterFS卷的框架,能够在OpenStack、 Kubernetes、 OpenShift等云平台上实现动态存储资源供应,支持GlusterFS多集群管理,便于管理员对GlusterFS进行操作。

下图展示了Heketi的功能:

4.1 创建ServiceAccount及RBAC授权

在部署Heketi服务之前,先创建ServiceAccount并完成RBAC授权:

# heketi-rbac.yam1
apiversion: v1
kind: ServiceAccount
metadata:
name: heketi-service-account
---
apiVersion: rbac.authorization.k8s.io/v1 
kind: Role 
metadata:
  name: heketi 
rules:
  - apiGroups:
  - "" 
  resources:
  - endpoints
    - services
    - pods
    verbs:
    - get
    - list
    - watch
  - apiGroups:
    - ""
    resourees:
    - pods/exec 
    verbs:
    - create
---
apiVersion: rbac.authorization.k8s.io/v1 
kind: RoleBinding 
metadata:
  name: heketi
roleRef:
  apiGroup: rbac.authorization.k8s.io 
  kind: Role
  name: heketi 
subiects:
  - kind: ServiceAccount
    name: heketi-service-account 
    namespace: default

创建:

# kubectl create -f heketi-rbac.yaml
serviceaccount/heketi-service-account created 
role.rbae.authorization.k8s.io/heketi created 
rolebinding.rbac.authorization.k8s.io/heketi created

4.2 部署Heketi服务

# heketi-deployment-svc.yaml
apiVersion: apps/v1
kind: Deployment 
metadata:
  name: heketi 
  labels:
    glusterfs: heketi-deployment
    deploy-heketi: heketi-deployment 
    annotations:
      description: Defines how to deploy Heketi 
  spec:
    replicas: 1 
    seleetor:
      matchLabels:
        name: deploy-heketi
        glusterfs: heketi-pod 
    template:
      metadata:
        name: deploy-heketi 
        labels:
          name: deploy-heketi
          glusterfs: heketi-pod 
      spec:
        serviceAccountName: heketi-service-account 
        containers:
        - image: heketi/heketi
          name: deploy-heketi 
          env:
          - name: HEKETI_EXECUTOR
          value: kubernetes
          - name: HEKETI_FSTAB
          value: "/var/1ib/heketi/fstal"
          - name: HEKETI_SNAPSHOT_LIMIT 
            value: "14"
          - name: HEKETI_KUBE_GLUSTER_DAEMONSET 
            value: "y" 
          ports:
          - containerPort: 8080 
          volumeMounts:
          - name: db
          mountPath: "/var/lib/heketi" 
          readinessProbe:
            timeoutSeconds: 3
            initialDelaySeconds: 3 
            httpGet:
              path: "/hello"
              port: 8080
          livenessProbe:
            timeoutSeconds: 3
            initialDelaySeconds: 30 
            httpGet:
              path: "/hello"
              port: 8080
        volumes:
        - name: db
          hostPath:
            path: "/heketi-datan"
---
kind: Service
apiVersion: v1 
metadata:
  name: heketi 
  labels:
    glusterfs: heketi-service
    deploy-heketi: support 
  annotations:
    description: Exposes Heketi Service 
spec:
  selector:
    name: deploy-heketi 
    ports:
      name: deploy-heketi
      port: 8080
      targetPort: 8080

需要注意的是,Heketi的DB数据需要持久化保存,建议使用hostPath或其他共享存储进行保存:

$ kubect1 create -f heketi-deploymnent-sve.yaml
deployment.apps/heketi created
service/heketi created

05 通过Heketi服务管理GlusterFS集群

Heketi能够管理GlusterFS集群之前,首先要为其设置 GlusterFS集群的信息。可以用一个topology.json配置文件 来完成各个GlusterFS节点和设备的定义,Heketi要求在一个GlusterFS集群中至少有3个节点。

  • 在topologyjson配置文件 hostnames字段的manage上填写主机名;
  • 在storage上填写IP地址;
  • devices要求是未创建文件系统的裸设备(可以有多块盘),以供Heketi自动完成PV (Physical Volume )、 VG( Volume Group ) 和 LV ( Logical Volume )的创建。

topology.json文件的内容如下:

{
  "clusters": [
    {
      "nodes": [
        {
          "node": {
            "hostnames": {
              "manage": [
                "k8s-node-1"
              ],
              "storage": [
                "192.168.18.3"
              ]
            },
            "zoon": 1
          },
          "devices": [
            "/dev/sdb"
          ]
        },
        {
          "node": {
            "hostnames": {
              "manage": [
                "k8s-node-2"
              ],
              "storage": [
                "192.168.18.4"
              ]
            },
            "zoon": 1
          },
          "devices": [
            "/dev/sdb"
          ]
        },
        {
          "node": {
            "hostnames": {
              "manage": [
                "k8s-node-3"
              ],
              "storage": [
                "192.168.18.5"
              ]
            },
            "zoon": 1
          },
          "devices": [
            "/dev/sdb"
          ]
        }
      ]
    }
  ]
}

进入Heketi容器,使用命令行工具heketi-cli完成GlusterFS集群的创建:

$ export HEKETI_CLI_SERVER=http://localhost:8080
$ heketi-cli topology 1oad --json=topology.json
Creating cluster ... ID: f643dalcd64691c5705932a46a95d1d5 
  Creating node k8S-node-1 ID: 883506b09la22bd13f10bc3d0flo51223
  Adding device/dev/sdb OK
  Creating node k8s-node-2 ID: e646879689106£82a9c4ac910a865cc8 
  Adding device/dev/sdb OK
  Creating node k8s-node-3 ID: b7783484180£6a592a30baebfb97d9be 
  Adding device/dev/sdb OK

经过上述操作, Heketi就完成了GlusterFS集群的创建,结果是在GlusterFS集群各个节点的/dev/sdb盘上成功创建了PVVG

查看Heketitopology信息,可以看到NodeDevice的详细信息,包括磁盘空间的大小和剩余空间。此时,GlusterFS的Volume和Brick还未创建:

$ heketi-cli topology info
Cluster Id: £643dalcd64691c5705932a46a95dla5
  Volumes:
  Nodes:
    Node Id: 883506b09la22bd13f10bc3d0fb51223 
    State: online
    Cluster Id: £643dalcd64691¢5705932a46a956105 
    Zone: 1
    Management Hostname: k8s-node -1
    Storage Hostname: 192.168.18.3 
    Devices:
      Id:b474f14b0903ed03ec80d4a989£943£2 
      Name: /dev/ sdb
      State:online Size (GiB):9 
      Used (GiB):0
      Free (GiB):9
    Bricks:
    Node Id: b7783484180£6a592a30baebfb97d9be 
    State: online
    Cluster Id: l643dalcd64691c5705932a46a95a1a5 
    Zone: 1
    Management Hostname: k8s-node-3
    Storage Hostname: 192.168.18.5 
    Devices:
      Id: fac3fa5aclde3d5bde3aa68f6aa61285 
      Name: /dev/sdb
      State:online 
      Size (GiB):9 
      Used (GiB):0 
      Free (GiB):9
    Bricks:

06 定义StorageClass

准备工作已经就绪,集群管理员现在可以在Kubernetes 集群中定义一个 StorageClass了。

storageclass-gluster-heketi.yaml配置文件的内容如下:

apiVersion: storage.k8s.io/v1 
kind: Storageclass 
metadata:
  name: gluster-heketi
provisioner: kubernetes.io/glusterfs 
parameters:
  resturl: "http: //172.17.2.2:8080" 
  restauthenabled: "false"

provisioner参数必须被设置为“kubernetes.io/glusterfs”。

resturl的地址需要被设置为API Server所在主机可以访问到的Heketi服务地址,可以使用服务ClusterIP+Port、 PodIP+Port,或将服务映射到物理机。

创建该StorageClass资源对象:

$ kubectl create -f storageclass-gluster-heketi.yaml 
storageclass/gluster-heketi created

07 定义PVC

现在,用户可以定义一个PVC申请Glusterfs存储空间了。

下面是PVC的YAML 定义,其中申请了1GiB空间的存儲资源,设置StorageClass为“gluster-heketi”,同时未设置Selector,表示使用动态资源供应模式

# pvc-gluster-heketi.yaml
apiVersion: V1
kind: PersistentVolumeClaim 
metadata:
  name: pve-gluster-heketi 
  spec:
    storageClassName: gluster-heketi 
    accessModes:
    - Readwriteonce
    resources:
      requests:
        storage: 1Gi

创建:

$ kubectl create -f ppvc-gluster-heketi.yaml 
persistentvolumeclaim/pvc-gluster-heketi created

PVC的定义一旦生成,系统便将触发Heketi进行相应的操作,主要为在 GlusterFS集群中创建brick,再创建并启动一个Volume

可以在Heketi的日志中查看整个过程:

......
[kubeexec] DEBUG 2020/04/26 00:51:30
/sre/github .com /heketi /heketi/executors/ kubeexec/kubeexec.go:250: Host:
k8s-node-1 Pod: glusterfs-ld7nh Command: gluster --mode=script volume create v01 87b9314cb76bafacfb7e9cdc04fcaf05 replica 3
192.168.18.3:/var/lib/heketi/mounts/vg b474f14b0903ed03ec80d4a989£943£2/brick_ d0 8520c9££769a0a9165£9815671f2cd/brick
192.168.18.5:/var/lib /heketi/mounts /vg fac3fa5aclde 3d5bde 3aa68f6aa61285 /brick 68 18dce118b8a54e9590199d44a3817b/brick
192.168. 18.4:/vef/1tb/heket1 /mounta/vg. 03532e7ab723933e8643o64b3Gxeelaz /bztok.9e
cb8f7fdelae937011£0440le7c6c56/brick
Result: volume create: vo1 87b9314cb76bafacfb7e9cdc0A fcaf05: success: please start the volume to access data
[kubeexec] DEBUG 2020/04/26 00:51:33
/src/github.com/heketi/heketi/executors/kubeexec/kubeexec.go:250: Host:
k8s-node-1 Pod: glusterfs-ld7nh Command: gluster --mode=script volune start vo1 87b9314cb76bafacfbTe 9cdc04fcaf05
Result: volume start: vol 87b9314cb7 6bafacfbTe 9cdc04fcaf05: suecess
......

查看PVC的详情,确认其状态为Bound(已绑定):

$ kubectl get pvc
NAME    STATUS       VOLUME        CAPACITY   ACCESSMODES   STORAGECLASS  AGE
pve-gluster-heketi Bound pvc-783cf949-2ala-11e7-8717-000c2 9eaed40 1Gi RWX qluster-heketi 6m

查看PV,可以看到系统通过动态供应机制系统自动创建的PV

$ kubectl get pv
NAME  CAPACITY  ACCESSMODES   RECLAIMPOLICY   STATUS  CLAIM   STORAGECLASS REASON AGE
pve-783cf949-2a1a-11e7-8717-000c29eaed4o 1Gi Rwx Delete Bound 1 default/pvc-gluster-heketi gluster-heketi 6m

查看该PV的详细信息,可以看到其容量、引用的StorageClass等信息都已正确设置,状态也为Bound,回收策略则为默认的Delete。同时Gluster的Endpoint 和Path也由Heketi自动完成了设置:

$ kubectl describe pv PVC-783c£949-2ala-11e7-8717-000c2geaed40 
Name: pvc-783¢£949-2ala-11e7-8717-000c29eaed40
Labels: <none>
Annotations: pv.beta.kubernetes.io/gid-2000
       pv.kubernetes.io/bound-by-controller=yes
       pv.kubernetes.io/provisioned-by=kubernetes.io/glusterfs
Storageclass: gluster-heketi
Status: Bound
Claim: default/pve-gluster-heketi
Reclaim Policy: Delete
Access Modes: RWX
Capacity: 1Gi 
Message:
Source:
  Type: Glusterfs (a Glusterfs mount on the host that shares a pod's lifetime)    
  EndpointsName: glusterfs-dynamic-pvc-gluster-heketi 
  Path: Vol_87b9314cb76bafacfbTe9cdc04fcaf05
  Readonly: false 
Events:
  <none>

至此,一个可供Pod使用的PVC就创建成功了。接下来Pod就能通过Volume的设置将这个PVC挂载到容器内部进行使用了。

08 Pod使用PVC的存储资源

下面是在Pod中使用PVC定义的存储资源的配置,首先设置一个类型为 persistentVolumeClaimVolume,然后将其通过volumeMounts设置挂载到容器内的目录路径下,注意,Pod需要与PVC属于同一个命名空间:

# pod-use-pve.yam1
apiVersion: v1
kind: Pod 
metadata:
  name: pod-use-pvc 
spec:
  containers:
  - name: pod-use-pvc
    image: busybox 
    command:
    - sleep
      - "3600"
    volumeMounts:
    - name: qluster-volume
        mountPath: "/pv-data"
        readonly: false
  volumes:
    name: qluster-volume 
    persistentVolumeclaim:
      claimName: pvc-gluster-heketi

创建之后,进入容器pod-use-pvc,在/pv-data目录下创建一些文件:

$ kubectl exec -ti pod-use-pve --/bin/sh 
/$ cd /pv-data
/$ touch a
/$ echo "hello" >b

可以验证文件a和b在GlusterFS集群中正确生成。

至此,使用Kubernetes最新的动态存储供应模式,配合StorageClass和Heketi 共同搭建基于GlusterFS的共享存储就完成了。


在使用动态存储供应模式的情况下,可以解决静态模式的下列问题:

  1. 管理员需要预先准备大量的静态PV
  2. 系统为PVC选择PV时可能存在PV空间比PVC申请空间大的情况,无法保证没有资源浪费

所以在Kubernetes中,建议用户优先考虑使用StorageClass的动态存储供应模式进行存储资源的申请、使用、回收等操作。

09 文末

本文主要结合之前的k8s的volume的知识并以GlusterFS为案例走了一下整体的使用流程,希望能帮助到大家,谢谢大家的阅读,本文完!

相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
目录
相关文章
|
3月前
|
Kubernetes Shell Perl
【Azure K8S|AKS】进入AKS的POD中查看文件,例如PVC Volume Mounts使用情况
【Azure K8S|AKS】进入AKS的POD中查看文件,例如PVC Volume Mounts使用情况
|
3月前
|
存储 Kubernetes 容器
Kubernetes 存储选项:持久化卷与存储类
【8月更文第29天】随着容器化的普及,越来越多的应用程序需要持久化数据以保持状态信息。Kubernetes 提供了一套完整的解决方案来管理和配置持久化存储,包括持久卷 (Persistent Volume, PV)、持久卷声明 (Persistent Volume Claim, PVC) 和存储类 (StorageClass)。本文将详细介绍这些概念,并通过实际示例来演示如何在 Kubernetes 中配置存储。
251 1
|
1月前
|
Prometheus Kubernetes 监控
k8s学习--kubernetes服务自动伸缩之水平伸缩(pod副本伸缩)HPA详细解释与案例应用
k8s学习--kubernetes服务自动伸缩之水平伸缩(pod副本伸缩)HPA详细解释与案例应用
k8s学习--kubernetes服务自动伸缩之水平伸缩(pod副本伸缩)HPA详细解释与案例应用
|
3月前
|
存储 Kubernetes 容器
k8s创建NFS动态存储
k8s创建NFS动态存储
|
4月前
|
存储 Kubernetes 应用服务中间件
k8s使用rbd作为存储
k8s使用rbd作为存储
60 6
|
3月前
|
存储 Kubernetes 数据安全/隐私保护
在K8S中,如果后端nfs存储的ip发生变化如何解决?
在K8S中,如果后端nfs存储的ip发生变化如何解决?
|
3月前
|
存储 缓存 Kubernetes
在K8S中,业务Pod数据如何存储?
在K8S中,业务Pod数据如何存储?
|
3月前
|
存储 JSON Kubernetes
在K8S中,存储敏感信息方式有哪些?
在K8S中,存储敏感信息方式有哪些?
|
3月前
|
存储 Kubernetes 容器
在k8S中,所支持的存储供应模式有哪些?
在k8S中,所支持的存储供应模式有哪些?
|
3月前
|
存储 Kubernetes 调度
在k8S中,共享存储的作用是什么?
在k8S中,共享存储的作用是什么?