热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

DockOne微信分享(二四六):同程艺龙大数据在Kubernetes的实践

【编者的话】同程艺龙是中国在线旅游行业的创新者和市场领导者,秉持让旅行更简单、更快乐的使命。作为同程艺龙的数据底层支撑部门,我们在2018年推动所有组件容器化部署,2019年推


【编者的话】同程艺龙是中国在线旅游行业的创新者和市场领导者,秉持 "让旅行更简单、更快乐" 的使命。作为同程艺龙的数据底层支撑部门,我们在2018年推动所有组件容器化部署,2019年推动所有服all in Kubernetes战略,在这个过程中我们也遇到了一些问题,比如存储组件是否应该上Kubernetes,外部世界如何和Kubernetes集群打通,本文将向大家介绍我们使用Kubernetes部署分布式系统的一些经验和思考。


同程艺龙数据中心容器化背景


同程艺龙是中国在线旅游行业的创新者和市场领导者,秉持 "让旅行更简单、更快乐" 的使命。作为同程艺龙的数据底层支撑部门,我们每天会产生海量的数据进行存储和计算,为了更好的支撑业务,我们在2018年推动所有的服务都采用了Docker Host模式部署 。 我们一开始采用脚本管理容器服务,虽然能够做到自动化部署,但是不同组件的资源池没有打通,机器剩余资源的把控不到位,服务的滚动更新和故障转移也处于一个人工处理的状态,这个时候我们急需一个统一调度和管理集群资源的平台,所以2019年我们开始尝试将所有服务部署到Kubernetes上,已经投产的存储服务有Elasticsearch,Tikv,Kudu,Kafka等一些节点类型少的服务,计算组件有Hive,Spark SQL等服务,在这条艰辛的on Kubernetes之路,我们也遇到了很多问题,今天向大家分享一下。


Kubernetes集群如何和外部世界打通


首先看下我们Kubernetes集群的架构图:



Kubernetes集群和外部机器通信,我们采用的OVS虚拟交换机的方式将物理网络和容器网络做成一个大二层的网络,这样Kubernetes集群外部的机器也能访问到容器。因为我们会部署分布式系统,有些分布式系统要求IP不变,所以Pod我们做了IP Local,根据Namespace和pod name来记录每个Pod的IP,IP保留时间为三天。为了防止极端情况下的需求,我们给Pod做了指定IP的功能,但是由于我们部署使用的是自定义对象或者StatefulSet对象,这个功能还需要在上层对象的Controller中支持。上面这些功能我们都是基于Contiv的netplugin插件,在使用过程中我们遇到节点veth pair删除不干净的情况,我们采用定时检查删除无用veth pair来保证网络的干净。


OVS架构图如下:



Pod网络的问题解决以后,Service的负载我们希望和Pod网络一样可以直接访问。这里我们使用Kubernetes Java Client Watch Service和Endpoints Event事件,将EndPoints和Service Cluster IP同步到同程艺龙的基础设施组件TVS上,TVS是一个四层负载均衡,我们通过HTTP的方式进行同步。在刚开始上线的时候,我们发现Kubernetes Client切换leader节点的时候会重新消费之前的Service event事件,所以同步一定要保证幂等性,Service删除事件同步要加上Kubernetes Service是否存在的校验,确认Service真的不在的时候,再去删除TVS的VIP。这种方式将我们的路由规则更集中式的管理,不会像kube-proxy将所有的规则同步到每台物理机器上。


Service网络解决以后,由于分布式系统的一些特性,有些组件是一定要通过域名才能启动和访问。所以我们会把Kubernetes集群内的节点域名全部注册到公司的DNS服务上,这里我们只要将Kubernetes内部域名改成公司提供的域名尾缀并重启集群和CoreDNS,然后将CoreDNS的域名同步一份到公司的DNS服务上。


做了上面这些支持后,我们觉得这样一个集群才符合生产环境的使用,既可以使用Kubernetes的很多特性,也和公司内部组件做了整合,用户的体验感也没有太大的变化,反而借助于Service和域名的自动同步,Kubernetes的编排能力,体验更佳。


存储计算组件上Kubernetes集群的实践


因为Kubernetes设计的初衷是为了部署计算型的组件,所以我们觉得部署计算节点对我们来说难度不大,我们部署了 Hive,Spark SQL,Tensorflow server等计算组件,不同组件我们采用不同的Namespace进行管理,不同组件的机器资源我们打上标签,做好资源池的划分。针对Hive这种两种及以上类型的节点,一开始我们会采用Helm写好模板做好一键部署,然后我们会投入人力做Hive的Operator,开发Operator可以将我们的一些人工容灾的思想用代码去变现出来,更新多节点类型的组件也会简单很多。


