AI独角兽商汤科技的内部服务容器化历程

本文由阿尔曼,商汤科技运维工程师于4月26日晚在Rancher微信群所作的技术分享整理而成。商汤科技是专一于计算机视觉领域的AI公司。本次分享结合了容器平台团队帮助公司业务/内部服务容器化历程,介绍商汤科技在容器化历程中使用的工具、拥有的最佳实践及值得分享的经验教训。java

搜索微信号RancherLabsChina,或文末扫码,添加Rancher小助手为好友,可加入官方技术交流群,实时参加下一次分享~node

内容目录

● 背景python

● 需求分析与技术选型mysql

● 容器镜像sql

● 监控报警docker

● 可靠性保障编程

● 总结json

背 景

商汤科技是一家计算机视觉领域的AI创业公司,公司内会有一些业务须要云端API支持,一些客户也会经过公网调用这些所谓SaaS服务。整体来说,云API的架构比较简单,另外因为公司成立不久,历史包袱要轻许多,不少业务在设计之初就有相似微服务的架构,比较适合经过容器化来适配其部署较繁复的问题。ubuntu

公司各个业务线相对独立,在组织上,体如今人员,绩效及汇报关系的差别;在技术上体如今编程语言,框架及技术架构的独自演进,而服务的部署上线和后续维护的工做,则划归于运维部门。这种独立性、差别性所加大的运维复杂度须要获得收敛。swift

咱们遇到的问题不是新问题,业界也是有很多应对的工具和方法论,但在早期,咱们对运维工具的复杂性增加仍是保持了必定的克制:ssh + bash script扛过了早期的一段时光,ansible也获得过数月的应用,但现实所迫,咱们最终仍是投向了Docker的怀抱。

Docker是革命性的,干净利落的UX俘获了技术人员的芳心,咱们当时所处的时期,容器编排的大战则正处于Docker Swarm mode发布的阶段,而咱们须要寻找那种工具,要既能应对日益增加的运维复杂度,也能把运维工程师从单调、重复、压力大的发布中解放出来。

Rancher是咱们在HackerNews上的评论上看到的,其简单易用性让咱们看到了生产环境部署容器化应用的曙光,可是要真正能放心地在生产环境使用容器,不“翻车”,仍是有很多工做要作。因为篇幅的缘由,事无巨细的描述是不现实的。我接下来首先介绍咱们当时的需求分析和技术选型,再谈谈几个重要的组成部分如容器镜像、监控报警和可靠性保障。

输入图片说明

需求分析与技术选型

暂时抛开容器/容器编排/微服务这些时髦的词在一边,对于咱们当时的状况,这套新的运维工具须要三个特性才能算成功:开发友好、操做可控及易运维。

开发友好

能把应用打包的工做推给开发来作,来消灭本身打包/编译如java/ruby/python代码的工做,但又要保证开发打出的包在生产环境至少要能运行,因此怎么能让开发人员方便正确地打出发布包,后者又能自动流转到生产环境是关键。长话短说,咱们采起的是Docker + Harbor的方式,由开发人员构建容器镜像,经过LDAP认证推送到公司内部基于Harbor的容器镜像站,再经过Harbor的replication机制,自动将内部镜像同步到生产环境的镜像站,具体实现可参考接下来的容器镜像一节。

操做可控

能让开发人员参与到服务发布的工做中来,因为业务线迥异的业务场景/技术栈/架构,使得只靠运维人员来解决发布时出现的代码相关问题是勉为其难的,因此须要可以让开发人员在受控的情境下,参与到服务平常的发布工做中来,而这就须要像其提供一些受限可审计且易用的接口,WebUI+Webhook就是比较灵活的方案。这方面,Rancher提供的功能符合需求。

易运维

