查看原文
其他

关于GitHub迁移到K8S的最佳实践,你最看重哪方面?

2017-08-17 数人云 数人云

识别二维码报名活动


报名即将截止啦!8月19日,来自微软、数人云、京东、当当网的四位IT老兵,《一起吹响Container+集结号》,看Serverless、DevOps、微服务、CI/CD、分布式调度任务等技术,在各个场景中与Container发生的碰撞与交互。


全球最大的代码托管和编程社交网络的GitHub,近期已经在开发、SRE等团队的配合下将服务切换到Kubernetes,因为其坐拥千万用户和亿级代码仓库,这可不是一个小工程,今天小数就跟大家分享下GitHub迁移到Kubernetes的整个过程。


在过去的一年中,GitHub逐步发展了运行Ruby On Rails应用的基础设施,该应用负责github.com和api.github.com。目前所有的WEB和API请求都由运行在GitHub Metal Cloud上的Kubernetes容器集群中。


将关键应用迁移到Kubernetes是一个非常有意思的挑战,今天就给大家分享下:


为什么尝试改变——释放SRE工程师


在此之前,主要的Ruby On Rails应用(github/github)还类似于8年前:“Unicorn processes”由Ruby进程管理器调用运行在 Puppet-managed的“God”。同样的,部署ChatOps如同第一次引入时所作:Capistrano在每个前端服务器上建立SSH连接,然后更新代码,重新启动应用,当峰值请求负载超过可用的前端CPU容量时,GitHub站点的SRE会释放额外的容量,并将其添加到活动前端服务器池当中。




在近几年中,虽然基本生产方法没有太大的变化,不过GitHub本身有了很多改变如:新的功能、更大的社区、更多的员工、以及更多的需求。所以这也就产生了很多新的问题,许多团队想将其负责的功能从某个大的应用中提取出来,形成一个可以独立运行和部署的小型服务。伴随着运行服务数量的增加,SRE团队开始为数十个其他应用提供类似的配置,从而增加了在服务器维护、配置和其他工作上花费的时间,但这些工作又和改进整个GitHub的工作流程没有直接关联。


新服务因为它们的复杂性和SRE团队的时间问题,需要几天、几周或者几个月的时间来进行部署,随着时间的推移,一些问题逐渐显现:这种方法并没有为工程师提供他们需要的灵活性,以继续构建世界级的服务。


工程师们需要一个自助平台,可以在上面试验、部署和扩展新的服务,还需要同样的平台来满足Ruby On Rails应用的需求,这样工程师或机器人就能以秒、天或更长的时间来分配额外的计算机资源去响应需求的变化。


为了满足这些需求,SRE、平台和开发者体验团队开始了一个联合项目:每天数十次地将github.com和api.github.com的代码部署到Kubernetes集群。



为什么是Kubernetes?


为了评估“平台即服务”的工具,GitHub仔细研究了Kubernetes,它是Google的一个项目,用于自动化部署、扩展和管理容器化应用的开源系统,通过以下几点为Kubernetes特性做了评估:该项目获得了火热的开源社区支持,首次运行实践(允许部署小型集群和应用在最初的几个小时),大量关于设计的经验。


因此迅速地扩大了实验力度和范围:立了一个小的项目去构建Kubernetes集群和部署工具,用来支持即将到来的Hack Week从而获得一些实际场景中的经验,GitHub内部对这个项目反映非常积极。


为什么从github/github开始?


在项目最初阶段,GitHub做了一个深思熟虑的决定:关键性工作负载的:github/github迁移,许多因素促成了这一决定,比较重要的几点是:


  • 需要自助扩展工具来处理持续的增长

  • 希望确保开发习惯和模式适用于大型应用和较小的服务

  • 可以更好地将应用与开发、Staging、生产、Enterprise、和其他环境隔离

  • 迁移一个关键的、高知名度的工作负载可以激发信心,让更多的Kubernetes在GitHub上采用。


Rapid iteration and confidence building with a review lab


作为迁移的一部分,进行了一些设计以及原型,并验证了前端服务器使用Kubernetes的基础服务如:Pod、部署和服务。通过在容器中运行gitub/github现有的测试套件,可以对这种新设计进行一些验证,但仍需观察这个容器是如何成为更大的Kubernetes资源一部分的,很快就清楚地认识到,在验证阶段,对Kubernetes和打算运行的服务进行探索性测试环境是必备的。