我们都会遇到存储组件应不应该上Kubernetes,我到底应不应该用共享存储的问题。我们认为存储组件是可以上Kubernetes的,这里我们采用的 Local PV+Ceph的方式,针对大数据存储组件,比如ES,TiKV,Kafka等组件,我们采用Local PV的方式,像物理机一样将数据存在本地磁盘,保证性能。针对Jupyter一些非重要的组件我们会采用Ceph RBD Image的方式,用来节省本地磁盘的空间。刚开始的时候我们采用批量创建Local PV的方式,后来我们希望控制磁盘的使用,一个或者两个存储组件配一些计算组件做到资源的混部,我们将Local PV的创建做成按需分配,合理的控制磁盘的使用。


存储组件我们第一个部署的组件是ElasticSearch,ES是非常容易支持的,因为客户端是http访问,对外只需要提供 ES client节点类型,不需要暴露集群内部节点信息,利用Service只需要提供一个TVS的VIP给到用户。刚开始我们使用StatefulSet部署Elasticsearch,由于Statefulset顺序性的限制,我们不能指定下掉某个节点,于是我们开发了一个高级版的AdvanceStatefulSet,通过指定序号就可以下线Pod。


像这样配置即可:


offlineStrategy:
podOrdinals:
- 0

我们将ES部署方式用Helm模板写好,做到自动化部署,每一个节点类型的容错还局限于AdvanceStatefulSet的Controller。ES官方也提供了Operator,因为处于beta版本,自定义资源还有很多问题,没有基于Sts做CRD,所以我们没有选择这种方式。我们觉得在Sts上层再建立一层CRD,可以更方便去管理多种节点类型,但是人力有限,我们对这个需求的优先级还不是很高,当前基于AdvanceSts管理也能够运维起来。


在部署Kudu组件的时候,我们延用ES的套路,发现节点域名解析不到的问题,当时我们还没有将Kubernetes内部域名同步到公司层面的DNS。在分布式系统中,很常见的场景是客户端连接到Master节点,Master节点会返回Worker节点域名,在Kubernetes集群外部的机器是没法访问到Worker的域名的。在没解决DNS问题之前,我们先采用Host模式部署,注意一下port冲突问题就好了。


因为我们在2018年所有的组件已经on Docker,我们只要将组件的部署方式迁移到Kubernetes上来管理,所以像Kafka,TiKV,PG,ZK这些组件,我们都可以轻松的上Kubernetes。不过在大数据组件当中,机器资源最多就属Hadoop组件,在以前Docker Host部署的时候,DataNode和yarn节点会挂载sata的12块盘,TiKV EleatiscSearch我们采用的是ssd raid50单块盘的方式,我们发现Local PV的方式不能很好的挂载多块盘,如果强行的挂载12个PV,scheduler需要支持每个PV在不同的磁盘,才能符合我们利用多块盘读写的目的。Local PV没法解决我们的需求,我们开始尝试HostPath,HostPath现在没有一个好的资源管理器,HostPath不能和机器属性绑定在一起,简单来说就是让HostPath具备Local PV机器绑定的特性。所以我们正在开发一个将HostPath也转变成PV资源进行管理,具备和Local PV一样的特性的Agent。当前我们采用的折中方案是AdvanceStatefulSet+nodeSelector+Affinity来部署yarn和DataNode,不过我们没有大规模使用,因为不够优雅。


Kubernetes集群部署分布式系统总结


我们认为在Kubernetes上部署存储或者计算型的组件是可行的,做好外部世界和Kubernetes集群内部的通信,或者将所有的组件都放在Kubernetes集群内部。针对性能要求比较高的组件,采用Host模式+Local PV的方式部署。在没有人力和开源成熟的Operator的时候,可以先用Helm模板化部署方式,先解决自动化部署。提供可视化的运维操作,通过人工组合操作的方式先代替Operator自动化运维。将一些通用的功能搬到Operator之上,并将Operator定制化能力提供给用户,让用户成为你的开发者,共同构建Kubernetes生态。当前我们维护了自己的AdvanceStatefulSet Controller,提供镜像原地升级,指定下线节点的功能,维护一个基础的Base Operator,我们希望将一些功能通用的覆盖所有组件,针对Hive这种多节点类型的服务开发独立的Operator。在社区我们积极参与TiDB Operator的开发,我们觉得当前TiDB的云原生方案是比较成熟,利用TiDB Operator部署的TiKV我们已经上生产了。这些支持得益于我们对于Service Pod DNS的支持,赋予Kubernetes的网络和磁盘静态分配绑定的能力。


