当前位置: 首页 > ds >正文

Kubernetes + GlusterFS + Heketi 动态卷管理实践 !

Kubernetes动态存储供给是云原生架构的关键挑战。

本文详解如何通过Heketi实现GlusterFS自动化管理,涵盖部署实践与问题处理,提供经生产验证的配置方案,助力构建高可用、弹性扩展的Kubernetes存储体系。

1. 安装要求

在开始之前,搭建GlusterFS集群需要满足以下几个条件:

  • 完成 kubernetes 集群搭建

  • 支持外网访问,并配置相关容器镜像加速地址

  • 每台宿主机预留有裸磁盘

  • 每台宿主机支持并加载相关模块

2. 学习目标

  • 完成 GlusterFS 集群部署搭建

  • 完成创建 Heketi 服务部署

  • 通过Heketi 管理 GlusterFS集群

  • SC ,PV ,PVC 创建验证

3. 准备工作

1、在各个节点都安装上GFS客户端
yum install glusterfs glusterfs-fuse -y2、给需要安装GFS管理服务的节点打上标签
kubectl label nodes k8s-master01  storagenode=glusterfs
kubectl label nodes k8s-node02  storagenode=glusterfs
kubectl label nodes k8s-node03  storagenode=glusterfs3、所有节点加载对应模块
modprobe dm_snapshot
modprobe dm_mirror
modprobe dm_thin_pool4、检查 modprobe 是否加载成功
lsmod | egrep  '(dm_snapshot|dm_mirror|dm_thin_pool)'[root@k8s-node03 ~]# lsmod | egrep  '(dm_snapshot|dm_mirror|dm_thin_pool)'
dm_thin_pool           70389  0
dm_persistent_data     75275  1 dm_thin_pool
dm_bio_prison          18209  1 dm_thin_pool
dm_mirror              22289  0
dm_region_hash         20813  1 dm_mirror
dm_log                 18411  2 dm_region_hash,dm_mirror
dm_mod                124501  4 dm_log,dm_mirror,dm_bufio,dm_thin_pool

4. 创建GlusterFS管理服务容器集群

4.1 部署GlusterFS 集群:
yaml 文件如下:
vim glusterfs-daemonset.yamlapiVersion: apps/v1
kind: DaemonSet
metadata:name: glusterfslabels:glusterfs: daemonsettannotations:description: GlusterFS DaemonSettags: glusterfs
spec:selector:matchLabels:glusterfs-node: podtemplate:metadata:name: glusterfslabels:glusterfs-node: podspec:nodeSelector:storagenode: glusterfs   # 节点标签glusterfshostNetwork: truecontainers:- image: gluster/gluster-centos:latestname: glusterfsvolumeMounts:- name: glusterfs-heketimountPath: "/var/lib/heketi"- name: glusterfs-runmountPath: "/run"- name: glusterfs-lvmmountPath: "/run/lvm"- name: glusterfs-etcmountPath: "/etc/glusterfs"- name: glusterfs-logsmountPath: "/var/log/glusterfs"- name: glusterfs-configmountPath: "/var/lib/glusterd"- name: glusterfs-devmountPath: "/dev"- name: glusterfs-miscmountPath: "/var/lib/misc/glusterfsd"- name: glusterfs-cgroupmountPath: "/sys/fs/cgroup"readOnly: true- name: glusterfs-sslmountPath: "/etc/ssl"readOnly: truesecurityContext:capabilities: {}privileged: true   # 特权模式readinessProbe:timeoutSeconds: 3initialDelaySeconds: 60exec:command:- "/bin/bash"- "-c"- systemctl status glusterd.servicelivenessProbe:timeoutSeconds: 3initialDelaySeconds: 60exec:command:- "/bin/bash"- "-c"- systemctl status glusterd.servicevolumes:- name: glusterfs-heketihostPath:path: "/var/lib/heketi"- name: glusterfs-run- name: glusterfs-lvmhostPath:path: "/run/lvm"- name: glusterfs-etchostPath:path: "/etc/glusterfs"- name: glusterfs-logshostPath:path: "/var/log/glusterfs"- name: glusterfs-confighostPath:path: "/var/lib/glusterd"- name: glusterfs-devhostPath:path: "/dev"- name: glusterfs-mischostPath:path: "/var/lib/misc/glusterfsd"- name: glusterfs-cgrouphostPath:path: "/sys/fs/cgroup"- name: glusterfs-sslhostPath:path: "/etc/ssl"创建 glusterfs-deamonset 
[root@k8s-master01 glusterfs-heketi]# kubectl apply -f glusterfs-daemonset.yaml
daemonset.apps/glusterfs created
4.2 验证部署结果

