当前位置:首页 > 旅游指南

hulk 美团容器平台架构及容器技术实践

美团的集装箱集群管理平台叫HULK。漫威动画中的Hulk生气的时候会变成“HULK”,类似于容器的“弹性膨胀”,所以我们把这个平台命名为HULK。好像有些公司的集装箱平台也有这个名字,纯属巧合。

2016年,美团开始使用容器。当时,美团已经有了一定的规模,在使用集装箱之前已经存在各种系统,包括CMDB、服务治理、监控报警、发布平台等等。当我们探索集装箱技术时,很难放弃原有的资产。因此,集装箱化的第一步是打开集装箱的生命周期和这些平台之间的交互,比如集装箱的应用/创建、删除/发布、释放和迁移。然后我们验证了容器的可行性,证明了容器可以作为在线核心业务的运行环境。

2018年,经过两年的运营和实践探索,我们对集装箱平台进行了一次升级,就是集装箱集群管理平台HULK 2.0。

把基于OpenStack的调度系统升级成容器编排领域的事实标准Kubernetes。提供了更丰富可靠的容器弹性策略。针对之前在基础系统上碰到的一些问题,进行了优化和打磨。

美团的容器使用现状是:目前有3000多个在线服务和3万多个容器实例,很多大并发、低延迟要求的核心链接服务已经在HULK上稳定运行。本文主要介绍了我们在集装箱技术方面的一些实践,属于基础系统的优化和完善。

美团集装箱平台基本架构

首先,介绍美团集装箱平台的基础设施。我相信每个集装箱平台的架构都差不多。

首先,集装箱平台连接服务管理、发布平台、CMDB、监控报警等系统。通过与这些系统连接,容器基本上具有与虚拟机相同的体验。R&D员工可以像虚拟机一样使用容器,而不会改变原有的使用习惯。

此外,容器提供了灵活的容量扩展,可以根据一定的灵活策略动态增加和减少服务的容器节点数量,从而动态调整服务处理能力。还有一个专门的模块——“服务画像”,主要功能是通过收集统计服务容器实例运行指标,更好的调度容器,优化资源分配。比如根据一个服务的容器实例的CPU、内存、IO等使用情况,可以区分该服务是计算密集型还是IO密集型,调度时要尽可能把互补的容器放在一起。再举一个例子,我们可以知道一个服务的每个容器实例在运行的时候会有500个左右的进程,所以我们会在创建容器的时候给容器增加一个合理的进程数限制(比如最多1000个进程),以避免容器出现问题的时候系统资源过多。如果这个服务的容器在运行的时候突然申请创建20,000个流程,我们有理由相信业务容器遇到了Bug,并且容器受到了之前的资源约束的限制,发出警报通知业务及时处理。

下一层是“容器编排”和“图像管理”。容器编排解决了容器动态实例的问题,包括创建容器的时间、创建位置、删除时间等等。映像管理解决了容器静态实例的问题,包括如何构建容器映像,如何分发,分发到哪里等等。

最底层是我们的容器运行时,美团使用主流的Linux+Docker容器方案,HULK Agent是我们在服务器上的管理代理。

展开前面的“容器运行时”,可以看到这个架构图,从下往上介绍:

最下层是CPU、内存、磁盘、网络这些基础物理资源。往上一层,我们使用的是CentOS7作为宿主机操作系统,Linux内核的版本是3.10。我们在CentOS发行版默认内核的基础上,加入一些美团为容器场景研发的新特性,同时为高并发、低延时的服务型业务做了一些内核参数的优化。再往上一层,我们使用的是CentOS发行版里自带的Docker,当前的版本是1.13,同样,加入了一些我们自己的特性和增强。HULK Agent是我们自己开发的主机管理Agent,在宿主机上管理Agent。Falcon Agent同时存在于宿主机和容器内部,它的作用是收集宿主机和容器的各种基础监控指标,上报给后台和监控平台。最上一层是容器本身。我们现在主要支持CentOS 6和CentOS 7两种容器。在CentOS 6中有一个container init进程,它是我们开发容器内部的1号进程,作用是初始化容器和拉起业务进程。在CentOS 7中,我们使用了系统自带的systemd作为容器中的1号进程。我们的容器支持各种主流编程语言,包括Java、Python、Node.js、C/C++等等。在语言层之上是各种代理服务,包括服务治理的Agent、日志Agent、加密Agent等等。同时,我们的容器也支持美团内部的一些业务环境,例如set信息、泳道信息等,配合服务治理体系,可以实现服务调用的智能路由。

