DockOne微信分享(二七四):Kubernetes 在快速发展的直播电商企业的落地经验


【编者的话】一个快速发展且由疫情加马达的直播电商公司,面对日益增大的单量,来不及改造的传统架构,如何快速落地 Kubernetes,以支持业务发展。本次分享将介绍杭州遥望网络科技公司如何将 KubeSphere 3.0 在生产环境进行落地,并基于 KubeSphere 打造多集群架构的电商支撑体系,使“双十一”直播活动的亿级交易核心订单系统在 KubeSphere 之上平稳运行。

公司业务

遥望网络成立于 2010 年 11 月,2018 年与上市公司星期六并购,并成为头部 MCN 机构;2019 年连续 5 个月成为快手 MCN 第一名;在多平台MCN机构排名中均名列前茅;2020 年双 11 期间,直播电商 GMV 达 13.22 亿人民币。
1.png

2.png

公司技术情况

公司在 10 余年的发展中,一直是业务导向,技术拆分成小组,不同业务组管理自己的服务及服务器,公司整体缺乏 DevOps 的理念和 Cloud Native 的基因;另一方面又是疫情加速下快速发展的订单量带来的系统压力,传统的部署模式,多 Java 应用分不同端口甚至 Nginx 耦合在一台虚拟机上,这种情况下,我们基本就不考虑平滑扩展了。为了尽快利用 Kubernetes 的快速扩缩容及自愈能力应对高并发的用户流量冲击,我们考虑了以下情况。

技术选型

由于我们属于互联网的直播电商业务,需要快速迭代发布以及快速回滚,并运维团队人手十分紧张,所以以下是我们 Kubernetes 开源产品选型的首要考虑因素。
  • 对开发测试同学友好的日志查询,支持应用快速发布回滚
  • 对运维友好的权限统一管理、授权,方便维护(我们运维团队初期就 1-2 个人)
  • 快速部署和上线,开箱即用
  • 多 Kubernetes 集群支持(多条业务线)隔离又统一


在调研了主流的三个开源容器混合云产品后,最终我们选择了 KubeSphere 3.0 来管理我们本地数据中心+公有云的多套 Kubernetes 集群,下面是我们的集群管理页面。
3.png

下面是我们头部主播瑜大公子 11 月 5 号当天就有 3.68 亿 GMV,订单系统 Pod 一共有 20+ 个,峰值达到 45M/s,通常这个时候主播都在发福利,所以用户访问量和交易量规模上升特别快,因此,在 KubeSphere 界面看到的订单系统的 Pod 内网瞬时流量也有很明显的激增。
4.png

业务平台与架构

底层一共 5 套 Kubernetes 集群,其中一套管理集群,4 套业务集群,均基于公有云与本地数据自建,由 KubeSphere 统一纳管。业务使用 Redis、ZooKeeper、Apollo 分别作为缓存、中间件、分布式配置管理。平台之上运行分销中心、供应链管理等多个业务模块。
5.png

多集群高可用部署

部署思路

这里使用 KubeSphere 开源 Kubernetes 集群安装工具 kubekey 进行部署,KubeKey 本身基于 Kubeadm,网络选择 flannel vxlan 模式,由于我们的集群分布在不通的环境上,vxlan 是最通用的方案,不用去考虑公有云各种各样的限制或者路由器支不支持等等。

同时,采用了三步走的部署思路,主要是由于我们之前没有 kubesphere v2.x 版本的使用经验,上生产的时候 3.0 还未 GA,分布式部署有利于排查问题,理解原理。我们选择使用 Docker 19.03.9 和 Kubernetes 1.18.6 构建集群,具体可以参考 KubeSphere 官方文档
6.png

多集群网络链接

KubeSphere 多集群的架构分为 Host 和 Member 集群角色,其中 Host 集群作为多集群的管理控制面,而 Member 集群被 Host 集群所纳管。因此我们将业务集群放在了 Member 集群,host 集群仅用于管理多个 Member 集群。
7.png

此图来自 KubeSphere 官网

五套 Kubernetes 集群分别作为 dev(开发环境)、test(测试环境)、Pre(预发布环境)、生产环境 1 和生产环境 2 使用,不同集群之间使用 ipsec vpn 及 Tower 代理来打通集群间的网络连通,这里仅仅是管理使用,由于业务之间没有耦合关系,所以不用考虑代理及 VPN 的速度和稳定性问题;而集群节点规模根据实际业务情况定期扩缩容。
8.png