我们可以看到:Master 节点没有跑 glusterfs 服务 。这是因为 Kubernetes 默认会阻止 DaemonSet 在 master 节点上运行工作负载。

[root@k8s-master01 glusterfs-heketi]# kubectl get pod  -l glusterfs-node=pod -o  wide
NAME              READY   STATUS    RESTARTS   AGE   IP                NODE         NOMINATED NODE   READINESS GATES
glusterfs-cdtrk   1/1     Running   0          51s   192.168.234.132   k8s-node02   <none>           <none>
glusterfs-kqcgs   1/1     Running   0          51s   192.168.234.133   k8s-node03   <none>           <none>

查看 Master 节点污点。

[root@k8s-master01 glusterfs-heketi]# kubectl describe nodes k8s-master01  |grep Taint
Taints:             node-role.kubernetes.io/control-plane:NoSchedule

如果想允许 DaemonSet 在 master 节点运行,执行如下命令 移除 master 节点的污点,或者在上述 glusterfs-daemonset.yaml 文件添加容忍(tolerations)也可,这里不做过多赘述。

kubectl taint nodes  k8s-master01 node-role.kubernetes.io/control-plane:NoSchedule-

5.创建Heketi服务

5.1 创建一个ServiceAccount、Role、RoleBinding
vim heketi-rbac.yamlapiVersion: v1
kind: ServiceAccount
metadata:name: heketi-service-account
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:name: heketinamespace: default
rules:
- apiGroups: [""]                   # 空字符串,表示 Core API Groupresources: ["pods","services","endpoints"] # 这个Role只可以操作Pod\svc\ep,操作方式在下面的verbs[]verbs: ["get","watch","list"]
- apiGroups: [""]                   # 空字符串,表示 Core API Groupresources: ["pods/exec"]verbs: ["create"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:name: heketi          namespace: default    # 权限仅在该ns下起作用
subjects:
- kind: ServiceAccount  # 类型是sa,说明这个sa有role为heketi的权限name: heketi-service-account
roleRef:                # 角色绑定信息kind: Role            # 绑定的对象是角色,也可以是集群角色name: heketi          # 绑定的Role nameapiGroup: rbac.authorization.k8s.io  # 默认
[root@k8s-master01 glusterfs-heketi]# kubectl apply -f heketi-rbac.yaml
serviceaccount/heketi-service-account created
role.rbac.authorization.k8s.io/heketi created
rolebinding.rbac.authorization.k8s.io/heketi created
5.2 部署Heketi服务
vim  heketi-deployment-svc.yamlapiVersion: apps/v1
kind: Deployment
metadata:name: deploy-heketilabels:glusterfs: heketi-deploymentdeploy-heketi: heket-deploymentannotations:description: Defines how to deploy Heketi
spec:selector:matchLabels:glusterfs: heketi-podreplicas: 1template:metadata:name: deploy-heketilabels:glusterfs: heketi-podname: deploy-heketispec:serviceAccountName: heketi-service-accountcontainers:- image: heketi/heketiimagePullPolicy: IfNotPresentname: deploy-heketienv:- name: HEKETI_EXECUTORvalue: kubernetes- name: HEKETI_FSTABvalue: "/var/lib/heketi/fstab"- name: HEKETI_SNAPSHOT_LIMITvalue: '14'- name: HEKETI_KUBE_GLUSTER_DAEMONSETvalue: "y"- name: HEKETI_ADMIN_KEY   # 设置 Heketi服务密钥value: "admin@123"        # 密钥值ports:- containerPort: 8080volumeMounts:- name: dbmountPath: "/var/lib/heketi"readinessProbe:timeoutSeconds: 3initialDelaySeconds: 3httpGet:path: "/hello"port: 8080livenessProbe:timeoutSeconds: 3initialDelaySeconds: 30httpGet:path: "/hello"port: 8080volumes:- name: dbhostPath:path: "/heketi-data"
---
kind: Service
apiVersion: v1
metadata:name: deploy-heketilabels:glusterfs: heketi-servicedeploy-heketi: supportannotations:description: Exposes Heketi Service
spec:selector:name: deploy-heketiports:- name: deploy-heketiport: 8080targetPort: 8080

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

