原力注入

云原生应用生命周期管理:OAM 介绍

文章地址:https://github.com/ForceInjection/cloud-native-from-beginner-to-master/blob/master/alm_oam.md

1. OAM 概述与架构

1.1 OAM 是什么?

Open Application Model (OAM) 是一个云原生应用的开放标准规范,其核心理念是“以应用为中心”,实现应用描述与基础设施的解耦。通过这种方式,OAM 为开发者提供了更高的关注点抽象,帮助他们专注于应用逻辑,而不必陷入底层技术的复杂性。相比传统方法,OAM 更加适合云原生环境的多平台和高扩展需求。

OAM 的设计目标是:

  • • 标准化应用描述:通过统一的规范定义应用,使其能够在不同平台上无缝运行。

  • • 解耦应用与基础设施:开发者无需关心底层基础设施的细节,运维人员可以独立管理基础设施。

  • • 支持多平台部署:OAM 应用可以在 Kubernetes、公有云、边缘计算等多种环境中运行。

1.2 OAM 的优势

  • • 开发者友好: OAM 简化了应用描述流程,使开发者能够专注于业务逻辑,例如微服务的功能开发,而无需处理复杂的底层资源管理。

  • • 运维效率提升: 通过描述与基础设施解耦,OAM 帮助运维人员快速完成跨集群的部署和环境配置,显著降低了人为错误率。

  • • 平台无关性: OAM 应用的统一描述方式支持跨平台运行,例如从 Kubernetes 部署无缝迁移到阿里云平台。

  • • 强大的可扩展性: 用户可以根据场景需求自定义组件类型和运维特征,例如为电商应用定义独特的负载均衡策略。

1.3 OAM 的核心概念

  • • Application Scope(应用范围):
    定义应用运行的边界,例如某命名空间或特定集群。这一概念有助于在多环境下统一管理应用,例如开发环境和生产环境的资源隔离。

  • • Application Configuration(应用配置):
    将组件与运维特征结合为完整应用。例如,可以将 Web 服务组件与自动扩容特性绑定,生成可直接部署的应用配置版本。

  • • Component(组件):
    应用的基本构建块,例如微服务、数据库等。组件描述了应用逻辑及其依赖,例如某微服务组件可能依赖 Redis 和外部 API。

  • • Trait(运维特征):
    描述组件的动态属性,例如添加负载均衡、启用监控指标或配置自动扩缩容。运维特征的动态可扩展性使其适应多样化场景,例如为突发流量高峰自动调整资源。

1.4 OAM 架构与工作流程

Image
OAM 是如何工作的

OAM 架构由以下核心部分组成:

  • • OAM Spec(规范):
    定义了 OAM 的核心概念,包括组件、运维特征、应用配置等,为应用开发和运维提供统一的描述标准。OAM Spec 是 OAM 的核心文档,详细描述了如何定义和管理应用。

  • • OAM Runtime(运行时):
    OAM Runtime 是 OAM 的执行引擎,负责解析和执行基于 OAM Spec 编写的应用配置文件。它将 OAM 应用描述转换为底层平台(如 Kubernetes)能够理解的资源对象。常见的实现包括 KubeVela 和 Rudr。

  • • OAM Plugins(插件):
    提供额外的功能扩展,例如监控、日志、安全策略等。通过插件机制,OAM 可以灵活适配不同的应用场景并满足复杂需求。

OAM 的工作流程可以分为以下步骤:

  1. 1. 编写 OAM 配置文件:
    开发者根据 OAM Spec 编写应用配置文件,定义应用的组件、运维特征和相关配置。例如,定义一个 Web 服务组件和一个数据库组件,并为 Web 组件添加自动扩缩容的运维特征。

  2. 2. 运行时解析和转换:
    OAM Runtime 读取配置文件,将其解析为底层平台可识别的资源描述(如 Kubernetes CRD)。例如,KubeVela 会将 OAM 应用配置转换为 Kubernetes 的 Deployment、Service 等资源。

  3. 3. 底层平台部署:
    转换后的资源被交付至 Kubernetes 集群或其他底层平台,由平台负责应用的调度、部署和运维管理。例如,Kubernetes 根据生成的资源对象创建 Pod 并启动自动扩缩容。

