跳转至

k8s 集群存储解决方案 GlusterFS

一. 存储解决方案介绍

1. GlusterFS

  • GlusterFS是一个开源的分布式文件系统
  • 具有强大的横向扩展能力
  • 通过扩展能够支持数 PB 存储容量和处理数千客户端
  • GlusterFS借助 TCP/I P或 InfiniBandRDMA 网络将物理分布的存储资源聚集在一起,使用单一全局命名空间来管理数据。

2. Heketi

二. 环境说明

2. GlusterFS 集群

主机 IP地址 硬盘 硬盘容量
g1 192.168.3.51 /dev/sdb 100G
g2 192.168.3.52 /dev/sdb 100G
g3 192.168.3.53 /dev/sdb 100G

三、GlusterFS 集群部署

1. 主机准备

1. 三台主机都执行, X 为 1,2,3
> hostnamectl set-hostname gX
1. 创建

1. 设置三台主机主机名对应
cat >> /etc/hosts <<'EOF'
192.168.3.51 g1
192.168.3.52 g2
192.168.3.53 g3
EOF
1. 在 g1 主机操作,然后 copy 到其它主机即可。
ssh-keygen -t rsa -f /root/.ssh/id_rsa -N '' && cd /root/.ssh && cp id_rsa.pub authorized_keys && cd ../
scp -r /root/.ssh g2:/root
scp -r /root/.ssh g3:/root
1. 查看硬盘。所有 GlusterFS 集群节点全部操作,仅在g1主机演示操作方法。
> llsblk
NAME            MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sda               8:0    0   50G  0 disk 
├─sda1            8:1    0    1G  0 part /boot
└─sda2            8:2    0   49G  0 part 
├─centos-root 253:0    0 46.1G  0 lvm  /
└─centos-swap 253:1    0  2.9G  0 lvm  [SWAP]
sdb               8:16   0  100G  0 disk 
sr0              11:0    1 1024M  0 rom
2. 格式化硬盘。
> mkfs.xfs /dev/sdb
Discarding blocks...Done.
meta-data=/dev/sdb               isize=512    agcount=4, agsize=6553600 blks
        =                       sectsz=512   attr=2, projid32bit=1
        =                       crc=1        finobt=0, sparse=0
data     =                       bsize=4096   blocks=26214400, imaxpct=25
        =                       sunit=0      swidth=0 blks
naming   =version 2              bsize=4096   ascii-ci=0 ftype=1
log      =internal log           bsize=4096   blocks=12800, version=2
        =                       sectsz=512   sunit=0 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0
1. 准备挂载目录。
> mkdir /glustersdb
2. 修改/etc/fstab文件实现自动挂载。
> cat /etc/fstab
/dev/sdb                /glustersdb             xfs     defaults        0 0
# 挂载所有
> mount -a

# 查看文件系统挂载情况
> df -h
文件系统                 容量  已用  可用 已用% 挂载点
devtmpfs                 1.4G     0  1.4G    0% /dev
tmpfs                    1.5G     0  1.5G    0% /dev/shm
tmpfs                    1.5G  8.7M  1.4G    1% /run
tmpfs                    1.5G     0  1.5G    0% /sys/fs/cgroup
/dev/mapper/centos-root   47G  1.6G   45G    4% /
/dev/sda1               1014M  137M  878M   14% /boot
tmpfs                    288M     0  288M    0% /run/user/0
/dev/sdb                 100G   33M  100G    1% /glustersdb

2. 安全设置(三台机器都执行)

1. 关闭 firewalld 防火墙。
> systemctl disable firewalld && systemctl stop firewalld
> firewall-cmd --state
not running
1. 所有主机均要修改,修改后,请重启系统让修改生效。。
> sed -ri 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config
1. 增加时间同步。
> crontab -l
0 */1 * * * ntpdate time1.aliyun.com

3. GlusterFS 安装

yum -y install centos-release-gluster
yum -y install glusterfs glusterfs-server glusterfs-fuse glusterfs-rdma fuse
 systemctl enable glusterd --now

4. GlusterFS 集群配置

在 GlusterFS 集群 g1 主机上添加 g2 和 g3 2台主机。

1. 在 g1 主机上添加 g2 g3
## 1. 添加 g2 主机
> gluster peer probe g2
peer probe: success.
...

## 2. 添加 g3 主机
> gluster peer probe g3
peer probe: success.
...

## 3. 查看状态
> gluster peer status
Number of Peers: 2

Hostname: g2
Uuid: eb262fcb-5fcf-4cbe-a632-d20d5eb7cf48
State: Peer in Cluster (Connected)
Other names:
192.168.3.52