[root@k8s-master01 glusterfs-heketi]# kubectl apply -f heketi-deployment-svc.yaml
deployment.apps/deploy-heketi created
service/deploy-heketi created
5.3 验证 pod 和 service
[root@k8s-master01 glusterfs-heketi]# kubectl get pod
NAME                             READY   STATUS    RESTARTS   AGE
deploy-heketi-59555bcd98-jd9mt   1/1     Running   0          85s[root@k8s-master01 glusterfs-heketi]# kubectl get svc
NAME            TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)    AGE
deploy-heketi   ClusterIP   10.1.206.52   <none>        8080/TCP   90s

6. 通过Heketi 创建GFS集群

在 Heketi 能够管理 GlusterFS 集群之前,首先要为其设置 GlusterFS 集群的信息。可以用一个 topology.json 配置文件来完成各个 GlusterFS 节点和设备的定义。Heketi 要求在一个 GlusterFS 集群中至少有 3 个节点。在  topology.json 配置文件 hostname 字段的 manage 上填写主机名,在 storage 上填写 IP 地址, devices 要求是未创建文件系统的裸设备(可以有多块盘)。topology.json 内容如下:

{"clusters": [{"nodes": [{"node": {"hostnames": {"manage": ["k8s-master01"],"storage": ["192.168.234.131"]},"zone": 1},"devices": ["/dev/sdb"]},{"node": {"hostnames": {"manage": ["k8s-node02"],"storage": ["192.168.234.132"]},"zone": 1},"devices": ["/dev/sdb"]},{"node": {"hostnames": {"manage": ["k8s-node03"],"storage": ["192.168.234.133"]},"zone": 1},"devices": ["/dev/sdb"]}]}]
}