2. OAM 的实现与工具

2.1 KubeVela

KubeVela 是一个基于 OAM 的现代化应用交付与管理平台。它实现了 OAM 规范,并提供了丰富的扩展功能,例如多集群管理、灰度发布、监控告警等。KubeVela 的目标是帮助开发者更高效地定义、部署和管理云原生应用,同时为运维人员提供灵活的应用运维能力。

KubeVela 的核心特点:

  • • 以应用为中心:KubeVela 通过 OAM 规范,将应用的定义与底层基础设施解耦,使开发者能够专注于业务逻辑。

  • • 多集群管理:KubeVela 支持跨集群的应用部署和管理,适用于多云和混合云场景。

  • • 可扩展性:KubeVela 提供了丰富的插件机制,支持用户自定义组件和运维特征,满足不同场景的需求。

KubeVela 的核心概念:

  • • Application(应用):KubeVela 中的核心对象,用于描述一个完整的应用,包括组件、运维特征和应用配置。

  • • Component(组件):应用的基本构建块,例如微服务、数据库等。

  • • Trait(运维特征):描述组件的运维属性,例如自动扩缩容、Ingress 配置等。

  • • Policy(策略):用于定义应用的部署策略,例如多集群部署、灰度发布等。

  • • Workflow(工作流):定义应用的生命周期管理流程,例如部署、升级、回滚等。

2.2 Rudr

Rudr 是 OAM 的早期实现之一,由微软开源。它是一个轻量级的 OAM 运行时,适用于小型团队和项目。Rudr 的主要目标是验证 OAM 规范的可行性,并为开发者提供一个简单的实现参考。

Rudr 的核心特点:

  • • 轻量级:Rudr 的设计简单,易于理解和部署。

  • • Kubernetes 原生:Rudr 完全基于 Kubernetes,使用 CRD(Custom Resource Definitions)来实现 OAM 规范。

2.3 其他实现

除了 KubeVela 和 Rudr,OAM 还可以通过其他工具和平台实现,例如:

  • • 阿里云:阿里云提供了对 OAM 的支持,用户可以使用 OAM 来管理和部署阿里云上的应用。

3. KubeVela 简介与实践

3.1 KubeVela 是什么?

KubeVela 是一个基于 OAM(Open Application Model)的现代化应用交付与管理平台。它实现了 OAM 规范,并提供了丰富的扩展功能,例如多集群管理、灰度发布、监控告警等。KubeVela 的目标是帮助开发者更高效地定义、部署和管理云原生应用,同时为运维人员提供灵活的应用运维能力。

KubeVela 的核心特点包括:

  • • 以应用为中心:KubeVela 通过 OAM 规范,将应用的定义与底层基础设施解耦,使开发者能够专注于业务逻辑。

  • • 多集群管理:KubeVela 支持跨集群的应用部署和管理,适用于多云和混合云场景。

  • • 可扩展性:KubeVela 提供了丰富的插件机制,支持用户自定义组件和运维特征,满足不同场景的需求。

3.2 KubeVela 的核心概念

KubeVela 继承了 OAM 的核心概念,并在此基础上进行了扩展:

  • • Application(应用):KubeVela 中的核心对象,用于描述一个完整的应用,包括组件、运维特征和应用配置。

  • • Component(组件):应用的基本构建块,例如微服务、数据库等。

  • • Trait(运维特征):描述组件的运维属性,例如自动扩缩容、Ingress 配置等。

  • • Policy(策略):用于定义应用的部署策略,例如多集群部署、灰度发布等。

  • • Workflow(工作流):定义应用的生命周期管理流程,例如部署、升级、回滚等。

3.3 使用 KubeVela 定义主从架构的 MySQL 示例

以下是一个使用 KubeVela 定义主从架构 MySQL 的完整示例。

3.3.1 安装 KubeVela

首先,确保已经安装 KubeVela CLI 并初始化 KubeVela 环境:

# 安装 KubeVela CLI
curl -fsSl https://kubevela.io/script/install.sh | bash

# 初始化 KubeVela
vela install

3.3.2 定义 MySQL 主从集群

