Tinder是国外的一款手机交友APP,作用是基于用户的地理位置,每天“推荐”一定距离内的四个对象,根据用户在 Facebook 上面的共同好友数量、共同兴趣和关系网给出评分,得分最高的推荐对象优先展示。

为什么

大概两年前,Tinder决定转向Kubernetes。Kubernetes通过不可变部署推动Tinder Engine向容器化以及低接触式运维发展。应用程序的构建、部署以及基础架构都可以由代码定义。

我们还致力于解决扩展以及稳定性的挑战。当扩展变得至关重要时,我们通常在等待新的EC2实例上线的这几分钟里备受煎熬。容器能够在几秒中内,而不是几分钟,完成调度并且上线,这对于我们很有吸引力。

一切并不容易。2019年初的迁移里,我们的Kubernetes集群一团乱麻,并且遇到各种问题,流量,集群大小以及DNS等。我们解决了这些有意思的问题,迁移了200多个服务,并且运行了一个大规模的Kubernetes集群,一共有1000个节点,15000个Pod以及48000个运行着的容器。

怎么做的

从2018年1月份起,我们就开始实验迁移的各个阶段了。首先将所有服务容器化,并且部署到一系列Kubernetes预生产环境上。从10月份起,我们开始系统性地将所有遗留服务迁移到Kubernetes上。第二年3月份,迁移工作结束,Tinder平台全都跑在了Kubernetes上。

为Kubernetes构建image

在Kubernetes集群里运行着超过30个微服务的源码仓库。这些仓库里的代码是不同语言编写的(比如,Node.js,Java,Scala,Go),同一种语言还有多个运行时环境。

build系统设计成可以为每个微服务做完整自定义的“build上下文”,通常包括Dockerfile以及一系列shell脚本。虽然内容都是全自定义的,这些build的上下文是遵循标准化的格式编写的。这样标准化的build上下文使得单个build系统可以处理所有的微服务。

图1-1 Builder容器的标准化构建流程

为了达到运行时环境的最大一致性,我们在开发和测试阶段使用相同的构建流程。当想设计一种方案来保证跨平台的build环境的一致性时,我们遇到了独特的问题。最终,所有build流程都在一个特别的“Builder”容器内执行。

Builder容器的实现要求一系列高级Docker技术。Builder容器继承本地user ID和secret(比如:SSH key, AWS认证等),因为需要访问Tinder的私有存储库。它mount了包含源码的本地目录来存储build artifact。该方案改进了性能,因为它不需要在Builder容器和宿主机之间拷贝build出来的artifact。无需任何配置,下次就可以重用存储好的build artifact。

对于某些服务来说,我们需要在Builder内创建另一个容器来实现编译环境和运行时环境的匹配(比如,安装Node.js bcrypt库生成平台特定的二进制artifact)。不同服务的编译需求可能并不相同,最终的Dockerfile是即时组装出来的。

Kubernetes集群架构和迁移

集群大小

我们决定使用kube-aws实现Amazon EC2实例上的自动化集群预配。之前,我们在一个通用节点池里运行所有东西,很快就发现需要将工作负载放到不同大小不同类型的实例上,才能最优化地使用资源。因为同时运行一些多线程的pod,和运行大量单线程Pod相比,能够得到更平滑的性能结果。

我们最后使用:

  • m5.4xlarge用于监控(Prometheus)

  • c5.4xlarge用于Node.js工作负载(单线程工作负载)

  • c5.2xlarge用于Java和Go(多线程工作负载)

  • c5.4xlarge用于控制平面(3个节点)

迁移

从遗留基础架构迁移到Kubernetes的准备步骤之一,是将已有的服务-服务的通信改为通过全新的Elastc Load Banlancer(ELB)的通信,ELB是在特定的虚拟私有云(VPC,Virtual Private Cloud)子网内创建的。该子网和Kubernetes VPC对等。这让我们可以逐步迁移模块,而无需考虑服务依赖的特定顺序。

这些端点使用weighted DNS记录集来创建,包含指向全新Kubernetes服务ELB的CNAME,weight为0。然后我们设置记录集的Time To Live(TTL)为0。随后慢慢调整weight值直至最终新服务器weight达到100%。直到这些都完成了,就可以将TTL调整为更合适的值。

我们的Java模块需要较低的DNS TTL,但是Node应用程序不需要。一名工程师重写了连接池的部分代码,将其封装进一个管理器,会每隔60秒刷新一次连接池。这在我们的场景里工作得很好,对性能没有太大影响。

学习

网络Fabric限制

在2019年1月8号的早晨,Tinder平台发生了一次宕机事件。为了解决之前的平台延迟增长,我们扩展了集群里的Pod和节点数量。这导致所有节点上的ARP缓存耗尽。

