草庐IT

T3 出行云原生容器化平台实践

kubesphere 2023-03-28 原文

公司简介

T3 出行是南京领行科技股份有限公司打造的智慧出行生态平台,由中国第一汽车集团有限公司、东风汽车集团有限公司、重庆长安汽车股份有限公司发起,联合腾讯、阿里巴巴等互联网企业共同投资打造。公司以“成为最值得信赖的出行服务企业”为品牌愿景,“科技引领 愉悦出行”为使命,倡导“可信,更自由”的出行理念,致力为用户提供“可信、安全、品质”出行服务,让用户感受更加自由的出行体验。

背景介绍

随着 T3 出行业务体量持续上涨,服务的稳定性需要系统化的保障。容器化改造将提供标准化的环境,基于应用运行环境实现完整的版本控制,消除开发到生产的环境差异,保证应用生命周期内环境一致性和标准化。同时容器化环境可以让服务共享计算资源,并通过混部方式来提高整体计算资源的利用率,降低企业应用的基础设施运营成本。

容器化之前 T3 出行是传统的虚拟机模式,所有业务都部署在虚拟机上,全体产研通过堡垒机、传统的监控系统、日志平台等进行日常应用的运维。而一旦服务容器化开始,我们必然需要一个云原生的容器化管理平台,让 T3 出行全体产研从传统的虚拟机操作模式转变为云原生操作模式。同时,之前日常的应用运维模式需要使用多个平台进行协作,产研定位一个应用性能问题往往需要来回切换多个平台。所以我们希望容器化平台可以集成周边的配套,如日志查看、监控系统,让产研尽量在一个平台内完成日常运维的工作;也可以作为平台工程的一部分,让产研在开发环境可以拥有足够的权限创建、更新、删除非基线环境,而无需了解底层架构知识,通过自助化的环境能力可以让研发并行开发测试,最终让业务可以快速、高效增长。

选型说明

我们的选型思路基本上是根据功能、UI 体验、社区活跃度、学习成本这 4 点来的。首先必须要满足我们对容器平台的需求(在背景介绍中已经描述),其次是社区活跃度以及生态,最后是 UI 体验,在 UI 体验中包含了用户的学习成本,我们希望以低学习成本的方式让 T3 出行的研发更够快速上手容器平台,同时也具备运维视角,如此就既满足了研发的应用视角纬度,也满足了运维的集群视角维度。
我们在选型期间对比了 Rancher、Openshift、KubeSphere,最终选择了 KubeSphere 作为 T3 出行云原生容器平台。KubeSphere 定位是以应用为中心的容器平台,提供简单易用的操作界面,帮助用户屏蔽掉那些技术细节,一定程度上降低了学习成本。同时 Kubesphere 具备优秀的容器管理能力、多集群支持能力、多租户能力、天然集成的可观测能力等,让我们可以在一个平台上满足了日常运维所需。

实践过程

多集群统一管理

KubeSphere 多集群中角色分为主集群和成员集群,由 1 个主集群和多个成员集群组成,与我们原先的集群规划不谋而合。主集群我们作为成员集群的控制面存在,通过主集群下发不同的管理策略给到成员集群。对于成员集群而言,我们根据不同的环境、不同的租户性质也会划分到不同集群。如根据环境区分,我们会有开发集群、测试集群、预生产集群、生产集群;而根据租户性质,我们会有一些对接三方业务的集群。

项目管理

在很多传统的 DevOps 平台中,并没有与项目进行联动,服务往往只是关联了组织架构,当组织架构变动,服务的元信息就不准确了。而且,对于一个项目来说,经常会有跨部门合作的情况,而业务发布的视角却是在各自的部门下的,项目成员无法在一个视图下看到项目的所有业务,在项目的协作过程中自然就增加了许多沟通成本。而 KubeSphere 就是基于项目维度对容器服务进行管理的,在 KubeSphere 中一个项目对应的就是 Kubernetes 一个 Namespace,租户之间的视图是隔离的,日常只需要在自己的项目视图下进行协作即可。

我们的 DevOps 平台正在逐步的往项目集成方向发展,目前我们是按照业务域进行统一管理,一个业务域代表了一个 KubeSphere 中的一个项目,业务域下会有多个相关的业务服务,无论组织架构如何变换,业务域始终不变。

多租户管理