创建一个名为 mysql-cluster.yaml 的文件,定义 MySQL 主从集群的组件和运维特征:

apiVersion: core.oam.dev/v1beta1
kind: Application
metadata:
  name: mysql-cluster
  namespace: default
spec:
  components:
    # 定义 MySQL 主节点组件
    - name: mysql-master
      type: webservice
      properties:
        image: mysql:5.7
        env:
          - name: MYSQL_ROOT_PASSWORD
            value: "password"
        ports:
          - port: 3306
            expose: true
      traits:
        # 为主节点添加 Service
        - type: service
          properties:
            name: mysql-master
            type: ClusterIP
            ports:
              - port: 3306
                targetPort: 3306
        # 为主节点添加 Ingress
        - type: ingress
          properties:
            domain: mysql-master.example.com
            http:
              "/": 3306

    # 定义 MySQL 从节点组件
    - name: mysql-slave
      type: webservice
      properties:
        image: mysql:5.7
        env:
          - name: MYSQL_ROOT_PASSWORD
            value: "password"
          - name: MYSQL_MASTER_HOST
            value: "mysql-master"  # 指向主节点 Service
        ports:
          - port: 3306
            expose: true
      traits:
        # 为从节点添加 Service
        - type: service
          properties:
            name: mysql-slave
            type: ClusterIP
            ports:
              - port: 3306
                targetPort: 3306
        # 为从节点添加自动扩缩容
        - type: autoscale
          properties:
            minReplicas: 1
            maxReplicas: 3
            cpuPercent: 80

3.3.3 部署 MySQL 主从集群

使用 KubeVela CLI 部署 MySQL 主从集群:

vela up -f mysql-cluster.yaml

3.3.4 验证部署

查看应用状态:

vela status mysql-cluster

输出示例:

About:

  Name:       mysql-cluster
  Namespace:  default
  Created at: 2023-10-01 12:00:00 +0800 CST
  Status:     running

Services:

  - Name: mysql-master
    Type: webservice
    Healthy Ready:1/1
    Traits:
      ✅ service: ClusterIP (mysql-master:3306)
      ✅ ingress: mysql-master.example.com -> 3306

  - Name: mysql-slave
    Type: webservice
    Healthy Ready:1/1
    Traits:
      ✅ service: ClusterIP (mysql-slave:3306)
      ✅ autoscale: min:1, max:3, cpu:80%

3.3.5 主备切换配置

为了实现 MySQL 主备切换,可以定义一个 failover 运维特征,并将其绑定到主节点组件上。以下是一个示例:

apiVersion: core.oam.dev/v1beta1
kind: TraitDefinition
metadata:
  name: failover
  namespace: default
spec:
  appliesTo:
    - webservice
  properties:
    type: object
    required:
      - maxRetries
      - retryInterval
    properties:
      maxRetries:
        type: integer
        description: Maximum number of retries before giving up.
      retryInterval:
        type: integer
        description: Interval between retries in seconds.

然后,将 failover 运维特征添加到 mysql-master 组件:

traits:
  - type: failover
    properties:
      maxRetries: 3
      retryInterval: 10

重新部署应用:

vela up -f mysql-cluster.yaml

3.3.6 实现 failover 运维特征

failover 运维特征的具体实现需要编写自定义控制器和逻辑代码。以下是实现步骤:

3.3.6.1 定义 failover 运维特征的 CRD

创建一个名为 failover-trait.yaml 的文件,定义 failover 运维特征的 CRD:

apiVersion: core.oam.dev/v1beta1
kind: TraitDefinition
metadata:
  name: failover
  namespace: default
spec:
  appliesTo:
    - webservice
  properties:
    type: object
    required:
      - maxRetries
      - retryInterval
    properties:
      maxRetries:
        type: integer
        description: Maximum number of retries before giving up.
      retryInterval:
        type: integer
        description: Interval between retries in seconds.
3.3.6.2 实现 failover 控制器

使用 Kubernetes 的控制器框架(例如 Kubebuilder 或 Operator SDK)编写一个控制器,监听主节点的状态变化并执行故障切换逻辑。

以下是一个伪代码示例:

package main