这是和ARP缓存相关的三个Linux值:

Credit[1]

gc_thresh3是hard cap。如果看到日志里出现“neighbor table overflow”,这意味着即使在ARP缓存同步垃圾回收(GC)之后,也没有足够的空间存储neighbor entry。这时,kernel会直接彻底丢弃数据包。

我们使用Flannel作为Kubernetes的网络fabric。通过VXLAN转发数据包。VXLAN是三层网络上的二层overlay scheme。它使用MAC Address-in-User Datagram Protocol(MAC-in-UDP)封装提供扩展二层网络segment的方式。物理数据中心网络上的传输协议是IP+UDP。

图2-1 Flannel图示

图2-2 VXLAN数据包

每个Kubernetes工作节点分配自己的/24虚拟地址空间。对于每个节点来说,有1个路由表entry,1个ARP表entry(在flannel.1接口上),以及1个转发数据库(FDB)entry。这些entry在worker节点第一次启动或者第一次发现新节点时添加[2]。

另外,节点-Pod(或者Pod-Pod)通信最终经过eth0接口。对应每个相应的节点源和节点目的地,都会在ARP表里对应一条额外添加的entry。

在我们的环境里,这样的通信非常常见。对于Kubernetes服务对象,会创建一个ELB,Kubernetes将每个节点注册到ELB上。ELB不知道Pod,被选中的节点也不一定是数据包的最终目的地。这是因为当节点从ELB接收到数据包时,它会评估自己服务的iptables规则,并且随机选择另一个节点上的Pod。

宕机发生的时候,集群里有605个节点。由于上述原因,超过了默认的 gc_thresh3值。一旦这种情况发生,不仅数据包会被丢弃,而且整个Flannel /24的虚拟地址空间都会从ARP表里丢失。节点-pod通信和DNS查询都会失败。(DNS在集群内部,本文后面会更为详细地解释这里的细节。)

要解决问题,需要提高gc_thresh1, gc_thresh2和gc_thresh3的值,并且重启Flannel重新注册丢失的网络。

大规模集群里运行DNS

为了实现迁移,我们重度依赖于DNS来辅助流量整型,并且渐进地将服务从遗留系统引流到Kubernetes上。我们在相关的Route53 RecordSet上设置相对较低的TTL值。当在EC2实例上运行遗留基础架构时,解析器配置指向Amazon的DNS。这是个自然的选择,没有关注我们和亚马逊服务TTL设置相对较低时的成本。

随着越来越多的服务进入Kubernetes,我们发现自己运行的DNS服务每秒需要响应250,000次请求。在应用程序里,开始遇到时不时发生但影响挺大的DNS查询超时问题。即使尝试了很多调优的方法,并且将DNS供应商切换到CoreDNS部署上,它在峰值时会消耗120个核1000个pod,但是这个问题仍然会发生。

在研究其他可能的原因和解决方案时,我们发现了一篇文章,介绍了一种竞争条件,会影响Linux数据包过滤框架netfilter。我们遇到的DNS超时问题,伴随着Flannel接口上insert_failed次数的增加,和这篇文章的发现很一致。

这个问题发生在源和目标网络地址翻译(SNAT和DNAT)以及后续contrack表插入的过程中。一个内部讨论并且被社区推荐的workaround是将DNS移到worker节点本身上。这时:

  • SNAT不需要了,因为流量还在节点本地。不需要通过eth0接口传输。

  • DNAT不需要了,因为目标IP对于节点来说就是本地,并不需要通过iptables规则去随机选择。

我们决定按照这种方案执行。CoreDNS作为DaemonSet部署到Kubernetes上,并且通过配置kubelet-cluster-dns命令的参数,将节点本地DNS注入到每个节点的resolv.conf文件里。这个workaround对DNS超时问题非常有效。

但是,我们仍然观察到被丢弃的数据包,并且Flannel接口的insert_failed数还在增加。这在使用了上述workaround后仍然发生,因为这个workaround仅仅避免了DNS流量的SNAT和/或DNAT。对于其他类型的流量,竞争条件仍然存在。幸运的是,我们的数据包绝大部分是TCP,当竞争发生后,数据包可以被成功地重新传输。能够解决所有类型流量的长期解决方案仍在讨论之中。

使用Envoy实现更好的负载均衡

随着后台服务向Kubernetes的迁移,我们开始遇到Pod间负载不均衡的问题。我们发现因为Http的Keepalive,每次滚动部署时,ELB连接会卡在第一个ready的Pod上,因此绝大部分流量会流过一小部分可用的Pod。我们第一次迁移尝试在新部署里设置最差情况下使用100%MaxSurge。这非常高效,但是对于一些大型部署并不可持续。