Hostname: g3
Uuid: 2fae8387-6d5f-4460-83f8-7b3007dd9d13
State: Peer in Cluster (Connected)
Other names:
192.168.3.53
1. 在 g2 主机上添加 g1 g3
## 1. 添加 g1 主机
> gluster peer probe g1
peer probe: success.
...

## 2. 添加 g3 主机
> gluster peer probe g3
peer probe: success.
...

## 3. 查看状态
> gluster peer status
Number of Peers: 2

Hostname: g1
Uuid: 13057b51-0599-40a5-8a99-f6c09c380ad0
State: Peer in Cluster (Connected)

Hostname: g3
Uuid: 2fae8387-6d5f-4460-83f8-7b3007dd9d13
State: Peer in Cluster (Connected)
Other names:
192.168.3.53
1. 在 g3 主机上添加 g1 g2
## 1. 添加 g2 主机
> gluster peer probe g1
peer probe: success.
...

## 2. 添加 g3 主机
> gluster peer probe g2
peer probe: success.
...

## 3. 查看状态
> gluster peer status
Number of Peers: 2

Hostname: g1
Uuid: 13057b51-0599-40a5-8a99-f6c09c380ad0
State: Peer in Cluster (Connected)

Hostname: g2
Uuid: eb262fcb-5fcf-4cbe-a632-d20d5eb7cf48
State: Peer in Cluster (Connected)
Other names:
192.168.3.52

5. 添加复制卷验证 GlusterFS 集群可用性

如果是为 K8S集群提供持久化存储,验证GlusterFS集群可用性或验证完成后,请重新添加硬盘。 gluster volume stop k8s-test-volume gluster volume status k8s-test-volume gluster volume delete k8s-test-volume umount /k8s-glusterfs-test-volume wipefs -a /dev/sdb

1. 三台机器均执行
gluster volume create k8s-test-volume replica 3 g1:/glustersdb/r1 g2:/glustersdb/r2 g3:/glustersdb/r3
gluster volume start k8s-test-volume
gluster volume status k8s-test-volume
gluster volume info k8s-test-volume
gluster volume set k8s-test-volume cluster.server-quorum-type none
gluster volume set k8s-test-volume cluster.quorum-type none
gluster volume quota k8s-test-volume enable 
gluster volume quota k8s-test-volume limit-usage / 10GB

6. 在 k8s 集群工作节点验证 GlusterFS 集群可用性

由于仅使用一个工作节点验证GlusterFS集群可用性,因此没有必要为所有工作节点全部安装GlusterFS客户端。

yum -y install centos-release-gluster
yum -y install glusterfs glusterfs-fuse
mkdir /k8s-glusterfs-test-volume    

如果使用主机名挂载,g1,g2,g3主机名需要添加到解析。

mount -t glusterfs g1:/k8s-test-volume /k8s-glusterfs-test-volume
df -h
gluster volume stop k8s-test-volume
gluster volume status k8s-test-volume
gluster volume delete k8s-test-volume

四、Heketi 安装

heketi是为glusterfs提供RESETFUL的API, 相当于给glusterfs和k8s之间架通了桥梁。k8s集群可以通过heketi提供的RESETFUL API完成对Glusterfs的PV申请和管理。

1. 下载 Heketi 二进制并安装

wget https://github.com/heketi/heketi/releases/download/v10.4.0/heketi-v10.4.0-release-10.linux.amd64.tar.gz
for i in `ls | grep heketi | grep .tar.gz`; do tar xvf $i; done
cp heketi/{heketi,heketi-cli} /usr/local/bin

3. 在 k8s 集群 master 节点修改 Heketi 配置文件