与此同时,项目成员观察到,现有的github/github抓取请求的模式已经开始显示出增长十分困难的迹象,部署速度和工程师的数量成正比,使用几个额外的部署环境作为验证拉取请求到github/github的部分过程也是如此,在工作高峰时,功能齐全的部署环境数量往往是固定的,这就降低了部署拉取请求的过程,工程师门经常要求在“Branch Lab”中测试更多的子系统,同时允许多名工程师同时进行部署,但每个工程师只能启动一个“Unicorn Process”,所以只在测试API和UI变更时有用,因为这些需求重叠很多,所以可以将这些项目结合起来,并开始在github/github上开发一个新的基于Kubernet/github的部署环境,被称之为:Review Lab。


在构建Review Lab的过程中,还发布了几个子项目:


  • 在AWS VPC上运行的Kubernetes集群管理使用了Terraform &  Kops

  • 一组Bash集成测试使用短暂的Kubernetes集群,后来在项目开始时大量使用,增强对Kuberbetes的信心。

  • 一个github Dockerfile/github

  • 对内部CI平台的增强,用来支持构建和将容器发布到容器注册中心

  • YAML表示50+Kubernetes资源,签入github/github

  • 对内部部署应用的增强,支持将Kubernetes的资源从一个存储库部署到Kubernetes的命名空间,以及从内部存储库中创建Kubernetes

  • 该服务结合了Haproxy和Consul-Template,将Unicorn Pods路由到现有的服务,发布服务信息。

  • 一种读取Kubernetes事件的服务,并将异常事件发送给内部服务跟踪系统

  • 一种名为kube-me且与Rpc兼容的服务,通过聊天向用户公开一组有限的kubectl命令。

  • 最终的结果是一个基于聊天的界面,用于为任何拉取请求创建GitHub的独立部署,一旦请求通过了所有需要的CI任务,用户即可部署他们的请求:



如同之前的“Branch Lab”一样,实验室在最后一次部署后就被清理掉,由于每个实验室都是在其Kubernetes名称空间中创建的,清理工作就像删除名称空间一样简单,部署系统会在需要时自动执行。


Review Lab是一个成功的项目积累了许多经验和成果,在为工程师提供这种环境之前,还为Kubernetes集群设计提供了必要的验证基础和原型环境,以及Kubernetes资源的设计和配置,这些资源现在用以描述github/github的工作负载,在发布后,它帮助工程师建立了信心,GitHub非常满意这个环境赋予工程师实验和通过自助的方式去解决问题。



Metal Cloud上的Kubernetes


随着Review Lab的发布后,注意力就转移到了github.com上,为了满足关键服务的性能的可靠性需求(依赖于低延迟访问其他数据服务),需要构建Kubernetes的基础设施,去支持在物理数据中心和POP中运行的云计算,同样,有12个子项目:


  • 关于容器网络,因为一个及时且详尽的帖子,GitHub选择了Calico,其提供了需要在IPIP模式下快速发送一个集群的功能,与此同时也提供了可以在以后的网络基础设施中进行探索的灵活性。


  • 通过十几次阅读Kelesyhightower写的《Kubernetes the hard way 》,GitHub将一些手动操作的服务器组装到了一个临时的Kubernetes集群中,此集群通过了相关测试。


  • 还构建了一些小工具,为每个集群生成所需的CA和配置,格式可以由Puppet和Secret Systems 使用。


  • 对两个实例配置进行了处理:Kubernetes节点和Kubernetes Apiservers,这种方式允许用户提供已经配置的集群名称,以便在规定的时间内引入。


  • 构建了一个小型的Go服务,用于消耗容器日志,将Key/Value格式的元数据附加到每一行,并将它们发送到主机的本地Syslog端点。


  • 加强内部负载均衡服务,用来支持Kubernetes Node Port。