以前我们会部署一个大的分布式系统业务混用,比如ES,现在我们可以利用Kubernetes切成小集群,每个集群都做好日志和监控的功能,业务可以申请自己的集群,资源上是隔离的,不会因为资源互相影响。懂组件的业务也可以根据自己的场景,不断优化自己集群的配置。当我们对组件性能把控不到位的时候,采用小集群是规避风险的一种方式。


关于监控,我们使用一个集群配一个Prometheus+Grafana的方案,做到监控隔离,Prometheus我们采用Thanos架构,提供统一的监控查询。


监控参考:



关于日志,我们采用sidecar注入到Pod的方式,收集到Kafka,Flink落地ES,保留七天,我们可以针对日志做一些报警策略。


日志参考:



一些天生支持云原生的组件探索


除了已有组件尝试部署到Kubernetes,我们也在探索新的组件,比如JupyterHub,JupyterHub我们采用的是Ceph共享存储。基于JupyterHub接口能力,提供自定义镜像和定制化框架的能力,每个用户可以申请自己的Jupyter,分配固定的资源配比。我们也尝试部署了KubeFlow,想借助于TensorFlow Operator 部署分布式任务能力提升算法侧的能力,不过因为KubeFlow要绑定Istio组件,我们觉得太大了,所以没有将其放到线上。我们会基于Jupyter提供更好的数据分析层面的交互能力。


我们还部署了TensorFlow Server,打通HDFS和TensorFlow Server,用户使用Spark训练的TF model生成到HDFS之上,可以自动部署成TF server,做到模型的自动部署和滚动更新。还有Dask等等服务。


我们发现已有组件官方都在做云原生的支持,新组件会自带Kubernetes的支持,所以on Kubernetes未来一定可以走的更远。


遇到的问题和未来规划


在on Kubernetes这条路上,Kubernetes不能拿来即用,要根据自己的场景适配。在不影响已有业务的情况下,提供不改变用户行为的场景。原本用户可以很方便看到日志,知道请求落到哪个点上,那么你就需要提供很好的日志收集服务,提供更稳定的服务,才能让用户相信你的能力。


在网络方面,我们会尝试DPDK来加速容器网络以及其他硬件方案,将大数据服务本地性需求弱化,做到存储和计算的分离,提升扩展性。


在磁盘方面,我们会提供不同的规格的尝试,当前我们是混部,我们会提供LVS+混部+分区的方案选择,提供更灵活的部署方式。


在平台层面,我们会将机器和底层研发用户分开,可视化的运维集群,提升安全性和便捷。


在技术变革的快车道上,我们要制定好如何在行驶中换轮胎,甚至是换引擎。


Q&A


Q:存储集群,出现Pod迁移怎么解决数据盘问题?


A:Local PV,只要你不删除PV和PVC,不会产生Pod偏移。你可以使用Sts volume Template试试。


Q:以前做过Zeppelin(类似Jupyter的工具)+Spark的应用,经常因为各种队列资源计算不足需要调整配置那些,如果上Docker的话,这种方便操作吗?就是担心容器集群会不会不稳定?


A:方便的。当前我们使用JupyterHub来创建Jupyter,Jupyter和Spark集群打通,提供用户直接写代码和集群交互。不过要注意资源控制。我们直接和Spark交互用的是Apache的Livy。Kubernetes集群你提高稳定性就可以了,我们现在用的很稳定。


Q:日志监控保留一周,那资源利用的数据保留多久?比如CPU内存网络硬盘这些数据?


A:容器的监控我们保留12天。历史数据我们用的Thanos架构,保存到Ceph中。物理机的监控我们是放在小米的Falcon。


Q:如果Pod挂了,出现Pod自动漂移到其他节点,挂载的Local PV数据是否也要做迁移?


A:如果Pod挂了无法拉起,不删除PV和PVC,Pod是不会漂移到其他节点。这是Local PV调度决定的。如果需要漂移到其他节点,需要手动的删除PV和PVC,Pod漂移到其他节点,然后将有问题那个物理机上的数据迁移到新的PV上来。


Q:Thanos监控数据如何存放?查询速度比原生的Prometheus如何?


A:Thanos是Prometheus的高可用架构,我们用来做一个集中查询。历史归档数据是存储在Ceph中,Prometheus存储比如七天的数据,还是和原来一样存储在本地。查询速度我们使用下来还可以,查询速度取决于你的监控数据的体量,你可以做一些横向扩展,数据量大的时候该慢还是慢的。


Q:请问一下Pod指定IP是怎么实现的?


