基于 Kubernetes 构建多集群的流水线

x33g5p2x  于2021-09-30 转载在 Kubernetes  
字(4.0k)|赞(0)|评价(0)|浏览(667)

基于Kubefed的多集群管理实践

多集群场景

主要分以下几个方面:

1)高可用低延时:应用部署到不同的集群去做高可用

2)容灾备份:特别是针对于数据库这类的应用 在a集群对外提供服务的同时给b集群做一次备份 这样在发生故障的时候 可以无缝的迁移到另一个集群去

3)业务隔离:尽管kubernetes提供了ns级别的隔离,你可以设置每个ns各自的使用的cpu 内存 甚至可以使用network policy配置不同ns的连通性 有一个更加彻底的物理隔离的环境依然是被需要的,避免业务之间的互相影响

4)避免厂商锁定:混合云场景下,企业希望可以选择多个公有云厂商和私有云方案,避免受限于单一云厂商,降低一定成本。

第三个是应用的异地多活,避免一个region的断电造成业务的不可用情况,实现不把鸡蛋放在同一个篮子。第四个是为了区分开发测试环境,把这些环境部署到不同的集群。最后一个是提高集群的拓展性,突破单一集群的节点上限。

多集群现有的解决方案

其实最简单的方式就是使用多个kubeconfig来分别管理不同的集群,包括其他一些其他产品也是这么做的,但是kubesphere还是想以一种更加cloud native的方式去管理多个集群。于是kubesphere先调研了一些已有的解决方案。

总体来说分为两个方向,第一个是偏向控制层的资源分发,比如k8s社区的federation v1 v2, 现在v1已经被弃用了,一会儿会详细介绍这两个项目。以及argocd/fluxcd ,这类场景是在流水线中实现应用的分发。第二个是致力于实现多集群之间的pod网络网络联通性。

Federation V1

上图是federationv1的架构图,可以看到有额外的apiserver(基于kube-apiserver开发) controller manger ,下面是被管控的集群。

上图是一个replicaset的示例,与普通的rs区别就是多了一些annotation ,里面主要引入了单独的apiserver, 带来了额外的维护成本。我们都知道k8s里一个资源是通过group/version/kind确定的, 但是v1里面gvk绑定导致对不同版本的集群api兼容性很差。

只支持特定的一些资源的联邦

Annotation 让整个resource过于臃肿设计之初未考虑rbac 无法提供跨集群的权限控制

Kubefed(Crd + Controller)

Kubefed 核心是一个基于crd + controller 的设计 ,用户在管理集群创建一个custom resource 定义,这个资源需要被分发到哪些集群以后会有对应的controller 做这个工作。

上图是它的架构图,可以看到 一个crd资源主要由三部分组成 template placement override 通过结合type configuration, 可以支持多个版本的资源,提高了集群之间的版本兼容性,同时在设计之初也考虑到了多集群的服务发现调度等。

上图为联邦资源的示例,例如deployment 在kubefed对应federateddeployment spec里面的template就是原来的deployment对应的yaml ;placement则表示这个deployment需要被下放到哪些集群 ;override可以通过不同的集群设定不同的配置, 例如 deployment的镜像tag 副本数等等。

Kubernetes with Kubefed

这里我们定义了两个概念:host集群指的是装了kubefed的集群,这是所有操作访问的入口,属于control plane;member集群指的是被管控集群 二者通过kubefed实现了联邦。

KubeSphere多集群架构

上图是KubeSphere整个多集群的架构,通过kubefed实现联邦化以后 ,所有的管理操作界面都集中在了左边的host集群上,在多租户的权限这块 也是改造成了crd ,通过Kubefed联邦化把租户相关的crd下放到member集群 。这里可能就会有用人会质疑了,为何不直接在host集群统一做认证授权以后再操作member集群, 这里其实当时在设计的时候也考虑过这种做法 ,并且我们发现rancher也是这么做的 ,但是考虑到host集群作为一个中心化的管理层有挂掉的可能 ,因此把租户这类资源下放到member集群以后 ,依然可以在发生宕机的时候登陆member集群进行业务发布, 提高了平台的灾备能力。

因此对于一个用户这样的资源来说,可以看到在图中host集群和member集群都存在。在一个API请求来到以后,会统一在host集群进行认证 ,通过以后再转发到member集群进行授权 ,对于host集群对于member集群网络不可达的私有场景下 kubefed是没办法做到联邦的,因此我们基于chilsel开源了tower 做了一个隧道。

统一多集群/单集群管理视角

