Kubevela 目前处于 1.1 版本。通常,我们认为 1.x 的版本是相对稳定的,可以尝试引入生产。在不断地跟踪和学习过程中,也感受到 Kubevela 的一些好的地方,这是一篇小结性的文档。
1. Kubevela 能解决什么问题
- 面向平台开发者
需要区分几个角色: 开发、运维、运维开发。开发面向的是业务需求,运维面向的是业务稳定,运维开发面向的是效率。运维开发提供各种各样的工具,打通开发和运维之间的壁垒,既要快速满足业务上线。又要保障业务稳定。
Kubevela 对开发和运维并没有太大吸引力,却能让运维开发耳目一新。因为,Kubevela 能显著提升团队的平台水平,直达主流梯队。
- 应用生命周期的管理
Kubevela 提供了管理应用生命周期的解决方案,应用的定义 applications,部署 appdeployments ,版本管理 applicationrevisions,回滚 approllouts,灰度 traits、approllouts。利用这些 CRD 对象,能够覆盖很大一部分业务需求。
- 应用负载和特性的组件化
Component 提供的是负载的定义,比如 Deployment、CloneSet。Trait 提供的是特征的定义,比如 Ingress、Istio。通过这两种抽象,Kubevela 允许平台的开发者能够组装、定制适合自己业务的平台。
而 Workflow 提供的编排能力,给集成各种云原生组件增添了更多可能,甚至能延展到 CICD 领域。
2. 多集群下应用面临的挑战
- 统一的视角
在面向应用的平台上,切换集群是一个非常糟糕的用户体验。我们需要的不是在每个集群上部署一套管理服务,然后通过修改数据源,查看不同集群上的数据。
我们应该以应用为中心,集群只是应用的一个属性,而不能将应用归属于某个集群。统一视角就是希望能够提供给用户一个 UI,包含完整的应用描述、所在运行时、实时服务画像等信息。
- 应用的定义
世界上,没有两个平台团队对应用的定义是一样的。
一个应用应该包含哪些属性,哪些特征,对哪些字段进行哪些限制,很多的细节需要推敲和考虑。当然你也可以选择背负技术债务,将问题延后解决,快速交付几个版本。但却也是道阻且长,越来越难。
每个团队在定义应用时,都会附带一些业务属性。自救是不可能的,繁杂的业务需求不会给平台的开发者喘息之机。
因此,OAM 的出现是个机会,有机会统一应用生命周期管理 (ALM)。虽前有 Kubernetes Applications 死在了沙滩,但 Kubevela 犹如黑夜星光,给人无限希望。
- 分批发布
分批发布有两个维度,单个集群中的多副本应用,多个集群中的同一个应用。
单个集群上的多副本,不会一次性更新,而是需要分批发布。这个过程,称之为 rollout,是一个逐步放量的过程。
多个集群或者多个区域的服务,在更新时,也需要观察时间,而不能一把就 show hand。
3. AppDeployment 下的多集群应用
这里主要是以 AppDeployment 作为主要对象,将应用在多个集群上进行发布。
- 在主集群上添加多个子集群
需要在同一个 kubeconfig 配置多个集群的 context,然后按照官方文档操作即可。这里添加了两个集群 prod-cluster-1 和 prod-cluster-2 。下面是查看集群的命令:
1 2 3 4 5 | kubectl get clusters.core.oam.dev NAME AGE prod-cluster-1 57d prod-cluster-2 57d |
---|
- 定义 Application 应用
需要提前定义 components 和 traits,下面是应用的定义:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | apiVersion: core.oam.dev/v1beta1 kind: Application metadata: name: cluster-test-app-cloneset namespace: default annotations: app.oam.dev/revision-only: "true" spec: components: - name: helloworld-cloneset type: cloneset properties: image: oamdev/helloworld-python:v1 env: - name: "TARGET" value: "KubeVela-v1" port: 8080 traits: - type: expose-nodeport properties: ports: - protocol: "TCP" port: 80 |
---|
由于有 app.oam.dev/revision-only: "true"
的 Annotations,因此相关的资源并不会被创建。我们在此只是定义应用,并不需要创建相应的负载。
- 修改应用的版本,产生不同的应用版本
为了更加逼近生产环境,我们修改上面 Application 的参数,比如:环境变量、镜像版本等,产生不同的应用版本。
1 2 3 4 5 6 | kubectl get applicationrevisions.core.oam.dev NAME AGE cluster-test-app-v1 57d cluster-test-app-v2 57d cluster-test-app-v3 57d |
---|
最终,分发到各个集群上的应用版本,由此产生。这些版本,大致相同而有细微差异,类似日常应用更新。
- AppDeployment 多集群分发应用
AppDeployment 提供了一个更加贴近用户对应用理解的视角。应用不仅包含的是对应用的定义,还有对运行时的选择。这里将 cluster-test-app-v1 部署到 prod-cluster-1 集群,设置 3 个副本数量;而将 cluster-test-app-v2 部署到 prod-cluster-2 集群,设置 4 个副本数量。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | apiVersion: core.oam.dev/v1beta1 kind: AppDeployment metadata: name: cross-cluster-app namespace: default spec: appRevisions: - revisionName: cluster-test-app-v1 placement: - clusterSelector: labels: env: stage name: prod-cluster-1 distribution: replicas: 3 - revisionName: cluster-test-app-v2 placement: - clusterSelector: labels: env: production name: prod-cluster-2 distribution: replicas: 4 |
---|
4 Workflow 下的多集群应用
Workflow 是 Kubevela 近期版本新增的一个特性,在这里主要用来生成 OCM 需要的跨集群资源对象。
4.1 配置 Open Cluster Management (OCM)
- 使用 vela 命令安装 Open Cluster Management
1 | vela addon enable ocm-cluster-manager |
---|
- 在主集群上添加多个子集群
需要在同一个 kubeconfig 配置多个集群的 context。在 dev1 集群上,添加 dev2 集群的 kubeconfig。
1 2 3 4 5 | kubectl config get-contexts CURRENT NAME CLUSTER AUTHINFO NAMESPACE * dev1-context dev1.cluster.local dev1-kubernetes-admin dev2-context dev2.cluster.local dev2-kubernetes-admin |
---|
- 配置环境变量
使用 dev1(主集群) 管理 dev2(子集群) 。在主集群上,执行命令:
1 2 3 4 | export HUB_CLUSTER_NAME=dev1 export MANAGED_CLUSTER_NAME=dev2 export CTX_HUB_CLUSTER=dev1-context export CTX_MANAGED_CLUSTER=dev2-context |
---|
- 查找添加子集群的 Token
在主集群上,执行命令:
1 2 3 | clusteradm get token xxxxxxxxxxxxxx |
---|
取出其中的 token 值,Base64 反解码,可以得到一个有效的 hub-token 值。
- 添加子集群
这里的 hub-apiserver 就是主集群的 kube-apiserver 的访问地址。在主集群上,执行命令:
1 | clusteradm join --context ${CTX_MANAGED_CLUSTER} --hub-token xxxxxxxxxxxxxx --hub-apiserver https://1.1.1.1:6443 --cluster-name ${MANAGED_CLUSTER_NAME} |
---|
- 接受新的集群添加请求
在主集群上,执行命令:
1 | clusteradm accept --clusters dev2 |
---|
- 查看被管理的集群
在主集群上,执行命令:
1 2 3 4 | kubectl get managedcluster NAME HUB ACCEPTED MANAGED CLUSTER URLS JOINED AVAILABLE AGE dev2 true https://dev1.chenshaowen.com:6443 True True 3m38s |
---|
- 在被管理的集群上安装 Kubevela rollout
在子集群上,执行命令:
代码语言:javascript复制helm repo add kubevela https://charts.kubevela.net/core
helm install vela-rollout --create-namespace -n vela-system kubevela/vela-rollout
4.2 新建 WorkflowStepDefinition 描述跨集群资源
在主集群使用 Workflow 将跨集群的资源定义在 WorkflowStepDefinition 中。下面是需要用到的资源之一:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | apiVersion: core.oam.dev/v1beta1 kind: WorkflowStepDefinition metadata: name: dispatch-traits namespace: vela-system spec: schematic: cue: template: | import ("vela/op") comp: op.#Load & { component: parameter.component } apply: op.#Apply & { value: { apiVersion: "work.open-cluster-management.io/v1" kind: "ManifestWork" metadata: { namespace: parameter.cluster name: parameter.component "-traits" } spec: { workload: manifests : comp.value.auxiliaries } } } parameter: { component: string cluster: string } |
---|
其中 ManifestWork 定义了分发到某个集群的配置和资源信息。这里只定义了 dispatch-traits,相应的我们还需要定义 dispatch-comp-rev。
分发资源的过程可以理解为,将待分发的资源打包成主集群上的 ManifestWork 对象,通过 OCM 分发到子集群的 AppliedManifestworks 对象,然后由子集群提取资源进行创建。
4.3 创建应用进行分发
这里使用 Application 在主集群 dev1 上定义一个应用,分发到子集群 dev2 上。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | apiVersion: core.oam.dev/v1beta1 kind: Application metadata: name: workflow-rollout-demo namespace: default spec: components: - name: nginx-server externalRevision: nginx-server-v1 type: webservice properties: image: nginx:1.20.0 port: 80 traits: - type: rollout properties: targetRevision: nginx-server-v1 targetSize: 2 rolloutBatches: - replicas: 1 - replicas: 1 workflow: steps: - name: dispatch-comp-rev-v1 type: dispatch-comp-rev properties: compRev: nginx-server-v1 cluster: dev2 - name: dispatchRollout type: dispatch-traits properties: component: nginx-server cluster: dev2 |
---|
在 OCM 多集群应用的场景下,子集群需要部署 Kubevela rollout 组件。因此,Kubevela 能够更精细地控制子集群 rollout 过程,比如滚动过程中每个批次的比例和数量等。
4.4 可能会碰到的问题
- OCM 在子集群创建资源时报错
E0905 14:36:23.461052 1 base_controller.go:270] "ManifestWorkAgent" controller failed to sync "nginx-server-traits", err: rollouts.standard.oam.dev "nginx-server" is forbidden: User "system:serviceaccount:open-cluster-management-agent:klusterlet-work-sa" cannot get resource "rollouts" in API group "standard.oam.dev" in the namespace "default"
提示是权限不够,在子集群上,直接给 klusterlet-work-sa 绑定了一个 admin 权限。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | kind: ClusterRoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: admin-ocm annotations: rbac.authorization.kubernetes.io/autoupdate: "true" roleRef: kind: ClusterRole name: cluster-admin apiGroup: rbac.authorization.k8s.io subjects: - kind: ServiceAccount name: klusterlet-work-sa namespace: open-cluster-management-agent |
---|
5. 总结
本篇主要讨论的是 Kubevela 在多集群下的应用,主要内容如下:
- 多集群下的应用,不同于单集群,不能简单地切换数据源实现,其对交互设计有更高的要求。多集群应用平台需要有统一的视角,查看应用在多集群下的服务画像,以应用为中心,将集群当做属性,分清主次。
- AppDeployment 是一个很好的抽象,也能给平台设计一些启发,还能看到一些 KubeFed 的身影。AppDeployment 是以用户视角呈现的多集群应用,但目前对 Workload 的处理粒度太大,面向的是整个 Application,也就是全量删除、更新、创建 Workload。如果用于生产,还需要配合 rollout 进行更新。
- 借助 Workflow 集成 OCM 下的 Kubevela 多集群应用,更具扩展性,后续也可以换成其他多集群组件,比如 Karmada。利用 OCM 的分发能力,加上子集群上的 Kubevela rollout 组件,我们可以实现分批发布、滚动更新。
实际上,多集群下的应用,不仅仅需要考虑的是对应用描述的分发,更重要的还有负载的滚动更新、资源的统一分配、应用的智能调度、应用的自动扩缩容、服务的状态画像等。Kubevela 针对的是看得见的应用,但支撑起整个应用平台还需要更多底层组件。
6. 参考
- https://open-cluster-management.io/getting-started/quick-start/#install-clusteradm-cli-tool
- https://www.chenshaowen.com/blog/using-kubefed-to-distribute-tekton-resource-cross-cluster.html
- https://www.cnblogs.com/tencent-cloud-native/p/15136879.html
原文 https://www.chenshaowen.com/blog/multi-cluster-applications-under-kubevela.html