A:Kubernetes是支持CNI接口的,我们使用Contiv的netplugin插件,当Pod调度起来,会走CNI接口申请一个IP。根据Namespace+podname对应一个唯一标识,这个标识和IP是存储在一个单独的etcd中。podname用deployment部署是随机的,所以我们基本上都会用我们开发的AdvanceSts来部署,这样名字是固定的。


Q:Kubernetes是直接部署在物理机还是虚拟机上的?


A:物理机,我们OVS网络没办法在虚拟机上部署。


以上内容根据2020年1月14日晚微信群分享内容整理。 分享人 程威,同程艺龙数据中心Kubernetes负责人 。DockOne每周都会组织定向的技术分享,欢迎感兴趣的同学加微信:liyingjiese,进群参与,您有想听的话题或者想分享的话题都可以给我们留言。




推荐阅读
  • 深入解析Serverless架构模式
    本文将详细介绍Serverless架构模式的核心概念、工作原理及其优势。通过对比传统架构,探讨Serverless如何简化应用开发与运维流程,并介绍当前主流的Serverless平台。 ... [详细]
  • 本文探讨了Web开发与游戏开发之间的主要区别,旨在帮助开发者更好地理解两种开发领域的特性和需求。文章基于作者的实际经验和网络资料整理而成。 ... [详细]
  • 本文档详细介绍了在 Kubernetes 集群中部署 ETCD 数据库的过程,包括实验环境的准备、ETCD 证书的生成及配置、以及集群的启动与健康检查等关键步骤。 ... [详细]
  • 深入解析ESFramework中的AgileTcp组件
    本文详细介绍了ESFramework框架中AgileTcp组件的设计与实现。AgileTcp是ESFramework提供的ITcp接口的高效实现,旨在优化TCP通信的性能和结构清晰度。 ... [详细]
  • 本文详细介绍了如何在 Android 中使用值动画(ValueAnimator)来动态调整 ImageView 的高度,并探讨了相关的关键属性和方法,包括图片填充后的高度、原始图片高度、动画变化因子以及布局重置等。 ... [详细]
  • 深入解析Hadoop的核心组件与工作原理
    本文详细介绍了Hadoop的三大核心组件:分布式文件系统HDFS、资源管理器YARN和分布式计算框架MapReduce。通过分析这些组件的工作机制,帮助读者更好地理解Hadoop的架构及其在大数据处理中的应用。 ... [详细]
  • 本文探讨了现代分布式架构的多样性,包括高并发、多活数据中心、容器化、微服务、高可用性和弹性架构等,并介绍了与这些架构相关的重要管理技术,如DevOps、应用监控和自动化运维。文章还深入分析了分布式系统的核心概念、主要用途及类型,同时对比了单体应用与分布式服务化的优缺点。 ... [详细]
  • 本文详细探讨了在微服务架构中,使用Feign进行远程调用时出现的请求头丢失问题,并提供了具体的解决方案。重点讨论了单线程和异步调用两种场景下的处理方法。 ... [详细]
  • 请看|间隔时间_Postgresql 主从复制 ... [详细]
  • NFS(Network File System)即网络文件系统,是一种分布式文件系统协议,主要用于Unix和类Unix系统之间的文件共享。本文详细介绍NFS的配置文件/etc/exports和相关服务配置,帮助读者理解如何在Linux环境中配置NFS客户端。 ... [详细]
  • 本文详细介绍了 Kubernetes 集群管理工具 kubectl 的基本使用方法,涵盖了一系列常用的命令及其应用场景,旨在帮助初学者快速掌握 kubectl 的基本操作。 ... [详细]
  • 当面临数据库清理任务时,若无删除或重建数据库的权限,可以通过编写SQL脚本来实现批量删除用户自定义的数据表和存储过程。本文将详细介绍如何构造这样的SQL脚本。 ... [详细]
  • 全能终端工具推荐:高效、免费、易用
    介绍一款备受好评的全能型终端工具——MobaXterm,它不仅功能强大,而且完全免费,适合各类用户使用。 ... [详细]
  • Docker 自定义网络配置详解
    本文详细介绍如何在 Docker 中自定义网络设置,包括网关和子网地址的配置。通过具体示例展示如何创建和管理自定义网络,以及容器间的通信方式。 ... [详细]
  • 深入理解Docker网络管理
    本文介绍了Docker网络管理的基本概念,包括为什么需要Docker网络管理以及Docker提供的多种网络驱动模式。同时,文章还详细解释了Docker网络相关的命令操作,帮助读者更好地理解和使用Docker网络功能。 ... [详细]
author-avatar
追忆幽梦_554
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有