DockOne微信分享(一二六):Kubernetes在微服务化游戏中的探索实践

本文讲的是DockOne微信分享(一二六):Kubernetes在微服务化游戏中的探索实践【编者的话】随着Kubernetes的持续火热,那在线游戏领域又将如何使用,又将碰到哪些问题,以及带来哪些价值? 本次分享将为大家介绍微服务化架构游戏领域中,Kubernetes支撑技术方案选型,功能优化以及实践过程中的一些思考。

【3 天烧脑式容器存储网络训练营 | 深圳站】本次培训以容器存储和网络为主题,包括:Docker Plugin、Docker storage driver、Docker Volume Pulgin、Kubernetes Storage机制、容器网络实现原理和模型、Docker网络实现、网络插件、Calico、Contiv Netplugin、开源企业级镜像仓库Harbor原理及实现等。

微服务化游戏容器化探索

随着Docker技术在近几年的快速发展,国内外掀起了一股容器之风。而我们也在这时,开启了游戏容器化的探索之路。最开始在Docker容器的应用上,还是以VM的模式去部署,毕竟游戏是非常复杂的应用,没有统一的模式。除此之外,对于一项全新技术的应用,大家都很谨慎,一步一步地去实践。

而在近一两年,部分游戏的架构也逐渐往微服务化方向转变,以下是一款游戏的架构:游戏的逻辑层按不同的服务划分为不同的模块,每个模块都是高内聚低耦合,之间的通信通过消息队列(或者API)来实现。模块的版本通过CI/CD,实现镜像标准交付,快速部署。在这些模块中,大部分是无状态服务,很容易实现弹性伸缩。

我们再来看另一款微服务化游戏的架构:也是按功能模块划分不同的服务,前端通过HAProxy来代理用户请求,后端服务可以根据负载来实现扩缩容。在服务发现模块中,通过Registrator来监视容器的启动和停止,根据容器暴露的端口和环境变量自动注册服务,后端存储使用了Consul,结合consul-template来发现服务的变化时,可以更新业务配置,并重载。

对于这些微服务化的游戏,服务模块小且多。那么,怎样快速部署,怎样弹性伸缩,怎样实现服务发现等等,都是我们需要解决的问题。容器化这些服务是一个不错的方案,接下来就是容器调度、编排平台的建设了。在当前也有多种方案可选,Mesos、Swarm等,而我们沿用了Kubernetes做来容器的整个调度管理平台,这也得利于之前VM模式下Kubernetes的成功应用。不同的是我们选择了高版本的Kubernetes,无论从功能的丰富上,性能的提升上,稳定性,可扩展性上来说,都有绝对的优势。以下会从几个维度来分析Kubernetes在微服务化游戏上的实践

基于kubernetes的解决方案

定制的网络与调度方案

集群的网络方案,是最为复杂,也是最为基础的一项。结合业务各模块之间的访问关系,我们选定的方案如下:

集群内各模块之间的通信:Overlay网络

我们基于Flannel来实现Overlay网络,每个主机拥有一个完整的子网,在这个扁平化的网络里面,管理简单。当我们创建容器的时候,会为容器分配一个唯一的虚拟IP,容器与容器之间(甚至母机与容器之间)可以方便地通信。当然,在实现中,业务也并非单纯的用IP来访问,而是结合DNS服务,通过域名来访问,后面会讲到。

以下是基于Flannel实现的Overlay网络的通信案例:

假设当sshd-2访问nginx-0:当packet{172.16.28.5:port => 172.16.78.9:port} 到达docker0时,根据node1上的路由规则,选对flannel.1作为出口,同时,根据iptables SNAT规则,将packet的源IP地址改为flannel.1的地址(172.16.28.0/12)。flannel.1是一个VXLAN设备,将packet进行隧道封包,然后发到node2。node2解包,然后根据node2上的路由规则,从接口docker0出发,再转给nginx-0。最终实现通信。

公司内网到集群内模块的通信:sriov-cni

sriov-cni是我们基于CNI定制的一套SRIOV网络方案,而CNI作为Kubernetes Network Plugins,插件式接入,非常方便,目前已开源,地址:https://github.com/hustcat/sriov-cni

