注:本文已发布超过一年,请注意您所使用工具的相关版本是否适用
在之前的文章当中我们讨论的都是在单个 kubernetes 集群内,我们该如何设计并实现一个 operator,但是随着我们应用的规模的上升或者是因为公司内部的各种其他原因(例如权限等)我们不得不采用多个 kubernetes 集群才能满足我们的需求,这时候,我们的 operator 该如何适应多集群这个场景呢?
当然目前在多集群的场景下也有了很多解决方案,例如 ClusterNet、Karmada 等等,但是可能由于权限或者并不想要那么重的解决方案等原因,我们有的时候还是会有 operator 直接监听多个集群的资源的需求。
https://github.com/admiraltyio/multicluster-controller 这个项目使用 controller-runtime 实现了多集群的 controller 但是已经 3 年没更新过了
在 controller-runtime 的库下 2019 年就有人提出了类似的需求 Support for controllers spanning across clusters
2020 年有人在 controller-runtime 提出了 POC,将 cluster 从 manager 中提取了出来,利用 controller-runtime 监听多集群的资源变得简单了起来
tips: 后续示例项目代码放到了 multi-cluster-operator 中
首先我们先设定一下需求和环境
之前的文章 Kind: 如何快速搭建本地 K8s 开发环境 已经比较详细的介绍了如何使用 kind 搭建集群,这里我就直接使用命令创建了
1 | |
主要逻辑见下方,其实就是在 TestReconciler 中加入了子集群的 client
1 | |
需要注意的是我们在 main.go 初始化的时候,需要使用 mgr.Add() 把子集群加入到 manager 中,这个在后面监听资源变化的时候会用到
1 | |
上面我们演示了如何像在多个集群创建资源,这个其实很简单,其实不需要 controller-runtime 也能实现,就像上面的这个例子,往往创建并不能解决问题,我们还需要跟进所创建资源的状态。
假设现在有这么一个需求:只要有一个 job 完成,那么我们就认为这个 CRD 的状态应该是 finished,该如何实现?
在 Move cluster-specific code out of the manager 的设计文档中有下面的一个简单示例,但是我觉得这个例子不是很好,因为实在是太简单粗暴了一些
Reconcile 方法内,由于并部只带这个资源是来自哪个集群,只能先试一下第一个集群,然后再试第二个集群所以我们可以在 **Reconcile 时候分辨是来自那个集群的事件么?**
1 | |
实现的难点在于我们如何区分事件的源集群,在 Reconcile 的参数 ctrl.Request 中只有 namespace 和 name 两个字段,所以我们想要区分集群也只有从这两个字段中想办法
1 | |
显然 namespace 相比 name 来说更适合一些,所以我们可以给 namespace 加一个规则,namespace 字段实际的值变成 ${cluster}/${namespace},所以我们需要在事件的入口加上集群的标志,然后再在 Reconcile 中根据集群使用对应的 client 进行操作即可
首先在监听的时候,我们可以自定义一个 handler,将集群名字注入进去
1 | |
然后我们在 Reconcile 内获取正确的集群 client 进行操作即可
1 | |
最后我们给出的实现只是一个最简单的 demo,在实际的项目中最好再对代码做一些抽象,我们可以把多集群的相关操作都抽象出来放在一起,这样会更容易维护
pkg/clusterx 这里有一个简单的示例,篇幅关系就不在文章内赘述了
注:本文已发布超过一年,请注意您所使用工具的相关版本是否适用
在之前的文章当中我们讨论的都是在单个 kubernetes 集群内,我们该如何设计并实现一个 operator,但是随着我们应用的规模的上升或者是因为公司内部的各种其他原因(例如权限等)我们不得不采用多个 kubernetes 集群才能满足我们的需求,这时候,我们的 operator 该如何适应多集群这个场景呢?
当然目前在多集群的场景下也有了很多解决方案,例如 ClusterNet、Karmada 等等,但是可能由于权限或者并不想要那么重的解决方案等原因,我们有的时候还是会有 operator 直接监听多个集群的资源的需求。
https://github.com/admiraltyio/multicluster-controller 这个项目使用 controller-runtime 实现了多集群的 controller 但是已经 3 年没更新过了
在 controller-runtime 的库下 2019 年就有人提出了类似的需求 Support for controllers spanning across clusters
2020 年有人在 controller-runtime 提出了 POC,将 cluster 从 manager 中提取了出来,利用 controller-runtime 监听多集群的资源变得简单了起来
tips: 后续示例项目代码放到了 multi-cluster-operator 中
首先我们先设定一下需求和环境
之前的文章 Kind: 如何快速搭建本地 K8s 开发环境 已经比较详细的介绍了如何使用 kind 搭建集群,这里我就直接使用命令创建了
1 | |
主要逻辑见下方,其实就是在 TestReconciler 中加入了子集群的 client
1 | |
需要注意的是我们在 main.go 初始化的时候,需要使用 mgr.Add() 把子集群加入到 manager 中,这个在后面监听资源变化的时候会用到
1 | |
上面我们演示了如何像在多个集群创建资源,这个其实很简单,其实不需要 controller-runtime 也能实现,就像上面的这个例子,往往创建并不能解决问题,我们还需要跟进所创建资源的状态。
假设现在有这么一个需求:只要有一个 job 完成,那么我们就认为这个 CRD 的状态应该是 finished,该如何实现?
在 Move cluster-specific code out of the manager 的设计文档中有下面的一个简单示例,但是我觉得这个例子不是很好,因为实在是太简单粗暴了一些
Reconcile 方法内,由于并部只带这个资源是来自哪个集群,只能先试一下第一个集群,然后再试第二个集群所以我们可以在 **Reconcile 时候分辨是来自那个集群的事件么?**
1 | |
实现的难点在于我们如何区分事件的源集群,在 Reconcile 的参数 ctrl.Request 中只有 namespace 和 name 两个字段,所以我们想要区分集群也只有从这两个字段中想办法
1 | |
显然 namespace 相比 name 来说更适合一些,所以我们可以给 namespace 加一个规则,namespace 字段实际的值变成 ${cluster}/${namespace},所以我们需要在事件的入口加上集群的标志,然后再在 Reconcile 中根据集群使用对应的 client 进行操作即可
首先在监听的时候,我们可以自定义一个 handler,将集群名字注入进去
1 | |
然后我们在 Reconcile 内获取正确的集群 client 进行操作即可
1 | |
最后我们给出的实现只是一个最简单的 demo,在实际的项目中最好再对代码做一些抽象,我们可以把多集群的相关操作都抽象出来放在一起,这样会更容易维护
pkg/clusterx 这里有一个简单的示例,篇幅关系就不在文章内赘述了