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。