1. 为 Heketi 创建一个专用用户
groupadd --system heketi
useradd -s /sbin/nologin --system -g heketi heketi
2. 给 Heketi 创建配置和数据路径
mkdir -p /var/lib/heketi /etc/heketi /var/log/heketi
1. 创建 /etc/heketi/heketi.json
{
"_port_comment": "Heketi Server Port Number",
"port": "38080",

"_use_auth": "Enable JWT authorization. Please enable for deployment",
"use_auth": true,

"_jwt": "Private keys for access",
"jwt": {
    "_admin": "Admin has access to all APIs",
    "admin": {
    "key": "adminQAZ2wsx"
    },
    "_user": "User only has access to /volumes endpoint",
    "user": {
    "key": "userQAZ2wsx"
    }
},

"_glusterfs_comment": "GlusterFS Configuration",
"glusterfs": {
    "_executor_comment": [
    "Execute plugin. Possible choices: mock, ssh",
    "mock: This setting is used for testing and development.",
    "      It will not send commands to any node.",
    "ssh:  This setting will notify Heketi to ssh to the nodes.",
    "      It will need the values in sshexec to be configured.",
    "kubernetes: Communicate with GlusterFS containers over",
    "            Kubernetes exec api."
    ],
    "executor": "ssh",

    "_sshexec_comment": "SSH username and private key file information",
    "sshexec": {
    "keyfile": "/etc/heketi/heketi_key",
    "user": "root",
    "port": "22",
    "fstab": "/etc/fstab"
    },

    "_kubeexec_comment": "Kubernetes configuration",
    "kubeexec": {
    "host" :"https://kubernetes.host:8443",
    "cert" : "/path/to/crt.file",
    "insecure": false,
    "user": "kubernetes username",
    "password": "password for kubernetes user",
    "namespace": "OpenShift project or Kubernetes namespace",
    "fstab": "Optional: Specify fstab file on node.  Default is /etc/fstab"
    },

    "_db_comment": "Database file name",
    "db": "/var/lib/heketi/heketi.db",

    "_loglevel_comment": [
    "Set log level. Choices are:",
    "  none, critical, error, warning, info, debug",
    "Default is warning"
    ],
    "loglevel" : "warning"
}
}
1. 创建 /etc/systemd/system/heketi.service 文件
[Unit]
Description=Heketi Server

[Service]
Type=simple
WorkingDirectory=/var/lib/heketi
EnvironmentFile=-/etc/heketi/heketi.env
User=heketi
ExecStart=/usr/local/bin/heketi --config=/etc/heketi/heketi.json
Restart=on-failure
StandardOutput=syslog
StandardError=syslog

[Install]
WantedBy=multi-user.target
2. 保存文件并下载环境文件:
wget -O /etc/heketi/heketi.env https://raw.githubusercontent.com/heketi/heketi/master/extras/systemd/heketi.env
3. 为 Heketi 用户分配所有必需的权限
chown -R heketi:heketi /var/lib/heketi /var/log/heketi /etc/heketi
4. 加载 Heketi 所需的所有内核模块
for i in dm_snapshot dm_mirror dm_thin_pool; do
  sudo modprobe $i
done

4. 配置 ssh 密钥并验证

sudo -i
ssh-keygen -f /etc/heketi/heketi_key -t rsa -N ''
chown heketi:heketi /etc/heketi/heketi_key*
for i in g1 g2 g3; do
  ssh-copy-id -i /etc/heketi/heketi_key.pub root@$i
done
ssh -i /etc/heketi/heketi_key root@g1

5. 启动 Heketi

/etc/heketi及/var/lib/heketi目录所有者是root, 但是安装提供的service文件的user又是heketi. 导致不修改权限就是启动不起来,因此需要修改权限再启动服务。

systemctl daemon-reload
systemctl enable --now heketi
systemctl status heketi

6. 验证 Heketi 是否可以使用

1. 创建
❯ heketi-cli --user admin --secret 'adminQAZ2wsx' --server http://192.168.1.99:38080 --json  cluster create
{"id":"478c0e0f83d0c3bbe3b66b1f0c29a72b","nodes":[],"volumes":[],"block":true,"file":true,"blockvolumes":[]}                                                                                                                                                                              
2. 查看
heketi-cli cluster info 478c0e0f83d0c3bbe3b66b1f0c29a72b --user admin --secret 'adminQAZ2wsx' --server http://192.168.1.99:38080    
heketi-cli --user admin --secret adminQAZ2wsx --server http://192.168.1.99:38080  --json  cluster list
3. 删除
heketi-cli cluster delete 478c0e0f83d0c3bbe3b66b1f0c29a72b --user admin --secret 'adminQAZ2wsx' --server http://192.168.1.99:38080

7. 创建并加载 Heketi 拓扑文件(创建集群添加 node,加载 磁盘至 node)

