一、缘起:从“脚本炼丹”到寻找分布式云原生解法

三年前,我在团队里接手了一套典型的“云原生混合体”:

  • 两家公有云(一个主云,一个备用云),都跑着各自托管 Kubernetes;
  • 内部机房里有几套自建集群,版本不一,网络拓扑也不一样;
  • 工厂、门店等边缘场景陆续上了 K3s / KubeEdge;
  • 监控用了一套 Prometheus + Grafana,自定义脚本同步指标;
  • 发布用了多种 CI/CD:部分是 Jenkins,部分是 GitLab CI,还有少数靠“人肉 kubectl apply”。

所有组件单拎出来都不算差,放在一起就是四个字:难以为继

最突出的几个痛点:

  1. 多集群运维效率低

    • 每加一个集群,就要复制一套监控、一套日志、一套策略;
    • 各集群的 CRD、插件版本经常不一致,排障时很难“快速对齐状态”。
  2. 多云发布与回滚缺乏统一控制

    • 金丝雀、蓝绿发布都是各团队自己在 Ingress / Istio YAML 里“手搓”;
    • 没有统一的 Rollout 抽象,跨云发布几乎全靠 wiki + 口口相传。
  3. GitOps 体系割裂

    • 有的业务用 ArgoCD,有的用 Flux,还有的就纯粹靠 CI 脚本推配置;
    • 多云多集群场景下缺少一个统一的“舰队视图”。

在这个背景下,我第一次在社区看到 Kurator:

“Kurator 是一个开源的分布式云原生平台,帮助用户构建和管理自己的分布式云原生基础设施,支持多云、多集群、云边协同。”

更吸引我的是它站在主流开源技术栈之上:Kubernetes、Istio、Prometheus、FluxCD、KubeEdge、Volcano、Karmada、Kyverno 等,把这些“零件”通过 Cluster Operator + Fleet Manager 串成了一套“分布式云原生控制平面”。

当时我的想法很直接:如果这套东西真能跑起来,我至少可以少写一半脚本。
于是,一场从“使用者”走向“共建者”的 Kurator 之旅就这么开启了。

如下是Kurator的相关架构流程图,可参考:

二、第一阶段:作为普通用户的 Kurator 初体验与踩坑

2.1 在实验环境拉起 Kurator:从 CLI 到 Fleet Manager

按照官方文档,Kurator 的推荐安装路径是:

  1. 在“宿主集群”安装 Kurator CLI;
  2. 部署 Cluster Operator,实现集群生命周期管理;
  3. 部署 Fleet Manager,将多集群纳入 Fleet 管理;
  4. 通过插件启用统一应用分发、统一监控、统一策略、统一 Rollout 等能力。

我在本地准备了一个 kind 集群作为宿主,部署步骤大致如下(以 Linux 为例):

# 1. 下载 Kurator CLI(版本号按实际为准)
curl -LO https://github.com/kurator-dev/kurator/releases/download/v0.6.0/kurator-0.6.0-linux-amd64.tar.gz

# 2. 安装到 PATH
sudo tar -zxvf kurator-0.6.0-linux-amd64.tar.gz -C /usr/local/bin/

# 3. 校验版本
kurator version

第一次踩坑:
安装完直接敲 kuratorcommand not found,最后发现是 /usr/local/bin 没在 PATH 里。
解决办法很简单,把下面加到 ~/.bashrcsource ~/.bashrc

export PATH=/usr/local/bin:$PATH

然后用 Helm 安装 Cluster Operator 与 Fleet Manager(仓库以文档为准):

helm repo add kurator https://kurator.dev/charts
helm repo update

# 安装 Cluster Operator
helm install kurator-cluster-operator kurator/cluster-operator \
  -n kurator-system --create-namespace

# 安装 Fleet Manager
helm install kurator-fleet-manager kurator/fleet-manager \
  -n kurator-system

第二个坑:
Helm 安装完成后立刻去创建 Kurator 自定义资源,经常遇到 no matches for kind "Cluster"no matches for kind "Fleet"
实际上是 CRD 还没完全注册好。后来养成习惯:安装后先用

kubectl get crd | grep kurator

确认 CRD 就绪,再继续。