以下是SRIOV网络拓扑图与实现细节:

  1. 母机上开启SRIOV功能,同时向公司申请子机IP资源,每个VF对应一个子机IP。
  2. Kubernetes在调度时,为每个Pod分配一个VF与子机IP。
  3. 在Pod拿到VF与IP资源,进行绑定设置后,就可以像物理网卡一样使用。

同时我们也做了一些优化:包括VF中断CPU绑定同时关闭物理机的irqbalance功能,容器内设置RPS,把容器内的中断分到各个CPU处理,来提升网络性能。

此类容器除了SRIOV网络之外,还有一个Overlay网络接口,也即是多重网络,可以把公司内网流量导入到Overlay集群中,实现集群内外之间的通信。在实际应用中,我们会用此类容器来收归通往集群内的通信,例如我们用HAProxy LB容器来提供服务。

对接公网:采用公司的TGW方案

TGW接入时,需要提供物理IP,所以对接TGW都会用到SRIOV网络的容器,例如上面提到的HAProxy LB容器。这样公网通过TGW访问haproxy,再由haproxy转到集群内容器,从而打通访问的整个链路。

集群内模块访问公司内网通信:NAT方案

调度:

在上述网络方案中,我们讲到SRIOV需要绑定物理IP,所以在容器调度中,除了Kubernetes原生提供的CPU\Memory\GPU之外,我们还把网络(物理IP)也作为一个计算资源,同时结合Kubernetes提供的extender scheduler接口,我们定制了符合我们需求的调度程序(cr-arbitrator)。其结构如下:

cr-arbitrator做为extender scheduler,集成到Kubernetes中,包括两部分内容:

预选算法:
在完成Kuernetes的predicates调度后,会进入到cr-arbitrator的预选调度算法,我们以网络资源为例,会根据创建的容器是否需要物理IP,从而计算符合条件的node(母机)。

优选算法:
在整个集群中,需要物理IP的容器与Overlay网络的容器并未严格的划分,而是采用混合部署方式,所以在调度Overlay网络的容器时,需要优化分配到没有开启sriov的node上,只有在资源紧张的情况下,才会分配到sriov的node上。

除了cr-arbitrator实现的调度策略外,我们还实现了CPU核绑定。可以使容器在其生命周期内使用固定的CPU核,一方面是避免不同游戏业务CPU抢占问题;另一方面在稳定性、性能上(结合NUMA)得到保障及提升,同时在游戏业务资源核算方面会更加的清晰。

域名服务与负载均衡

在网络一节,我们讲到Kubernetes会为每个Pod分配一个虚拟的IP,但这个IP是非固定的,例如Pod发生故障迁移后,那么IP就会发生变化。所以在微服务化游戏架构下,业务模块之间的访问更多地采用域名方式进行访问。在Kubernetes生态链中,提供了SkyDNS作为DNS服务器,可以很好的解决域名访问问题。
  
在Kubernetes集群中,业务使用域名访问有两种方式:

  • 通过创建service来关联一组Pod,这时service会拥有一个名字(域名),Pod可以直接使用此名字进行访问。
  • 通过Pod的hostname访问(例如redis.default.pod...)。原生功能不支持,主要是kube2sky组件在生成域名规则有缺陷。针对这个问题,我们进行了优化,把Pod的hostname也记录到etcd中,实现SkyDNS对Pod的hostname进行域名解析。

负载均衡

通常情况下,游戏的一个模块可以通过deployment或者是replication controller来创建多个pod(即多组服务),同时这些容器又需要对外提供服务。如果给每个pod都配置一个公司内网IP,也是可以解决,但带来的问题就是物理IP资源浪费,同时无法做到负载均衡,以及弹性伸缩。因此,我们需要一个稳固、高效的Loadbalancer方案来代理这些服务,其中也评估了Kubernetes的service方案,不够成熟,在业务上应用甚少。刚好Kubernetes的第三方插件service-loadbalancer提供了这方面的功能,它主要是通过haproxy来提供代理服务,而且有其它在线游戏也用了haproxy,所以我们选择了service-loadbalancer。

service-loadbalancer除了HAProxy服务外,还有一个servicelb服务。servicelb通过Kubernetes的master api来时时获取对应Pod信息(IP和port),然后设置HAProxy的backends,再reload haproxy进程,从而保证HAProxy提供正确的服务。

