Kubevela 下的多集群应用

开源镜像容器GPU

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 领域。

  1. 多集群下应用面临的挑战

  • 统一的视角

在面向应用的平台上,切换集群是一个非常糟糕的用户体验。我们需要的不是在每个集群上部署一套管理服务,然后通过修改数据源,查看不同集群上的数据。

我们应该以应用为中心,集群只是应用的一个属性,而不能将应用归属于某个集群。统一视角就是希望能够提供给用户一个 UI,包含完整的应用描述、所在运行时、实时服务画像等信息。

  • 应用的定义

世界上,没有两个平台团队对应用的定义是一样的。

一个应用应该包含哪些属性,哪些特征,对哪些字段进行哪些限制,很多的细节需要推敲和考虑。当然你也可以选择背负技术债务,将问题延后解决,快速交付几个版本。但却也是道阻且长,越来越难。

每个团队在定义应用时,都会附带一些业务属性。自救是不可能的,繁杂的业务需求不会给平台的开发者喘息之机。

因此,OAM 的出现是个机会,有机会统一应用生命周期管理 (ALM)。虽前有 Kubernetes Applications 死在了沙滩,但 Kubevela 犹如黑夜星光,给人无限希望。

  • 分批发布

分批发布有两个维度,单个集群中的多副本应用,多个集群中的同一个应用。

单个集群上的多副本,不会一次性更新,而是需要分批发布。这个过程,称之为 rollout,是一个逐步放量的过程。

多个集群或者多个区域的服务,在更新时,也需要观察时间,而不能一把就 show hand。

  1. AppDeployment 下的多集群应用

这里主要是以 AppDeployment 作为主要对象,将应用在多个集群上进行发布。

  • 在主集群上添加多个子集群

需要在同一个 kubeconfig 配置多个集群的 context,然后按照官方文档操作即可。这里添加了两个集群 prod-cluster-1 和 prod-cluster-2 。下面是查看集群的命令:


        
          
kubectl get clusters.core.oam.dev  
  
NAME             AGE  
prod-cluster-1   57d  
prod-cluster-2   57d  

      
  • 定义 Application 应用

需要提前定义 components 和 traits,下面是应用的定义:


        
          
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 的参数,比如:环境变量、镜像版本等,产生不同的应用版本。


        
          
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 个副本数量。


        
          
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

        
          
vela addon enable ocm-cluster-manager  

      
  • 在主集群上添加多个子集群

需要在同一个 kubeconfig 配置多个集群的 context。在 dev1 集群上,添加 dev2 集群的 kubeconfig。


        
          
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(子集群) 。在主集群上,执行命令:


        
          
export HUB_CLUSTER_NAME=dev1  
export MANAGED_CLUSTER_NAME=dev2  
export CTX_HUB_CLUSTER=dev1-context  
export CTX_MANAGED_CLUSTER=dev2-context  

      
  • 查找添加子集群的 Token

在主集群上,执行命令:


        
          
clusteradm get token  
  
xxxxxxxxxxxxxx  

      

取出其中的 token 值,Base64 反解码,可以得到一个有效的 hub-token 值。

  • 添加子集群

这里的 hub-apiserver 就是主集群的 kube-apiserver 的访问地址。在主集群上,执行命令:


        
          
clusteradm join --context ${CTX\_MANAGED\_CLUSTER} --hub-token xxxxxxxxxxxxxx --hub-apiserver https://1.1.1.1:6443 --cluster-name ${MANAGED\_CLUSTER\_NAME}  

      
  • 接受新的集群添加请求

在主集群上,执行命令:


        
          
clusteradm accept --clusters dev2  

      
  • 查看被管理的集群

在主集群上,执行命令:


        
          
kubectl get managedcluster  
  
NAME   HUB ACCEPTED   MANAGED CLUSTER URLS                JOINED   AVAILABLE   AGE  
dev2   true           https://dev1.chenshaowen.com:6443   True     True        3m38s  

      
  • 在被管理的集群上安装 Kubevela rollout

在子集群上,执行命令:


        
          
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 中。下面是需要用到的资源之一:


        
          
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 上。


        
          
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 权限。


        
          
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  

      
  1. 总结

本篇主要讨论的是 Kubevela 在多集群下的应用,主要内容如下:

  • 多集群下的应用,不同于单集群,不能简单地切换数据源实现,其对交互设计有更高的要求。多集群应用平台需要有统一的视角,查看应用在多集群下的服务画像,以应用为中心,将集群当做属性,分清主次。
  • AppDeployment 是一个很好的抽象,也能给平台设计一些启发,还能看到一些 KubeFed 的身影。AppDeployment 是以用户视角呈现的多集群应用,但目前对 Workload 的处理粒度太大,面向的是整个 Application,也就是全量删除、更新、创建 Workload。如果用于生产,还需要配合 rollout 进行更新。
  • 借助 Workflow 集成 OCM 下的 Kubevela 多集群应用,更具扩展性,后续也可以换成其他多集群组件,比如 Karmada。利用 OCM 的分发能力,加上子集群上的 Kubevela rollout 组件,我们可以实现分批发布、滚动更新。

实际上,多集群下的应用,不仅仅需要考虑的是对应用描述的分发,更重要的还有负载的滚动更新、资源的统一分配、应用的智能调度、应用的自动扩缩容、服务的状态画像等。Kubevela 针对的是看得见的应用,但支撑起整个应用平台还需要更多底层组件。

  1. 参考

0
0
0
0
关于作者
关于作者

文章

0

获赞

0

收藏

0

相关资源
字节跳动客户端性能优化最佳实践
在用户日益增长、需求不断迭代的背景下,如何保证 APP 发布的稳定性和用户良好的使用体验?本次分享将结合字节跳动内部应用的实践案例,介绍应用性能优化的更多方向,以及 APM 团队对应用性能监控建设的探索和思考。
相关产品
评论
未登录
看完啦,登录分享一下感受吧~
暂无评论