数人云上海&深圳两地“容器之 Mesos/K8S/Swarm 三国演义”的嘉宾精彩实录持续更新^_^今天小数带来的是 Bilibili 运维开发工程师吴佳兴的分享。相信不少小伙伴都是 B 站的粉丝,快来看看他们在业务高峰是如何利用容器技术应对各种压力的吧。
吴佳兴, Bilibili 运维开发工程师 同时也是 Dockone.io 社区译者,在配置管理、运维自动化、 Python 开发、 CICD 及容器方面有一定经验。
今天主要讲 B 站在 Docker 的一些收获和实践经验。我叫吴佳兴,现任 Bilibili 运维开发工程师,同时也是 dockone.io 社区翻译,过去做过 Salt 配置管理、基础运维,目前工作重点是容器方面的一些建设。 Bilibili 是一家弹幕视频网站,深耕于垂直领域,流量可观,有一亿的活跃用户, 100 万的活跃 UP 主,主要做直播、游戏、视频等。
上图是本次演讲的纲要, B 站定位是一家创业型的公司,并不是为了容器化而容器化,使用容器技术是为了解决问题。 B 站在 2015 年曾做过容器的尝试,把 SLB 的节点容器化,当时用的版本是 1.9 ,去年 8 月份重点评估了能否解决线上或者测试环境遇到的问题。
主要存在如下列出的问题。首先应用部署不够标准化,有很多历史存留的问题,有些应用是 supervisord 跑起来的,有些应用没有服务脚本,而且物理机上的混布非常严重,比如直播弹幕的一些消息组件在业务高峰的时候把物理机打爆,其他的应用可能会误伤掉。 B 站也分 BU ,各个业务方有调用的关系,这个调用的关系在测试环境没有一个稳定的集成环境来做集成测试,也是需要解决的。
B 站经常遇到测试环境炸了的情况,这是运维一直比较头疼的问题,也是推动容器的一个出发点,即用故障或者是痛点来推动,这样的推动进程会更快一点,解决方案自然就是容器化。
如何产出镜像,是首先要解决的问题。有两种方案,一种是运维帮忙做好镜像,可以直接用,但是代码没有办法打包进去, B 站选择的方案是用 Jenkins 加上 Mesos 来做动态可扩缩的 CI 基础设施,实际用到的组件核心是 Mesos plugin , Jenkins-Master 可以通过 Mesos plugin 在 Mesos Master 起一个 Jenkins framework , framework 是一个调度层,可以在 Mesos Slave 上进行调度和决策,用 Mesos Plugin 组件相当于在 Slave 上动态地起 Jenkins Slave 进行构建,主要的构建就是从 Gitlab push 触发第一次构建。构建用到了 Jenkins2.0 的 Pipeline ,就是 Pipeline as Code ,所有都可以用 groovy 脚本实现。我们会为每一种语言都定制一种 Pipeline 模版。
这是实际运行情况的截图,指定 Jenkins Slave 在 Mesos 上面起起来,并且定义环境变量,一些用来做构建的变量,调用 Pipeline 实现镜像的产出,通过它可以直接构建镜像。另外, Jenkins2.0 也有非常多值得吸引人的特性,因为 Jenkins 在 1.0 的时候是主打是 CI 部分, 2.0 重点在 CD 部分有耕耘,主要是并发测试包括与 Docker 的结合。 Jenkins Pipeline 会分为几个步骤,从构建、打包、 Docker build 以及最终在 Marathon 运行起来。
B 站测试环境一直面临一个问题。举例来说,一个依赖服务有一个 V1 的稳定版本,假如这个依赖服务需要进行迭代,发布 V2 版本,但在集成环境发布 V2 版本,其他的依赖方调用可能会有问题。 B 站的做法与业界没有大差异,即做一些环境的区分。如果使用容器化基础设施,环境的区分会非常的弱化,可以简单理解为在 Slave 上有一个环境的属性, attribute 就是 Env 等于 UAT 或者 FAT 。 B 站做到了一个效果,在跑完单元测试后,根据用户的需求,去部署到 FAT 环境或者是 UAT 环境,为每一个跑起来的 API 对应地绑上一个 DNS 的域名,比如功能测试环境想访问集成环境的服务,可以通过 Add-host 的方式进行访问。此外,从集成环境到生产环境是有一个 tag image 的过程,在集成环境产出的镜像,经过测试通过的步骤,经过 retag 的方式,最后产出一个正式环境可以用的镜像。
为了支撑这套构建以及实际容器的运行,需要建设容器化的基础运行设施,在 CI 方面最终的产出物是一个镜像,如何支撑它的运行?首先是服务发现。因为 Docker 容器是飘动的,要做到在 LB 上可发现。 B 站使用的 Consul ,即 Marathon 的 app 在启动的时候会有 instance 出来,我们会监听 Marathon 的 eventbus ,并把这个事件记录到 Consul 里面,同时对应的会有一个 APP-LB ,在上面绑定一个 consul template 做动态渲染,实现服务的注册和服务发现。
容器监控,之前也有调研过 Cadvisor 、普罗米修斯之类。因为一些痛点, B 站最终选择的方案是自研,主要是收集基础层面的还有应用层面的监控数据,应用层面可以复用现有的部分,比如代码埋点或者定期采集的数据,这里提供一个自研的 monitor agent ,可以通过 Docker exec 的方式去采集容器的监控数据,然后打到 influxdb 并用 grafana 做展示。
网络也是做容器的时候一个令人苦恼的问题, B 站之前花了很多时间在网络选型方面做调研,最终选择的方案是 Macvlan 。调研过 VXLAN 、 Calico ,最终选择 Macvlan 的原因是因为 VXLAN 做过压力测试,发现私有云方面覆盖网络的损耗比较大。如果使用 Calico 的话要做一个 BGP 网络,当时网络工程师否决了这个建议,最终选择了 Macvlan 这个损耗和侵入性比较小的方式。我们自研了一个 ipam plugin ,因为 Docker12 开始就支持 network plugin ,可以通过 ipam plugin 来实现 IP 地址的管理,并且注册到 consul 。
Logging 方面比较简单。 Docker 提供 log driver ,通过 syslog 的方式打到远端。另外 APP 应用层面的一些日志,直接与原有的 VM 一样,用 UDP 或者是 TCP 打到 Flume 。
Registry 没有使用 Harbor ,目前是 LVS 后面挂了两台 Docker Registry , registry 是 V2 版本。也遇到一些痛点,比如镜像, Docker Registry V2 版本之前许诺使可以实现镜像完全删除的,但 Docker 官方也说暂时还没有实现这一点,如果要完全删除一个镜像,还需要通过 GC 的手段,目前在考虑 Habor ,因为 Harbor 可以实现很关键的一点就是镜像权限的区分。
B 站开发了一套 BiliPaaS 管理工具,做用户的入口或者是镜像发布的需求,包括镜像的管理,并开发了一个 Web Console 直接登录到容器进行操作,包括监控、告警、配置等。 Jenkins 发布出来的镜像,打到集成环境之后,通过 retag , retag 成 v5.1.3 ,在生产环境做一个灰度发布的界面。容器 Console 可以在 Web 上进行编辑。
Autoscale ,即弹性扩缩,目前决策的依据监控数据是基础的监控数据,也做过一些尝试,发现不太理想,因为 CPU 跟 memory 飙升很可能是异常情况造成的,并不是业务的上升导致的,后期会考虑加入 QPS , SLB 或者 CDN 层面的监控数据业务层面来做这个 Autoscale 决策。
在容器的基础设施建设过程中, B 站遇到了很多问题。我们使用的是 1.12 ,在 3.16 的使用过程中发现内核 CFS 支持的时候会有一个 crash 的情况,只能升到 4.4.27 ,但是 4.4.27 已经把 AUFS 默认的内置给取消掉了,于是只能被迫升到了 overlayfs2 , overlayfs2 也遇到了问题, XFS 与 overlayfs2 搭配起来后,比如镜像,会出现镜像文件的损坏,还有 Docker registry 删除的问题,以及 Docker 自身的问题、 Mesos 的问题,刚才提到的 Jenkins 拉起过程中也遇到一些坑,它会突然拉不起来了,变得不可控,因为是 Mesos Plugin 直接通过 Jenkins Framework 调用的。
B 站会通过 QPS 的业务层指标实现弹性扩缩,另外想引入 Harbor 做开发环境的即开即用,这方面开发已经提过需求,比如希望消费镜像,在开发环境做开发。 B 站目前实现的是 web 服务和无状态服务容器化,如大数据无状态服务的容器化,一些 TCP 应用包括 Cache 、 MQ 还没有实现容器化。 B 站会有短暂性的业务高峰或者是波动性的数次高峰,需要进行弹性扩缩,这方面也在调研,做混合云方面的基础建设。
分享就到这里,谢谢大家。