0x01 前言
我使用Rancher2作为容器的编排工具已经有大半年的时间,直到今天还是使用单机NFS服务作为存储为容器提供数据持久化服务。找到新工作后一直在忙于学习工作上的新事物,所以直到今天才开始研究适用于容器的高可用数据持久化服务。
但在测试的过程中发现Rancher2所使用的hyperkube内置Gluster的驱动太旧,需要使用5.x版本的Gluster才能正常工作,而这花了我3天时间才找到问题的原因。
0x02 准备
基础架构及流程如下:
这流程图看起来是有那么一点点复杂,简单描述如下:
- Client通过Rancher Web GUI创建Pod的时候创建一个新的PVC或者直接创建一个PVC
- 创建PVC的时候选择指定的Storage Class
- Storage Class使用配置好的信息通过Restful API调用Heketi API创建Volume
- Heketi调用Gluster Cluster创建Volume
- Pod拿到Volume信息后挂载使用
严格来说这流程不太对,但主要是这么回事。如果不用Heketi的情况下,是需要使用gluster client手动创建Volume,但不符合自动化的需求。这里会使用Heketi,它能提供API接口给Rancher内的Storage驱动使用,同时又能管理Gluster node,这是一个成熟的解决方案,一举多得。
Gluster在默认情况下是3副本模式,可用性较高。另外也不需要过于担心Heketi故障的问题,它只提供API接口,故障后只会导致无法创建新的Volume而已。而挂载的时候会使用Gluster某一个node作为挂载点,另外还有一个option附有所有node的IP,当正在使用的node故障后会自动切换。
首选需要准备一套Rancher2环境,可以参考以下文章进行部署:
然后准备4台虚拟机,分别为1台Heketi,3台Gluster node,这3个node至少要有一个未经格式化的磁盘,比如我的虚拟机:
其实Heketi也可以通过一些常见的技术实现高可用,比如keepalived,而Heketi自身是有个数据库的,这个数据库可以放在Gluster的一个Volume内。但本文篇幅有限,不涉及这部分内容。
0x03 安装Gluster
正如前面所说的,我们需要安装5.x版本以适配Rancher2内置的驱动,所以需要在Gluster所有node内执行以下命令:
yum install centos-release-gluster5 -y \ && yum install glusterfs-server -y \ && systemctl enable glusterd \ && systemctl restart glusterd \ && systemctl status glusterd
可以检查这服务所监听的端口:
至此,GlusterFS安装的工作全部完成,非常简单。
0x04 安装Heketi
在Heketi服务器上执行以下命令即可完成安装Heketi的工作:
yum install centos-release-gluster5 -y \ && yum install heketi heketi-client -y
完成安装后先不要启动Heketi,需要先进行配置工作:
vim /etc/heketi/heketi.json
按需修改如下注释中的内容:
{
"_port_comment": "Heketi Server Port Number",
# 端口
"port": "8080",
"_use_auth": "Enable JWT authorization. Please enable for deployment",
# 是否启用用户验证
"use_auth": false,
"_jwt": "Private keys for access",
"jwt": {
"_admin": "Admin has access to all APIs",
"admin": {
# 管理员级别用户的key
"key": "My Secret"
},
"_user": "User only has access to /volumes endpoint",
"user": {
# 用户级别的key
"key": "My Secret"
}
},
"_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."
],
# 配置GlusterFS所用的方式
"executor": "ssh",
"_sshexec_comment": "SSH username and private key file information",
"sshexec": {
# SSH免密登陆的key所在的路径
"keyfile": "/etc/heketi/heketi.key",
# SSH用户
"user": "root",
# SSH端口
"port": "22",
# fstab文件所在的路径
"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",
# Heketi数据库路径
"db": "/var/lib/heketi/heketi.db",
"_loglevel_comment": [
"Set log level. Choices are:",
" none, critical, error, warning, info, debug",
"Default is warning"
],
# 日志级别
"loglevel" : "debug"
}
}
在此,我只修改以下内容:
- executor:SSH
- keyfile:/etc/heketi/heketi.key
- user:root
- port:22
- fstab:/etc/fstab
紧接着生成SSH Key并分发到3台Gluster中以实现免密登陆:
# 生成SSH Key [root@heketi-node1 ~]# ssh-keygen -t rsa -q -f /etc/heketi/heketi.key -N "" # 修改SSH Key权限 [root@heketi-node1 ~]# chown heketi:heketi /etc/heketi/heketi.key && chmod 400 /etc/heketi/heketi.key # 部署SSH Key到Gluster Node [root@heketi-node1 ~]# ssh-copy-id -i /etc/heketi/heketi.key [email protected] [root@heketi-node1 ~]# ssh-copy-id -i /etc/heketi/heketi.key [email protected] [root@heketi-node1 ~]# ssh-copy-id -i /etc/heketi/heketi.key [email protected]
至此已完成Heketi的基本配置,现在尝试启动Heketi:
systemctl enable heketi \ && systemctl restart heketi \ && systemctl status heketi
接下来要准备拓扑结构的文件,比如我的:
{
"clusters": [
{
"nodes": [
{
"devices": [
"/dev/sdb"
],
"node": {
"hostnames": {
"manage": [
"10.1.3.15"
],
"storage": [
"10.1.3.15"
]
},
"zone": 1
}
},
{
"devices": [
"/dev/sdb"
],
"node": {
"hostnames": {
"manage": [
"10.1.3.16"
],
"storage": [
"10.1.3.16"
]
},
"zone": 1
}
},
{
"devices": [
"/dev/sdb"
],
"node": {
"hostnames": {
"manage": [
"10.1.3.17"
],
"storage": [
"10.1.3.17"
]
},
"zone": 1
}
}
]
}
]
}
其中一些key的含义如下:
- manage:管理通道的IP
- storage:数据通道的IP
- zone:故障域
- devices:磁盘路径
可以创建不同故障域以提升数据的可靠性;磁盘路径可以是多个;通道必须填写IP,因为Heketi无法解析域名。完成后执行以下命令即可:
# 执行命令 [root@heketi-node1 ~]# heketi-cli topology load --json=/etc/heketi/topology.json # 返回的结果 Creating cluster ... ID: 6a84b0b18e9af56173431e5d4ef16b89 Allowing file volumes on cluster. Allowing block volumes on cluster. Creating node 10.1.3.15 ... ID: c264795f04903148775d62181a1a00ed Adding device /dev/sdb ... OK Creating node 10.1.3.16 ... ID: 61412a8ed3ca971bffd0ee36a80dfd59 Adding device /dev/sdb ... OK Creating node 10.1.3.17 ... ID: f31f5f32a591342232b97caa6bd5cae0 Adding device /dev/sdb ... OK
在返回的结果中有Cluster ID的部分,这在后续需要用到的。至此,Heketi的安装配置工作已全部完成。
在继续之前可以尝试使用以下命令:
# 列出Cluster [root@heketi-node1 ~]# heketi-cli cluster list Clusters: Id:6a84b0b18e9af56173431e5d4ef16b89 [file][block] # 查看Cluster信息 [root@heketi-node1 ~]# heketi-cli cluster info 6a84b0b18e9af56173431e5d4ef16b89 Cluster id: 6a84b0b18e9af56173431e5d4ef16b89 Nodes: 61412a8ed3ca971bffd0ee36a80dfd59 c264795f04903148775d62181a1a00ed f31f5f32a591342232b97caa6bd5cae0 Volumes: Block: true File: true # 列出Node [root@heketi-node1 ~]# heketi-cli node list Id:61412a8ed3ca971bffd0ee36a80dfd59 Cluster:6a84b0b18e9af56173431e5d4ef16b89 Id:c264795f04903148775d62181a1a00ed Cluster:6a84b0b18e9af56173431e5d4ef16b89 Id:f31f5f32a591342232b97caa6bd5cae0 Cluster:6a84b0b18e9af56173431e5d4ef16b # 查看Node信息 [root@heketi-node1 ~]# heketi-cli node info 61412a8ed3ca971bffd0ee36a80dfd59 Node Id: 61412a8ed3ca971bffd0ee36a80dfd59 State: online Cluster Id: 6a84b0b18e9af56173431e5d4ef16b89 Zone: 1 Management Hostname: 10.1.3.16 Storage Hostname: 10.1.3.16 Devices: Id:8a50a043463b591b518a61c19abdc374 Name:/dev/sdb State:online Size (GiB):49 Used (GiB):0 Free (GiB):49 Bricks:0
还可以查看拓扑信息:
[root@heketi-node1 ~]# heketi-cli topoligy info
0x05 Rancher2挂载
因为没有配置用户信息,所以只需要Heketi服务器的IP、端口和Cluster的ID即可,比如我的信息:
- 服务器IP:10.1.3.21
- 端口:8080
- Cluster ID:6a84b0b18e9af56173431e5d4ef16b89
我们还可以通过浏览器访问Heketi的这个URI确认服务是否正常:
在默认情况下,很多驱动在Rancher2里都属于实验性功能,我们需要手动打开。因为没有全面测试过,所以在后续的Rancher2升级中可能会出现问题,这需要使用者自行衡量风险。不过开源软件不都是这样的吗?
首先来到下图中的页面激活被禁用的存储驱动:
然后来到存储类页面,添加一个存储类:
然后按下图进行配置:
- 名称:自定义名称
- 提供者:Gluster Volume
- REST URL:Heketi服务器地址
- 集群ID:Heketi集群ID
- 回收策略:
- 在工作负载释放后删除卷和底层设备:PVC释放后会删除PV,该PV内的数据会被删除,慎用
- 保留卷以进行手动清理:PVC释放后会保留PV,数据保留。
完成后保存即可,随后即可手动创建一个PVC:
配置信息如下:
单击创建后稍等片刻即可看到PV信息已经自动创建:
单击上图中的PV,再打开注释部分可以看到以下信息:
再会到Heketi,执行以下命令可以查看该Volume的详细信息:
# 列出Volume [root@heketi-node1 ~]# heketi-cli volume list Id:d79bb11df638f5b78e3f0cd8c20a6f32 Cluster:6a84b0b18e9af56173431e5d4ef16b89 Name:vol_d79bb11df638f5b78e3f0cd8c20a6f32 # 查看指定的Volume [root@heketi-node1 ~]# heketi-cli volume info d79bb11df638f5b78e3f0cd8c20a6f32 Name: vol_d79bb11df638f5b78e3f0cd8c20a6f32 Size: 10 Volume Id: d79bb11df638f5b78e3f0cd8c20a6f32 Cluster Id: 6a84b0b18e9af56173431e5d4ef16b89 Mount: 10.1.3.16:vol_d79bb11df638f5b78e3f0cd8c20a6f32 Mount Options: backup-volfile-servers=10.1.3.15,10.1.3.17 Block: false Free Size: 0 Reserved Size: 0 Block Hosting Restriction: (none) Block Volumes: [] Durability Type: replicate Distributed+Replica: 3 Snapshot Factor: 1.00
至此,所有配置工作皆已完成。
在实际使用中可以省略手动创建PVC的步骤,在创建Pod的时候新建即可:
同样的,需要填写一些信息:
但是在这里填写信息后并不会立刻创建PVC,而是在完成该Pod所有信息的填写并且运行时才会创建:
进入容器检查挂载情况并touch一个文件:
然后来到Gluster各个Node查看文件是否成功被复制:
0x06 结语
这套东西部署起来非常简单,但用起来需要考虑诸如网络、IO、存储高可用和Rancher自动化等等问题,还得对Centos调优,工作可预见的繁杂。
至少目前有一套高可用的数据持久化解决方案,接下来要替换掉我目前使用的单机NFS。










