2.2 第一次纳管已有集群:AttachedCluster 的“惊喜”

Kurator 不强迫你重建所有集群,而是提供了 AttachedCluster 将已有的 Kubernetes 直接纳入管理。

例如,我有一个托管在公有云 A 的生产集群 prod-ap-a,只需要准备它的 kubeconfig 并写成 Secret:

kubectl create namespace kurator-fleet

kubectl create secret generic prod-ap-a-kubeconfig \
  -n kurator-fleet \
  --from-file=config=/path/to/prod-ap-a.kubeconfig

然后定义 AttachedCluster:

apiVersion: cluster.kurator.dev/v1alpha1
kind: AttachedCluster
metadata:
  name: prod-ap-a
  namespace: kurator-fleet
spec:
  kubeconfig:
    name: prod-ap-a-kubeconfig
    key: config
kubectl apply -f attachedcluster-prod-ap-a.yaml

这样,这个原本“各玩各的”的生产集群,就进入了 Kurator 的视野。
当时给我最大的感受是:Kurator 真的是“站在现有资产之上”,而不是推倒重来。

2.3 初次把集群组成“舰队”:我的第一个 Fleet

在宿主集群上创建完几个 AttachedCluster 之后,我按文档定义了第一个 Fleet:

apiVersion: fleet.kurator.dev/v1alpha1
kind: Fleet
metadata:
  name: fleet-ap-prod
  namespace: kurator-fleet
spec:
  clusters:
    - name: prod-ap-a
      kind: AttachedCluster
    - name: prod-ap-b
      kind: AttachedCluster
  plugin:
    metric:
      thanos:
        objectStoreConfig:
          secretName: thanos-oss-config
    policy:
      kyverno:
        podSecurity:
          standard: restricted
          validationFailureAction: Enforce

这一刻的主观体验非常明显:

  • 以前我脑子里对多集群的认知是“一个个散落的集群”;
  • 现在变成了“业务域 = 一个 Fleet”,其中有哪些集群、启用了哪些监控与策略,一眼就能看清。

从“使用者视角”看,这个抽象极大降低了思维负担:
不再是“这几个集群要装什么”,而是“这个 Fleet 应该具备什么能力”。

Kurator,正是我们用来尝试实现这个目标的关键组件之一。

大体流程可参考如下:

三、第二阶段:走近 Kurator 社区——从第一个 Issue 开始

用得越多,越会遇到一些细节问题。最开始我只是在项目的 GitHub Issues 区找解决办法,后来发现:
与其“等别人解决”,不如“自己发个 Issue 把坑说清楚”。

3.1 我的第一个 Issue:监控插件安装的“隐形前提”

在给 Fleet 启用统一监控插件时,我遇到了一个问题:

  • Fleet 中声明了 metric.thanos 配置;
  • 但有些集群上已经自行部署过 Prometheus,和 Kurator 预置的安装逻辑冲突;
  • 结果是这些集群的 Thanos Sidecar Pod 无法正常拉起。

我在 Issue 里尽量写清楚了复现步骤和期望行为:

  1. 环境拓扑(多少个集群、哪些有预装 Prometheus);
  2. Fleet 配置 YAML;
  3. 实际现象(Pod 日志、Events、CR 状态);
  4. 自己尝试过的几个 workaround。

很快就有 Maintainer 回复,建议:

  • 在这些已有 Prometheus 的集群里暂时关闭自动安装;
  • 并在下一版本改进文档,对“已有监控环境”的场景给出更清晰的指引。

这次经历让我感受到两个点:

  1. Kurator 社区对场景反馈非常重视,并不是“只讨论代码实现”;
  2. 作为用户,哪怕不会 Go,也可以通过高质量 Issue 帮助项目完善边角体验。

3.2 文档 PR:把“场景经验”写回官方说明

接着,我做了一件更简单但很有成就感的事:
给 Kurator 文档提了一个小 PR,补充了“已有 Prometheus 场景下启用统一监控”的注意事项。

文档改动大致类似这样(伪代码形式):

## 注意事项:已有 Prometheus 场景

如果成员集群已经部署了 Prometheus,请优先确认:

1. 该 Prometheus 版本与 Kurator 所需的 Thanos Sidecar 版本兼容;
2. 集群中未重复安装 Prometheus Operator;
3. 如使用自定义命名空间或 ServiceMonitor,请在 Fleet 插件配置中显式指定对应 Selector。

示例配置:

```yaml
plugin:
  metric:
    thanos:
      objectStoreConfig:
        secretName: thanos-oss-config
      prometheus:
        namespace: monitoring
        serviceMonitorSelector:
          matchLabels:
            team: platform

PR 合并后,我第一次在官方文档里看到了自己的文字,那种“自己踩过的坑变成别人不会再踩的台阶”的感觉,非常直接地推动我继续参与进来。

而且,也可以参考如下示意图:


![](https://i-blog.csdnimg.cn/direct/4fa1b7b9d8a44fb6a878fd2255d77e62.png)

## 四、第三阶段:提交第一个功能性 PR —— 优化 Fleet 状态可观测性

随着内部使用规模变大,我们平台团队对 Kurator 的诉求也从“能跑”变成了“好运维”。  
其中一个痛点是:我们需要更清晰地看到 **Fleet 当前到底有哪些插件处于什么状态**。

### 4.1 痛点:Fleet 状态信息对平台 SRE 不够友好

在早期版本里,Fleet 的状态主要包括:

- 成员集群数量;  
- 部分插件控制器的 Ready 状态;  
- 但对每个插件在不同集群里的具体状态,暴露得不够直观。

内部 SRE 的需求是:

> “我想一眼看出:  
> - 这个 Fleet 下每个集群的监控插件是否正常;  
> - 策略引擎(Kyverno)是否都已安装并加载策略;  
> - Rollout 控制器是否就绪。”

于是我开了一个 Feature Request 类型的 Issue,和 Maintainer 讨论后,决定尝试自己写一个小改动:  
给 Fleet 的 Status 增加一个更结构化的 `PluginConditions` 字段,用于反映各插件在各集群内的状态摘要。

### 4.2 设计:为 FleetStatus 引入插件级别条件

在和社区讨论后,我们确定了类似下面的结构(伪代码示意,实际字段以项目为准)::contentReference[oaicite:10]{index=10}  

```go
type FleetStatus struct {
    // ... 其他字段 ...
    PluginConditions []PluginCondition `json:"pluginConditions,omitempty"`
}

type PluginCondition struct {
    Name      string            `json:"name"`
    Type      string            `json:"type"`
    Status    corev1.ConditionStatus `json:"status"`
    Reason    string            `json:"reason,omitempty"`
    Message   string            `json:"message,omitempty"`
    Clusters  []string          `json:"clusters,omitempty"`
    UpdatedAt metav1.Time       `json:"updatedAt,omitempty"`
}

这样,我们就可以在 Reconcile 的过程中,对每个插件的安装和运行状态进行汇总:

  • 当某个插件在所有成员集群里都 Ready 时,设置 Status=True
  • 若有部分集群安装失败或未就绪,标记为 Status=False,并在 Clusters 里列出问题集群。

4.3 实现:在 Reconcile 中聚合插件运行状态

在具体实现时,我参考了 Kurator 现有的控制器模式(使用 controller-runtime),大致加入了类似下面的逻辑(核心片段示例):

func (r *FleetReconciler) reconcilePluginStatus(ctx context.Context, fleet *v1alpha1.Fleet) error {
    var pluginConds []v1alpha1.PluginCondition

    // 以 metric 插件为例
    metricCond := v1alpha1.PluginCondition{
        Name: "metric",
        Type: "Installed",
    }

    notReadyClusters := make([]string, 0)

    for _, c := range fleet.Spec.Clusters {
        ready, reason := r.isMetricPluginReadyOnCluster(ctx, c.Name)
        if !ready {
            notReadyClusters = append(notReadyClusters, c.Name)
            metricCond.Status = corev1.ConditionFalse
            metricCond.Reason = "ClusterNotReady"
            metricCond.Message = reason
        }
    }

    if len(notReadyClusters) == 0 {
        metricCond.Status = corev1.ConditionTrue
        metricCond.Reason = "AllReady"
        metricCond.Message = "metric plugin is ready on all clusters"
    } else {
        metricCond.Clusters = notReadyClusters
    }

    metricCond.UpdatedAt = metav1.Now()
    pluginConds = append(pluginConds, metricCond)

    fleet.Status.PluginConditions = pluginConds
    return nil
}