运维复杂度实话说是咱们关注的核心,毕竟容器化是运维部门为适应复杂度与日俱增而发起的,屁股决定脑壳。考虑到自己容器的黑盒性和稳定性欠佳的问题,再加上真正把容器技术搞明白的人寥寥无几,能平稳落地的容器化运维在咱们这里体现为三个需求:多租户支持,稳定且出了事能知道,故障切换成本低。多租户是支持多个并行业务线的必要项;容器出问题的状况太多,线上环境以操做系统镜像的方式限定每台机器Docker和内核版本;因为传统监控报警工具在容器化环境捉襟见肘,须要一整套新的监控报警解决方案;没人有把握能现场调试全部容器问题(如跨主机容器网络不通/挂载点泄漏/dockerd卡死/基础组件容器起不来),须要蓝绿部署的出故障后能马上切换,维护可靠与可控感对于一个新系统相当重要。

技术架构图

总结一下,Rancher, Harbor, Prometheus/Alertmanager为主的开源系统组合能够基本知足容器管理的大部分需求,整体架构以下图

输入图片说明

容器镜像

容器镜像服务是公司级别的IT基础设施,在各个办公区互联带宽有限的物理限制下,须要给分散在多个地理位置的用户以一致、方便、快速的使用体验。咱们主要使用了Vmware开源的Harbor工具来搭建容器镜像服务,虽然Harbor解决了如认证、同步等问题,但Harbor不是这个问题的银色子弹,仍是须要作一些工做来使镜像服务有比较好的用户体验。这种体验咱们以Google Container Registry为例来展示。

做为Google的开放容器镜像服务,全球各地的用户都会以同一个域名gcr.io推拉镜像docker push gcr.io/my_repo/my_image:my_tag,但其实用户推拉镜像的请求,因为来源地理位置不一样,可能会被GeoDNS分发在不一样的Google数据中心上,这些数据中心之间有高速网络链接,各类应用包括GCR会经过网络同步数据。这样的方法既给用户一致的使用体验,即全部人都是经过gcr.io的域名推拉镜像,又由于每一个人都是同本身地理位置近的数据中心交互而不会太“卡”,而且因为Google Container Registry底层存储的跨数据中心在不断高速同步镜像(得益于Google优异的IT基础设施),异国他乡的别人也能感受很快地拉取咱们推送的镜像(镜像“推”和“拉”的异步性是前提条件)。

花篇幅介绍Google Container Registry的目的是,用户体验对用户接受度相当重要,然后者每每是一个新服务存活的关键,即在公司内部提供相似GCR通常的体验,是咱们容器镜像服务为了成功落地而想接近的产品观感。为了达到这种观感,须要介绍两个核心的功能,开发/生产镜像自动同步,镜像跨办公区同步。另外,虽然有点超出镜像服务自己,但因为特殊的国情和使用关联性,国外镜像(DockerHub, GCR, Quay)拉取慢也是影响容器镜像服务使用体验的关键一环,镜像加速服务也是须要的。

开发/生产镜像自动同步

因为开发环境(公司私网),生产环境(公网)的安全性和使用场景的差别,咱们部署了两套镜像服务,内网的为了方便开发人员使用是基于LDAP认证,而公网的则作了多种安全措施来限制访问。但这带来的问题是如何方便地向生产环境传递镜像,即开发人员在内网打出的镜像须要能自动地同步到生产环境。

咱们利用了Harbor的replication功能,只对生产环境须要的项目才手动启用了replication,经过这种方式只需初次上线时候的配置,后续开发的镜像推送就会有内网Harbor自动同步到公网的Harbor上,不须要人工操做。

镜像跨办公区同步

因为公司在多地有办公区,同一个team的成员也会有地理位置的分布。为了使他们能方便地协做开发,镜像须要跨地同步,这咱们就依靠了公司已有的swift存储,这一起没有太多可说的,带宽越大,同步的速度就越快。值得一提的是,因为Harbor的UI须要从MySQL提取数据,因此若是须要各地看到同样的界面,是须要同步Harbor MySQL数据的。

镜像加速

不少开源镜像都托管在DockerHub、Google Container Registry和Quay上,因为受制于GFW及公司网络带宽,直接pull这些镜像,速度如龟爬,极大影响工做心情和效率。