KubeSphere 中的多租户管理是基于企业空间维度来完成的,企业空间是用来管理项目、DevOps 项目、应用模板和应用仓库的一种逻辑单元。我们可以在企业空间中控制资源访问权限,也可以安全地在团队内部分享资源。企业空间可以关联多个集群中的多个项目,并对企业空间中的成员进行权限管理,引用 KubeSphere 官方配图便于大家直观的理解:

我们是以业务域为项目维度进行统一管理,那么企业空间作为 KubeSphere 最小的租户管理单元自然是被我们按照业务域进行划分。所以 T3 当下的多租户管理逻辑就是:企业空间(业务域)→ 集群(开发、测试等)→ 项目(业务域)。同时在企业空间中,我们也抽象出了部门管理纬度,使用 KubeSphere 的部门管理,便于我们给不同的人员赋予不同集群(环境)操作权限。

内部 DevOps 平台与 KubeSphere 的结合

T3 容器化之前已有一套 DevOps 平台,这套 DevOps 平台交付的制品是部署在虚拟机上的。而容器化项目开展的前置条件就是必须支持容器发布,如果让现有的 DevOps 平台改造成云原生化的 DevOps 平台工作量巨大,项目风险不可控,所以我们最终选择了 DevOps 平台与 KubeSphere 的结合。内部 DevOps 平台新增容器发布功能,只进行容器服务的发布和 Pod 副本数的扩缩容操作,由 KubeSphere 对发布后的容器进行接管,给研发人员展示容器发布后的应用状态,让研发人员自助式的与容器进行交互。

可以说,KubeSphere 接管了 T3 容器化发布的后半场,研发人员执行发布后,便会来到 KubeSphere 上进行与容器的交互操作,如日志查看、监控查看、进入容器控制台、查看容器事件等。

效果

  • T3 出行的业务已经全面容器化,所有的集群已被 KubeSphere 纳管,产研的日常应用维护工作都需要基于 KubeSphere 平台进行开展。
  • 得益于 KubeSphere 的以应用为中心的设计,帮用户屏蔽了底层技术细节,目前 T3 出行全体产研都可以自助式的使用 KubeSphere 进行日常的工作,也让 T3 产研从传统的应用维护模式成功的转向了云原生应用维护模式。
  • KubeSphere 集成了监控、日志、事件,提高了 T3 产研日常的人效。
  • KubeSphere 集群级别的可观测,是我们提升集群资源利用率的参考依据。

未来规划

  1. 内部 DevOps 平台与 KubeSphere 深度融合,给 T3 产研带来更好的体验。
  2. 基于 T3 的业务场景采用更多优秀的开源项目,与社区共同成长。
  3. FinOps 与 Serverless 的探索与实践。

本文由博客一文多发平台 OpenWrite 发布!