这些工作并没有白费,都通过了内部验收测试的集群,因此,GitHub的信心十足,同样的一组Inputs(由Review Lab使用的Kubernetes资源),相同的数据集(网络服务Review Lab连接到VPN上),同样的工具都会产生类似的结果,不到一周,虽然大部分的时间都花费在了内部通信和排序上,但对迁移产生了非常重大的影响:可以将整个工作负载从运行在AWS上的Kubernetes集群迁移到一个运行在GitHub数据中的集群。


Raising the confidence bar


Kubernetes集群在Github Metal Cloud上的成功和可复制性,所以是时候对“Unicorn”进行部署来替代当前前端服务器池了,在GitHub,工程师及其团队通过创建一个Flipper特性去验证新功能是很常见的做法,若可行即选择它,然后加强部署系统再去部署一套新的Kubernetes资源,github-produciton名称空间和现有的生产服务器,提高GLB支持员工请求路由到不同的后端:基于Flipper-infuenced的cookie,允许员工在任务控制栏的一个按钮上选择实验Kubernetes后端。



来自内部用户的负载可以帮助发现问题、修复BUG,并开始适应Kubernetes的生产,在此期间,通过模拟未来想要执行的应用、编写运行手册和执行Failure Tests来增强信心,还将少量的生产流量路由到这个集群,去确认对于负载下性能和可靠性的设定,从每秒100个请求开始,然后扩展到github.com和api.github.com请求的10%,在几个模拟试验中曾短暂地停止用来重新评估完全迁移的风险。



Cluster Groups


因为一些Failure Tests导致了意料之外的结果,特别是模拟单个Apiserver节点故障的测试破坏了集群,这种方式对运行工作负载的可用性造成了负面影响,根据调查显示,这些测试没有取得决定性的效果,但帮助识别出相关的破坏可能是一个相互作用的各种客户连接到Kubernetes Apiserver(像Calico-Agent Kubelet Kube-Proxy,Kube-Controller-Manager)和内部负载均衡器的行为在一个Apiserver节点中的失败,因为检测到Kuberntes集群降级可能会破坏服务,所以开始关注了每个站点上运行的关键应用,并自动化地将请求从一个不健康的集群迁移到其他健康的集群。


类似的工作已经放在GitHub的流程图中,支持此应用部署到多个独立运营的网站,和其他积极的方式进行取舍。最终选定的设计是:使用部署系统支持多个“分区”增强它通过一个定制的支持提供集群乏味内配置Kubernetes资源注释,放弃现有的联合解决方案,允许使用业务逻辑已经出现在GitHub的部署系统。


从10%到100%


有了集群组,GitHub逐渐将前端服务器转换为Kubernetes节点,并增加了路由到Kubernetes的流量,与其他一些工程师团队一起,在一个多月的时间内完成了前端的转换,同时,在这此期间保持了预计的性能和可接受的错误率。



在迁移过程中,遇到了一直持续至今的问题:在高负载/或高利用率的容器中,一些Kubernetes节点会出现内核错误并会重启,虽然GitHub对这种情况不是很满意,而且进行了最高优先级的排查,但还是很高兴地看到Kubernetes能够自动地绕过这些故障,并继续在错误范围内服务流量。


GitHub进行了一些Failure Tests,模拟了与echo c/proc/sysrq触发相似的内核错误,这是一个很有用的补充。


未来


本文的灵感来自于将此应用迁移到Kubernetes的经验,并且期待着更多的迁移,虽然在第一次迁 52 29541 52 15533 0 0 2700 0 0:00:10 0:00:05 0:00:05 3095的范围被有意限制在无状态的工作负载中,但对在Kubernetes上尝试运行有状态的服务模式抱有很大兴趣。


在项目的最后阶段,GitHub还发布了一个工作流,用于将新的应用和服务部署到类似的Kubernetes集群中。工程师们几个月以来已经在此集群中部署了数十个应用,每一个都需要SRE的配置管理和支持,有了自助式的应用供应工作流,SRE可以将更多的时间花在向工程团队的其他成员交付基础设施产品上去支持最佳实践,为每个人构建更快,更有弹性的GitHub体验。


推荐阅读:

聊聊调度框架,K8S、Mesos、Swarm 一个都不能少

从Google实践看SRE(8大黄金准则要注意)

如果没按这7种习惯,你可能实践的是假DevOps

关于容器监控,这3种工具你可能用得上



☟  阅读原文,报名活动

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存