监控与告警

监控、告警是整个游戏运营过程中最为核心的功能之一,在游戏运行过程中,对其性能进行收集、统计与分析,来发现游戏模块是否存在问题,负载是否过高,是否需要扩缩容之类等等。在监控这一块,我们在cAdvisor基础上进行定制,其结构如下:

  • 每个母机部署cAdvisor程序,用于收集母机上容器的性能数据,目前包括CPU使用情况、memory、网络流量、TCP连接数。
  • 在存储方面,目前直接写入到TenDis中,后续如果压力太大,还可以考虑在TenDis前加一层消息队列,例如Kafka集群。
  • Docker-monitor,是基于cAdvisor收集的数据而实现的一套性能统计与告警程序。在性能统计方面,除了对每个容器的性能计算外,还可以对游戏的每个服务进行综合统计分析,一方面用于前端用户展示,另一方面可以以此来对服务进行智能扩缩容。告警方面,用户可以按业务需求,配置个性化的告警规则,docker-monitor会针对不同的告警规则进行告警。

日志收集

Docker在容器日志处理这一块,目前已很丰富,除了默认的json-file之外,还提供了gcplogs、awslogs、fluentd等log driver。而在我们的日志系统中,还是简单的使用json-file,一方面容器日志并非整个方案中的关键节点,不想因为日志上的问题而影响Docker的正常服务;另一方面,把容器日志落地到母机上,接下来只需要把日志及时采集走即可,而采集这块方案可以根据情况灵活选择,可扩展性强。我们当前选择的方案是Filebeat + Kafka + Logstash + Elasticsearch,其结构如下:

我们以DaemonSet方式部署Filebeat到集群中,收集容器的日志,并上报到Kafka,最后存储到Elasticsearch集群,整个过程还是比较简单。而这里有个关键点,在业务混合部署的集群中,通过Filebeat收集日志时怎样去区分不同的业务?而这恰恰是做日志权限管理的前提条件,我们只希望用户只能查看自己业务的日志。以下是具体的处理方案与流程:

  • 首先我们在Docker日志中,除了记录业务程序的日志外,还会记录容器的name与namespace信息。
  • 接着我们在Filebeat的Kafka输出配置中,把namespace作为topic进行上报,最终对应到Elasticsearch的index。
  • 在我们的平台中,一个namespace只属于一个业务,通过namespace,可以快速的搜索到业务对应的日志,通过容器的name,可以查看业务内每个模块的日志。

基于image的发布扩容

在微服务化游戏中,模块与模块之间是高内聚低偶合,模块的版本内容一般都会通过持续集成来构建成一个个镜像(即image),然后以image来交付、部署。同时,游戏版本发布都有一个时间窗,整个发布流程都需要在这个时间窗里完成,否则就会影响用户体验。怎样做到版本的高效发布? 这里有两个关键点:一是基于Kubernetes的发布有效性;一是image下发效率;

Kubernetes在容器image发布这一块的支持已比较稳定,对于无状态的服务,还可以考虑rolling-update方式进行,使游戏服务近乎无缝地平滑升级,即在不停止对外服务的前提下完成应用的更新。

在提高image下发效率方面,我们基于Distribution打造了一个企业级镜像中心,主要涉及到以下几点:

  • Ceph集群提供稳定、强大的后端数据存储。
  • 性能优化:mirror方案与P2P方案,实现快速的下载镜像。同时对于时效性更高的用户需求,还可以实现image预部署方案。
  • 安全方面:不同类型用户不同的权限验证方案。例如公司内部用户会提供安全认证,其它用户提供用户名密码认证。
  • Notification Server实现pull\push日志记录,便于后续分析与审计。

以上便是Kubernetes在微服务化游戏中的一个解决方案,定制的网络与调度方案,为游戏容器的运行提供基础环境;域名服务与负载均衡,解决游戏高可用、弹性伸缩问题;通过性能数据、日志的收集、统计分析,及时发现程序问题与性能瓶颈,保证游戏容器稳定、可持续性运行;最后,基于image的发布扩容,使得游戏部署流程更加标准化以及高效。

Q&A

Q:CPU核绑定,能说下实现的细节吗?

