在Kubernetes中,使用GlusterFS文件系统,操作步骤通常是:
创建brick-->创建volume-->创建PV-->创建PVC-->Pod挂载PVC
如果要创建多个PV,则需要手动重复执行,可通过Heketi管理glusterfs。
Heketi是用来管理GlusterFS卷的生命周期的,并提供了一个RESTful API接口供Kubernetes调用,因为GlusterFS没有提供API调用的方式,所以我们借助heketi。通过Heketi,Kubernetes可以动态配置GlusterFS卷,Heketi会动态在集群内选择bricks创建所需的volumes,确保数据的副本会分散到集群不同的故障域内,同时Heketi还支持GlusterFS多集群管理,便于管理员对GlusterFS进行操作。
Heketi要求在每个glusterfs节点上配备裸磁盘,用于Heketi创建PV和VG。通过Hekete,Kubernetes中使用PV步骤为:
创建StorageClass-->创建PVC-->Pod挂载PVC
这种方式称为基于StorageClass的动态资源供应。
提示:本实验基于Kubernetes部署glusterfs,同时glusterfs管理组件Heketi也使用Kubernetes部署。
提示:本实验不涉及Kubernetes部署,Kubernetes部署参考001-019。
主机 | IP | 磁盘 | 备注 |
---|---|---|---|
k8smaster01 | 172.24.8.71 | Kubernetes master节点 | |
k8smaster02 | 172.24.8.72 | Kubernetes master节点 | |
k8smaster03 | 172.24.8.73 | Kubernetes master节点 | |
k8snode01 | 172.24.8.74 | sdb | Kubernetes node节点glusterfs节点 |
k8snode02 | 172.24.8.75 | sdb | Kubernetes node节点glusterfs节点 |
k8snode03 | 172.24.8.76 | sdb | Kubernetes node节点glusterfs节点 |
磁盘规划
k8snode01 | k8snode02 | k8snode03 | |||||||
---|---|---|---|---|---|---|---|---|---|
PV | sdb1 | sdb1 | sdb1 |
1.4 部署条件
超融合部署需要具有已经部署的Kubernetes集群管理访问权限。如果Kubernetes节点满足以下要求,则可以选择将GlusterFS作为超融合服务部署:
注意:节点上安装的GlusterFS客户端版本应尽可能接近服务器的版本。要获取已安装的版本,可通过glusterfs --version或kubectl exec <pod> -- glusterfs --version命令查看。
所有节点NTP配置;
所有节点添加相应主机名解析:
1 172.24.8.71 k8smaster01
2 172.24.8.72 k8smaster02
3 172.24.8.73 k8smaster03
4 172.24.8.74 k8snode01
5 172.24.8.75 k8snode02
6 172.24.8.76 k8snode03
注意:若非必要,建议关闭防火墙和SELinux。
1 [root@k8snode01 ~]# fdisk /dev/sdb -l #检查sdb是否为裸磁盘
1 [root@k8snode01 ~]# yum -y install centos-release-gluster
2 [root@k8snode01 ~]# yum -y install glusterfs-fuse #安装glusterfs-fuse
提示:k8snode01、k8snode02、k8snode03类似操作,根据1.4要求安装glusterfs-fuse组件;
安装相应源之后,会在/etc/yum.repos.d/目录多出文件CentOS-Storage-common.repo,内容如下:
# CentOS-Storage.repo
#
# Please see http://wiki.centos.org/SpecialInterestGroup/Storage for more
# information
[centos-storage-debuginfo]
name=CentOS-$releasever - Storage SIG - debuginfo
baseurl=http://debuginfo.centos.org/$contentdir/$releasever/storage/$basearch/
gpgcheck=1
enabled=0
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-SIG-Storage
1 [root@k8snode01 ~]# cat > /etc/sysconfig/modules/glusterfs.modules <<EOF
2 #!/bin/bash
3
4 for kernel_module in dm_snapshot dm_mirror dm_thin_pool;do
5 /sbin/modinfo -F filename \${kernel_module} > /dev/null 2>&1
6 if [ \$? -eq 0 ]; then
7 /sbin/modprobe \${kernel_module}
8 fi
9 done;
10 EOF
11 [root@k8snode01 ~]# chmod +x /etc/sysconfig/modules/glusterfs.modules
12 [root@k8snode01 ~]# lsmod |egrep "dm_snapshot|dm_mirror|dm_thin_pool" #所有glusterfs node节点检查
提示:可通过modprobe <name>加载给定的模块。
1 [root@k8smaster01 ~]# kubectl label nodes k8snode01 storagenode=glusterfs
2 [root@k8smaster01 ~]# kubectl label nodes k8snode02 storagenode=glusterfs
3 [root@k8smaster01 ~]# kubectl label nodes k8snode03 storagenode=glusterfs
提示:在后续使用DaemonSet部署时候kube-templates/glusterfs-daemonset.yaml存在如下针对label的Selector:
spec:
nodeSelector:
storagenode: glusterfs
1 [root@k8smaster01 ~]# yum -y install git
2 [root@k8smaster01 ~]# git clone https://github.com/gluster/gluster-kubernetes.git
1 [root@k8smaster01 ~]# cd gluster-kubernetes/deploy/
2 [root@k8smaster01 deploy]# cp topology.json.sample topology.json
3 [root@k8smaster01 deploy]# vi topology.json
1 {
2 "clusters": [
3 {
4 "nodes": [
5 {
6 "node": {
7 "hostnames": {
8 "manage": [
9 "k8snode01"
10 ],
11 "storage": [
12 "172.24.8.74"
13 ]
14 },
15 "zone": 1
16 },
17 "devices": [
18 "/dev/sdb"
19 ]
20 },
21 {
22 "node": {
23 "hostnames": {
24 "manage": [
25 "k8snode02"
26 ],
27 "storage": [
28 "172.24.8.75"
29 ]
30 },
31 "zone": 1
32 },
33 "devices": [
34 "/dev/sdb"
35 ]
36 },
37 {
38 "node": {
39 "hostnames": {
40 "manage": [
41 "k8snode03"
42 ],
43 "storage": [
44 "172.24.8.76"
45 ]
46 },
47 "zone": 1
48 },
49 "devices": [
50 "/dev/sdb"
51 ]
52 }
53 ]
54 }
55 ]
56 }
提示:heketi配置文件及介绍参考《附009.Kubernetes永久存储之GlusterFS独立部署》。
若需要修改heketi的暴露方式,若需要修改为NodePort,可参考https://lichi6174.github.io/glusterfs-heketi/。
所有部署相关yaml位于/root/gluster-kubernetes/deploy/kube-templates,本实验采用默认参数。
1 [root@k8smaster01 deploy]# cp heketi.json.template heketi.json
2 [root@k8smaster01 deploy]# vi heketi.json
3 {
4 "_port_comment": "Heketi Server Port Number",
5 "port" : "8080",
6
7 "_use_auth": "Enable JWT authorization. Please enable for deployment",
8 "use_auth" : true, #开启用户认证
9
10 "_jwt" : "Private keys for access",
11 "jwt" : {
12 "_admin" : "Admin has access to all APIs",
13 "admin" : {
14 "key" : "admin123" #管理员密码
15 },
16 "_user" : "User only has access to /volumes endpoint",
17 "user" : {
18 "key" : "xianghy" #用户密码
19 }
20 },
21
22 "_glusterfs_comment": "GlusterFS Configuration",
23 "glusterfs" : {
24
25 "_executor_comment": "Execute plugin. Possible choices: mock, kubernetes, ssh",
26 "executor" : "${HEKETI_EXECUTOR}", #本实验使用Kubernetes方式
27
28 "_db_comment": "Database file name",
29 "db" : "/var/lib/heketi/heketi.db", #heketi数据存储
30
31 "kubeexec" : {
32 "rebalance_on_expansion": true
33 },
34
35 "sshexec" : {
36 "rebalance_on_expansion": true,
37 "keyfile" : "/etc/heketi/private_key",
38 "port" : "${SSH_PORT}",
39 "user" : "${SSH_USER}",
40 "sudo" : ${SSH_SUDO}
41 }
42 },
43
44 "backup_db_to_kube_secret": false
45 }
新版Kubernetes的# kubectl get pod命令无--show-all选项,需要如下操作修正部署gk-deploy脚本。
1 [root@k8smaster01 deploy]# vi gk-deploy
2 924 #heketi_pod=$(${CLI} get pod --no-headers --show-all --selector="heketi" | awk '{print $1}')
3 925 heketi_pod=$(${CLI} get pod --no-headers --selector="heketi" | awk '{print $1}')
由于国内glusterfs镜像可能无法pull,建议通过V**等方式提前pull镜像,然后上传至所有glusterfs node节点。
1 [root@V** ~]# docker pull gluster/gluster-centos:latest
2 [root@V** ~]# docker pull heketi/heketi:dev
3 [root@V** ~]# docker save -o gluster_latest.tar gluster/gluster-centos:latest
4 [root@V** ~]# docker save -o heketi_dev.tar heketi/heketi:dev
5 [root@k8snode01 ~]# docker load -i gluster_latest.tar
6 [root@k8snode01 ~]# docker load -i heketi_dev.tar
7 [root@k8snode01 ~]# docker images
8
1 [root@k8smaster01 deploy]# ./gk-deploy -h #查看部署参数
2 [root@k8smaster01 deploy]# kubectl create ns heketi #建议部署在独立的namespace中
3 [root@k8smaster01 deploy]# ./gk-deploy -g -n heketi topology.json --admin-key admin123 --user-key xianghy
4 ……
5 Do you wish to proceed with deployment?
6
7 [Y]es, [N]o? [Default: Y]: y
提示:部署脚本更多参数参考:https://github.com/gluster/gluster-kubernetes/blob/master/deploy/gk-deploy。
注意:若部署失败,需要通过下方式彻底删除后重新部署:
1 [root@k8smaster01 deploy]# ./gk-deploy --abort --admin-key admin123 --user-key xianghy -y -n heketi
2 [root@k8smaster01 deploy]# kubectl delete -f kube-templates/ -n heketi
glusterfs node节点需要执行如下彻底清理:
1 [root@k8snode01 ~]# dmsetup ls
2 [root@k8snode01 ~]# dmsetup remove_all
3 [root@k8snode01 ~]# rm -rf /var/log/glusterfs/
4 [root@k8snode01 ~]# rm -rf /var/lib/heketi
5 [root@k8snode01 ~]# rm -rf /var/lib/glusterd/
6 [root@k8snode01 ~]# rm -rf /etc/glusterfs/
7 [root@k8snode01 ~]# dd if=/dev/zero of=/dev/sdb bs=512k count=1
8 [root@k8snode01 ~]# wipefs -af /dev/sdb
1 [root@k8smaster01 ~]# kubectl get nodes --show-labels | grep -E 'NAME|node'
2 [root@k8smaster01 ~]# kubectl get all -n heketi
1 [root@k8smaster01 ~]# kubectl get pods -o wide -n heketi
1 [root@k8smaster01 ~]# kubectl exec -it heketi-65f4555d74-72hrf -n heketi -- heketi-cli cluster list --user admin --secret admin123 #集群列表
2 [root@k8smaster01 ~]# kubectl -n heketi exec -ti heketi-65f4555d74-72hrf /bin/bash [root@heketi-65f4555d74-72hrf /]# heketi-cli cluster list --user admin --secret admin123 #进入heketi容器查看
3 [root@k8smaster01 ~]# curl http://10.254.111.219:8080/hello
4 Hello from Heketi
注意:使用4.6脚本为一键部署,也可使用gluster-kubernetes/deploy/目录下的文件,分开逐步部署,整理部署思路如下:
独立部署完整过程参考:https://jimmysong.io/kubernetes-handbook/practice/using-heketi-gluster-for-persistent-storage.html。
由于在master节点管理heketi需要进入heketi容器或者使用kubectl exec -ti 方式,建议直接在master节点安装heketi客户端,直接管理、
1 [root@k8smaster01 ~]# yum -y install centos-release-gluster
2 [root@k8smaster01 ~]# yum -y install heketi-client
1 [root@k8smaster01 ~]# echo "export HEKETI_CLI_SERVER=http://$(kubectl get svc heketi -n heketi -o go-template='{{.spec.clusterIP}}'):8080" >> /etc/profile.d/heketi.sh
2 [root@k8smaster01 ~]# echo "alias heketi-cli='heketi-cli --user admin --secret admin123'" >> ~/.bashrc
3 [root@k8smaster01 ~]# source /etc/profile.d/heketi.sh
4 [root@k8smaster01 ~]# source ~/.bashrc
5 [root@k8smaster01 ~]# echo $HEKETI_CLI_SERVER
6 http://heketi:8080
1 [root@k8smaster01 ~]# heketi-cli cluster list
2 Clusters:
3 Id:67004a06fbcb4fa525bcec1fbaa9ef2d [file][block]
4 [root@k8smaster01 ~]# heketi-cli cluster info 67004a06fbcb4fa525bcec1fbaa9ef2d #集群详细信息
5 Cluster id: 67004a06fbcb4fa525bcec1fbaa9ef2d
6 Nodes:
7 40cdd4c1d0c389939193d6dea3c5bfe8
8 62873c54cf61025fda91e6d44433378b
9 d48986357840d28653304e7170599da5
10 Volumes:
11 5f15f201d623e56b66af56313a1975e7
12 Block: true
13
14 File: true
15 [root@k8smaster01 ~]# heketi-cli topology info 67004a06fbcb4fa525bcec1fbaa9ef2d #查看拓扑信息
16 [root@k8smaster01 ~]# heketi-cli node list #查看所有node
17 Id:40cdd4c1d0c389939193d6dea3c5bfe8 Cluster:67004a06fbcb4fa525bcec1fbaa9ef2d
18 Id:62873c54cf61025fda91e6d44433378b Cluster:67004a06fbcb4fa525bcec1fbaa9ef2d
19 Id:d48986357840d28653304e7170599da5 Cluster:67004a06fbcb4fa525bcec1fbaa9ef2d
20 [root@k8smaster01 ~]# heketi-cli node info 40cdd4c1d0c389939193d6dea3c5bfe8 #node节点信息
21 [root@k8smaster01 ~]# heketi-cli volume create --size=2 --replica=2 #默认为3副本的replica模式
1 [root@k8smaster01 ~]# heketi-cli volume list #列出所有卷
2 [root@k8smaster01 ~]# heketi-cli volume info fc296ab350dcc36e00dd3b3643a04645 #卷信息
3 [root@k8smaster01 ~]# heketi-cli volume delete fc296ab350dcc36e00dd3b3643a04645 #删除卷
kubernetes共享存储provider模式:
静态模式(Static):集群管理员手工创建PV,在定义PV时设置后端存储的特性;
动态模式(Dynamic):集群管理员不需要手工创建PV,而是通过StorageClass的设置对后端存储进行描述,标记为某种"类型(Class)";此时要求PVC对存储的类型进行说明,系统将自动完成PV的创建及与PVC的绑定;PVC可以声明Class为"",说明PVC禁止使用动态模式。
基于StorageClass的动态存储供应整体过程如下图所示:
提示:关于Kubernetes的部署参考《附003.Kubeadm部署Kubernetes》。
关键字说明:
提示:关于glusterfs各种不同类型的卷见《004.RHGS-创建volume》。
1 [root@k8smaster01 ~]# echo -n "admin123" | base64 #将密码转换为64位编码
2 YWRtaW4xMjM=
3 [root@k8smaster01 ~]# mkdir -p heketi
4 [root@k8smaster01 ~]# cd heketi/
5 [root@k8smaster01 ~]# vi heketi-secret.yaml #创建用于保存密码的secret
6 apiVersion: v1
7 kind: Secret
8 metadata:
9 name: heketi-secret
10 namespace: heketi
11 data:
12 # base64 encoded password. E.g.: echo -n "mypassword" | base64
13 key: YWRtaW4xMjM=
14 type: kubernetes.io/glusterfs
15 [root@k8smaster01 heketi]# kubectl create -f heketi-secret.yaml #创建heketi
16 [root@k8smaster01 heketi]# kubectl get secrets -n heketi
17 NAME TYPE DATA AGE
18 default-token-6n746 kubernetes.io/service-account-token 3 144m
19 heketi-config-secret Opaque 3 142m
20 heketi-secret kubernetes.io/glusterfs 1 3m1s
21 heketi-service-account-token-ljlkb kubernetes.io/service-account-token 3 143m
22 [root@kubenode1 heketi]# vim gluster-heketi-storageclass.yaml #正式创建StorageClass
23 apiVersion: storage.k8s.io/v1
24 kind: StorageClass
25 metadata:
26 name: gluster-heketi-storageclass
27 parameters:
28 resturl: "http://10.254.111.219:8080"
29 clusterid: "67004a06fbcb4fa525bcec1fbaa9ef2d"
30 restauthenabled: "true" #若heketi开启认证此处也必须开启auth认证
31 restuser: "admin"
32 secretName: "heketi-secret" #name/namespace与secret资源中定义一致
33 secretNamespace: "heketi"
34 volumetype: "replicate:3"
35 provisioner: kubernetes.io/glusterfs
36 reclaimPolicy: Delete
37 [root@k8smaster01 heketi]# kubectl create -f gluster-heketi-storageclass.yaml
注意:storageclass资源创建后不可变更,如修改只能删除后重建。
1 [root@k8smaster01 heketi]# kubectl get storageclasses #查看确认
2 NAME PROVISIONER AGE
3 gluster-heketi-storageclass kubernetes.io/glusterfs 85s
4 [root@k8smaster01 heketi]# kubectl describe storageclasses gluster-heketi-storageclass
1 [root@k8smaster01 heketi]# vi gluster-heketi-pvc.yaml
2 apiVersion: v1
3 kind: PersistentVolumeClaim
4 metadata:
5 name: gluster-heketi-pvc
6 annotations:
7 volume.beta.kubernetes.io/storage-class: gluster-heketi-storageclass
8 spec:
9 accessModes:
10 - ReadWriteOnce
11 resources:
12 requests:
13 storage: 1Gi
注意:accessModes可有如下简写:
1 [root@k8smaster01 heketi]# kubectl create -f gluster-heketi-pvc.yaml -n heketi
2 [root@k8smaster01 heketi]# kubectl get pvc -n heketi
3 [root@k8smaster01 heketi]# kubectl describe pvc gluster-heketi-pvc -n heketi
4 [root@k8smaster01 heketi]# kubectl get pv -n heketi
5 [root@k8smaster01 heketi]# kubectl describe pv pvc-ca949559-094a-11ea-8b3c-000c29fa7a79 -n heketi
1 [root@k8smaster01 heketi]# kubectl describe endpoints glusterfs-dynamic-ca949559-094a-11ea-8b3c-000c29fa7a79 -n heketi
提示:由上可知:PVC状态为Bound,Capacity为1G。查看PV详细信息,除容量,引用storageclass信息,状态,回收策略等外,同时可知GlusterFS的Endpoint与path。EndpointsName为固定格式:glusterfs-dynamic-PV_NAME,且endpoints资源中指定了挂载存储时的具体地址。
通过5.3所创建的信息:
1 [root@k8smaster01 ~]# kubectl get pod -n heketi
2 [root@k8smaster01 ~]# kubectl exec -ti glusterfs-b854k -n heketi -- lsblk #glusterfs节点查看
3 [root@k8smaster01 ~]# kubectl exec -ti glusterfs-b854k -n heketi -- df -hT #glusterfs节点查看
4 [root@k8smaster01 ~]# kubectl exec -ti glusterfs-b854k -n heketi -- gluster volume list
5 [root@k8smaster01 ~]# kubectl exec -ti glusterfs-b854k -n heketi -- gluster volume info vol_29ba6f9665522ad5893412e61799a433 #glusterfs节点查看
1 [root@xxx ~]# yum -y install centos-release-gluster
2 [root@xxx ~]# yum -y install glusterfs-fuse #安装glusterfs-fuse
提示:本环境master节点也允许分发pod,因此所有master也必须安装glusterfs-fuse以便于正常挂载,同时版本需要和glusterfs节点一致。
1 [root@k8smaster01 heketi]# vi gluster-heketi-pod.yaml
2 kind: Pod
3 apiVersion: v1
4 metadata:
5 name: gluster-heketi-pod
6 spec:
7 containers:
8 - name: gluster-heketi-container
9 image: busybox
10 command:
11 - sleep
12 - "3600"
13 volumeMounts:
14 - name: gluster-heketi-volume #必须和volumes中name一致
15 mountPath: "/pv-data"
16 readOnly: false
17 volumes:
18 - name: gluster-heketi-volume
19 persistentVolumeClaim:
20 claimName: gluster-heketi-pvc #必须和5.3创建的PVC中的name一致
21 [root@k8smaster01 heketi]# kubectl create -f gluster-heketi-pod.yaml -n heketi #创建Pod
1 [root@k8smaster01 ~]# kubectl get pod -n heketi | grep gluster-heketi
2 gluster-heketi-pod 1/1 Running 0 4m58s
3 [root@k8smaster01 ~]# kubectl exec -it gluster-heketi-pod /bin/sh -n heketi #进入Pod写入测试文件
4 / # cd /pv-data/
5 /pv-data # echo "This is a file!" >> a.txt
6 /pv-data # echo "This is b file!" >> b.txt
7 /pv-data # ls
8 a.txt b.txt
9 [root@k8smaster01 ~]# kubectl exec -it gluster-heketi-pod -n heketi -- df -h #查看所挂载的glusterfs
1 [root@k8smaster01 ~]# kubectl get pods -n heketi -o wide #查看对应的glusterfs node
1 [root@k8smaster01 ~]# kubectl exec -ti glusterfs-b854k -n heketi -- cat /var/lib/heketi/mounts/vg_2c7a02d1b1b7c1f165283b6691062102/brick_16e37a18a5e5fd40e14338ba78d99565/brick/a.txt
2 This is a file!
提示:通过Pod写入相应的测试文件,然后通过glusterfs node节点查看是否存在。
1 [root@k8smaster01 ~]# cd heketi/
2 [root@k8smaster01 heketi]# kubectl delete -f gluster-heketi-pod.yaml -n heketi
3 [root@k8smaster01 heketi]# kubectl delete -f gluster-heketi-pvc.yaml
4 [root@k8smaster01 heketi]# kubectl get pvc -n heketi
5 [root@k8smaster01 heketi]# kubectl get pv -n heketi
6 [root@k8smaster01 heketi]# kubectl exec -ti glusterfs-b854k -n heketi gluster volume list | grep gluster
参考:https://www.linuxba.com/archives/8152
https://www.cnblogs.com/blackmood/p/11389811.html