我们使用的另一个缓解措施是人为地夸大关键服务的资源请求,以便其中的Pod与其他高负载Pod一起拥有更多的空间。这也不是很好,因为会浪费资源,我们的Node应用程序是单线程的,它在1个核的时候更高效。唯一有效的方案是使用更好的负载均衡技术。

我们调研了Envoy。我们在非常有限的范围内部署了Envoy并且得到了很好的效果。Envoy是开源的,高性能的7层代理,非常适合大型的面向服务的架构。它能够实现高级负载均衡技术,包括自动重试,断流以及全局限速。

最后我们在每个Pod里以sidecar模式部署Envoy,然后连接到本地容器端口。为了最大限度地减少潜在的级联并保持较小的爆破半径,我们使用了front-proxy Envoy Pod,每个服务每个可用Zone里部署一个。这就是一个小型的服务发现机制,对于给定服务返回每个AZ的Pod列表。

然后front-Envoys服务将这个服务发现机制和上游的集群和路由连接起来。我们配置了合理的timeout时间,增加了所有断流设置,然后加入了最小的重试设置来解决偶发的故障,让部署更为流畅。在这些front Envoy服务之前放置了TCP ELB。即使主要的front proxy层需要pin Envoy pod保持keepalive,它们仍然能够更好地处理负载,通过least_request配置后台的负载。

对于部署,我们在应用程序和sidecar pod上都使用了preStop hook。这个hook调用sidecar健康检查失败的admin端点,sleep一小段之后,给些时间让正在进行的连接结束并耗尽。

能够进展如此迅速的一个原因是能够轻松地将丰富的metric和我们常规的Prometheus系统集成起来。这让我们在迭代配置中能够观测到到底发生了什么,并且截断流量。

结果很明显。一开始服务非常不均衡,现在集群里最重要的12个服务之前运行了这一系统。今年我们计划改进程全服务网格,提供更先进的服务发现,断流,异常值检测,限流和跟踪日志。

图 3-1 切换到Envoy时某服务的CPU收敛过程

使用envoy前的调用链

Envoy服务调用链

结论

通过这些学习和研究,我们成长为一个强大的自研基础架构团队,非常熟悉如何设计,部署以及运维大型Kubernetes集群。Tinder的整个工程师团队现在都拥有了如何在Kubernetes上做容器化以及部署应用程序的知识和经验。

在我们的遗留基础架构上,当需要额外扩容时,通常需要等待几分钟新的EC2实例才能启动上线。现在容器调度并能承载流量只需要几秒钟。在单个EC2实例上调度多个容器还提供了更好的水平密度。最终,2019年里,我们比上一年节省了EC2上的花费。

整个过程花了大概2年,最终2019年3月份我们完成了迁移。Tinder Platform完全运行在Kubernetes集群里,这个集群包含200个服务,1,000个节点,15,000个Pod以及48,000个运行着的容器。

基础架构不再是运维团队的保留任务。相反,整个公司的工程师都在承担这个职责,并且任何事情都是代码,工程师们控制自己的应用程序如何构建及部署。

相关链接:

  1. https://linux.die.net/man/7/arp

  2. https://github.com/coreos/flannel/blob/master/backend/vxlan/vxlan.go#L45-L48

原文链接:https://medium.com/@tinder.engineering/tinders-move-to-kubernetes-cda2a6372f44

基于Kubernetes的DevOps实战培训

基于Kubernetes的DevOps战培训将于2019年9月27日在上海开课,3天时间带你系统掌握Kubernetes,学习效果不好可以继续学习。本次培训包括:容器特性、镜像、网络;Kubernetes架构、核心组件、基本功能;Kubernetes设计理念、架构设计、基本功能、常用对象、设计原则;Kubernetes的数据库、运行时、网络、插件已经落地经验;微服务架构、组件、监控方案等,点击下方图片或者阅读原文链接查看详情。

