本文由 4 月 12 日晚姜江,新东方运维工程师所做的技术分享整理而成。
姜江,一名伪 SRE。十余年 IT 运维从业经历,早年在金融行业从事 linux,AIX,Oracle 的运维支持,现在专注于运维自动化、容器和 cloud native 相关技术的研究和落地。目前就职于新东方,负责新东方容器云平台的探索和实践。
大家好!话说加入 Rancher 官方微信群也有三年多了,每天在群里看着大家讨论技术问题给我很多启发 。 我今天也来和大家分享一下我在 rancher 上的一些实践,希望能为各位的实践提供一些参考。
为了避免大家歧义,下面说的 Rancher 指的 Rancher 1.6 上的 cattle 引擎。
摘要
Rancher 是一个对用户很友好的产品,吸引了大批的用户和粉丝。在实际落地过程中,大家可能已经注意到 Rancher 组件之间的耦合存在单点。那么如何部署才能提高 Rancher 的可用性和可扩展性呢?Rancher 在官方文档中给出了一些指导方案,用户可以根据自己的需要选择合适的方案落地。我今天和大家分享的是 新东方在 Rancher 全组件负载均衡架构的实践,供大家在探索自己的高可用方案时做个参考。
1. Rancher 的部署架构演变
Rancher 1.6 是一套小巧而实用的容器管理平台,我个人认为 Rancher 的定位应该是容器编排引擎的后台支撑系统, 或者说是编排引擎的系统,因此 Rancher1.6 的架构并不是分布式架构,而是传统的 C/S 架构。 无数的 client(agent)连接到一个中心的 Server ,中心的 Server 连接一个数据库做持久化。这种架构就必然会涉及一个老话题,如何增强 C/S 之间的高可用性、可扩展性和解耦问题。我今天和大家聊内容是:Rancher 1.6 全组件负载均衡设计。
一般 Rancher 的简单部署方案是这样的:
一个 server,一些节点 ,一个 mysql 数据库。从这张图上就可以发现 Rancher 在部署上的一些问题:
SPOF 问题,Server 的单点,数据库的单点等。
扩展性问题,单 server 能带动的 client 数量有限。
强耦合问题,server 写死数据库地址,client 写死 server 地址等等。
总结下来就是下面这个图
下面就对这个架构进行优化,我们的目标是达到 Server/Client 和数据库三个组件的自由扩展,如何做到呢? Rancher 官方文档中已经给了答案,只需要在 C/S 中间增加一层负载均衡方案,在数据库一侧增加高可用方案即可。
总体架构就演变为这样:
我们看到,Server 一侧使用 Rancher Server HA 方案,将 server 扩展为多个。
中间增加一层负载均衡,这个负载均衡常见的私有云方案有 LVS+Nginx 或者 F5, 在公有云中可以使用阿里云的 SLB 或者 AWSELB 等等。Rancher 的数据量并不算太大,可以简单的使用 Mysql 的主从方案。
优化到这步已经可以满足日常工作需要了,这里大家会注意到 mysql 主从还是会影响 server 的可靠性。 一旦出现主库问题,Mysql 切换的时候 server 肯定就 down 了, 切换也需要一定的时间,启动后还需要重启 server 等等。如果希望更进一步提高 server 的可靠性,或者希望数据库切换对 Rancher Server 透明,那就需要使用更高级的数据库高可用方案。
我们的 DBA 推荐使用 Maxscale 中间件+Galera 集群的方案, Galera 为多主库的分布式数据方案,发生写入操作后 Galera 会同步数据到其他数据库中,直到同步都完成后返回完成写入操作。MaxScale 是数据库中间件,它通过解析 mysql 协议判断读写操作,可以将读写操作分离。一旦数据库发生故障整个数据库集群的切换对外界是无感知的。
这个方案的部署图是这样的:
每个组件都介绍一下, 负载均衡采用互联网最常用的 LVS-DR+Nginx 方案。数据库采用 Galera 集群做多主库的数据库复制,通过 Maxscale 中间件来做高可用和读写分离。
这就是我们现在最终的架构, 这个架构的好处有几点:
可靠性大大增加, 所有组件都可以扩展,server, client,数据库和负载均衡本身。
每个组件的扩展并不影响其他组件,所有组件的扩展都可以在线进行。
配置解耦,通过域名映射的方式,server 连接数据库的域名映射为 maxsacle 中间件的 ip, client 连接 server 的域名映射为负载均衡的 Vip。
故障切换透明,对其他组件无感知。数据库故障,server 故障都可以在线解决,解决后重新加入集群。
顺便提一下,这个架构中的数据库部分还可以进一步优化为:
MaxScale 前增加一层 LVS 四层负载均衡(设备可复用 c/s 之间的负载均衡),那么这个方案就可以说是全模块无死角的负载均衡架构了。 但是我们实际实施的时候并没有采用这样的方案,考虑到 Rancher Server 和 Client 断开一段时间后并不会影响主机上的容器运行。
这段时间完全可以做一些维护, 采用 Galera 和 Maxscale 后已经大大的减少了数据库切换时间,并且实测 MaxScale 的稳定性很好,感觉没有必要再投入更多资源在 MaxScale 上。更何况加入更多的组件会使得整个系统的复杂度上升,这实际上增加了维护成本并且扩展了故障域,可靠性有可能不升反降。因此这个方案也只是停留在纸面上了。
那么说到这里大家对整体架构就有了初步认识,下面说说实现。
篇幅和时间原因,我这里只是点一下配置的要点,具体的实践过程可以关注我的工作笔记 http://jiangjiang.space
2. Rancher 各个组件负载均衡的配置
2.1 LVS-DR + Nginx
LVS-DR 设置:
LVS1 : 配置 keepalived,配置虚拟 ip,配置到 Nginx1 和 Nginx2 的四层转发
LVS2 : 配置 keepalived,配置虚拟 ip,配置到 Nginx1 和 Nginx2 的四层转发
Nginx1 :配置 nginx 到 rancher server 8080 上的七层转发
Nginx2 :配置 nginx 到 rancher server 8080 上的七层转发
A. 安装 keepalived 和 ipvsadmin
LVS 从 2.6 内核开始就已经是内核的一部分了,因此只需要安装 ipvsadmin 和 keepalived,通过 yum 安装或者源码安装都可以,步骤略过。
B. 配置 keepalived.conf
vi /etc/keepalived/conf/rancher.conf
C. Nginx 节点配置
Nginx 节点配置分为两部分:
虚拟 IP(VIP)设置到回环设备上(lo),当接收到 lvs 发来的包后本机网卡才会处理这些包。
设置 Nginx 的 Websocket 转发到 rancher server 的 8080 端口上。
VIP 配置在 lo 上的配置:
下面设置 Nginx 的 Websocket 转发到 Rancher server 的 8080 端口上。 安装 nginx 过程略过,在 conf.d 中增加虚拟主机配置。 vi /usr/local/nginx/conf/conf.d/rancher.conf
配置好后,直接访问 http://VIP:80 应该就可以看到 Rancher 控制台界面了。如果没有则是配置错误,继续调整。
参考文档:
https://www.cnblogs.com/liwei0526vip/p/6370103.html
2.2 galera 和 Maxscale
以下步骤摘自新东方资深 DBA 傅少峰的文档。
https://mariadb.com/downloads 下载并安装 mariadb 10.2
安装如下 rpm 包
MariaDB-client-10.2.11-1.el7.centos.x86_64
MariaDB-devel-10.2.11-1.el7.centos.x86_64
MariaDB-server-10.2.11-1.el7.centos.x86_64
MariaDB-common-10.2.11-1.el7.centos.x86_64
MariaDB-compat-10.2.11-1.el7.centos.x86_64
galera-25.3.22-1.rhel7.el7.centos.x86_64.rpm
jemalloc-3.6.0-1.el7.x86_64.rpm
jemalloc-devel-3.6.0-1.el7.x86_64.rpm
maxscale-2.1.16-1.centos.7.x86_64.rpm
maxscale-devel-2.1.16-1.centos.7.x86_64.rpm
maxscale 可以复用其中一个数据库节点或者单独部署到一个机器。
mysql 配置注意的地方,其他参数省略。
galera 配置
执行:
建立 cattle 数据库和用户(连接任何一个 galera 实例执行):
创建 maxscale 监控用户(连接任何一个 galera 实例执行):
数据库准备完毕,下面是配置 MaxScale。
MaxScale 配置
配置文件: /etc/maxscale.cnf
启动 maxscale
参考资料:
https://www.jianshu.com/p/772e17c10e08
https://linux.cn/article-5767-1.html#3_2234
2.3 server 、client 和 数据库的连接和设置
数据库准备好了,下面就可以启动 server 了。启动过程非常简单,只需要修改 rancher server 的启动参数如下:
逐条解释一下:
Server 启动后就可以增加 client 了,登陆 Rancher 管理控制台,选择 infrastructure->Hosts->Add Host
这样一个完整的负载均衡的 Rancher 就搭建完成了。
3 应用交付和负载均衡
现在说最后一个话题,应用交付和负载均衡。 所谓应用交付说的是如何将 Rancher 上的一个应用公布到公网上给用户使用。为了能在前方接住大量的用户请求,一般都会统一搭建站点级别的入口负载均衡。示意图如下:
如图所示,用户请求从公网进来后,通过各路 ISP 接入设备到达站点边缘,连接通过各种防御设备到达入口负载均衡(LVS+Keepalived+Nginx),再由入口负载均衡统一代理到内部源站点上,这就是常见的应用交付过程。
在 Rancher 上的应用对接入口负载均衡一般采用 Traefik, Traefik 是一个容器化 7 层代理软件,性能接近 Nginx。 之前群里也有多位大拿分享过 Traefik 的应用, 我这里就不重复介绍了,大家可以参考爱医康架构师张新峰的分享:《关于高可用负载均衡的探索》
我下面要讲的是 traefik 与 LVS+Nginx 负载均衡的对接和我对 traefik 的一些实践。
利用 traefik 交付应用的整个过程我总结为下图:
1. 用户在浏览器中输入 www.myxdf.com,通过 DNS 查询到这个域名对应的公网 ip 地址。
2. 这个公网 ip 地址指向我们站点的入口负载均衡(LVS+Nginx),入口负载均衡收到请求后根据域名的设置,将请求转发给 Rancher 上的 Traefik 节点,我称这些节点为 Ranhcer edge。
3. traefik 收到请求后,根据 traefik.frontend.rule 将请求转给打了标记的容器(或者 rancher lb)
根据这个流程我们需要做以下几个配置。
3.1 定义边界(rancher edge host)
什么是边界? 边界就是 Rancher cluster 中对外转发的中转站,边界是特殊的一个 Rancher host,边界上只跑 treafik,其他什么容器都不跑,边界最好也不要接入任何存储(比如 Rancher nfs),边界需要做严格的安全加固。 当然也可以不将边界放在专门的 host 上,可以将边界混合到整个 Rancher 集群中,这样的好处是节省计算资源,两种模式都可以。
下面介绍如何将 host 定义为专门的边界节点:在 Ranhcer 控制台上, 打开 infrastructure ,点击 Hosts 中。找到作为边界的 host 点击 Edit:
在 Labels 中增加 label,增加这个 label 后 traefik 就会自动运行在这台 host 上。
在 Required Container Label 中随便增加一个 lable 不用给值, 我这里写的 cn.xdf.edge
这个 lable 加入后,这个节点上就不会被调度任何其他容器了。这样一个边界节点就制作好了。
3.2 启动 traefik 到 边界节点
在社区商店中找到这个可爱的小交警,启动 traefik。
配置说明如下:
好了启动 traefik 后,容器已经在 edge Host 上启动了!
登陆管理界面看看:
3.3 在 traefik 上发布应用服务
假设现在要把 mydockerapp04.myxdf.com 这个域名的应用发布出去。 首先将 mydockerapp04.myxdf.com 这个域名匹配到对应的 Rancher stack 上面去。
这个就是我们的 mydockerapp04 应用, 它是一些 tomcat 容器和一个内部 lb 组成的。
按照 traefik 的文档,只需要将 label 打到容器上即可,这里我的做法是增加了一个内部的 lb,直接将 label 打在 lb 上。这里必须的 label 是:
label 加入后应用就发布到 traefik 中了。
3.4 从站点入口负载均衡转发到 Traefik
在站点入口负载均衡上做转发配置,转发到 treafik 边界节点。 负载均衡上所有源站都是通过 80 端口转发,通过设置不通的 server_name 来区分转发目的地。将 server_name 设置为*.myxdf.com
。意思是所有 myxdf.com 的二级域名全部转发给 traefik,这样做是为了跳过在入口负载均衡上配置明细转发规则(比如 mydockerapp01 转发到哪里这样的一条一条的规则),所有明细的转发规则全部交给 traefik 来管理。
这样做有很大的优势,我们之前也看到了 traefik 设置转发规则非常简单,只需要在容器或者 ranhcer lb 上打 label 即可。如果需要修改或者删除规则,也只需要修改或删除对应的 label 即可,管理灵活又免去了每次都要手动到入口负载均衡上刷新配置的麻烦。
Nginx 配置如下:
3.5 在 DNS 上设置域名指向站点入口负载均衡
在 DNS 上添加域名指向, 这里就没有办法偷懒了,需要把所有明细域名都写上。
如果你不是公网应用,也可以使用 dnsmasq 或者 bind 甚至 AD 域的 DNS 等在内网建立 DNS 指向,DNS 指向的 IP 为内网 LVS 的 vip。
Rancher 里面也有修改 DNS 的 APP,比如 aliyun DNS、Gandi.net 等等。这些 APP 有的是自动添加 DNS 记录的,有的是根据 label 添加,大家有兴趣可以继续研究下。
至此, 整个转发过程就完成了。 用户已经可以通过外网访问这个应用了。
通过浏览器:打开 mydockerapp04.myxdf.com
当然这个域名其实并不存在,是我瞎掰的,只为了方便大家理解这个过程。那么今天的分享也就结束了,下面是提问时间。
Q&A
Q1:数据库、负载均衡、Rancher 是跑在裸机还是虚拟机上?
A1:数据库,负载均衡,Rancher 都是虚机, 我们站点的入口负载均衡是物理机,大家 share。
Q1 补充:里面的问题是不是全部跑在 docker 容器里面啊?
A1 补充:全部在虚拟机上。
Q2:请问容器数据持久化使用的什么啊?
A2:本机 volume 和 Rancher nfs ,另外 glusterfs 读存储是 Rancher nfs ,写存储是 glusterfs。
Q3:除了卷挂载方式还有其他持久化方法吗?
A3:牛小南总那里做了一套 Rancher 的 ceph 你可以尝试一下。目前我也没找到更好的挂载卷方式。
Q4:咱们现在的集群规模有多少台主机?traefik 和 dns 都是自动配置的吗?服务的网络模式是 managed,有 host 模式吗?对于 cpu 型容器,内存型和网络传输型容器有分类管理吗?
A4:其实目前主机并不多,不到 20 台, 按照 Rancher 官方文档估计一个 server 应该能带动 50 个节点。 traefik 和 dns 可以自动配置,需要对应你自己的环境做一些脚本。网路是 rancher vxlan,内存型有,网络传输类的还没有,后期考虑。
Q5:proxysql 与 maxscale 哪个好,MySQL 数据卷是容器吗?
A5:mysql 是虚机跑的,proxysql 也是一个中间件,功能差不多,我们没有应用所以不好对比。
Q6:边界、数据库、LB、Rancher 总共大致用了多少台主机?
A6:这里其实是给大家做的一个 demo 边界两台,数据库三台,lb 四台, Rancher 两台。我们具体的环境就不太方便透露啦。
Q7:请问是否有将 spring boot 微服务应用到 Rancher 上?具体是如何实践的?
A7:spring boot 目前 Rancher 社区商店里还没有,我也在考虑是否做一个。如果你有了解也可以定制一个贡献给社区。
Q8:Rancher 上的应用都是无状态的么?有状态的话,存储用的什么?性能如何?
A8:rancher 适合做无状态应用。有状态的我最近在搞 es,直接用的本机硬盘。我们本机硬盘有 ssd 加速所以还好,而且 es 这类应用,本来就是分布式,一个两个节点出问题是有的补救的。 其他有状态应用就要小心了,我也一直在观察 cattle 对这些应用的调度。一般可以通过打 host label 来限定实例所在主机等方式。但是总体来说有状态应用还是要小心又小心。
Q9:请问 traefik 一个域名根据项目 path 选择转发不同的 web 应用该如何配置?
A9:在 traefik 的文档里是有的,我没有记错的话是 traefik_path。还是具体查一下文档。
Q10:请问,如何将应用发布到集群中,可以讲个大概思路么?包括灰度,红绿。
A10:灰度和蓝绿都可以借助 traefik。启动多个 stack 通过切换 label 来做。简单一些的可以考虑用 service 的升级功能,升级后替换镜像。
Q11:gkusterfs 是直接挂 Rancher client 主机上么?
A11:早期 glusterfs 有 Rancher 对应的 app 后来去掉了。现在我的做法就比较土了,就是直接映射子目录上去。我也没找到更好的办法,期待群里有大牛能分享下这部分。
Q12:我们都知道 Java 项目启动比较费时,从容器启动成功到 Java 项目启动成功还是有一定时间的,项目启动成功后有时候还需要一个预热的过程,否则请求打上来很容易超时。请问如何实现 Java 项目完全正常前不会加入到 Traefik 负载后端造成 502?
A12:这个之前在群里有类似的讨论,也可以这样:先启动应用,label 先不打,或者打到一个静态应用上显示个 sorry 页面之类的。 等应用完全 ok 了再打上去,可以配合 api 搞个自动化。
Q13:请问四层负载与七层负载有什么区别?
A13:简单的说,4 层就是常说的 tcp 层面负载均衡,比如 socket 之类的;7 层就是 http 等。我刚刚给出的参考文档里面有详细说明,先了解下。
Q14:请问有没有实现根据请求负载的压力自动扩缩容?
A14:目前正在搞,大家也知道现在 2.0 出来了,本来自动扩缩容,日志和监控都要细化的。我们项目可能 1.6 、2.0 都会用,后面再考虑吧。
Q15:用的 cattle 环境还是 k8s?考虑点是什么?
A15:cattle。cattle 很小巧,简约,学习成本低。因此全世界范围内有不少粉丝。cattle 做无状态应用做的很 ok。因此我们先搞 cattle。后面也会引入 k8s。
Q16:rancher 中使用 webhook 是否可实现自动扩容?
A16:可以的,甚至可以通过 zabbix 做的 trigger 来调用 webhook。网上这方面介绍挺多的。
Q17:你觉得 Rancher 目前哪些部分还需要完善?
A17:说说 cattle。我之前还在想,是否应该给 cattle 加入有状态支持,现在想想 cattle 本来的优势就是架构简单,所以还是继续保持吧。 就做好无状态也很好。
再说说 Rancher,我觉得 Rancher 应该在 1.6 中去掉 mesos。swarm/k8s 等七七八八的支持,以后 1.6 系列改名为 cattle 就专心搞无状态,比如之前有嘉宾分享就用 cattle 做 ipfs,或者就用 cattle 做负载均衡等等。 这样 cattle 其实有自己很好的定位。Rancher 则踏踏实实的去做 k8s 的后台支持和管理,品牌定义清晰、集中资源。
Q18 :可以通过内存或 cpu 监控来自动做容器的扩缩容吗?有没有什么组件可以实现?
A18:可以,webhook 就 ok。我之前就打算用 zabbix 的 trigger 来做,你也可以直接在你的应用里面调用 Rancher api 或者 webhook。这部分还没有继续深入研究,等有成果再和大家分享。
Q19:Rancher 在 2.0 中只支持了 k8s 吧,cattle 是不是就不支持了?
A19:我也是看群里大家讨论,cattle 在 2.0 beta 彻底去掉了。官方继续支持一年,随后我估计就是社区支持的状态了。
Q20:文中提到“每个组件都介绍一下, 负载均衡采用互联网最常用的 LVS-DR+Nginx 方案。数据库采用 Galera 集群做多主库的数据库复制,通过 Maxscale 中间件来做高可用和读写分离。”
请问为什么必须使用 lvs+nginx,我个人感觉 nginx 完全可以满足需求了啊?lvs+keepalived 或者 nginx+keepalived 就足够了,这里有什么特殊原因吗?
A20:是这样的。一开始我也是一个 nginx,后来就想得给 nginx 做高可用,就增加了 keepalived ,这个是没问题的。后来又一想以后机器多了怎么办? 来个负载均衡吧。自然就选择了最常用 lvs+nginx。 lvs-dr+nginx 你可以看一下我附上的参考文档,里面介绍的很详细。希望能对你有帮助。
Q21: haproxy 与 nginx 优劣是什么?哪个更适合生产环境?Rancher 中使用的是 haproxy 而不是 nginx,这说明 haproxy 更好吗?
A21: nginx 目前应用最为广泛,其实两者现在功能上在互相追赶,性能上也有很多对比。 这就是看你熟悉哪个了吧。 国内互联网行业大部分都是 nginx, 应用广,案例多,所以我们也是 nginx。
Rancher 里面的 haproxy 我估计是这样的,因为之前 nginx 做 4 层负载均衡差一些,因此大多数厂商都选择 haproxy,包括红帽的 openshift 里也是内嵌 haproxy。我觉得还是出于功能考虑。之前群里有大牛讨论 kong traefik 这些新性技术现在选择更多了,还是看自己的喜好吧。
Q22:以后 Rancher2.0 主用 k8s,不用 cattle 了吗?
A22:据说不支持了。
Q23:单个 Rancher Server 能带多少 Agent?
A23:官方文档说 8G jvm 的 server 一个能带 50 个 agent。具体我也没有测过,群里我看多有跑 host 很多的朋友,期待他们以后有机会分享下。
评论