api-server高可用

由于我们公有云的 Kubernetes 集群是选择基于阿里云 ECS 进行自建集群,而由于阿里云 SLB 不支持某服务器同时作为客户端和 server 端,因此我们选择在中间加了 2 台 HAProxy 来代理 6443 端口,同时开启 check port;当然,你也可以选择用静态 Pod 维护一个 ipvs 规则,来进行代理,这个就看大家怎么选择了。
9.png

多集群流水线设计

发布

CI/CD 部分我们使用了 KubeSphere 内置的基于 Jenkins 的 DevOps 系统,核心原则尽可能的使用 pipeline 跟 Shell 脚本,不用或者少用 Jenkins 插件。
10.png

我们采用 env 与集群 kubeconfig 匹配的方式,不同的环境与集群发布权限一一对应,否则直接抛错,其中开发环境、测试环境可以选择开发分支发布(而 release/master 分支不允许),提测完毕合并到 release 打 tag(分常规版本与 hotfix 版本),tag 由系统名称与版本号构成,然后发布至预发布环境。
11.png

预发布环境如果验证没问题,则直接将该镜像放在生产环境进去跑,减去重复 CI 的过程。但这有一个前提条件就是你的镜像是无状态的,服务启动时去拉对应环境的 Apollo 配置由启动参数动态传入,一般是环境标签;同时将CI/CD代码放置在独立仓库,KubeSphere 上就留一个 Jenkinsfile 框架。
12.png

发布到生产之后,测试同学再进行回归,验证无误后,该 Release,tag 代码合并到 master 分支;其他的开发分支可以继续合并到 release,标记新的 tag 同步在预发布环境中验证。

镜像 ID 部分,dev/test 环境使用 “date+build number” 作为镜像的 tag,预发布和生产环境使用 git tag 作为镜像 tag。
13.png

这里只所以要选择 app_name 是因为我们后端 Web 层跟 Service 层耦合在一个 Git 工程下,甚至 Task 也在一起依赖于同一个 common,没有完成服务拆分。部分 pom 没有独立,每次需要先去跑父 pom,再去打包 Web 或 Service 或 Task。

回滚

回滚其实就很简单了,打了 git tag 的镜像会保留 5 份在 Node 节点中,如果没有,就去 Harbor 镜像仓库中拉,回滚的操作实际上就是一个滚动替换的动作,回滚界面,开发可以选择最近 5 个 tag 版本。
14.png

15.png

目前看到的实际上已经是上一个版本,正在测试的版本呢,只需要选择 branch 或 tag 跟 env,以及 app_name 即可。回滚直接选择已存在的 git tag 即可,如果不存在则跑 CI 流程。

服务暴露

模式 1

以下是我们比较老的一套,通用的 jetty 基础镜像 + shell 启动脚本传入 env,app_name 的形式启动。而发布流程,则是上传更新包到 fileserver,每次发布,镜像启动之后都去 fileserver,wget,env 传入的 app_name 代码包到 webapps 下;这里每个项目都配置了大量的 env。

同时,Nginx 即作为后端代理,又作为前端静态 Server 来使用,规则比较复杂;为了快速上线,我们没有对这套逻辑进行改造;可以看到,代理链路有点长,但在当前情况下,也是没办法的办法。
16.png

模式 2

这套模式就是 Kubernetes 服务对外暴露比较标准的模式了,也是我们当前采用的模式。由于 KubeSphere 官方提供的模板是按 namespace 的维度去监听 service,这样多个项目就有非常多的 ingress-nginx 实例,同时需要多个 SLB 去做代理,成本比较高,与公司实际情况不太相符,所以我们将其改成了全局监听。即在同一套 Kubernetes 集群中只有一套全局的 ingress-nginx 对外暴露服务。
17.png

监控与日志收集方案

日志管理

日志部分采用的是 KubeSphere 提供的日志查询与收集套件,即默认收集 stdout 与 stderr 打印内容,同时加上 workspace,namespace,pod ID 等信息;KubeSphere 日志套件使用了 fluentd 的轻量级版本即 fluentd-bit,日志量大的同学可以考虑将日志存储到外部的 Kafka 或 Elasticsearch。
18.png