A:在创建容器的时候,通过Kubernetes的resources项指定所需的CPU核数,再由scheduler调度到具体的母机上。我们对kubelet进行了改造,增加了CPU核计算与绑定逻辑,主要有两方面:一是计算母机上空闲的CPU核并分配到当前的容器;另一个是结合NUMA的cache机制,尽可能的把同一个NUMA node的CPU核分配给容器,从而提高性能。

Q:存储方面一笔带过了,文中提到把数据直接写到tendis ,都包含哪些业务数据呢?另外,Tendis的driver 已经开源了么?

A: Tendis是基于RocksDB和Twemproxy的Redis集群方案,提供高效的,可线性扩展,数据落地硬盘的Cache集群服务。和TenDB, TenDB cluster一起是腾讯游戏的Ten系列数据库解决方案。Tendis目前暂时没有开源。Tendis存储了容器的元数据,例如容器的名称,UID,状态信息,性能数据包括了CPU使用率、内存使用情况,TCP连接数,网络流量等。

Q:service loadblance如何实现的能详细介绍下吗?

A: service loadblance由两部分组成,一个是HAProxy程序,一个是service LB程序。其中servie LB程序通过访问k8s master api的watch service\endpoint的变化,得到当前正常服务的容器IP+port信息,然后把这些容器的IP+port绑定到HAProxy的backends,再reload haproxy程序,从而确保HAProxy的backends是最新的

Q:镜像mirror方案与P2P方案能简单介绍下实现技术方案吗?

A:mirror方案如下图,我们会在主要城市部署mirror节点,用于缓存镜像,这样在pull镜像的时候就可以从最近城市来拉取。

P2P方案:其结构如下图:

以上内容根据2017年06月13日晚微信群分享内容整理。分享人黄惠波,腾讯互娱高级工程师。主导腾讯游戏计算资源调度平台的建设工作。目前专注在线游戏容器调度平台的研发工作,包括Kubernetes/Docker的定制化开发以及容器技术在游戏领域的应用实践。 DockOne每周都会组织定向的技术分享,欢迎感兴趣的同学加微信:liyingjiesa,进群参与,您有想听的话题或者想分享的话题都可以给我们留言。

原文发布时间为:2017-06-22

本文作者:DarkForces.

原文标题:DockOne微信分享(一二六):Kubernetes在微服务化游戏中的探索实践

时间: 2024-10-10 14:23:53

DockOne微信分享(一二六):Kubernetes在微服务化游戏中的探索实践的相关文章

DockOne微信分享(六十九):微服务选型之Modern Node.js

本文讲的是DockOne微信分享(六十九):微服务选型之Modern Node.js[编者的话]目前Node.js的发展非常快,大家可能还停留在:Node.js性能很好,Node.js里都是回调,写起来很恶心,Node.js只能做前端工具,Node.js是单线程部署会有问题,以及这样的八卦<uber用go替代Node.js重写了地理位置服务>... 可是真相呢? 在微服务盛行的今天,为什么我们要选用Node.js去构建微服务呢?本次分享将试图从以下2个方面给出答案: 被误解的Node.js:除

DockOne微信分享(六十六): Docker网络方案初探

本文讲的是DockOne微信分享(六十六): Docker网络方案初探[编者的话]这次主要跟大家聊聊Docker的网络方案,首先是现有容器网络方案介绍, 接下来重点讲解Calico的特性及技术点,作为引申和对比再介绍下Contiv的特性,最后给出对比测试结果. 随着容器的火热发展,数人云越来越多的客户对容器网络特性要求也开始越来越高,比如: 一容器一IP: 多主机容器互联: 网络隔离: ACL: 对接SDN等等. 这次主要跟大家聊聊Docker的网络方案,首先是现有容器网络方案介绍, 接下来重点

DockOne微信分享(六十五):公有云上的容器实践分享

本文讲的是DockOne微信分享(六十五):公有云上的容器实践分享[编者的话]本次分享介绍普元基于微服务架构,在公有云上的一次容器实践,包括如何选型,做了哪些技术验证,遇到了哪些问题,如何解决的.分享中还包括对于云平台本身高可靠.高性能.持续发布.服务注册发现等方面的设计方案,以及后续的发展愿景及规划,旨在与大家探讨一些关于Docker.Kubernetes.CoreOS.Hystrix等具体技术的实践经验,同时希望大家能给我们的平台设计提供更好的建议. 大家好,我是普元软件的顾伟,很高兴有机会