提交 PR 后,经历了几轮 Review,主要是:

  • 字段命名与现有 Condition 体系的对齐;
  • 序列化与兼容性(是否会影响已有用户的 CRD 升级);
  • 单元测试与 e2e 场景覆盖。

最终这个改动被合入,那天我在内部群里贴了截图,SRE 同事看到 kubectl get fleet -o yaml 里多出来的 pluginConditions 字段,直呼“终于有点平台产品味了”。

这次经历对我最大的启发是:

社区其实很欢迎“来自一线场景的改进建议”,只要你愿意把场景说清楚,并用代码承载它。

如下是Kurator产品的官方架构图,很清晰可以看到Kurator的设计组成等:

五、第四阶段:把 Kurator 真正落地到企业生产的“血肉”里

在熟悉了 Kurator 内部实现之后,我开始推动平台团队在企业内部系统性地落地这套分布式云原生平台。

5.1 整体架构:从多云多集群走向“Fleet 化”

最终,我们落地的大致架构是这样的(文字版拓扑):

  • 控制平面:

    • 一个 Kurator 宿主集群(部署在主云 A 的一个专用 VPC 中);
    • 安装 Kurator CLI、Cluster Operator、Fleet Manager、统一监控与策略插件。
  • 成员集群:

    • 云 A:prod-ap-a-1prod-ap-a-2
    • 云 B:prod-ap-b-1
    • 私有云:prod-onprem-1
    • 边缘:edge-factory-*(部分运行 KubeEdge)
  • Fleet 规划:

    • fleet-online-ap:面向线上业务的亚太生产集群;
    • fleet-online-eu:面向欧盟用户的集群;
    • fleet-edge:所有工厂与门店边缘集群;
    • fleet-shared:跨区域共享服务(监控、日志、中间件)。

通过这种规划,我们把“物理分布极其分散的集群”,在逻辑上压缩成了 4 个 Fleet,方便按业务域进行治理。

5.2 Kurator + FluxCD:统一应用分发的 GitOps 实践

在应用分发上,我们采用 Kurator 基于 FluxCD 的 GitOps 模型:

  • 每个系统一个 Git 仓库,下设 base 与各环境 overlay;
  • Kurator Application 描述源和分发策略;
  • Fleet 决定这些应用应该部署到哪些集群。

典型 Application 配置(简化):

apiVersion: apps.kurator.dev/v1alpha1
kind: Application
metadata:
  name: user-center
  namespace: kurator-fleet
spec:
  source:
    gitRepository:
      url: https://git.example.com/cloud/user-center.git
      ref:
        branch: main
      interval: 2m
  syncPolicies:
    - name: ap-prod
      destination:
        fleet: fleet-online-ap
      kustomization:
        path: ./deploy/overlays/prod-ap
        targetNamespace: uc
        prune: true
    - name: eu-prod
      destination:
        fleet: fleet-online-eu
      kustomization:
        path: ./deploy/overlays/prod-eu
        targetNamespace: uc
        prune: true

这让我们获得了几个非常明显的收益:

  1. 业务团队只关注 Git 仓库,不再关心具体要“打到哪个集群”。

  2. 应用的多云部署策略在 Application 层可视化,而不是散落在各种脚本里;

  3. 回滚变得可预期:

    • 回滚 Git 即回滚配置;
    • Rollout 负责流量层面的渐进式调整。

5.3 Rollout:从 YAML 手搓到统一渐进式发布

此前,我们的金丝雀发布逻辑写在五花八门的配置里:

  • 有的是 Istio VirtualService;
  • 有的是 Nginx Ingress annotation;
  • 有的干脆写在 CI 脚本里。

引入 Kurator Rollout 后,我们将统一发布策略沉淀为 Rollout CR,并配合 Istio 网格使用。

比如订单服务的跨集群金丝雀发布:

apiVersion: rollout.kurator.dev/v1alpha1
kind: Rollout
metadata:
  name: order-service-canary
  namespace: order
spec:
  workload:
    apiVersion: apps/v1
    kind: Deployment
    name: order-service
  traffic:
    provider: istio
    host: order.api.example.com
  strategy:
    canary:
      steps:
        - weight: 5
        - weight: 20
        - weight: 50
      analysis:
        interval: 2m
        metrics:
          - name: error-rate
            type: prometheus
            query: |
              sum(rate(http_requests_total{app="order-service",code=~"5.."}[5m])) /
              sum(rate(http_requests_total{app="order-service"}[5m]))
            threshold:
              max: 0.02
          - name: p99-latency
            type: prometheus
            query: |
              histogram_quantile(0.99, sum(rate(http_request_duration_seconds_bucket{app="order-service"}[5m])) by (le))
            threshold:
              max: 400
      autoPromotionEnabled: true
      autoRollbackEnabled: true

迁移后的结果:

  • SRE 只需要看一个 Rollout 对象,就能理解整个发布策略
  • 各团队共用一套发布模式,新同事上手成本大幅降低;
  • 某次订单服务版本问题,通过自动回滚 + Git revert,将影响控制在小范围灰度。

5.4 Kyverno 策略 + Fleet:统一安全基线终于有了落地抓手

在安全团队的推动下,我们还基于 Kurator + Kyverno 完成了统一安全基线的建设:

  • 定义了一套公司级 Pod 安全策略(禁止特权容器、强制资源请求等);
  • 通过 Fleet Policy 插件,把这些策略“按域”分发到各个生产 Fleet;
  • 对不同业务线细化规则(如金融业务命名空间启用更严格策略)。

一个典型 Kyverno 策略(示例):

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: require-cpu-memory-limits
spec:
  validationFailureAction: Enforce
  rules:
    - name: check-limits
      match:
        resources:
          kinds:
            - Pod
      validate:
        message: "CPU and memory limits are required."
        pattern:
          spec:
            containers:
              - resources:
                  limits:
                    cpu: "?*"
                    memory: "?*"

通过 Kurator,我们不需要在每个集群单独安装 Kyverno + 配置策略,而是交给 Fleet 层统一分发。
这让安全团队第一次拥有了“多云多集群统一策略控制面”,而不是在不同控制台之间来回切。

如下是它开源的截图展示:

而且,如下是它的一些开源数据。

六、与 Kurator 社区共建的收获:技术与组织双视角

这几年用 Kurator、提 Issue、提 PR 以及与 Maintainer 反复交流,对我个人和团队来说都产生了不小改变。

6.1 对我个人的成长

  1. 技术视野被“拉高维度”

    • 从怎么玩 Kubernetes 单集群,到思考“多云多集群管控面应该长什么样”;
    • 通过阅读 Kurator、Karmada、Istio 等项目源码,对控制器模式、CRD 设计有了更系统的理解。
  2. 对“开源协作方式”的理解更真实

    • Issue 并不是“抱怨墙”,而是连接使用者与维护者的桥梁;
    • Maintainer 关注的不只是代码质量,还有场景合理性与可维护性。
  3. 写代码的“叙事能力”被逼着提升

    • 每一个 PR 后面,都要能讲清楚“解决了谁的什么问题”;
    • 这也反向帮助我在公司内部更好地解释平台技术方案。

6.2 对团队与组织的影响

  1. 平台产品思维增强

    • 吸收 Kurator 的 Fleet / Application / Rollout 抽象思想,我们在内部也开始用类似的 CR 去抽象自己的平台能力;
    • 而不是把所有逻辑都塞进一个“超级 CI 脚本”。
  2. 与安全、网络、业务团队的协作变得更“对齐”

    • 用 CR 和 GitOps 描述的东西是可审计、可回滚、可对话的;
    • 安全策略不再只是 PDF 文档,而是实际落到 Kyverno Policy 上。
  3. 培养了一批“平台+社区双栖”的工程师

    • 团队里出现了更多愿意看上游项目代码、参与 Issue 讨论的同事;
    • 这对平台长期演进、避免“自造轮子”非常关键。