进入Heketi 容器,使用命令行工具 heketi-cli 完成 GlusterFS 集群构建(http://10.1.206.52:8080 是 heketi 服务 ip 和 端口)

# export HEKETI_CLI_SERVER=http://10.1.206.52:8080 
# heketi-cli -s $HEKETI_CLI_SERVER --user admin --secret admin@123 topology load --json=/root/topology.json
Creating cluster ... ID: 8cc1a0f8174e2fd04f517e01a1166ad0Allowing file volumes on cluster.Allowing block volumes on cluster.Creating node k8s-master01 ... ID: e0798f5083772ecd434492db152369f2Adding device /dev/sdb ... OKFound node k8s-node02 on cluster b3248f93d7e48e225ec22a19bfcf7896Adding device /dev/sdb ... OKFound node k8s-node03 on cluster b3248f93d7e48e225ec22a19bfcf7896Adding device /dev/sdb ... OK

经过上述操作,我们已经完成通过 Heketi 对 GlusterFS 集群进行创建,结果是在 GlusterFS 集群各个节点的 /dev/sdb 盘上成功创建了 PV 和 VG 。

执行如下命令(容器里运行),可查看 Heketi 的 topology 信息,包括 Node 和 Device 的详细信息,磁盘空间的剩余空间。

# heketi-cli -s $HEKETI_CLI_SERVER --user admin --secret admin@123 topology  info

7. 测试验证

7.1 创建 StrongerClass

storageclass-glusterfs-heketi.yaml  配置文件如下:

vim storageclass-glusterfs-heketi.yaml apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:name: gluster-heketi
provisioner: kubernetes.io/glusterfs  # GlusterFS 存储驱动,Kubernetes v1.13+ 版本以后开始被标记弃用,更高版本已经完全弃用
reclaimPolicy: Retain
parameters:resturl: "http://10.1.206.52:8080"   # Heketi 服务地址restauthenabled: "true"restuser: "admin"restuserkey: "admin@123"gidMin: "40000"gidMax: "50000"volumetype: "replicate:3"
allowVolumeExpansion: true[root@k8s-master01 glusterfs-heketi]# kubectl apply -f storageclass-glusterfs-heketi.yaml
storageclass.storage.k8s.io/gluster-heketi created
7.2 创建 PVC

如下yaml 文件,申请了 1 GiB 空间的存储资源,设置 StorageClass 为 “gluster-heketi"  ,同时未设置 Selector ,表示使用动态资源供应模式:

vim pvc-gluster-heketi.yamlapiVersion: v1
kind: PersistentVolumeClaim
metadata:name: pvc-gluster-heketi
spec:accessModes: - ReadWriteOncestorageClassName: gluster-heketi  # StorageClass 名称resources:requests:storage: 5Gi[root@k8s-master01 glusterfs-heketi]# kubectl apply -f pvc-gluster-heketi.yaml
persistentvolumeclaim/pvc-gluster-heketi created

PVC 的定义一旦生成,系统便将触发 Heketi 进行相应的操作,主要为在 GulsterFS 集群中创建 brick ,再创建并启动一个 Volume。也会自动创建 PV ,查看 PVC 的详情,确认其状态为 Bound(已绑定)。

【问题】:创建 pvc 之后 ,若出现 pvc 状态为 Pending ,没有看到自动创建的 pv,describe 查看 pvc 的 pod 显示如下信息。

Events:Type     Reason              Age                     From                         Message----     ------              ----                    ----                         -------Warning  ProvisioningFailed  3m29s (x441 over 113m)  persistentvolume-controller  no volume plugin matched name: kubernetes.io/glusterfs

这是因为 Kubernetes 自从1.13 版本开始,一些内置 Provisioner (in-tree)  已被标记为弃用,到更高版本可能已经完全弃用。上述报错说明,此 Kubernetes 版本的 GlusterFS 存储插件:  kubernetes.io/glusterfs  已经完全不能使用 。在 Kubernetes 1.28 版本中,存储供应器(Provisioner)的生态已经全面转向 CSI(Container Storage Interface) 标准  。GlusterFS CSI 驱动:gluster.org/glusterfs (需安装)。关于 GlusterFS CSI 驱动安装,这里就不做过多赘述,后续有时间再给大家更新。可以参考 GitHub 仓库地址:https://github.com/gluster/gluster-csi-driver

7.3 创建 Pod 使用 PVC 的存储资源

解决完 GlusterFS 存储插件问题之后,创建 pod 对 pvc 存储资源进行使用。

vim pod-use-pvc.yaml apiVersion: v1
kind: Pod
metadata:name: pod-use-pvc
spec:containers:- name: pod-use-pvcimage: busyboxcommand:- sleep- "3600"volumeMounts:- name: gluster-volumemountPath: "/pv-data"readOnly: falsevolumes:- name: gluster-volumepersistentVolumeClaim:claimName: pvc-gluster-heketi   # pvc 名称

至此,使用 Kubernetes 动态存储供应模式,配合 StorageClass 和 Heketi 共同搭建基于 GlusterFS 的共享存储所有实验已经完成啦 ~

http://www.xdnf.cn/news/6843.html

相关文章:

  • 中大型水闸安全监测系统解决方案
  • 深度学习驱动下的目标检测技术:原理、算法与应用创新(三)
  • 【C#】 lock 关键字
  • 【笔记】导出Conda环境依赖以复现项目虚拟环境
  • 深度学习驱动下的目标检测技术:原理、算法与应用创新(二)
  • LLM学习笔记(七)注意力机制
  • C# NX二次开发-实体离散成点
  • 使用pyinstaller生成exe时,如何指定生成文件名字
  • Linux!启动~
  • WHAT - 前端同构 Isomorphic Javascript
  • Ubuntu系统安装VsCode
  • UAI 2025重磅揭晓:录取数据公布(附往届数据)
  • Python字符串常用内置函数详解
  • 独立开发者利用AI工具快速制作产品MVP
  • Qt功能区:Ribbon使用
  • Linux复习笔记(六)shell编程
  • 实现书签-第一部分
  • 中大型水闸安全监测系统建设实施方案
  • 在服务器上安装AlphaFold2遇到的问题(2)
  • 【C++】 —— 笔试刷题day_30
  • 【C++ | 内存管理】C++ weak_ptr 详解:成员函数、使用例子与实现原理
  • 力扣654题:最大二叉树(递归)
  • 实时技术方案对比:SSE vs WebSocket vs Long Polling
  • Java Set系列集合详解:HashSet、LinkedHashSet、TreeSet底层原理与使用场景
  • 产品经理入门——认识产品经理
  • OCCT知识笔记之Poly_Triangulation详解
  • YOLOv7训练时4个类别只出2个类别
  • vue使用Fabric和pdfjs完成合同签章及批注
  • 第八节第三部分:认识枚举、枚举的作用和应用场景
  • DeepSearch:WebThinker开启AI搜索研究新纪元!