热门标签 | 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,进群参与,您有想听的话题或者想分享的话题都可以给我们留言。




推荐阅读
  • 什么是大数据lambda架构
    一、什么是Lambda架构Lambda架构由Storm的作者[NathanMarz]提出,根据维基百科的定义,Lambda架构的设计是为了在处理大规模数 ... [详细]
  • 一、Hadoop来历Hadoop的思想来源于Google在做搜索引擎的时候出现一个很大的问题就是这么多网页我如何才能以最快的速度来搜索到,由于这个问题Google发明 ... [详细]
  • Oracle优化新常态的五大禁止及其性能隐患
    本文介绍了Oracle优化新常态中的五大禁止措施,包括禁止外键、禁止视图、禁止触发器、禁止存储过程和禁止JOB,并分析了这些禁止措施可能带来的性能隐患。文章还讨论了这些禁止措施在C/S架构和B/S架构中的不同应用情况,并提出了解决方案。 ... [详细]
  • 基于PgpoolII的PostgreSQL集群安装与配置教程
    本文介绍了基于PgpoolII的PostgreSQL集群的安装与配置教程。Pgpool-II是一个位于PostgreSQL服务器和PostgreSQL数据库客户端之间的中间件,提供了连接池、复制、负载均衡、缓存、看门狗、限制链接等功能,可以用于搭建高可用的PostgreSQL集群。文章详细介绍了通过yum安装Pgpool-II的步骤,并提供了相关的官方参考地址。 ... [详细]
  • 本文介绍了在Linux下安装和配置Kafka的方法,包括安装JDK、下载和解压Kafka、配置Kafka的参数,以及配置Kafka的日志目录、服务器IP和日志存放路径等。同时还提供了单机配置部署的方法和zookeeper地址和端口的配置。通过实操成功的案例,帮助读者快速完成Kafka的安装和配置。 ... [详细]
  • 本文介绍了OpenStack的逻辑概念以及其构成简介,包括了软件开源项目、基础设施资源管理平台、三大核心组件等内容。同时还介绍了Horizon(UI模块)等相关信息。 ... [详细]
  • 2018深入java目标计划及学习内容
    本文介绍了作者在2018年的深入java目标计划,包括学习计划和工作中要用到的内容。作者计划学习的内容包括kafka、zookeeper、hbase、hdoop、spark、elasticsearch、solr、spring cloud、mysql、mybatis等。其中,作者对jvm的学习有一定了解,并计划通读《jvm》一书。此外,作者还提到了《HotSpot实战》和《高性能MySQL》等书籍。 ... [详细]
  • REVERT权限切换的操作步骤和注意事项
    本文介绍了在SQL Server中进行REVERT权限切换的操作步骤和注意事项。首先登录到SQL Server,其中包括一个具有很小权限的普通用户和一个系统管理员角色中的成员。然后通过添加Windows登录到SQL Server,并将其添加到AdventureWorks数据库中的用户列表中。最后通过REVERT命令切换权限。在操作过程中需要注意的是,确保登录名和数据库名的正确性,并遵循安全措施,以防止权限泄露和数据损坏。 ... [详细]
  • Jquery 跨域问题
    为什么80%的码农都做不了架构师?JQuery1.2后getJSON方法支持跨域读取json数据,原理是利用一个叫做jsonp的概念。当然 ... [详细]
  • 本文总结了初学者在使用dubbo设计架构过程中遇到的问题,并提供了相应的解决方法。问题包括传输字节流限制、分布式事务、序列化、多点部署、zk端口冲突、服务失败请求3次机制以及启动时检查。通过解决这些问题,初学者能够更好地理解和应用dubbo设计架构。 ... [详细]
  • [翻译]微服务设计模式5. 服务发现服务端服务发现
    服务之间需要互相调用,在单体架构中,服务之间的互相调用直接通过编程语言层面的方法调用就搞定了。在传统的分布式应用的部署中,服务地 ... [详细]
  • Kylin 单节点安装
    软件环境Hadoop:2.7,3.1(sincev2.5)Hive:0.13-1.2.1HBase:1.1,2.0(sincev2.5)Spark(optional)2.3.0K ... [详细]
  • 讨伐Java多线程与高并发——MQ篇
    本文是学习Java多线程与高并发知识时做的笔记。这部分内容比较多,按照内容分为5个部分:多线程基础篇JUC篇同步容器和并发容器篇线程池篇MQ篇本篇 ... [详细]
  • 你知道Kafka和Redis的各自优缺点吗?一文带你优化选择,不走弯路 ... [详细]
  • 前言最近一段时间在整公司项目里一个功能的优化,用到了多线程处理。期间也是踩了不少的坑,在这里想说下我遇到的问题和注意事项。以及怎样知道启动的那些多线程都 ... [详细]
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社区 版权所有