所以说,如果你感兴趣,可以参考官方文档部署:

七、对 Kurator 与分布式云原生的几点建议和创想

结合这几年的使用和贡献经历,我也在不断思考:
Kurator 以及更广义的分布式云原生,下一步可以往哪走?

7.1 抽象层面:从“多集群管理”走向“分布式基础设施编程”

现在 Kurator 已经很好地解决了“多云多集群的生命周期管理与统一治理”问题:

  • Cluster Operator 管集群;
  • Fleet 管“集群舰队”;
  • Application / Rollout / Policy / Pipeline 管分布式应用与策略。

下一步可以考虑在抽象层再抬一层:

  • 把“多云部署拓扑(单云、双活、多活、冷备)”、“网络连通性需求”、“合规域”等整合为一个更高阶的“分布式基础设施编程模型”;
  • Kurator 则负责把这个高阶描述分解为 Karmada 策略、Fleet 配置、Application / Rollout / Policy 等具体实现。

这会让平台工程师真正站在“整体系统”的高度编程,而不是在各种 CR 之间频繁切换上下文。

7.2 边缘场景:断网 GitOps 与自治策略

与 KubeEdge 结合的云边一体场景,是 Kurator 未来很有潜力的方向之一:

  • 边缘集群网络不稳定是常态;

  • 需要一套“断网 GitOps”机制:

    • 网络良好时,同步中心 Git 仓库的期望状态;
    • 断网时,边缘按本地缓存和策略自治运行;
    • 网络恢复时,能安全地进行状态对齐与冲突解决。

在策略层面,则可以考虑:

  • 为边缘节点定义本地自治策略(如资源上限、降级路径);
  • 当与中心断联一段时间后自动进入“离线策略模式”,而不是简单标记为“NotReady”。

7.3 软件供应链安全:把 SLSA 要求沉淀成默认配置

Kurator 已经在版本迭代中强调了对统一 Rollout、Pipeline 以及供应链安全的支持:

  • 利用 Tekton/Chains 为镜像生成签名与溯源信息;
  • 配合策略引擎限制“只允许经过签名的镜像在生产运行”。

从社区贡献者角度,我很期待未来能看到:

  • 一套“开箱即用”的供应链安全 best practice 模板;
  • 对各类语言/框架(Java、Go、Node、Python)的流水线模版;
  • 在 Policy 层提供“必须带签名 + 必须有 SBOM + 必须通过扫描”的复合策略。

这样,企业就可以用 Kurator 作为“安全云原生供应链”的参考实现,而不是从零搭建。

7.4 社区协作:加强与 Karmada、Flux 等上游的双向联动

Kurator 的成功很大程度上得益于它紧紧“站在主流项目的肩膀上”。

从贡献者角度我也希望未来:

  • Kurator 中沉淀下来的多云多集群实践,可以反哺 Karmada、FluxCD 等项目的设计;
  • 在 CNCF 多集群 / 平台工程相关工作组中,共同探索标准化 API 形态;
  • 让更多企业在“多云分布式云原生”的道路上,少走弯路、少造轮子。

八、结语:把自己的实践写进 Kurator,也把 Kurator 写进自己的平台

回头看我与 Kurator 的这段经历,其实可以用三句话总结:

  1. 先把它当工具用,解决自己“多云多集群”的真实问题;
  2. 再把踩过的坑与改进建议,通过 Issue/PR 写回社区;
  3. 最后再把社区沉淀下来的能力,反过来固化到自己的企业平台里。

对我个人而言,这是一段从“脚本炼丹的运维”长成“懂架构的开源共建者”的过程;
对团队而言,这是一次从“单集群视角”转向“分布式云原生视角”的集体升级。

如果你恰好也在为多云、多集群、云边一体这些问题烦恼,我非常真诚地建议你:

  • 不妨像当年的我一样,先用一个测试集群把 Kurator 跑起来;
  • 在实践中发现问题,就大胆去开 Issue、提 PR;
  • 把你所在行业的场景和经验,写进 Kurator,也写成一篇自己的“贡献经历”。

说不定,下一个在 Kurator 文档、代码和 Roadmap 里留下痕迹的,就是你。🙂

更多推荐