当前位置: 首页 > 科技观察

滴滴弹性云:从物理机到Kubernetes的坑与经验

时间:2023-03-19 23:17:33 科技观察

今天给大家带来一些关于滴滴弹性云的分享,内容就是从物理机到Kubernetes的那些坑与经验。我先简单介绍一下自己。我叫谭林。我以前在Intel做OpenStack,也花了不少精力在开源社区。后来来到滴滴弹性云团队,主要从事基于Kubernetes的基础平台建设。可以说,我从一个做饭的“大厨”变成了一个“吃货”。今天的分享主要分为四个部分:整体架构产品功能解决方案详情展望我们在准备构建弹性云的时候,问了自己三个问题:为什么要构建私有云?我们为什么选择容器?我们为什么选择Kubernetes?我们为什么要做私有云??因为滴滴的集群太大,有几万台物理机(这样的规模需要我们搭建私有云平台),导致之前没有更好的解决方案,导致资源占用极低,资源浪费很大.问题。另一个主要原因是滴滴发展太快,新业务不断涌现。过了一段时间,听说新部门成立了,随着新需求的出现,更新迭代异常频繁。这些对于平台的稳定性都是非常重要的。性方面提出了特别高的要求。这个问题不是一堆人能解决的,需要一个好的平台和机制来解决。为什么选择容器?KVM/Xen等传统虚拟化已经存在多年,非常稳定,但是它的缺点大家都知道,就是损耗比较大。另外,传统混合部门是滴滴目前正在使用的解决方案(即继续保持原有的传统混合部门)。虽然可以部分解决资源占用低的问题,但是因为完全没有隔离,所以很容易让程序相互影响。容器是一个比较折衷的方案,有一定的隔离性,损失也比较小,这是我们选择它的主要原因。同时,更重要的是容器镜像带来的新玩法,因为镜像环境是一致的,对运维人员特别友好。因此,他们不再需要关心那些复杂的配置文件,也不需要频繁的走初始化过程,也不需要担心每次上线更新对新服务的影响。为什么选择Kubernetes?大家都知道比较出名的容器平台有Mesos、Kubernetes和Swarm。一年前,我们在Mesos和Kubernetes之间犹豫了很久。后来主要是觉得要做一个基于容器的平台。与Mesos相比,Kubernetes更侧重于容器。Swarm当时还很年轻,很多功能还不完善。与Kubernetes相比,它更加成熟。当然,更关键的原因是Kubernetes社区更具活力,设计结构更清晰,可扩展性也高。现在回想一年前的选择,我很庆幸我们做出了正确的选择,因为之前,Kubernetes与两者相比,只是旗鼓相当,而现在却大有一统江山之势。我们目前还在基于Kubernetes1.6版本进行改造。1.8版本发布后,我们会尽量跟上,与社区保持同步。整体架构项目介绍滴滴弹性云的目标是为滴滴提供一个稳定、高效、可扩展的基于容器技术的服务管理平台。简单回顾一下ElasticCloud的项目历程:2016年7月,ElasticCloud项目正式上线,随后10月发布最新版本。2017年4月,第二版出版。在几个月的经验中,我们根据用户反馈对产品形态和底层网络方案进行了大规模优化。第三个版本目前正在开发中,这个版本将更加注重用户交互和可视化。到目前为止,我们总共有300多台主机和2000+个容器实例,数量不算多,但目前滴滴的核心业务线有很多在我们的平台上运行,预计规模将呈指数级增长2018年上涨。总体目标为了解决前面提出的三个问题,我们的总体目标有四点:实现资源按需分配,提高资源利用率,实现资源弹性伸缩,快速响应负载变化,保持基础环境一致,以及实现服务的快速交付保证服务的容错,实现基础设施的免费运维解决方案根据不同的产品线和需求,我们具体的产品解决方案主要分为两部分:基于容器的轻量级虚拟机,称为静态容器组。一个更纯粹的微服务容器,我们称之为弹性伸缩组。同时,我们也整合了滴滴现有的部署监控和日志收集系统。如上图所示,就是整体架构。中间最大的一块就是我们的K8S集群,主要分为控制节点和工作节点两部分。上半部分是我们的控制台和管理员入口,左半部分是滴滴现有的一些权限认证系统和服务树,右半部分是我们的网络方案。所以按照流程,我们做的主要操作是在用户先通过授权系统认证后,创建服务(即K8S实例),实现容器的扩缩容和部署更新。之后,我们的平台会进行实时监控和日志采集,完成监控数据的上报和镜像拉取。刚才说的主要是跟管理员相关的工作流程。现在让我们看看用户流量。首先,我们已经意识到每个容器都可以通过IPAM组件获得一个独立的IP。这个IP可以和物理机双向通信,这样用户流量就可以直接通过容器IP访问实例。同时,我们还提供了一个四层LB,让用户只需访问一个VIP,就可以自动将流量发送到后续容器。产品功能接下来,我们就详细说说滴滴弹性云的具体产品功能。功能类型前面提到,我们主要提供两种产品:静态容器和动态伸缩,伸缩组又分为有状态伸缩组和无状态伸缩组。其实一开始我们只是想提供Deployment,K8S支持的很好,也就是无状态伸缩,这也是最好用容器的产品形态。但是在实际落地的过程中,我们发现根本就不是一回事。首先,并不是所有的程序都可以很容易的转化为Cloud-Native服务,所以对于这样的传统服务,我们还是需要提供更接近物理机用户体验的产品。它的问题是不能弹性伸缩,但是好处是可以挂载本地存储,IP不变。同时,为了支持有状态的服务,我们还改进了有状态的伸缩组。它支持弹性缩放和挂载网络存储。然而,更让人意外的是,用户之所以选择有状态伸缩组,很大一部分原因并不是因为挂载Ceph,而是因为有状态伸缩组的容器IP/HostName保持不变,所以不管是从监控还是日志,两者都更友好。而无状态伸缩这个我们一开始最想推广的服务,只会在一些对弹性伸缩的速度要求特别高的场景下使用。功能特点具体到产品功能的特点,我们主要有三大部分:复杂的配置简化,在线流程标准化服务管理有时会让用户感到困惑。所以我们做了减法,简化了很多配置,只留给用户一些接口,避免不必要的麻烦。比如我们支持多种访问方式,可以一键完成从Git代码仓库到在线镜像的转换过程,也支持直接通过自定义镜像。同时,我们还对镜像进行了分层(基础镜像→环境镜像→服务镜像),实现RD和SRE每个角色负责不同的镜像制作,这样分工更加合理,层次分明更加清晰,权责明确,高效有序。监控日志的自动配置和关联也被减去。希望用户少关注这一点,以获得更好的体验。相对于减法,我们在上线流程的标准化上也做了很多加法,因为我们是一个严肃的运维平台,之所以强调严肃,是因为只要有就很容易出错涉及的人。一方面,我们应该尽量减少需要人工参与的地方;另一方面,我们应该尝试通过各种规范来减少人们犯错误的机会。比如在变更审批系统中,每一次上线变更都需要开发负责人审核;同时也进行了改造,每次都可以分组为小流量灰度。每次发布更新时都有强制观察时间。如果在观察过程中,比如你发布第二套后,发现你的代码在更新过程中有bug,我们也支持一键回滚。服务管理在服务管理方面,我们实现了服务不可用自动重启、一键扩容、负载均衡。最重要的是倒逼用户多住异地。我们两个机房肯定都有实例。方案细节现在介绍一下我们方案的细节,主要包括:网络监控日志镜像市场网络介绍SDN我们的网络方案主要是基于Onos+OVS的SDN网络方案,每个容器都有一个OverlayIP,和物理机中的不同机房,实现容器间的“大二层”互通,通过交换机连接机房网络。物理机可以通过容器OverlayIP直接访问容器,反之亦然。IP在IP上,静态容器和可伸缩容器都可以绑定Hostname。容器不变的Hostname保证了容器漂移到其他主机后IP不变。当容器发布更新时,它会一直保持稳定。对于随机分配IP的情况,我们也提供IP池,保证IP只会从IP池中出现。负载均衡我们在弹性云中使用独立的4层和7层负载均衡器来实现动态负载均衡和自动故障排除。网络开放架构目前的弹性云容器网络大致分为三种:同一主机之间的容器通信、跨主机的容器通信、容器与物理机之间的通信。每个部署容器的主机都会部署一套Ovs网络组件,其中最关键的是两个OvsBridges,一个负责建立与外界通信的隧道,称为Ovs-tunnelbridge。一个负责在本机上集成容器通信,叫做Ovs-intbridge。所有的Ovs-tunnel都会和OnosController建立连接,OnosController负责查询流表,并在流表和其他主机之间建立隧道。因此,三种通信方式可以理解为:容器与宿主机通信:直接通过Ovs-int网桥进行通信,因此Ovs-tunnel与外界之间不依赖隧道。跨主机的容器通信:Ovs-tunnel在第一次通信时也会查询Onos,Onos返回目标容器的主机信息,Ovs-tunnel将容器数据通过主机之间的隧道发送给目标容器的主机。目标容器主机上的Ovs-tunnel会不断向上层传递数据,通过Ovs-int传递给容器。容器与物理机通信:容器发送给物理机的数据包,会由Ovs-tunnel通过隧道发送给Overlay网关,Overlay网关进行Vxlan解包,将数据传输到物理网络。相反,物理机发送给容器的数据包,被Overlay网关封装成Vxlan数据包,然后通过隧道发送给容器主机,再由主机传给上层的容器层。网络IP分配因产品而异,各IP分配方案如下:静态容器组:IP和Hostname不变。有状态伸缩组:IP和Hostname不变,支持IP池。无状态伸缩组:支持IP池,IP随机分配,灵活性更高。创建过程这是创建容器网络的过程。一旦用户需要创建容器,控制节点会对整个集群进行调度,选择合适的工作节点,节点最重要的核心Kubelet负责创建容器,控制节点将请求发送给它。具体创建步骤如下:当Kubelet收到调度到Node的Pod信息后,会先创建一个没有网络配置的Infrastructure基础容器,用于承载Pod中所有容器的网络Namespace。KubeletExec启动CNIPlugin,将第一步创建的网络Namespace、Pod名称、容器ID等作为标准输入传递给新启动的Plugin进程。CNIPlugin根据收到的参数,去IPController申请容器的网络IP。IPController会判断容器属于哪个子网,子网内是否有可用的IP,是否有绑定的IP地址等,然后到SDNIPAM端根据需要申请虚拟服务器计算出的IP地址和子网信息。端口(覆盖IP)。IPAM会将创建的虚拟端口返回给API调用方IPController,同时将信息同步到SDNOnos。IP控制器会将返回的端口保存在自己的存储库中。如果是绑定IP的Pod,它还会将Pod绑定到虚拟Port(OverlayIP),下次Pod再次申请时,还是会申请Port(OverlayIP)。数据保存后,会将Port信息返回给CNIPlugin。CNIPlugin收到Port信息后,会根据其中的OverlayIP、Gateway、VlanTag等信息,创建VethPair、配置Veth信息、配置路由、添加Ovs-bridge等操作。至此,还没有任何网络的基础容器,有网络配置(除了与外部通信的Ovs网络外,Lo网络也会同时加入)。CNIPlugin配置网络成功后,会将结果返回给Kubelet。Kubelet会使用配置成功的基础容器的网络Namespace继续创建其他业务容器。如果配置失败,会从第一步开始继续创建基础容器,直到网络配置成功。监控需求监控主要有两个需求:基础监控:基础监控使用谷歌开源容器监控软件Cadvisor/Cgroup作为监控数据源,数据上报给Odin,监控数据可以在Odin和elasticcloud上扩展页。物理机监控代理无法收集到有效的容器监控数据。Cadvisor、Proc、Cgroup容器的基本监控项与物理机有明显区别,但用户的需求并没有改变。业务监控:业务监控与物理机需求完全一致,复用物理机监控方式。这张图是elasticcloud配置监控和查看监控的示意图。我们在每台物理机上获取了容器的基本监控指标,获取了容器内的服务指标。日志要求日志主要考虑三个方面:日志时效性:在线日志采集延迟2分钟,满足大部分场景。紧急情况下可以登录容器查看日志。日志持久化:生成的容器直接拉取到远程存储,选择分布式存储日志在Ceph中存储一份。日志展示:有很多丰富的日志展示和分析系统,用于事后追溯。这是我们在弹性云平台上创建的容器的运行日志,也是一个简单的示意图。通常用户登录容器,一旦容器发布更新,漂移后数据就会丢失,所以我们直接将日志记录到Ceph中。如果用户不喜欢用这个,可以直接登录远程,远程采集系统可以使用不同的系统。比如ES和HDFS提供了更丰富的日志展示和分析系统。持久化存储主要提供本地卷和网络卷:本地卷HostPath提供给静态容器组,我们将宿主机上的目录挂载到容器中作为数据存储卷,具有稳定性和可读性高的优点.网络卷Ceph的优点是多备份比较可靠,支持容器迁移。缺点是网络抖动不可避免,所以必须使用Ceph服务进行改造,防止网络抖动影响整个服务流程。OverlayFS我们选择OverlayFS作为存储,一方面是因为它有更好的性能/稳定性,当然它也有缺点。比如DeviceMapper可以通过LVM解决磁盘容量限制,但是OverlayFS无法自己解决,需要依赖XFS来限制。但是,我们发现在某些场景下,由于XFS没有开启ftype功能,导致系统读写缓慢。因此,如果您也选择OverlayFS+XFS方式,建议将ftype设置为1。图像市场如上图所示。图像市场主要是分层的。目的是让不同的用户关注不同的东西:基础环境镜像:elasticcloud管理员创建的镜像:FROM官方镜像,添加了使用的服务各种Agent镜像,常用软件,系统配置(添加用户、切割原木等)。兼顾最复杂的周边应用整合,让影像更小。服务环境镜像:SRE同学制作维护的镜像:FROM基础环境镜像,安装服务运行所需的环境和配置。更注重服务环境的保护,让形象满足产品线的使用。服务镜像:使用RD代码中的Dockerfile(一般只需要将代码复制到需要的在线目录下),FROM服务环境镜像,弹性云系统生成的服务提供镜像。经验与展望经验经验首先要强调的是“云计算无非就是运维,无非就是可靠性”。产品做的再好,运维人员不靠谱,出错了也没人敢用你的产品,说的再好也没用。其次,“网上无小事,对网上要保持敬畏之心”。以前在开源社区工作,做过很多解决方案,但是现在做云计算解决方案的时候,发现现实和想象有很大的差距。可以说,云计算的实施难度更大。可能大家看了一些网上的分享会觉得搭建容器环境还是比较容易的,但是最难的是我们已经有了像我们这样现成的系统。想要实现,就需要做出各种突破、妥协,甚至砍掉一些功能。有的时候这些不是我们想做的,但是为了推动落实又不得不去做。此外,技术挑战是一方面,但用户习惯是更大的挑战,尤其是在业务方面。他们肯定会说我为什么要搬家,我现在用得很好,即使你告诉他们这样做会为公司节省成本,可以提高运维的便利性,他们还是会觉得我不缺钱,怕麻烦。再者,他们又不是做运维的,显然感受不到这些带来的好处。另一方面,有些用户认为我可以上你的云,但是你不想改变我的习惯,我还得保持原来的样子。但问题是,以前是物理机,现在安装了容器,就不可能保持原来的方法了。运维是一项特别困难的工作。网上无小事,稍有变动,回滚方案考虑不周,回滚方案验证不充分,分分钟出事。我相信每个人都清楚这一点。未来展望对于弹性云的未来规划,最好的是更细粒度的隔离。如果你对容器有更深入的了解,就会知道Docker现在更多的是隔离Memory占用和CPU占用。但是在实际过程中,我们会发现,比如你给用户一块8G内存,在某些极端配置下,这8G内存会不断刷新读写,那么你的L3Cache很快就会被maxedout,导致大量的CacheMiss,这对程序性能还是会有很大的影响。二是静态容器的弹性伸缩。因为静态容器确实像虚拟机一样,运维成本特别高,所以一旦物理机挂了,容器也挂了,很多东西就找不回来了。而如果要扩容,只能按照传统的方式,先申请一个容器,然后去里面进行部署、配置等,会给运维同学带来很大的麻烦。三是更智能的扩容算法。目前我们是根据实时使用率来扩容,但其实对我们来说,很多业务高峰期是有规律的。如果能提前预测到高峰期,做自适应扩容,将大大提升资源。使用率。最重要的一点是依靠社会,回馈社会。我们打算解放双手,回馈社区一些不需要那么多定制的解决方案。谭林,滴滴出行弹性云架构师,云计算专家,曾在英特尔从事云计算研究。OpenStackIronic项目的核心开发者,《OpenStack设计与实现》的作者,在OpenStackSummitSRECon峰会上多次分享Topics。目前从事基于Kubernetes的私有云平台研发,专注于研发运维提升服务稳定性和效率。