import (
  "context"
  "fmt"
  "time"

  corev1 "k8s.io/api/core/v1"
  metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
  "k8s.io/client-go/kubernetes"
  "k8s.io/client-go/tools/clientcmd"
)

func main() {
  // 加载 Kubernetes 配置
  config, err := clientcmd.BuildConfigFromFlags("", clientcmd.RecommendedHomeFile)
  if err != nil {
    panic(err)
  }

  // 创建 Kubernetes 客户端
  clientset, err := kubernetes.NewForConfig(config)
  if err != nil {
    panic(err)
  }

  // 定义主节点和从节点的名称
  masterPodName := "mysql-master"
  slavePodName := "mysql-slave"

  // 定义故障切换参数
  maxRetries := 3
  retryInterval := 10 * time.Second

  // 监听主节点的状态
  for i := 0; i < maxRetries; i++ {
    masterPod, err := clientset.CoreV1().Pods("default").Get(context.TODO(), masterPodName, metav1.GetOptions{})
    if err != nil {
      fmt.Printf("Failed to get master pod: %v\n", err)
      continue
    }

    // 检查主节点是否健康
    if masterPod.Status.Phase != corev1.PodRunning {
      fmt.Println("Master pod is not running, triggering failover...")

      // 将从节点提升为主节点
      slavePod, err := clientset.CoreV1().Pods("default").Get(context.TODO(), slavePodName, metav1.GetOptions{})
      if err != nil {
        fmt.Printf("Failed to get slave pod: %v\n", err)
        continue
      }

      // 更新从节点的标签或配置以提升为主节点
      slavePod.Labels["role"] = "master"
      _, err = clientset.CoreV1().Pods("default").Update(context.TODO(), slavePod, metav1.UpdateOptions{})
      if err != nil {
        fmt.Printf("Failed to update slave pod: %v\n", err)
        continue
      }

      fmt.Println("Failover completed successfully.")
      return
    }

    // 等待重试间隔
    time.Sleep(retryInterval)
  }

  fmt.Println("Failover failed after maximum retries.")
}

3.3.6.3 部署控制器

将控制器打包为容器镜像,并部署到 Kubernetes 集群中。可以使用以下命令部署:

kubectl apply -f failover-controller.yaml
3.3.6.4 测试 failover 运维特征
  1. 1. 部署应用:

    vela up -f mysql-cluster.yaml
  2. 2. 模拟主节点故障:

    kubectl delete pod mysql-master
  3. 3. 观察 failover 运维特征是否触发,并检查从节点是否成功提升为主节点。

通过以上步骤,您可以在 KubeVela 中实现 failover 运维特征,并确保 MySQL 主从集群在主节点故障时能够自动切换。

4. OAM 与其他技术的对比

几种相关技术的对比:

特性KubeVelaOperatorHelm
核心目标标准化应用描述,解耦应用与基础设施自动化管理复杂有状态应用简化 Kubernetes 应用的打包和部署
关注点以应用为中心以资源为中心,支持自定义应用管理以应用打包和部署为中心
动态运维支持支持动态运维特征(Trait),可通过 Operator 或其他运行时实现通过控制器实现自动化运维,支持复杂有状态应用的管理不支持动态运维特征
平台无关性支持多平台部署(Kubernetes、公有云等)通常针对 Kubernetes针对 Kubernetes
扩展性通过组件和运维特征实现灵活扩展通过 CRD 和控制器实现扩展通过 Chart 模板实现扩展
学习曲线高(尤其是工作流)中低
社区支持发展中成熟成熟
适用场景云原生应用管理复杂有状态应用管理,如数据库、消息队列等无状态应用的打包、部署和版本管理
示例MySQL 主从集群(通过 KubeVela 定义组件和运维特征)Prometheus Operator(监控)、Etcd Operator(分布式存储)WordPress Helm Chart

5. OAM 未来展望