国外手机交友APP Tinder向Kubernetes迁移的过程相关推荐

  1. VPGAME 的 Kubernetes 迁移实践

    作者 | 伍冲斌 VPGAME 运维开发工程师 导读:VPGAME 是集赛事运营.媒体资讯.大数据分析.玩家社群.游戏周边等为一体的综合电竞服务平台.总部位于中国杭州,在上海和美国西雅图分别设立了电竞 ...

  2. 如何开发一款用户体验优秀的语音交友app?

    在数字时代,人们越来越依赖智能手机上的应用程序来与他人进行交流.其中,语音交友app成为了最受欢迎的应用之一.然而,开发一款成功的语音交友app需要深入了解用户需求与体验.本文将探讨如何开发一款用户体 ...

  3. 相亲交友app开发的系统功能

    相亲交友app开发的系统功能 1.用户认证: 相亲交友app开发实名认证功能,提高用户信息真实性 2.资料管理: 婚恋app源码的资料管理功能,方便用户填写和修改基本资料. 3.通话设置: 相亲app ...

  4. 想开发一套多人交友app必须知道的

    近年来,视频交友app迅速崛起,对比于传统的一对多直播来说,社交app在设计上互动性更强. 一般一套交友app开发涉及以下核心功能点: 1. 直播功能:这个和传统直播功能一样,能支持直播RTMP推流, ...

  5. uni-app实战之社区交友APP(5)搜索和发布页开发

    文章目录 前言 一.搜索页开发 1.搜索页面搭建 2.搜索结果显示和优化 二.发布页开发 1.自定义导航栏开发 2.文本域组件使用 3.底部操作条组件开发 4.多图上传功能开发 5.删除选中图片功能实 ...

  6. uni-app实战之社区交友APP(20)兼容处理和打包上线

    文章目录 前言 一.APP完善 1.隐藏滚动条 2.APP更新操作 3.APP打包上线 二.小程序完善 1.小程序自定义导航栏 2.小程序分享功能实现 3.小程序隐藏版本更新检测 三.微信和支付宝小程 ...

  7. 语音交友app开发中的用户积分系统

    引言 在当今数字时代,语音交友app已成为一种流行的社交工具.它们给用户提供了一个平台,在这里他们可以结交新朋友,分享他们的生活和信仰,并建立深厚的人际关系.然而,市场上存在大量的语音交友app,这使 ...

  8. 婚恋交友APP投快手信息流广告怎么收费的,婚恋交友APP快手短视频推广怎么做的,快手开户代运营返点多少

    婚恋交友APP投快手短视频推广效果怎么样? 1.能够获得最大的人流量曝光 有人流量的地方才可以实现产品的转化,人是产品最终的消费者.而快手平台上拥有超过7亿的注册用户,用快手短视频做广告可以实现巨大的 ...

  9. 七夕总结:2018新型婚恋交友 App 激增!18禁,年轻人有点敢玩

    作者|元小发 本文经授权转载自七麦研究院(ID:Qimaiyanjiuyuan) 2017 年,有人做过一份单身狗的专题报告,报告显示,中国目前的单身人口已高达 2 亿,正面临第四次单身潮. 近日,珍 ...

最新文章

  1. 第四层到第七层的高层交换技术及其应用
  2. [SOJ] 简单哈希
  3. Springboot 整合微信小程序实现登录与增删改查
  4. Spring源码导入IDEA
  5. P4707-重返现世【dp,数学期望,扩展min-max容斥】
  6. linux 更改父进程名称,[Linux进程]在父进程和子进程中分别修改变量
  7. 在python中使用什么工具管理模块_怎么使用Python pip(管理模块工具)
  8. java jar killed_我的Java应用程序被OOMKilled了,原因竟是这样?
  9. Atitit prj tek dfkt 项目常见技术难点目录第一章 开发效率 2第一节 更加简单的语言 2第二节 简单
  10. Entering emergency mode . Exit the shell to continue . Type journa lctl to view system logs .
  11. c语言printf输出格式
  12. 星空下的新赛点,民营航空迎来新机会
  13. 微信公众号授权登陆流程
  14. pc端MNIST数据集pytorch模型CNN网络转换为onnx部署树莓派4B和神经棒NCS2(使用openvino2021框架)
  15. Cheat Engine(CE)-----下载安装及入门
  16. Shiro自定义Ream
  17. 头条抖音后端技术3面,2021Java通用流行框架大全,含面试题+答案
  18. Java实现家庭收支记账软件
  19. 欧文分校计算机科学硕士项目,申请2019加州大学欧文分校计算机科学硕士要求都有哪些?...
  20. Mysql基础知识01

热门文章

  1. pDC-SetPixel() 含义
  2. gitlab安装及其汉化版
  3. RabbitMQ中文教程
  4. IDEA 没有 .iml 文件
  5. ExpandableListView,默认箭头放到右侧
  6. 【独立版】智慧城市同城V4_2.1.4全开源全插件VUE版,修复房产信息组件后台资料编辑中会显示其他平台小区的问题
  7. 获取Android MD5签名
  8. 关于阿里云已添加域名解析记录,证书申请显示未检测到DNS配置记录,请修改后重新发起审核的原因。
  9. 搞不懂多维分析!如何制作多角度、灵活动态的多维分析报表?
  10. 2018年初寒假网易有道前端实习面试经历