我们选择把那部分老的业务日志直接落盘,没有打印,同时不去麻烦开发同学,我们将它又打印到了 stdout,stderr,再进行上面流程。
19.png

日志检索我们直接用的是 KubeSphere 官方内置的日志检索页面,足够日常开发运维使用,不用再跳到单独的 Kibana 页面去查询日志。
20.png

这里有个非常好用的特性功能,即日志检索页面点击日志条目直接跳转至该 Pod,webshell 界面,同时显示该条日志上下文;好比你在服务器上执行 tail -f xxx.log 查看日志的效果;非常方便运维人员逐级排错。
21.png

监控

监控使用 KubeSphere 内置的 Prometheus-operator 和集群监控界面,暂时没有过多精力进行深入规则配置或者绘制统一监控大盘,目前默认的监控指标基本上够用,这部分会放在下一个规划阶段进行增强。
22.png

总结与展望

总结

KubeSphere 3.0 基本上可以满足一套平台搞定多业务场景的需求,包含 DevOps,监控告警,事件查询,操作审计等一套完整容器 PaaS 平台所必备的功能;虽说目前还有一些小的 bug,但完全可以用技术手段去弥补或者规避,相信在下个版本会有比较好的体验。

另外对于 KubeSphere 感兴趣的同学可以看我的踩坑记录,见:https://kubesphere.com.cn/foru ... sions

后期规划

  • 阶段一,所有业务全线发布至 Kubernetes
  • 阶段二,引入 Apache SkyWalking 做链路追踪,容器 image 全线无状态化,减少 CI 次数,提升发布速度,依据官方 3.1 版本发布速度来决定要不要自行修改,并加入钉钉,短信告警
  • 阶段三,自定义监控大盘,引入 UV,PV,QPS,服务健康程度,5xx,4xx 日志统计,服务更新状态监控等细化监控指标
  • 阶段四,尝试引入 lstio,因为后端使用 Dubbo,目前的 Java 配置,不支持我们去修改 Dubbo 源代码来适配 Istio,欢迎 Java 大牛来交流 Dubbo 结合 Istio 的使用场景


Q&A

Q:灰度发布,你们 Kubernetes 怎么实现?
A:这个阶段暂时还没有做,会在下个阶段首先使用 ingress-nginx 规则实现 Web 层,后面上 Istio 实现 Web 层,Dubbo 层需要改造源代码或者更换框架,暂时还没这个打算。

Q:发布操作是开放给研发自主发布吗?
A:是的,shell 中做了判断,全部交由开发,测试自己发。

Q:请问你们的回滚中的数据库脚本怎么回滚?
A:写一个 image 判断即可,选择上一个版本的 git tag,如果该镜像已存在则直接发布。

Q:本地落盘的日志输出到 stdout stderr 是怎么实现的?
A:KubeSphere自带的工具。

Q:请问你们部署服务是将代码打包到镜像当中吗?还是服务启动是拉取最新代码?ES 的日志存储很大出现 index 错误是怎么修复的?
A:老的架构是通用镜像拉取代码包,新的是打到镜像中;ES 这个问题暂时没有碰到过。

Q:11 月 5 号当天就有 3.68 亿 GMV,订单系统 Pod 一共有 20+ 个,峰值达到 45M/s,请问 Pod 规格是多少,交易核心系统单机的 QPS 能达到多少?日常有没有对线上 Pod 进行超卖?在大流量时,超卖对 Pod 的饥饿影响,有没有相关经验分享下?
A:Pod 本身没有限制 CPU,内存;加了 JVM 启动参数,xmx 是 4G;Kubernetes Node 为 16 核 64GB。

Q:KubeSphere 内置的 Istio 支持平滑升级到最新版吗?
A:可以平滑升级,但是不能跨 Istio 大版本升级。

以上内容根据2020年11月17日晚微信群分享内容整理。 分享人薛兴林,遥望网络科技有限公司运维负责人,负责遥望网络整体运维与架构设计等工作,开源爱好者。DockOne每周都会组织定向的技术分享,欢迎感兴趣的同学加微信:liyingjiesf,进群参与,您有想听的话题或者想分享的话题都可以给我们留言。

0 个评论

要回复文章请先登录注册