DockOne微信分享(六十八):应用容器env化实战

本文讲的是DockOne微信分享(六十八):应用容器env化实战[编者的话]随着Docker技术的火热发展, Docker在代码构建发布中扮演着越来越重要的角色.Docker让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到流行的Linux机器上.Docker非常适用于如下场景: 应用容器的自动化打包和发布: 自动化测试和持续集成.发布: 这次主要和大家聊聊应用容器在配置管理中遇到的问题.首先是介绍现有容器常用的配置文件加载方式,接下来重点介绍数人云组件在自动化打包和发布遇到的

DockOne微信分享(六十四):基于Docker实现DevOps的一些探索

本文讲的是DockOne微信分享(六十四):基于Docker实现DevOps的一些探索[编者的话]本次分享从DevOps介绍:Docker介绍:基于Docker实现DevOps的优势:Docker化DevOps流水线实例分享等四方面展开. DevOps介绍 DevOps(Deveplopment和Operations的简称),中译为开发运维一体化,可定义为是一种过程.方法.文化.运动或实践,主要是为了通过一条高度自动化的流水线来加强开发和其他IT职能部门之间的沟通和协作,加速软件和服务的交付.

DockOne微信分享(六十七):互联网场景下闪存优化测试和应用

本文讲的是DockOne微信分享(六十七):互联网场景下闪存优化测试和应用[编者的话]闪存在这几年存储领域发展非常快,应用也越来越广泛,如何能更好的使用闪存,本次分享讲一些闪存相关的优化和应用. 闪存应用场景 数据库 NoSQL 分布式存储 CDN 公有云存储 综合上面几种场景看,闪存主要适合有比较高的随机IO需求和带宽需求的场景.场景选择上,也是要发挥闪存的长处.目前上面业务中 未来几年发展比较快的会是在公有云存储这一部分.下图就是某厂商云盘对比,可以看到闪存的价格已经很接近机械硬盘了,而单从

DockOne微信分享( 一零二):基于容器的日志管理实践

本文讲的是DockOne微信分享( 一零二):基于容器的日志管理实践[编者的话]业务平台每天产生大量日志数据,为了实现数据分析,需要将生产服务器上的所有日志收集后进行大数据分析处理,Docker提供了日志驱动,然而并不能满足不同场景需求,本次将结合实例分享日志采集.存储以及告警等方面的实践经验. 2013年以来Docker迅速火了起来,它的理念带来了非常大的便利性,不过实际应用中会发现还有监控.日志.网络等问题尚待解决,本文会结合实例分享数人云做容器日志系统的经验. 基于ELK的日志管理系统架构

DockOne微信分享(九十六):爱油科技基于SpringCloud的微服务实践

本文讲的是DockOne微信分享(九十六):爱油科技基于SpringCloud的微服务实践[编者的话]本次分享主要介绍了爱油科技基于Docker和Spring Cloud将整体业务微服务化的一些实践经验,主要包括: 微服务架构的分层和框架选型 服务发现和配置管理 服务集成和服务质量保证 基于领域驱动设计 实施DevOps 从单体应用到微服务 单体应用 对于单体应用来说,优点很多,例如: 小而美,结构简单易于开发实现 部署门槛低,单个Jar包或者网站打包即可部署 可快速实现多实例部署 然而随着业务

DockOne微信分享(一二〇):基于Kubernetes的私有容器云建设实践

本文讲的是DockOne微信分享(一二〇):基于Kubernetes的私有容器云建设实践[编者的话]本次分享将为大家介绍易宝支付私有容器云从0到1的建设之路.包括技术选型.理论基础.基于Kubernetes的容器云和CI/CD落地过程中的挑战和踩过的坑. 建设背景及目标 在Docker技术流行开来之前,保证软件交付的质量和速度对于大多数企业来说都是困难的.业务的复杂性带来了应用的复杂性,面对成千上万的不同应用,运维部门需要时刻应对来自不同应用.不同环境的挑战.特别是在自动化运维程度不高的企业,"