1. 编写 heketi-topology.json
{
    "clusters": [
        {
            "nodes": [
                {
                    "node": {
                        "hostnames": {
                            "manage": [
                                "192.168.3.51"
                            ],
                            "storage": [
                                "192.168.3.51"
                            ]
                        },
                        "zone": 1
                    },
                    "devices": [
                        "/dev/sdb"
                    ]
                },
                {
                    "node": {
                        "hostnames": {
                            "manage": [
                                "192.168.3.52"
                            ],
                            "storage": [
                                "192.168.3.52"
                            ]
                        },
                        "zone": 1
                    },
                    "devices": [
                        "/dev/sdb"
                    ]
                },
                {
                    "node": {
                        "hostnames": {
                            "manage": [
                                "192.168.3.53"
                            ],
                            "storage": [
                                "192.168.3.53"
                            ]
                        },
                        "zone": 1
                    },
                    "devices": [
                        "/dev/sdb"
                    ]
                }
            ]
        }
    ]
}
1. 加载 heketi-topology.json
❯ heketi-cli topology load --user admin --secret adminQAZ2wsx --server http://192.168.1.99:38080 --json=/etc/heketi/heketi-topology.json
Creating cluster ... ID: ae3a904be7d1219955c9ec3544bcd291
        Allowing file volumes on cluster.
        Allowing block volumes on cluster.
        Creating node 192.168.3.51 ... ID: 77c8af95a371b3fcaaaf68928e0167b0
                Adding device /dev/sdb ... OK
        Creating node 192.168.3.52 ... ID: f4f4cd72b69ea64562a2a13f352c7a85
                Adding device /dev/sdb ... OK
        Creating node 192.168.3.53 ... ID: 9e0b61edba43bdf2083af71624217a01
                Adding device /dev/sdb ... OK
2. 查看集群中 node 列表
heketi-cli node list --user admin --secret 'adminQAZ2wsx' --server http://192.168.1.99:38080 --json
3. 删除 node 列表
heketi-cli node delete --user admin --secret 'adminQAZ2wsx' --server http://192.168.1.99:38080 --json <node_id>
4. 验证节点及设备添加情况
heketi-cli --user admin --secret adminQAZ2wsx --server http://192.168.1.99:38080  topology info --json
1. 添加新硬盘
lsblk

...
sdc             252:32   0   50G  0 disk
2. 添加 GlusterFS 集群节点中的设备到 Heketi 集群 (每个 node 都执行)
heketi-cli --user admin --secret 'adminQAZ2wsx' --server http://192.168.1.99:38080   device add --name "/dev/sdc" --node 77c8af95a371b3fcaaaf68928e0167b0
heketi-cli --user admin --secret 'adminQAZ2wsx' --server http://192.168.1.99:38080   device add --name "/dev/sdc" --node 9e0b61edba43bdf2083af71624217a01
heketi-cli --user admin --secret 'adminQAZ2wsx' --server http://192.168.1.99:38080   device add --name "/dev/sdc" --node f4f4cd72b69ea64562a2a13f352c7a85
3. 验证节点及设备添加情况
heketi-cli --user admin --secret adminQAZ2wsx --server http://192.168.1.99:38080  topology info --json

8. 测试通过 Heketi 在 GlusterFS 集群中添加 volume

1. 创建
heketi-cli --user admin --secret adminQAZ2wsx --server http://192.168.1.99:38080 volume create --size=5 --replica=2
2. 查看
heketi-cli --user admin --secret adminQAZ2wsx --server http://192.168.1.99:38080 volume list
3. 在GlusterFS集群节点中验证即可看到已创建的卷。
gluster volume list

五、K8S 集群使用 GlusterFS 集群

提示:k8s中使用glusterfs的时候, 会根据pvc的申请自动创建对应的pv, 然后绑定。

1. 在k8s集群master节点创建storageclass资源清单文件

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: glusterfs
provisioner: kubernetes.io/glusterfs #表示存储分配器,需要根据后端存储的不同而变更
parameters:
  resturl: "http://192.168.1.99:38080" #heketi API服务提供的URL,为k8s集群master节点IP
  restauthenabled: "true" #可选参数,默认为"false",heketi服务开启认证时,必须设置为"true"
  restuser: "admin" #可选参数,开启认证时设置相应用户名
  restuserkey: "adminQAZ2wsx" #可选,开启认证时设置密码
  volumetype: "replicate:2" #可选参数,设置卷类型及其参数,如果未分配卷类型,则有分配器决定卷类型;如”volumetype: replicate:3”表示3副本的replicate卷,”volumetype: disperse:4:2”表示disperse卷,其中‘4’是数据,’2’是冗余校验,”volumetype: none”表示distribute卷
1. 创建资源
kubectl apply -f storageclass-gluserfs.yaml
2. 在 k8s 集群 master 节点验证是否创建 storageclass 存储对象
kubectl get sc

2. 在 k8s 集群 master 节点创建用于创建 PVC 的资源清单文件

kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: glusterfs-mysql
  namespace: default
  annotations:
    volume.beta.kubernetes.io/storage-class: "glusterfs"
spec:
  accessModes:
  - ReadWriteMany
  resources:
    requests:
      storage: 2Gi
1. 创建资源
kubectl apply -f glusterfs-pvc.yaml