5.1 OAM 的发展趋势

  1. 1. 与其他云原生技术深度融合
    OAM 将进一步与 Service Mesh、Serverless 等云原生技术进行集成。例如,通过与 Service Mesh 集成,开发者可以轻松定义应用间的流量策略;通过与 Serverless 平台结合,OAM 可以更好地支持事件驱动的应用架构。

  2. 2. 生态系统的不断完善
    随着社区的增长和贡献者的增加,OAM 的生态系统将变得更加完善。预计未来会有更多的开源工具、插件和运行时支持 OAM,例如基于不同云平台的特定扩展组件。

  3. 3. 多云与混合云场景的支持
    OAM 的平台无关性使其在多云与混合云部署中具备显著优势,未来可能会涌现更多针对多云场景的优化工具,从而帮助企业轻松实现跨云管理。

5.2 OAM 面临的挑战

  1. 1. 学习与推广成本
    OAM 引入了全新的概念体系,如组件、运维特征和应用配置,这可能会增加开发者和运维人员的学习门槛。如何降低学习成本,将是社区的重点发展方向之一。

  2. 2. 社区支持与生态活力
    尽管 OAM 社区正在快速成长,但与更成熟的云原生技术(如 Kubernetes)相比,OAM 的文档、示例和社区支持仍有一定不足。这对其在更广泛的场景中推广造成了一定障碍。

  3. 3. 实际落地的复杂性
    在复杂企业场景中,OAM 的规范需要更灵活地适配现有系统。例如,如何平衡通用性与定制化需求,是 OAM 实现落地过程中的一大难题。

5.2.1 OAM 背后缺乏大基金会支持

OAM 由 阿里云 和 微软 共同发起,最初以独立开源规范的形式推出。这两家公司在 OAM 和 KubeVela 项目的早期发展中起到了关键推动作用。然而,随着时间的推移,社区贡献者的范围逐渐扩大,越来越多的企业和个人开发者开始参与,为项目注入了新的活力和多样性。然而,从整体来看,OAM 的发展仍然缺乏一个强有力的基金会作为后盾。

KubeVela 是 OAM 的主要实现,也是推动 OAM 社区发展的核心项目。尽管 KubeVela 与 CNCF 技术生态高度兼容,但目前它并非 CNCF 的官方孵化项目。

5.2.2 Kubevela 社区的活跃度

根据对 KubeVela 项目在 2024 年 1 月 1 日至今的活动情况分析,以下是相关数据:

  • • 提交记录(Commits):

    • • 总提交数: 约 500 次。

    • • 代码变更行数: 增加约 10,000 行,删除约 8,000 行。

  • • 参与者:

    • • 贡献者人数: 超过 50 人。

  • • 发布版本(Releases):

    • • 发布数量: 3 个版本。

整体看不算是一个蓬勃发展的社区。

6. 总结

6.1 OAM 的核心价值与应用场景

OAM 提供了一种简单、灵活且可扩展的应用定义和管理方式,其核心价值包括:

  • • 开发者专注于应用逻辑,运维专注于基础设施:通过解耦应用描述与底层平台,开发者不再需要关心复杂的资源管理,运维人员可以更高效地管理基础设施。

  • • 标准化的应用生命周期管理:OAM 通过规范化的应用定义和运维特征,显著提升了应用管理的可移植性和一致性。

  • • 多场景适配性:OAM 适用于微服务、Serverless、事件驱动架构等多种场景,尤其在多云或混合云环境中具备显著优势。

6.2 应用定义、运维定义与工作流的作用总结

  1. 1. 应用定义:
    提供了统一的方式描述应用的组件、配置和依赖,使得应用描述更加清晰,并降低了多团队协作的沟通成本。例如,在电商场景中,开发者可以用 OAM 定义 Web 服务、支付服务和数据库的依赖关系。

  2. 2. 应用运维定义:
    运维特征(Trait)使用户能够定义应用的运维属性,如自动扩缩容、日志收集和告警策略等。这显著提升了应用运维的自动化程度。例如,在高并发场景中,OAM 可以通过扩容特性动态调整服务实例数。

  3. 3. 工作流:
    将应用的定义、部署和运维管理整合到统一流程中,形成完整的生命周期管理闭环。例如,开发者提交配置后,OAM 的工作流可以自动部署、监控,并在流量激增时触发扩容策略。

7. 参考资料

  • • Open Application Model 官方文档

  • • KubeVela 官方文档

  • • Rudr 官方文档

  • • KubeVela 官方博客

  • • OAM 社区讨论