我是LEE,老李,一个在IT行业摸爬滚打16年的技术老兵。
今天跟大家分享一个腾讯开源的多K8S多集群和应用管理软件 - Clusternet (Cluster Internet)。 我们先从一些场景和问题开始了解起这个软件到底有什么用。
- 越来越多的 k8s 集群需要管理和维护,不同版本的 k8s api 可能存在比较明显的差异(比如1.18.x与1.22.x就存在明显的差异)
- 需要对不同的 k8s 执行下发应用任务(可以跟依赖一定的策略),或者删除应用配置的任务。
- 需要批量操作不同的 k8s 环境中若干不同应用配置变更的任务。
- 公有云产品与自建不同的 k8s 环境融合。
以上几点足够一个容器管理平台小组足够头痛了,当然我也是不例外,看了各种各样的 Open Cluster Management(OCM)软件平台,发现了他们基本类似,总是让我有点点“鸡肋”的感觉,为啥呢? 归总下来如下:
- 依赖 k8s Federation 方案,绝大多数基本都是 Federation 的优化或者专门定制版本。
- 没有太多方案亮点,对需要轻量级且能直接解决问题的人没有太多帮助。
- 概念笼统,因为技术而做的软件工程,架构复杂,k8s东西就够多了,还要再搞东西。
- 现在很多公司都已部署 Istio 和 Knative,主要发布的 OCM 没有考虑相关的兼容。
- 应用和部署工程量大,容易对底层架构产生较多影响,小伙伴需要重新学习,容易形成反感。
那么结合我选择系统的背景如下:
- 最好不要让我搞一个全新的架构,没有时间,我需要快速上手。
- 架构简单,利于快速定位问题和排障。
- 利于其他团队对架构理解,能够争取更多的赞同票。
- 足够的轻量,能够兼容多种k8s环境和版本,不挑食。
在 github 找了一大圈总算找到了还算过得去的 OCM 软件 Clusternet,它就两个组件 clusternet-hub 和 clusternet-agent 组成,没有其他依赖的外部组件。 clusternet-hub 与 clusternet-agent 之间关系就是注册、订阅、推送的关系,逻辑非常简单。
Clusternet 开源项目简介
Clusternet ( Cluster Internet ) 是腾讯云开源的兼具多集群管理和跨集群应用编排的云原生项目,让管控多集群就像上网一样简单。
无论你的 Kubernetes 集群是运行在公有云、私有云还是混合云上,都拥有一致的管理/访问体验,利用 K8S API 集中部署和协调多集群的应用程序和服务。Clusternet 采用 Addon 插件的方式,方便用户一键安装、运维及集成,轻松地管理数以百万计的 Kubernetes 集群,让云计算像 Internet一样无所不在,自由便捷。
以 Clusternet 项目为基础实现多云多集群管理平台,为用户提供跨云、跨集群、跨 region/zone 的分布式容器服务,将更好的满足多种场景需求。
- 多租户
- 高可用与容灾
- 多云多中心
- 服务边缘计算
Clusternet 架构介绍
Clusternet 面向未来云原生多云多集群而设计,领先的架构支持用户以全局视角统一管理各个集群及应用,轻松地将用户业务发布至全球,一次发布处处运行。
Clusternet 遵循云原生理念,所有管理组件通过 Addon 的方式灵活部署在 Kubernetes 集群中,实现 K8S-on-K8S 集群管理集群。
对比社区其他多集群管理方案,无需学习和维护复杂的平台软件和系统,也无需维护额外的控制面的组件及 etcd。Clusternet 集群管理完全复用已有的 Kubernetes 集群及端口,通过 AA (Aggregated APIServer)的方式进行工作,方便灵活扩展,大大减轻运维复杂度和资源消耗。
Aggregated APIServer 的参考资料:
https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/apiserver-aggregation/
-
clusternet-hub
组件 clusternet-hub 部署和运行在父集群中,通过 AA(Aggregated APIServer)的方式进行工作。
主要负责:- 批准各个子集群的注册请求,并为其创建专属的资源,如命名空间(namespace)、服务帐户(ServiceAccount)和 RBAC 规则等。
- 维护父集群跟各个子集群的长链接。
- 提供 Kubernetes 风格 的 REST API 用于访问各个子集群,尤其是对于边缘子集群的访问,同时还支持子集群的服务互访。
- 支持多集群的应用分发及治理。
-
clusternet-agent
组件 clusternet-agent 部署在各个子集群中。
主要负责:- 将当前集群自动注册到父集群中作为子集群。
- 建立与父集群的 TCP 全双工的 websocket 安全隧道。支持通过 FeatureGate “SocketConnection” 选择是否要建立安全隧道。如果关闭该 特性的话,即意味着父集群可以通过直连的方式访问子集群。
- 上报集群的心跳信息,包括 Kubernetes 版本、平台信息healthz/readyz/livez 健康状态、集群容量、节点状态等。
从上面的介绍看出 clusternet-hub 就是一个“监工”,负责汇总集群信息,以及资源规则创建和变更动作的下发。而 clusternet-agent 是一个代理,代理从上游 k8s 到下游各个 k8s 的控制指令,同时周期性上报当前集群的运行信息。Clusternet-hub 可向自身所在集群发布应用,该种方式最大化的利用父集群资源,并可以快速地扩展用户现有的集群,轻松具备管理海量公有云、私有云。
Clusternet 应用发布介绍
Clusternet 支持向不同集群分发和管理各种应用资源,包括原生 Kubernetes 各类资源(Deployment/StatefulSet/ConfigMap/Secret 等)、各类 CRD 资源,以及 HelmChart 应用等等。
下图是 Clusternet 的多集群应用分发模型,其中绿色的模块是需要用户去创建的,紫色的模块是 Clusternet 内部做流转的资源对象。Clusternet 提供了 kubectl 插件,可以通过 “kubectl clusternet apply” 命令来创建资源。
Clusternet 资源分发模型采用松耦合的设计,用户无须更改或重新编写已有的资源对象,仅需要额外定义分发策略 (Subscription)和差异化配置(Localization/Globalization)即可实现多集群的应用分发。
兼容任意资源类型
完全兼容 K8s 的标准资源,比如Deployment、StatefulSet、DaemonSet,以及各种自定义的 CRD 等,无需学习复杂的多集群资源的 CRD 定义。Subscription
定义希望安装到集群中的资源。对于每个匹配的集群,将在其专属的命名空间中创建相应的Base对象。Localization 和 Globalization
在多集群应用分发的时,还可以利用 Localization 和 Globalization 差异化策略用于不同集群间的差异化配置。其中Localization描述 namespace-scoped (命名空间作用域)的差异化配置策略,Globalization 描述 cluster-scoped (集群作用域) 的差异化配置策略,两者均支持按照 Priority(优先级)进行管理和配置。这个特性对于面向多集群的蓝绿发布、金丝雀发布、版本升级等场景非常灵活实用。Base 和 Description
Clusternet 会自动生成 Base 和 Description 对象,用以观察和跟踪各个应用资源的分发情况。其中 Description 是 Base 对象通过 Localization 和 Globalization 差异化配置渲染后得到的对象,即描述着最终要部署到目标子集群的对象定义。
[Tips] Localization 和 Globalization 这个概念简单也复杂,Globalization是全局概念,Localization 是基于 namespace 概念。 Localization 可以覆盖 Globalization 配置。
下面我们看看官方给我们举得栗子,看看香不香...
查询对应 k8s 集群的 ClusterID
$ kubectl get clsrr
NAME CLUSTER ID STATUS AGE
clusternet-dc91021d-2361-4f6d-a404-7c33b9e01118 dc91021d-2361-4f6d-a404-7c33b9e01118 Approved 3d6h
部署应用的配置文件
# examples/applications/subscription.yaml
apiVersion: apps.clusternet.io/v1alpha1
kind: Subscription
metadata:
name: app-demo
namespace: default
spec:
subscribers: # 认为发布到哪个集群,是用亲和性来理解?????
- clusterAffinity:
matchLabels:
clusters.clusternet.io/cluster-id: dc91021d-2361-4f6d-a404-7c33b9e01118 # 这个目标集群的Id
feeds: # 在这里定义对应的需要发布的资源
- apiVersion: apps.clusternet.io/v1alpha1
kind: HelmChart
name: mysql
namespace: default
- apiVersion: v1
kind: Namespace
name: foo
- apiVersion: apps/v1
kind: Service
name: my-nginx-svc
namespace: foo
- apiVersion: apps/v1
kind: Deployment
name: my-nginx
namespace: foo
在上游 k8s 集群执行终端上执行命令:
$ kubectl clusternet apply -f examples/applications/
helmchart.apps.clusternet.io/mysql created
namespace/foo created
deployment.apps/my-nginx created
service/my-nginx-svc created
subscription.apps.clusternet.io/app-demo created
$ # or
$ # kubectl-clusternet apply -f examples/applications/
$ kubectl clusternet get mcls -A
NAMESPACE NAME CLUSTER ID SYNC MODE KUBERNETES READYZ AGE
clusternet-5l82l clusternet-cluster-hx455 dc91021d-2361-4f6d-a404-7c33b9e01118 Dual v1.21.0 true 5d22h
$ # list Descriptions
$ kubectl clusternet get desc -A
NAMESPACE NAME DEPLOYER STATUS AGE
clusternet-5l82l app-demo-generic Generic Success 2m55s
clusternet-5l82l app-demo-helm Helm Success 2m55s
$ kubectl describe desc -n clusternet-5l82l app-demo-generic
...
Status:
Phase: Success
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal SuccessfullyDeployed 2m55s clusternet-hub Description clusternet-5l82l/app-demo-generic is deployed successfully
$ # list Helm Release
$ # hr is an alias for HelmRelease
$ kubectl clusternet get hr -n clusternet-5l82l
NAME CHART VERSION REPO STATUS AGE
helm-demo-mysql mysql 8.6.2 https://charts.bitnami.com/bitnami deployed 2m55s
Clusternet 核心技术介绍
通过对 github 上项目 Readme 研究,官方提供的学习资料并不多。官方提供主要资料主要满足的是介绍性质,没有实际性质的参考手册。希望官方以后能够逐步补齐,那个时候我也可以看时间继续跟进。
上图为各个模块主要调用关系,逻辑比较简单,各位看官一看就知道模块之间扭转过程。
重点介绍下 clusternet-agent 的功能
clusternet-agent 运行在下游的 k8s 集群内,负责注册当前集群到上游控制集群,同时建立命令通道,以及周期上报当前集群的工作状态。
clusternet-agent 的工作模式主要3种工作模式,由启动参数 --cluster-sync-mode 来配置
-
Push
上游控制 k8s 集群中的所有资源更改将被 clusternet-hub 自动同步、推送和应用到下游运行了clusternet-agent 的 k8s 集群。 -
Pull
下游 k8s 集群通过 clusternet-agent 监视、同步并应用从上游控制 k8s 集群到下游 k8s 集群的所有资源更改。 -
Dual
结合了推和拉模式。也是官方推荐的模式,需要配合 FeatureGate AppPusher 一起使用。
FeatureGate AppPusher 和 clusternet-agent 是运行在同一个集群内,要使用 AppPusher 的主要原因,我想官方是为了考虑数据传输与同步的问题。
我们都知道一个管理平台发送控制指令到不同被控制的端点时,会受到各种不可控的因素,导致变更这个动作不能 100% 传送的被控制端点,或者这些端点不一定能够正确的执行这些任务。那么推送下来的任务就是一个“事务性”的任务,也就是说只有100%成功或者100%的失败。加入我们碰到了不可控,导致需要任务执行所有端点不能100%全部完成任务,怎么办????
- 如果出现之间的传输异常,AppPusher 提供了一种方式来帮助切换Push模式到Pull模式。
- 如果 AppPusher 工作异常或者禁用,同时 clusternet-agent 的 cluster-sync-mode 是 Push 和 Dual,那么应用从上游控制 k8s 集群到下游 k8s 集群的变更的任务将失败,下游 k8s 集群的 cluster-sync-mode 将转换成 Pull 模式。
Clusternet 局限与不足
通过这段时间对 Clusternet 的功能调研和简单的使用,我简单总结了一些从我实用角度感观。
- 就是解决了跨集群发布应用的问题,其他跟应用相关的资源配额,应用网络限制,服务网格兼容等等都没有做,所以简单是他的核心优点也是他最可怕的缺点。
- 使用了 k8s 的原生技术AA,这个是非常的好的,但是又多了一个新概念 Extend K8S Api Server,需要小伙伴们继续花时间啃,至少目前还没有看到很多项目用了这个技术。
- 就此时文章发布的时间,目前正式 github release 的版本是 0.3,还有很多时间需要继续迭代,看了下项目的热度也比较有限。
- 不是CNCF 项目,所以以后能不能成为标准和以及是不是以后社区主流解决方案,需要继续观察。
- 如果你希望使用多租户的功能,怕是要你失望了,我没有看到特别强大的针对 tenant 和 project 相关联的处理的地方。
参考文档
安装Aggregated APIServer
https://kubernetes.io/docs/tasks/extend-kubernetes/setup-extension-api-server/
配置Aggregated APIServer
https://kubernetes.io/docs/tasks/extend-kubernetes/configure-aggregation-layer/