DockOne微信分享(二七四):Kubernetes 在快速发展的直播电商企业的落地经验
【编者的话】一个快速发展且由疫情加马达的直播电商公司,面对日益增大的单量,来不及改造的传统架构,如何快速落地 Kubernetes,以支持业务发展。本次分享将介绍杭州遥望网络科技公司如何将 KubeSphere 3.0 在生产环境进行落地,并基于 KubeSphere 打造多集群架构的电商支撑体系,使“双十一”直播活动的亿级交易核心订单系统在 KubeSphere 之上平稳运行。
公司业务
遥望网络成立于 2010 年 11 月,2018 年与上市公司星期六并购,并成为头部 MCN 机构;2019 年连续 5 个月成为快手 MCN 第一名;在多平台MCN机构排名中均名列前茅;2020 年双 11 期间,直播电商 GMV 达 13.22 亿人民币。公司技术情况
公司在 10 余年的发展中,一直是业务导向,技术拆分成小组,不同业务组管理自己的服务及服务器,公司整体缺乏 DevOps 的理念和 Cloud Native 的基因;另一方面又是疫情加速下快速发展的订单量带来的系统压力,传统的部署模式,多 Java 应用分不同端口甚至 Nginx 耦合在一台虚拟机上,这种情况下,我们基本就不考虑平滑扩展了。为了尽快利用 Kubernetes 的快速扩缩容及自愈能力应对高并发的用户流量冲击,我们考虑了以下情况。技术选型
由于我们属于互联网的直播电商业务,需要快速迭代发布以及快速回滚,并运维团队人手十分紧张,所以以下是我们 Kubernetes 开源产品选型的首要考虑因素。- 对开发测试同学友好的日志查询,支持应用快速发布回滚
- 对运维友好的权限统一管理、授权,方便维护(我们运维团队初期就 1-2 个人)
- 快速部署和上线,开箱即用
- 多 Kubernetes 集群支持(多条业务线)隔离又统一
在调研了主流的三个开源容器混合云产品后,最终我们选择了 KubeSphere 3.0 来管理我们本地数据中心+公有云的多套 Kubernetes 集群,下面是我们的集群管理页面。
下面是我们头部主播瑜大公子 11 月 5 号当天就有 3.68 亿 GMV,订单系统 Pod 一共有 20+ 个,峰值达到 45M/s,通常这个时候主播都在发福利,所以用户访问量和交易量规模上升特别快,因此,在 KubeSphere 界面看到的订单系统的 Pod 内网瞬时流量也有很明显的激增。
业务平台与架构
底层一共 5 套 Kubernetes 集群,其中一套管理集群,4 套业务集群,均基于公有云与本地数据自建,由 KubeSphere 统一纳管。业务使用 Redis、ZooKeeper、Apollo 分别作为缓存、中间件、分布式配置管理。平台之上运行分销中心、供应链管理等多个业务模块。多集群高可用部署
部署思路
这里使用 KubeSphere 开源 Kubernetes 集群安装工具 kubekey 进行部署,KubeKey 本身基于 Kubeadm,网络选择 flannel vxlan 模式,由于我们的集群分布在不通的环境上,vxlan 是最通用的方案,不用去考虑公有云各种各样的限制或者路由器支不支持等等。同时,采用了三步走的部署思路,主要是由于我们之前没有 kubesphere v2.x 版本的使用经验,上生产的时候 3.0 还未 GA,分布式部署有利于排查问题,理解原理。我们选择使用 Docker 19.03.9 和 Kubernetes 1.18.6 构建集群,具体可以参考 KubeSphere 官方文档。
多集群网络链接
KubeSphere 多集群的架构分为 Host 和 Member 集群角色,其中 Host 集群作为多集群的管理控制面,而 Member 集群被 Host 集群所纳管。因此我们将业务集群放在了 Member 集群,host 集群仅用于管理多个 Member 集群。此图来自 KubeSphere 官网
五套 Kubernetes 集群分别作为 dev(开发环境)、test(测试环境)、Pre(预发布环境)、生产环境 1 和生产环境 2 使用,不同集群之间使用 ipsec vpn 及 Tower 代理来打通集群间的网络连通,这里仅仅是管理使用,由于业务之间没有耦合关系,所以不用考虑代理及 VPN 的速度和稳定性问题;而集群节点规模根据实际业务情况定期扩缩容。
api-server高可用
由于我们公有云的 Kubernetes 集群是选择基于阿里云 ECS 进行自建集群,而由于阿里云 SLB 不支持某服务器同时作为客户端和 server 端,因此我们选择在中间加了 2 台 HAProxy 来代理 6443 端口,同时开启 check port;当然,你也可以选择用静态 Pod 维护一个 ipvs 规则,来进行代理,这个就看大家怎么选择了。多集群流水线设计
发布
CI/CD 部分我们使用了 KubeSphere 内置的基于 Jenkins 的 DevOps 系统,核心原则尽可能的使用 pipeline 跟 Shell 脚本,不用或者少用 Jenkins 插件。我们采用 env 与集群 kubeconfig 匹配的方式,不同的环境与集群发布权限一一对应,否则直接抛错,其中开发环境、测试环境可以选择开发分支发布(而 release/master 分支不允许),提测完毕合并到 release 打 tag(分常规版本与 hotfix 版本),tag 由系统名称与版本号构成,然后发布至预发布环境。
预发布环境如果验证没问题,则直接将该镜像放在生产环境进去跑,减去重复 CI 的过程。但这有一个前提条件就是你的镜像是无状态的,服务启动时去拉对应环境的 Apollo 配置由启动参数动态传入,一般是环境标签;同时将CI/CD代码放置在独立仓库,KubeSphere 上就留一个 Jenkinsfile 框架。
发布到生产之后,测试同学再进行回归,验证无误后,该 Release,tag 代码合并到 master 分支;其他的开发分支可以继续合并到 release,标记新的 tag 同步在预发布环境中验证。
镜像 ID 部分,dev/test 环境使用 “date+build number” 作为镜像的 tag,预发布和生产环境使用 git tag 作为镜像 tag。
这里只所以要选择 app_name 是因为我们后端 Web 层跟 Service 层耦合在一个 Git 工程下,甚至 Task 也在一起依赖于同一个 common,没有完成服务拆分。部分 pom 没有独立,每次需要先去跑父 pom,再去打包 Web 或 Service 或 Task。
回滚
回滚其实就很简单了,打了 git tag 的镜像会保留 5 份在 Node 节点中,如果没有,就去 Harbor 镜像仓库中拉,回滚的操作实际上就是一个滚动替换的动作,回滚界面,开发可以选择最近 5 个 tag 版本。目前看到的实际上已经是上一个版本,正在测试的版本呢,只需要选择 branch 或 tag 跟 env,以及 app_name 即可。回滚直接选择已存在的 git tag 即可,如果不存在则跑 CI 流程。
服务暴露
模式 1
以下是我们比较老的一套,通用的 jetty 基础镜像 + shell 启动脚本传入 env,app_name 的形式启动。而发布流程,则是上传更新包到 fileserver,每次发布,镜像启动之后都去 fileserver,wget,env 传入的 app_name 代码包到 webapps 下;这里每个项目都配置了大量的 env。同时,Nginx 即作为后端代理,又作为前端静态 Server 来使用,规则比较复杂;为了快速上线,我们没有对这套逻辑进行改造;可以看到,代理链路有点长,但在当前情况下,也是没办法的办法。
模式 2
这套模式就是 Kubernetes 服务对外暴露比较标准的模式了,也是我们当前采用的模式。由于 KubeSphere 官方提供的模板是按 namespace 的维度去监听 service,这样多个项目就有非常多的 ingress-nginx 实例,同时需要多个 SLB 去做代理,成本比较高,与公司实际情况不太相符,所以我们将其改成了全局监听。即在同一套 Kubernetes 集群中只有一套全局的 ingress-nginx 对外暴露服务。监控与日志收集方案
日志管理
日志部分采用的是 KubeSphere 提供的日志查询与收集套件,即默认收集 stdout 与 stderr 打印内容,同时加上 workspace,namespace,pod ID 等信息;KubeSphere 日志套件使用了 fluentd 的轻量级版本即 fluentd-bit,日志量大的同学可以考虑将日志存储到外部的 Kafka 或 Elasticsearch。我们选择把那部分老的业务日志直接落盘,没有打印,同时不去麻烦开发同学,我们将它又打印到了 stdout,stderr,再进行上面流程。
日志检索我们直接用的是 KubeSphere 官方内置的日志检索页面,足够日常开发运维使用,不用再跳到单独的 Kibana 页面去查询日志。
这里有个非常好用的特性功能,即日志检索页面点击日志条目直接跳转至该 Pod,webshell 界面,同时显示该条日志上下文;好比你在服务器上执行 tail -f xxx.log 查看日志的效果;非常方便运维人员逐级排错。
监控
监控使用 KubeSphere 内置的 Prometheus-operator 和集群监控界面,暂时没有过多精力进行深入规则配置或者绘制统一监控大盘,目前默认的监控指标基本上够用,这部分会放在下一个规划阶段进行增强。总结与展望
总结
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,进群参与,您有想听的话题或者想分享的话题都可以给我们留言。