在kubesphere里面一个租户就是一个workspace ,一个租户可以为其分配指定的某些集群 ,也可以限制其cpu和内存的配额 ,一个租户既可以像从前那样创建一个单集群的ns ,也可以在多集群下创建一个联邦的ns。不管是单集群场景还是多集群场景,我们统一了其管理视角 对于用户来说都是一个入口 解决了管理上的难题。

Tower 提供私有云场景下的集群代理能力

前面有提到对于host集群到member集群网络不可达的情况下,目前kubefed还没有办法做到联邦,也就是没办法从host集群推送deployment到member集群。因此 kubesphere基于chisel开源了tower 实现了私有云场景下集群联邦管理 ,tower分为server和agent,用户只需要在私有集群创建一个agent, agent通过server的地址建立一个隧道, server端再为这个隧道代理请求到member集群的apiserver ,再为其分配一个kubeconfig ,就可以实现集群联邦。

多集群下的流水线设计与实现

KubeSphere & Devops

这里先简单介绍一下KubeSphere 与Devops的关系 :Devops自身是KubeSphere可以选择安装的一个组件 ,其中里面集成了Jenkins 以及内置的模板和插件,你可以通过图形化的方式创建一个流水线,并且租户之间也做了隔离。

单集群流水线

我们先来看看单集群下一个传统的流水线流程:首先研发push代码到仓库以后 ,Jenkins会通过webhook出发一次构建 以及push镜像的过程, 最终再通过一些cd插件或者kubectl 把代码库的yaml部署到k8s里去 ,这里我们默认k8s里的一些yaml是与代码放在一起的。

多集群下的Devops改造

前提我们提到 Kubefed里面核心的多集群联邦是通过crd和controller来实现的,而在2.1版本以及之前 KubeSphere则是前端通过后端转发直接调用了Jenkins的API。这种命令式的API肯定是不适合云原生的场景的 ,因此3.0 Devops模块重点改造成了声明式的API ,前端只需要告诉后台它想要什么 ,至于如何实现则完全交给controller去做。

在图片里可以看到 主要crd有三种:分别是devpsproject这个对应k8s的ns  ,凭证这个主要死类似于dockerhub的token以及kubeconfig这类敏感信息 ,然后是pipeline ,前端创建custom resource以后, 这个时候K8s的controller会watch到pipeline 这个资源的创建, 然后对接Jenkins 触发对应的ci/cd。

Devops技术架构

多集群场景下 devops与federation类似,你可以选择性的在host集群或者member集群启用devops,然后在host集群创建一个federatedpipeline 分发到各个环境 独立进行ci/cd互不干扰,也可以在host集群ci ,然后通过cd 把应用部署到各个集群上去。

下面我将介绍两个实际情况中客户遇到的场景:

场景1: 单个流水线部署应用到Dev/Staging/Production环境

第一个是在单个pipeline里面部署应用到开发staging 生产环境,图片里是这个流水线的流程,第一个则是checkout 获取代码 ,然后跑单测,你也可以选择性的集成sonarqube进行代码分析 ,然后对镜像build/push ,然后一开始会把应用部署到测试集群进行测试,验证没问题以后再部署到staging环境, 最后则是生产环境。

这里展示了具体的流水线定义,其中的每一步都可以通过图形化的方式进行编辑 ,这大大降低了用户的Jenkins file的学习成本 ,也让整个平台更加易用。

增加流水线审批环节

前面我们提到部署到测试环境以后是需要验证的 ,不能直接再部署到其他环境 ,因此这里平台增加了审批功能 ,只有管理员点击同意以后 ,才能进行下一步的部署。

场景2: 单个流水线一键部署应用到多个集群

场景2比较适用于应用的多集群部署,前面几步都跟之前比较类似,最大的区别就是最后一步直接通过apply yaml到host集群,这里为了直观我截取了Jenkins file的一部分内容 ,这个yaml本质上是一个federated deployment这样的crd,通过host集群的kubefed 直接下放到member集群,这样就减少了对member集群的权限的依赖。

Roadmap

对接原生的Kubernetes API(Karmada):目前来说Kubefed API还是太多了,每一个资源都需要一个API,尽管我们已经做了一定的屏蔽,但对于二次开发来说还是有一定难度,所以我们还是比较倾向去兼容k8s原生API,因为去年还没有Karmada项目,因此我们只能用KubeFed项目。如何从Kubefed迁移到Karmada是我们比较关心的,也希望后续能够与Karmada社区加强合作。

多集群服务发现
*
多集群之间的调度

相关文章