美团主要使用CentOS系列的开源组件,因为我们认为红帽有很强的开源技术实力。与直接使用开源社区的版本相比,我们希望红帽的开源版本能够帮助解决大多数系统问题。我们还发现,即使部署了CentOS的开源组件,也可能还有社区和红帽没有解决的问题。某种程度上也说明国内大型互联公司在技术应用场景、规模、复杂程度等方面已经达到了世界领先水平,所以会在社区之前,在红帽客户之前遇到这些问题。

集装箱遇到的一些问题

在容器技术本身,我们主要遇到四个问题:隔离性、稳定性、性能和普及性。

隔离包含两个层面:第一个问题是,容器能不能正确认识自身资源配置;第二个问题是,运行在同一台服务器上的容器会不会互相影响。比如某一台容器的IO很高,就会导致同主机上的其他容器服务延时增加。稳定性:这是指在高压力、大规模、长时间运行以后,系统功能可能会出现不稳定的问题,比如容器无法创建、删除,因为软件问题发生卡死、宕机等问题。性能:在虚拟化技术和容器技术比较时,大家普遍都认为容器的执行效率会更高,但是在实践中,我们遇到了一些特例:同样的代码在同样配置的容器上,服务的吞吐量、响应时延反而不如虚拟机。推广:当我们把前面几个问题基本上都解决以后,仍然可能会碰到业务不愿意使用容器的情况,其中原因一部分是技术因素,例如容器接入难易程度、周边工具、生态等都会影响使用容器的成本。推广也不是一个纯技术问题,跟公司内部的业务发展阶段、技术文化、组织设置和KPI等因素都密切相关。

容器的实现

本质上,容器将服务于系统中相同业务目标的相关流程组合成一个组,并将它们放在一个名为namespace的空房间中。同一个命名空间中的进程可以相互通信,但是看不到其他命名空间中的进程。每个命名空间都可以有自己独立的主机名、进程ID、系统、IPC、网络、文件系统、用户等资源。在某种程度上,实现了一个简单的虚拟化:多个彼此不知道的系统可以同时在一台主机上运行。

另外,为了按命名空间限制物理资源的使用,需要限制进程可以使用的CPU、内存等资源。这是组技术,意思是控制组。比如我们常说的4c4g容器实际上限制了这个容器命名空间中使用的进程,最多可以使用4个内核的计算资源和4GB的内存。

简而言之,Linux内核提供了用于隔离的命名空间和用于资源限制的Cgroup。Namespace+Cgroup构成了容器的底层技术(rootfs是容器的文件系统层技术)。

美团的解决、改进和优化

隔离;检疫

之前一直在处理虚拟机,但是直到使用了容器之后,才发现容器中的CPU和内存的信息是服务器主机的信息,而不是容器本身的配置信息。直到现在,容器的社区版还是这样。比如一个4c4g的容器,可以看到容器内部有40个CPU和196GB的内存资源,这其实是容器所在主机的信息。这给人的感觉就是“自我膨胀”,觉得自己很有能力,其实不然,会带来很多问题。

上图是内存信息隔离的例子。社区Linux的内核在获取系统内存信息时,统一返回主机的内存信息,无论是在主机上还是在容器中。如果容器中的应用程序是根据它找到的主机内存配置的,那么实际的资源是远远不够的,很快就会造成系统中的OOM异常。

我们做的隔离工作是,当我们获取容器中的内存信息时,内核根据容器的Cgroup信息返回容器的内存信息(类似LXCFS的工作)。

CPU信息隔离的实现和内存类似,我就不赘述了。这里有一个CPU数量如何影响应用程序性能的例子。