一种可行方案是将这些镜像经过代理下载下来,docker tag后上传到公司镜像站,再更改相应manifest yaml,但这种方案的用户体验就是像最终幻想里的踩雷式遇敌,普通用户不知道为何应用起不了,即便知道了是由于镜像拉取慢,镜像有时能拉有时又不能拉,他的机器能拉,个人机器不能拉,得搞明白哪里去配默认镜像地址,并且还得想办法把镜像从国外拉回来,上传到公司,整个过程繁琐耗时低智,把时间浪费在这种事情上,实在是浪费生命。

咱们采起的方案是,用mirror.example.com的域名来mirror DockerHub,同时公司nameserver劫持quay,gcr,这样用户只须要配置一次docker daemon就能够无痛拉取全部经常使用镜像,也不用担忧是否哪里须要override拉取镜像的位置,并且每一个办公区都作相似的部署,这样用户都是在办公区本地拉取镜像,速度快而且节约宝贵的办公区间带宽。

值得一提的是,因为对gcr.io等域名在办公区内网作了劫持,但咱们手里确定没有这些域名的key,因此必须用http来拉取镜像,因而须要配置docker daemon的--insecure-registry这个项

用户体验

配置docker daemon(以Ubuntu 16.04为例)

sudo -s
cat << EOF > /etc/docker/daemon.json
{
  "insecure-registries": ["quay.io", "gcr.io","k8s.gcr.io],
  "registry-mirrors": ["https://mirror.example.com"]
}
EOF
systemctl restart docker.service

测试

# 测试解析,应解析到一个内网IP地址(private IP address)
# 拉取dockerhub镜像
docker pull ubuntu:xenial
# 拉取google镜像
docker pull gcr.io/google_containers/kube-apiserver:v1.10.0
# 拉取quay镜像
docker pull quay.io/coreos/etcd:v3.2
# minikube
minikube start --insecure-registry gcr.io,quay.io,k8s.gcr.io --registry-mirror https://mirror.example.com

技术架构图

输入图片说明

监控报警

因为zabbix等传统监控报警工具容器化环境中捉襟见肘,咱们须要从新创建一套监控报警系统,幸好prometheus/alertmanager使用还算比较方便,而且已有的zabbix因为使用不善,致使已有监控系统的用户体验不好(误报/漏报/报警风暴/命名不规范/操做复杂等等),否则在有限的时间和人员条件下,只是为了kick start而什么都得另起炉灶,仍是很麻烦的。

其实分布式系统的监控报警系统,不论在是否用容器,都须要解决这些问题:能感知机器/容器(进程)/应用/三个层面的指标,分散在各个机器的日志要能尽快收集起来供查询检索及报警低信噪比、不误报不漏报、能“望文生义”等。

而这些问题就像以前提到的,prometheus/alertmanager已经解决得比较好了:经过exporter pattern,插件化的解决灵活适配不一样监控目标(node-exporter, cAdvisor, mysql-exporter, elasticsearch-exporter等等);利用prometheus和rancher dns服务配合,能够动态发现新加入的exporter/agent;alertmanager则是一款很优秀的报警工具,能实现alerts的路由/聚合/正则匹配,配合已有的邮件和咱们本身添加的微信(现已官方支持)/电话(集成阿里云语音服务),天天报警数量和频次达到了oncall人员能接受的状态。

至于日志收集,咱们仍是听从了社区的推荐,使用了Elasticsearch + fluentd + Kibana的组合,fluentd做为Rancher的Global Serivce(对应于Kubernetes的daemon set),收集每台机器的系统日志,dockerd日志,经过docker_metadata这个插件来收集容器标准输出(log_driver: json_file)的日志,rancher基础服务日志,既本地文件系统压缩存档也及时地发往相应的elasticsearch服务(并未用容器方式启动),经过Kibana可视化供产品售后使用。基于的日志报警使用的是Yelp开源的elastalert工具。

为每一个环境手动建立监控报警stack仍是蛮繁琐的,因而咱们也自定义了一个Rancher Catalog来方便部署。

监控报警系统涉及的方面太多,而至于什么是一个“好”的监控报警系统,不是我在这里能阐述的话题,Google的Site Reliability Engineering的这本书有我认为比较好的诠释,但一个抛砖引玉的观点能够分享,即把监控报警系统也当成一个严肃的产品来设计和改进,须要有一我的(最好是核心oncall人员)承担产品经理般的角色,来从人性地角度来衡量这个产品是否真的好用,是否有观感上的问题,特别是要避免破窗效应,这样对于创建oncall人员对监控报警系统的信赖和承认相当重要。

技术架构图 输入图片说明

可靠性保障

分布式系统在提高了并发性能的同时,也增大了局部故障的几率。健壮的程序设计和部署方案可以提升系统的容错性,提升系统的可用性。可靠性保障是运维部门发起的一系列目的在于保障业务稳定/可靠/鲁棒的措施和方法,具体包括:

● 生产就绪性检查

● 备份管理体系

● 故障分析与总结

● chaos monkey

主要谈谈chaos monkey,整体思路就是流水不腐,户枢不蠹。经过模拟各类可能存在的故障,发现系统存在的可用性问题,提醒开发/运维人员进行各类层面的改进。

预期

  • 大多数故障无需人马上干预

  • 业务异常(如HTTP 502/503)窗口在两分钟之内

  • 报警系统应该保证

    不漏报
    
         没有报警风暴
    
         报警分级别(邮件/微信/电话)发到该接收报警的人

测试样例

咱们须要进行测试的case有:

  • service升级

  • 业务容器随机销毁

  • 主机遣散

  • 网络抖动模拟

  • Rancher基础服务升级

  • 主机级别网络故障

  • 单主机机器宕机

  • 若干个主机机器宕机

  • 可用区宕机

部署示例(单个租户 & 单个地域)

输入图片说明

总 结

一、体量较小公司也能够搭建相对可用的容器平台。

二、公司发展早期投入一些精力在基础设施的建设上,从长远来看仍是有价值的,这种价值体如今很早就能够积累一批有能力有经验有干劲儿的团队,来不断对抗规模扩大后的复杂性猛增的问题。一个“让人直观感受”,“看起来”混乱的基础技术架构,会很大程度上影响开发人员编码效率。甚至能够根据破窗原理揣测,开发人员可能会以为将会运行在“脏”,“乱”,”差”平台的项目不必把质量看得过重。对于一个大的组织来说,秩序是一种难得的资产,是有没法估量的价值的。

三、镜像拉取慢问题也能够比较优雅地缓解。

四、国内访问国外网络资源整体来说仍是不方便的,即便没有GFW,带宽也是很大的问题。而咱们的解决方案也很朴素,就是缓存加本地访问,这样用比较优雅高效地方法解决一个“苍蝇”问题,改善了不少人的工做体验,做为工程人员,内心是很知足的。

五、容器化也能够看做是一种对传统运维体系的重构。

六、容器化本质上是当容器成为技术架构的所谓building blocks以后,对已有开发运维解决方案从新审视,设计与重构。微服务、云原生催生了容器技术产生,然后者,特别是Docker工具自己美妙的UX,极大地鼓舞了技术人员与企业奔向运维“应许之地”的热情。虽然你们都心知肚明银色子弹并不存在,但Kubernetes ecosystem愈来愈看起来前途不可限量,给人以无限但愿。而贩卖但愿自己被历史不断证实,倒真是稳赚不亏的商业模式。

致 谢

一、感谢Richard Stallman为表明的自由软件运动的参与者、贡献者们,让小人物、小公司也能有大做为。

二、感谢Google Search让搜索信息变得如此便利。

三、感谢Docker公司及Docker软件的贡献者们,催生了一个巨大的行业也改善了众多开发/运维人员的生活。

四、感谢Rancher这个优秀的开源项目,提供了如Docker般的容器运维UX。

五、感谢GitHub让软件协做和代码共享如此便利和普及。

六、感谢mermaid插件的做者们,能够方便地用markdown定义编辑好看的流程图。

相关文章
相关标签/搜索