有关T3 出行云原生容器化平台实践的更多相关文章

  1. ruby-on-rails - 使用 Ruby on Rails 进行自动化测试 - 最佳实践 - 2

    很好奇,就使用ruby​​onrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提

  2. 叮咚买菜基于 Apache Doris 统一 OLAP 引擎的应用实践 - 2

    导读:随着叮咚买菜业务的发展,不同的业务场景对数据分析提出了不同的需求,他们希望引入一款实时OLAP数据库,构建一个灵活的多维实时查询和分析的平台,统一数据的接入和查询方案,解决各业务线对数据高效实时查询和精细化运营的需求。经过调研选型,最终引入ApacheDoris作为最终的OLAP分析引擎,Doris作为核心的OLAP引擎支持复杂地分析操作、提供多维的数据视图,在叮咚买菜数十个业务场景中广泛应用。作者|叮咚买菜资深数据工程师韩青叮咚买菜创立于2017年5月,是一家专注美好食物的创业公司。叮咚买菜专注吃的事业,为满足更多人“想吃什么”而努力,通过美好食材的供应、美好滋味的开发以及美食品牌的孵

  3. ruby-on-rails - Rails 中同一个类的多个关联的最佳实践? - 2

    我认为我的问题最好用一个例子来描述。假设我有一个名为“Thing”的简单模型,它有一些简单数据类型的属性。像...Thing-foo:string-goo:string-bar:int这并不难。数据库表将包含具有这三个属性的三列,我可以使用@thing.foo或@thing.bar之类的东西访问它们。但我要解决的问题是当“foo”或“goo”不再包含在简单数据类型中时会发生什么?假设foo和goo代表相同类型的对象。也就是说,它们都是“Whazit”的实例,只是数据不同。所以现在事情可能看起来像这样......Thing-bar:int但是现在有一个新的模型叫做“Whazit”,看起来

  4. ruby-on-rails - 向 Rails 3 添加 Ruby 扩展方法的最佳实践? - 2

    我有一个要在我的Rails3项目中使用的数组扩展方法。它应该住在哪里?我有一个应用程序/类,我最初把它放在(array_extensions.rb)中,在我的config/application.rb中我加载路径:config.autoload_paths+=%W(#{Rails.root}/应用程序/类)。但是,当我转到railsconsole时,未加载扩展。是否有一个预定义的位置可以放置我的Rails3扩展方法?或者,一种预先定义的方式来添加它们?我知道Rails有自己的数组扩展方法。我应该将我的添加到active_support/core_ext/array/conversion

  5. Ruby 最佳实践 : working with classes - 2

    参见下面的示例,我想最好使用第二种方法,但第一种也可以。哪种方法最好,使用另一种的后果是什么?classTestdefstartp"started"endtest=Test.newtest.startendclassTest2defstartp"started"endendtest2=Test2.newtest2.start 最佳答案 我肯定会说第二种变体更有意义。第一个不会导致错误,但对象实例化完全过时且毫无意义。外部变量在类的范围内不可见:var="string"classAvar=A.newendputsvar#=>strin

  6. ruby - 存储外部 API 的密码 - 最佳实践 - 2

    如果我构建了一个应用程序来访问来自Gmail、Twitter和Facebook的一些数据,并且我希望用户只需输入一次他们的身份验证信息,并且在几天或几周后重置,那会怎样是在Ruby中动态执行此操作的最佳方法吗?我看到很多人只是拥有他们客户/用户凭证的配置文件,如下所示:gmail_account:username:myClientpassword:myClientsPassword这看起来a)非常不安全,b)如果我想为成千上万的用户存储此类信息,它就无法工作。推荐的方法是什么?我希望能够在这些服务之上构建一个界面,因此每次用户进行交易时都必须输入凭据是不可行的。

  7. 【云原生】SpringCloud-Spring Boot Starter使用测试 - 2

    目录SpringBootStarter是什么?以前传统的做法使用SpringBootStarter之后starter的理念:starter的实现: 创建SpringBootStarter步骤在idea新建一个starter项目、直接执行下一步即可生成项目。 在xml中加入如下配置文件:创建proterties类来保存配置信息创建业务类:创建AutoConfiguration测试如下:SpringBootStarter是什么? SpringBootStarter是在SpringBoot组件中被提出来的一种概念、简化了很多烦琐的配置、通过引入各种SpringBootStarter包可以快速搭建出一

  8. ruby-on-rails - 使用设计身份验证的 API 访问 - 最佳实践? - 2

    我正在使用Devise在Rails应用程序中,并希望通过API公开一些模型数据,但应该像应用程序一样限制对API的访问。$curlhttp://myapp.com/api/v1/sales/7.json{"error":"Youneedtosigninorsignupbeforecontinuing."}很明显。在这种情况下是否有访问API的最佳实践?我更喜欢一步验证+获取数据,但这只是为了让客户的工作更轻松。他们将使用JQuery在客户端提取数据。感谢您提供任何信息!凡妮莎 最佳答案 我建议您按照以下帖子中的选项2:使用APIke

  9. ruby-on-rails - 在多个页面上使用相同表单的 Rails 最佳实践 - 2

    我正在开发一个Rails2.3.1网站。在整个网站中,我需要一个用于在各种页面(主页、创建帖子页面、帖子列表页面、评论列表页面等)上创建帖子的表单——只要说这个表单需要在由各种Controller)。这些页面中的每一个都显示在相应的Controller/操作中检索到的各种其他信息。例如,主页列出了最新的10篇文章、从数据库中提取的内容等。因此,我已将帖子创建表单移动到它自己的部分中,并将该部分包含在所有必要的页面中。请注意,部分POST中的表单到/questions(路由到PostsController::create——这是默认的Rails行为)。我遇到的问题是当Posts表单没有正

  10. ruby-on-rails - Rails 'service objects' 最佳实践 - 类方法或实例化 - 2

    我正在按照我一直在研究的研讨会实现“服务对象”,我正在构建一个redditAPI应用程序。我需要对象返回一些东西,所以我不能只执行初始化程序中的所有内容。我有这两个选择:选项1:类需要实例化classSubListFromUserdefuser_subscribed_subs(client)@client=client@subreddits=sort_subs_by_name(user_subs_from_reddit)endprivatedefsort_subs_by_name(subreddits)subreddits.sort_by{|sr|sr[:name].downcase}

随机推荐