众所周知,JVM GC(垃圾对象回收)对Java程序执行的性能有一定的影响。默认的JVM使用公式“parallelgcthreads = (ncpus

显式的传递JVM启动参数“-XX:ParallelGCThreads”告诉JVM应该启动几个并行GC线程。它的缺点是需要业务感知,为不同配置的容器传不同的JVM参数。在容器内使用Hack过的glibc,使JVM(通过sysconf系统调用)能正确获取容器的CPU资源数。我们在一段时间内使用的就是这种方法。其优点是业务不需要感知,并且能自动适配不同配置的容器。缺点是必须使用改过的glibc,有一定的升级维护成本,如果使用的镜像是原生的glibc,问题也仍然存在。我们在新平台上通过对内核的改进,实现了容器中能获取正确CPU资源数,做到了对业务、镜像和编程语言都透明(类似问题也可能影响OpenMP、Node.js等应用的性能)。

有一段时间,我们的容器以root权限运行,实现方法是在docker运行时添加' privileged = true '参数。这种广泛的使用使容器能够看到服务器上所有容器的磁盘,这导致了安全问题和性能问题。安全问题很容易理解。为什么会导致性能问题?想象一个场景,其中每个容器进行一次磁盘状态扫描。当然权限过大的问题是可以随意挂载,随意修改NTP时间等等。

在新版本中,我们移除了容器的根权限,并发现了一些副作用,例如导致一些系统调用失败。默认情况下,我们向容器添加两个附加权限,sys_ptrace和sys_admin,这样容器就可以运行GDB并更改主机名。如果有需要更多权限的特殊容器,可以在我们的平台上按照服务粒度进行配置。

Linux中有两种io:directio和缓冲IO。直接IO直接写入磁盘,缓冲IO先写入缓存,再写入磁盘,大多数情况下都是缓冲IO。

Linux内核3。x我们使用的,在社区版中,所有的容器Buffer IO共享一个内核缓存,缓存没有隔离,没有速率限制,这使得高IO容器很容易影响到同一主机上的其他容器。缓冲IO Cache隔离和限速在Linux 4中实现。x通过Cgroup V2,这是明显改善。我们还借鉴了CGroup V2,在我们的Linux 3.10内核中实现了同样的功能:每个容器根据自己的内存配置有相应比例的IO Cache,Cache数据写入磁盘的速率受Cgroup V2的配置限制。

Docker本身支持容器上更多的Cgroup资源限制,但是Kubernetes在调用Docker时可以传递更少的参数。为了减少容器之间的相互影响,我们根据服务映像的资源分配,对不同服务的容器设置不同的资源限制,除了常见的CPU和内存,还有IO限制、ulimit限制、PID限制等。所以我们扩展了Kubernetes来完成这些任务。

企业在使用容器的过程中生成核心转储文件是很常见的。比如C/C++程序的内存访问越界时,或者系统OOM时,系统选择一个占用内存较多的进程进行kill,默认会生成一个核心转储文件。

社区容器系统的默认核心转储文件将在主机上生成。因为有些核心转储文件比较大,比如JVM的核心转储通常是几GB,或者是一些有bug的程序,它频繁的核心转储很容易快速填满主机的存储空间,会导致磁盘IO高,也会影响其他容器。另一个问题是,业务容器的用户没有访问主机的权限,所以他无法获取转储文件进行下一步分析。

所以我们修改了核心转储的流程,让转储文件写入容器自己的文件系统,使用容器自己的Cgroup IO吞吐量限制。

稳定

在实践中,我们发现Linux内核和Docker是影响系统稳定性的主要因素。虽然是非常可靠的系统软件,但是在大规模、高强度的场景中还是存在一些bug。这也从侧面说明,我们国内的互联网公司在应用规模和应用复杂程度上也是世界领先的。

在内核端,美团发现了Kernel 4.x Buffer IO限制的实现问题,得到了社区的确认和修复。我们还跟进了CentOS的一系列Ext4补丁,解决了一段时间内频繁进程阻塞的问题。

我们遇到了《红帽》中Docker的两个关键稳定性问题:

在Docker服务重启以后,Docker exec无法进入容器,这个问题比较复杂。在解决之前我们用nsenter来代替Docker exec并积极反馈给RedHat。后来Red Hat在今年初的一个更新解决了这个问题。https://access.redhat.com/errata/RHBA-2017:1620是在特定条件下Docker Daemon会Panic,导致容器无法删除。经过我们自己Debug,并对比最新的代码,发现问题已经在Docker upstream中得到解决,反馈给Red Hat也很快得到了解决。https://github.com/projectatomic/containerd/issues/2

面对开源社区的系统软件,比如系统内核、Docker、Kubernetes,有一种观点认为不需要自己分析问题,只需要从社区获取最新的更新即可。然而,我们不同意。我们认为技术团队自身的能力很重要,主要原因如下:

美团的应用规模大、场景复杂,很多问题也许很多企业都没有遇到过,不能被动的等别人来解答。对于一些实际的业务问题或者需求(例如容器内正确返回CPU数目),社区也许觉得不重要,或者不是正确的理念,可能就不会解决。社区很多时候只在Upstream解决问题,而Upstream通常不稳定,即使有Backport到我们正在使用的版本,排期也很难进行保障。社区会发布很多补丁,通常描述都比较晦涩难懂。如果没有对问题的深刻理解,很难把遇到的实际问题和一系列补丁联系起来。对于一些复杂问题,社区的解决方案不一定适用于我们自身的实际场景,我们需要自身有能力进行判断和取舍。

美团在解决开源系统的问题时,一般会经历五个阶段:深入挖掘、研究解决、关注社区、与社区互动、最终为社区做贡献。

演出

集装箱平台性能主要包括两个方面:

业务服务运行在容器上的性能。容器操作(创建、删除等等)的性能。

上图是CPU分配的例子。我们使用的主流服务器是一个双向24核服务器,它包含两个节点,每个节点有12个内核,总共有48个逻辑处理器,包括超线程。它属于典型的NUMA(非均匀内存访问)体系结构:系统中的每个节点都有自己的内存,节点中的中央处理器访问自己的内存的速度比另一个节点快得多(差别大约是一倍)。

过去我们遇到过网络中断集中在CPU0上的问题,在大流量下可能导致网络延时增加甚至丢包。为了保证网络处理能力,我们从Node0预留了8个逻辑CPU来处理网络中断和主机系统任务,比如图像解压缩等高CPU工作。这八个逻辑处理器不运行任何容器工作负载。

在容器调度方面,我们的容器CPU分配应该尽量不跨节点。实践证明,跨节点访问内存对应用性能有很大影响。在一些计算密集型场景中,容器分配将使节点内的吞吐量增加30%以上。按Node分配的方案也有一些缺点:会导致CPU碎片的增加,为了更高效的使用CPU资源。在实际系统中,我们会根据服务映像的信息,跨节点分配一些对CPU不敏感的服务容器来使用CPU资源。

上图是一个实际服务的响应延迟的TP指标线在CPU分配优化前后的对比。可以看出,TP999线已经下降了一个数量级,各项指标更加稳定。

性能优化:文件系统

第一步是选择文件系统进行性能优化。根据应用读写的统计特点,我们选择了Ext4文件系统(85%以上的文件读写是针对1M以内的文件)。

Ext4文件系统有三种日志模式:

Journal:写数据前等待Metadata和数据的日志落盘。Ordered:只记录Metadata的日志,写Metadata日志前确保数据已经落盘。Writeback:仅记录Metadata日志,不保证数据比Metadata先落盘。

我们选择了写回模式(默认排序),这是几种挂载模式中速度最快的,但它的缺点是出现故障时数据不容易恢复。我们的大多数容器都是无状态的,所以当它们失败时,只需在另一台机器上调用另一个容器。所以在性能和稳定性方面,我们选择了性能。容器为应用程序提供了可选的基于内存的文件系统tmpfs,可以提高读写大量临时文件的服务性能。

如上图所示,在美团创建虚拟机至少需要三个步骤,平均时间超过300秒。使用镜像创建容器的平均时间为23秒。集装箱的灵活性和快速性得到了明显的体现。

23秒的集装箱扩展平均时间包括各部分的优化,如扩展链路优化、图像分布优化、初始化和服务上拉优化等。接下来,本文主要介绍了图像分发和解压缩的优化。

上图是美团集装箱形象管理的总体框架,其特点如下:

存在多个Site。支持跨Site的镜像同步,根据镜像的标签确定是否需要跨Site同步。每个Site有镜像备份。每个Site内部有实现镜像分发的P2P网络。

图像分布是影响容器扩展时间的重要环节。

跨Site同步:保证服务器总能从就近的镜像仓库拉取到扩容用的镜像,减少拉取时间,降低跨Site带宽消耗。基础镜像预分发:美团的基础镜像是构建业务镜像的公共镜像,通常有几百兆的大小。业务镜像层是业务的应用代码,通常比基础镜像小很多。在容器扩容的时候如果基础镜像已经在本地,就只需要拉取业务镜像的部分,可以明显的加快扩容速度。为达到这样的效果,我们会把基础镜像事先分发到所有的服务器上。P2P镜像分发:基础镜像预分发在有些场景会导致上千个服务器同时从镜像仓库拉取镜像,对镜像仓库服务和带宽带来很大的压力。因此我们开发了镜像P2P分发的功能,服务器不仅能从镜像仓库中拉取镜像,还能从其他服务器上获取镜像的分片。

从上图可以看出,随着分发服务器数量的增加,原始分发时间也迅速增加,而P2P图像分发时间基本保持稳定。

Docker的拉图是一个并行下载,串行解压的过程。为了提高解压速度,我们组也做了一些优化工作。

对于单层解压,我们用并行解压算法代替Docker默认的串行解压算法,用pg代替g。

Docker的图像具有层次结构,图像层的合并是“解压一层合并一层,解压一层合并一层”的串行操作。其实只有合并需要串行,解压缩可以并行。我们将多层解压缩改为并行,解压缩后的数据首先放入临时存储空,最后根据层间依赖关系串行合并。之前的改变(将所有层并行解压到临时空)导致磁盘IO数量几乎翻倍,也导致解压过程不够快。所以我们使用基于内存的Ramdisk来存储提取的临时文件,减少了额外写文件带来的开销。做了以上工作后,我们发现容器的分层也会影响下载和解压的时间。上图是我们简单测试的结果:无论分层图像如何并行解压缩,解压缩时间都可以大大增加,尤其是对于层数较多的图像。

传播

推广容器的第一步是讲容器的优点。我们认为容器具有以下优点:

轻量级:容器小、快,能够实现秒级启动。应用分发:容器使用镜像分发,开发测试容器和部署容器配置完全一致。弹性:可以根据CPU、内存等资源使用或者QPS、延时等业务指标快速扩容容器,提升服务能力。

这三个功能的结合可以为企业带来更大的灵活性和更低的计算成本。

因为集装箱平台本身是技术产品,客户是各种业务的研发团队,所以需要考虑以下因素:

产品优势:推广容器平台从某种程度上讲,自身是一个ToB的业务,首先要有好的产品,它相对于以前的解决方案(虚拟机)存在很多优势。和已有系统打通:这个产品要能和客户现有的系统很好的进行集成,而不是让客户推翻所有的系统重新再来。 原生应用的开发平台、工具:这个产品要易于使用,要有配合工作的工具链。虚拟机到容器的平滑迁移:最好能提供从原有方案到新产品的迁移方案,并且容易实施。与应用RD紧密配合:要提供良好的客户支持,(即使有些问题不是这个产品导致的也要积极帮忙解决)。资源倾斜:从战略层面支持颠覆性新技术:资源上向容器平台倾斜,没有足够的理由,尽量不给配置虚拟机资源。

总结

Docker集装箱与Kubernetes的安排是目前集装箱云的主流做法之一,美团的集装箱集群管理平台HULK也采用了这样的方案。本文主要分享了美团在集装箱技术方面的一些探索和实践。内容主要涵盖了美团集装箱云在Linux内核、Docker、Kubernetes做的一些优化工作,以及在美团内部推进集装箱化进程的一些思考。欢迎与我们交流讨论。

本文转载自公众号:美团技术队。

1.《hulk 美团容器平台架构及容器技术实践》援引自互联网,旨在传递更多网络信息知识,仅代表作者本人观点,与本网站无关,侵删请联系页脚下方联系方式。

2.《hulk 美团容器平台架构及容器技术实践》仅供读者参考,本网站未对该内容进行证实,对其原创性、真实性、完整性、及时性不作任何保证。

3.文章转载时请保留本站内容来源地址,https://www.lu-xu.com/junshi/1631286.html

上一篇

最温顺的蛇排名 世界上最温顺的蛇

下一篇

元旦旅游去哪里好 元旦旅游哪里去?2019年去哪里跨年?这些胜地不可或缺哦!

哈曼丹王储 迪拜王储结婚,妻子还是表妹,问题为何婚礼现场新娘却没出现?

  • 哈曼丹王储 迪拜王储结婚,妻子还是表妹,问题为何婚礼现场新娘却没出现?
  • 哈曼丹王储 迪拜王储结婚,妻子还是表妹,问题为何婚礼现场新娘却没出现?
  • 哈曼丹王储 迪拜王储结婚,妻子还是表妹,问题为何婚礼现场新娘却没出现?
去泰国旅游需要什么手续 第一次去泰国,有哪些问题需要注意?

去泰国旅游需要什么手续 第一次去泰国,有哪些问题需要注意?

泰国 这是一个旅游业非常成熟的国家 虽然很多朋友认为 去泰国旅游和周末郊游一样方便 但是我们经常在后台 我收到了许多来自新朋友的“各种”问题 比如这个 ▼   泰国的签证和入境要求 虽然之前有专门介绍过 但是因为不断有新朋友来问问题, 因此,今天我们专门解决你的问题 对问题和答案进行总结...

广州雾霾 打脸西方媒体!富力主帅回应“雾霾”问题:广州一尘不染,超级干净

  • 广州雾霾 打脸西方媒体!富力主帅回应“雾霾”问题:广州一尘不染,超级干净
  • 广州雾霾 打脸西方媒体!富力主帅回应“雾霾”问题:广州一尘不染,超级干净
  • 广州雾霾 打脸西方媒体!富力主帅回应“雾霾”问题:广州一尘不染,超级干净

产后第一次月经量大怎么办 医生偷偷告诉你:常见产后月经问题大全!

  • 产后第一次月经量大怎么办 医生偷偷告诉你:常见产后月经问题大全!
  • 产后第一次月经量大怎么办 医生偷偷告诉你:常见产后月经问题大全!
  • 产后第一次月经量大怎么办 医生偷偷告诉你:常见产后月经问题大全!
磨腮 别磨了,别磨了,再磨腮帮子都要出问题啦

磨腮 别磨了,别磨了,再磨腮帮子都要出问题啦

在漫漫长夜里,这个声音一直伴随着你吗?“咯吱~咯吱~咯吱”。有的人睡觉的时候磨牙,让自己感觉不舒服,周围的人听着更难受。 所以问题来了 我们为什么要磨牙? 磨牙是病吗? 是否治疗?   晚上磨牙也叫晚上磨牙。磨牙的因素很多,有些是工作学习压力大,情绪混乱。还有缺钙;还有个别牙齿畸形的情况,我们都知...

问男朋友的100个问题 男生总问你这3个问题,100%爱上你了,你逃也逃不掉了!

  • 问男朋友的100个问题 男生总问你这3个问题,100%爱上你了,你逃也逃不掉了!
  • 问男朋友的100个问题 男生总问你这3个问题,100%爱上你了,你逃也逃不掉了!
  • 问男朋友的100个问题 男生总问你这3个问题,100%爱上你了,你逃也逃不掉了!

在希腊当岛主的日子 那么问题来了,“十一”去希腊怎么样?

安卓内存清理 安卓手机越用越卡?使用这6种内存清理方法,手机再战3年不是问题

  • 安卓内存清理 安卓手机越用越卡?使用这6种内存清理方法,手机再战3年不是问题
  • 安卓内存清理 安卓手机越用越卡?使用这6种内存清理方法,手机再战3年不是问题
  • 安卓内存清理 安卓手机越用越卡?使用这6种内存清理方法,手机再战3年不是问题