Kruise Rollout 全链路灰度实践

简介: OpenKruise 是一个基于 Kubernetes 的扩展套件,主要聚焦于云原生应用的自动化,比如部署、发布、运维以及可用性防护。本文介绍通过 OpenKruise 构建自动化运维的方式实现基于 Istio 的全链路灰度功能。

作者:旦酱、十眠


什么是全链路灰度?


在发布应用的过程中,我们通常希望用少量特定流量来验证新版本的发布是否正常,以保障整体稳定性。这个过程被称为灰度发布。关于灰度发布,我们通过逐步增加发布的范围,来验证新版本的稳定性。如果新版本出现问题,我们也能及时发现,控制影响范围,保障整体的稳定性。

灰度发布一般具有以下特点:

  • 逐步增加发布的影响范围,拒绝一次性全部发布。
  • 阶段性的发布过程,可以通过金丝雀发布方式小心验证,以验证新版本的稳定性;
  • 可暂停、可回滚、可继续、可自动化状态流转,以便灵活地控制发布过程并确保稳定性;


据调研数据 70% 的线上问题都是由于变更导致,我们常说安全生产三板斧,可灰度、可观测、可回滚,也是为了控制变更带来的风险与影响面。通过采用灰度发布的方式,我们能够更加稳健地发布新版本,避免因发布过程中出现的问题而带来的损失。


全链路灰度是微服务场景下灰度发布方案的最佳实践,通常每个微服务都会有灰度环境或分组来接受灰度流量。我们希望进入上游灰度环境的流量也能进入下游灰度的环境中,确保1个请求始终在灰度环境中传递,从而形成流量“泳道”。在“泳道”内的流量链路中,即使这个调用链路上有一些微服务应用不存在灰度环境,那么这些微服务应用在请求下游应用的时候依然能够回到下游应用的灰度环境中。

全链路灰度为微服务发布保驾护航


这种方式可以根据服务的实际情况,可以对单个服务可以进行独立的发布和流量控制,也可以控制多个服务同时进行发布变更,从而保证整个系统的稳定性。同时,还可以采用自动化的部署方式,实现快速、可靠的发布过程,提高发布效率和稳定性。


Istio 全链路灰度技术解析


如何通过 Istio 实现全链路灰度能力,想必大家都很关心这个话题,今天我们就详细谈一下基于 istio 实现全链路灰度能力的几个关键技术细节。


流量标签全链路透传
在对微服务进行全链路灰度的过程中,一个最需要考虑的问题是流量中 header 透传的问题,一些微服务会仅保留特定的 header 进行透传,而去除其它 header,利用 Kruise Rollout,可以有效减少发布中对网关资源进行配置的复杂性,但却无法解决 header 透传的问题。如何保证灰度标识能够在链路中一直传递下去呢?分布式链路追踪技术对大型分布式系统中请求调用链路进行详细记录,核心思想就是通过一个全局唯一的 traceid 和每一条的 spanid 来记录请求链路所经过的节点以及请求耗时,其中 traceid 是需要整个链路传递的。借助于分布式链路追踪思想,我们也可以传递一些自定义信息,比如灰度标识。业界常见的分布式链路追踪产品都支持链路传递用户自定义的数据,其数据处理流程如下图所示:


我们可以借助 Tracing Baggage 机制在全链路中传递对应染色标识,因为大部分 Tracing 框架都支持 Baggage 概念及能力,如:OpenTelemetry、Skywalking、Jaeger 等等。我们只需要在 Envoy outbound Filter 中讲指定的透传 key 如 x-mse-tag 从 Tracing 协议指定位置的 Baggage 中读出 x-mse-tag 对应的值,并塞入到 Http 的 Header 中,供 Envoy 进行路由。


流量路由

通过对服务下所有节点按照标签名和标签值不同进行分组,使得订阅该服务节点信息的服务消费端可以按需访问该服务的某个分组,即所有节点的一个子集。服务消费端可以使用服务提供者节点上的任何标签信息,根据所选标签的实际含义,消费端可以将标签路由应用到更多的业务场景中。


在 Istio 中我们可以通过 Istio Gateway、DestinationRule 和 VirtualService 配置路由和外部访问;


节点打标
如何给服务节点添加不同的标签?我们只要在业务应用描述资源 Deployment 中的 Pod 模板中为节点添加标签即可。在使用 Kubernetes Service 作为服务发现的业务系统中,服务提供者通过向 ApiServer 提交 Service 资源完成服务暴露,服务消费端监听与该 Service 资源下关联的 Endpoint 资源,从 Endpoint 资源中获取关联的业务 Pod 资源,读取上面的 Labels 数据并作为该节点的元数据信息。


为什么选择 Kruise Rollout?


从上述技术细节中可以看出,实现基于 Istio 的全链路灰度操作非常复杂且成本较高。首先,需要创建灰度的 Deployment 并打上灰度的节点标识。其次,还需要配置 Istio 的流量路由 CRD,包括每一跳请求的 VirtualService 和 DestinationRule 规则,并且这些流量规则还需要与请求标识相配合。如果只是纸上谈谈技术细节,可能还能勉强理解,但如果真要实践起来,成本确实非常高。同时,如果在配置过程中出现错误,可能会导致生产流量出现问题,对业务造成重大影响。为了降低全链路灰度实践的成本,不得不提 Kruise Rollout 了。Kruise Rollout[1]是 OpenKruise 社区开源提出的一个渐进式交付框架。其设计理念是提供一组能够将流量发布与实例灰度相结合,支持金丝雀、蓝绿、A/B Testing 等多样化发布形式,以及支持基于 Prometheus Metrics 等自定义 Metrics 实现发布过程自动化,无感对接、易扩展的旁路式标准 Kubernetes 发布组件。



从上图中我们可以看到 OpenKruise Rollout 能够将复杂的灰度发布过程自动化,因此通过 OpenKruise Rollout 可以大幅度降低全链路灰度的实施成本,对于使用者来说只需要配置 Kruise Rollout 的 CRD,然后直接进行应用发布,即可实现全链路灰度发布。


Kruise + Istio 全链路灰度实践


谈完技术实现的细节,下面我们就开始基于 Kruise Rollout 跟 Istio 的全链路灰度能力实践


配置服务

首先部署两个服务 mocka 和 mockb,服务 mocka 会调用服务 mockb,⚠️服务只会保留流量中的 header my-request-id 而去除其它 header(我们也可以通过接入 OpenTelemetry 实现动态流量标签透传),整个服务的访问可以表示为:


服务的配置文件为:

apiVersion: v1
kind: Service
metadata:
  name: mocka
  namespace: e2e
  labels:
    app: mocka
    service: mocka
spec:
  ports:
  - port: 8000
    name: http
  selector:
    app: mocka
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mocka-base
  namespace: e2e
  labels:
    app: mocka
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mocka
  template:
    metadata:
      labels:
        app: mocka
        version: base
    spec:
      containers:
      - name: default
        image: registry.cn-beijing.aliyuncs.com/aliacs-app-catalog/go-http-sample:1.0
        imagePullPolicy: Always
        env:
        - name: version
          value: base
        - name: app
          value: mocka
        - name: upstream_url
          value: "http://mockb:8000/"
        ports:
        - containerPort: 8000
---
apiVersion: v1
kind: Service
metadata:
  name: mockb
  namespace: e2e
  labels:
    app: mockb
    service: mockb
spec:
  ports:
  - port: 8000
    name: http
  selector:
    app: mockb
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mockb-base
  namespace: e2e
  labels:
    app: mockb
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mockb
  template:
    metadata:
      labels:
        app: mockb
        version: base
    spec:
      containers:
      - name: default
        image: registry.cn-beijing.aliyuncs.com/aliacs-app-catalog/go-http-sample:1.0
        imagePullPolicy: Always
        env:
        - name: version
          value: base
        - name: app
          value: mockb
        ports:
        - containerPort: 8000

服务的 header 部分处理代码如下所示:

// All URLs will be handled by this function
m.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
    requestId := r.Header.Get("my-request-id")
    fmt.Printf("receive request: my-request-id: %s\n", requestId)
    response := fmt.Sprintf("-> %s(version: %s, ip: %s)", app, version, ip)
    if url != "" {
        // 新请求只发送my-request-id
        content := doReq(url, requestId)
        response = response + content
    }
    w.Write([]byte(response))
})

之后部署 Istio Gateway、DestinationRule 和 VirtualService 配置路由和外部访问:

apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
  name: gateway
  namespace: e2e
spec:
  selector:
    istio: ingressgateway
  servers:
    - hosts:
        - "*"
      port:
        name: http
        number: 80
        protocol: HTTP
---
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: dr-mocka
  namespace: e2e
spec:
  host: mocka
  trafficPolicy:
    loadBalancer:
      simple: ROUND_ROBIN
  subsets:
    - labels:
        version: base
      name: version-base
---
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: dr-mockb
  namespace: e2e
spec:
  host: mockb
  trafficPolicy:
    loadBalancer:
      simple: ROUND_ROBIN
  subsets:
    - labels:
        version: base
      name: version-base
---
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: vs-mocka
  namespace: e2e
spec:
  gateways:
  - simple-gateway
  hosts:
    - "*"
  http:
  - route:
      - destination:
          host: mocka
          subset: version-base
---
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: vs-mockb
  namespace: e2e
spec:
  hosts:
    - mockb
  http:
    - route:
        - destination:
            host: mockb
            subset: version-base

部署完成后整个结构如下图所示:

在本地集群中,可以通过运行如下指令获取 Gateway 入口 ip 以及 port 对服务进行访问:

kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="http2")].nodePort}'
kubectl get po -l istio=ingressgateway -n istio-system -o jsonpath='{.items[0].status.hostIP}'

此时运行 curl http://GATEWAY_IP:PORT 可以得到如下结果:

-> mocka(version: base, ip: 10.244.1.36)-> mockb(version: base, ip: 10.244.1.37)


配置 Rollout 和 TrafficRouting 规则
之后部署 Rollout,分别对 mocka 和 mockb 进行控制。Rollout 以及 TrafficRouting 配置的策略如下:

  • 添加了匹配 my-request-id=canary 的 header 规则,包含指定 header 的流量会走灰度环境
  • 为发布的 pod 添加了 label istio.service.tag=gray 以及 version=canary


⚠️pod label 的添加规则是什么?

在配置中为新版本 pod 打上了两个 label,其中 istio.service.tag=gray 的目的是为了在 DestinationRule 中指定包含该 label 的 pod 作为一个 subset,lua 脚本会为 DestinationRule 自动添加该 Subset。添加 version=canary 的目的是为了覆盖原始版本中的 version=baselabel,如果不覆盖该 label,原始 DestinationRule 也会将稳定版本的流量导入新版本 pod 中。

apiVersion: rollouts.kruise.io/v1alpha1
kind: Rollout
metadata:
  name: rollouts-a
  namespace: demo
  annotations:
    rollouts.kruise.io/rolling-style: canary
    rollouts.kruise.io/trafficrouting: mocka-tr
spec:
  disabled: false
  objectRef:
    workloadRef:
      apiVersion: apps/v1
      kind: Deployment
      name: mocka-base
  strategy:
    canary:
      steps:
      - replicas: 1
      patchPodTemplateMetadata:
        labels:
          istio.service.tag: gray
          version: canary
---
apiVersion: rollouts.kruise.io/v1alpha1
kind: TrafficRouting
metadata:
  name: mocka-tr
  namespace: demo
spec:
  strategy:
    matches:
      - headers:
        - type: Exact
          name: my-request-id
          value: canary
  objectRef:
  - service: mocka
    customNetworkRefs:
    - apiVersion: networking.istio.io/v1alpha3
      kind: VirtualService
      name: vs-mocka
    - apiVersion: networking.istio.io/v1beta1
      kind: DestinationRule
      name: dr-mocka
---
apiVersion: rollouts.kruise.io/v1alpha1
kind: Rollout
metadata:
  name: rollouts-b
  namespace: demo
  annotations:
    rollouts.kruise.io/rolling-style: canary
    rollouts.kruise.io/trafficrouting: mockb-tr
spec:
  disabled: false
  objectRef:
    workloadRef:
      apiVersion: apps/v1
      kind: Deployment
      name: mockb-base
  strategy:
    canary:
      steps:
      - replicas: 1
      patchPodTemplateMetadata:
        labels:
          istio.service.tag: gray
          version: canary
---
apiVersion: rollouts.kruise.io/v1alpha1
kind: TrafficRouting
metadata:
  name: mockb-tr
  namespace: demo
spec:
  strategy:
    matches:
      - headers:
        - type: Exact
          name: my-request-id
          value: canary
  objectRef:
  - service: mockb
    customNetworkRefs:
    - apiVersion: networking.istio.io/v1alpha3
      kind: VirtualService
      name: vs-mockb
    - apiVersion: networking.istio.io/v1beta1
      kind: DestinationRule
      name: dr-mockb


开始灰度发布
修改 mocka 和 mockb 中的环境变量为 version=canary 开始发布。Kruise Rollout 将自动获取网关资源并进行修改,此时查看 VirtualService 和 DestinationRule 可以得到,VirtualService 定义了路由规则将带有 my-request-id=canary 的 header 的流量路由至 canary 版本。DestinationRule 添加了对于包含 label istio.service.tag=gray 新的 Subset。

apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"networking.istio.io/v1beta1","kind":"VirtualService","metadata":{"annotations":{},"name":"vs-mocka","namespace":"demo"},"spec":{"gateways":["simple-gateway"],"hosts":["*"],"http":[{"route":[{"destination":{"host":"mocka","subset":"version-base"}}]}]}}
    rollouts.kruise.io/origin-spec-configuration: '{"spec":{"gateways":["simple-gateway"],"hosts":["*"],"http":[{"route":[{"destination":{"host":"mocka","subset":"version-base"}}]}]},"annotations":{"kubectl.kubernetes.io/last-applied-configuration":"{\"apiVersion\":\"networking.istio.io/v1beta1\",\"kind\":\"VirtualService\",\"metadata\":{\"annotations\":{},\"name\":\"vs-mocka\",\"namespace\":\"demo\"},\"spec\":{\"gateways\":[\"simple-gateway\"],\"hosts\":[\"*\"],\"http\":[{\"route\":[{\"destination\":{\"host\":\"mocka\",\"subset\":\"version-base\"}}]}]}}\n"}}'
  creationTimestamp: "2023-09-12T07:49:15Z"
  generation: 40
  name: vs-mocka
  namespace: demo
  resourceVersion: "98670"
  uid: c7da3a99-789c-4f1e-93a4-caaee41cbe06
spec:
  gateways:
  - simple-gateway
  hosts:
  - '*'
  http:
  # -- lua脚本自动添加的规则
  - match:
    - headers:
        my-request-id:
          exact: canary
    route:
    - destination:
        host: mocka
        subset: canary
  # --
  - route:
    - destination:
        host: mocka
        subset: version-base
---
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"networking.istio.io/v1beta1","kind":"VirtualService","metadata":{"annotations":{},"name":"vs-mockb","namespace":"demo"},"spec":{"hosts":["mockb"],"http":[{"route":[{"destination":{"host":"mockb","subset":"version-base"}}]}]}}
    rollouts.kruise.io/origin-spec-configuration: '{"spec":{"hosts":["mockb"],"http":[{"route":[{"destination":{"host":"mockb","subset":"version-base"}}]}]},"annotations":{"kubectl.kubernetes.io/last-applied-configuration":"{\"apiVersion\":\"networking.istio.io/v1beta1\",\"kind\":\"VirtualService\",\"metadata\":{\"annotations\":{},\"name\":\"vs-mockb\",\"namespace\":\"demo\"},\"spec\":{\"hosts\":[\"mockb\"],\"http\":[{\"route\":[{\"destination\":{\"host\":\"mockb\",\"subset\":\"version-base\"}}]}]}}\n"}}'
  creationTimestamp: "2023-09-12T07:49:16Z"
  generation: 40
  name: vs-mockb
  namespace: demo
  resourceVersion: "98677"
  uid: 7c96ee2b-96ce-48e4-ba6d-cf94171ed854
spec:
  hosts:
  - mockb
  http:
  # -- lua脚本自动添加的规则
  - match:
    - headers:
        my-request-id:
          exact: canary
    route:
    - destination:
        host: mockb
        subset: canary
  # -- 
  - route:
    - destination:
        host: mockb
        subset: version-base
---
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"networking.istio.io/v1beta1","kind":"DestinationRule","metadata":{"annotations":{},"name":"dr-mocka","namespace":"demo"},"spec":{"host":"mocka","subsets":[{"labels":{"version":"base"},"name":"version-base"}],"trafficPolicy":{"loadBalancer":{"simple":"ROUND_ROBIN"}}}}
    rollouts.kruise.io/origin-spec-configuration: '{"spec":{"host":"mocka","subsets":[{"labels":{"version":"base"},"name":"version-base"}],"trafficPolicy":{"loadBalancer":{"simple":"ROUND_ROBIN"}}},"annotations":{"kubectl.kubernetes.io/last-applied-configuration":"{\"apiVersion\":\"networking.istio.io/v1beta1\",\"kind\":\"DestinationRule\",\"metadata\":{\"annotations\":{},\"name\":\"dr-mocka\",\"namespace\":\"demo\"},\"spec\":{\"host\":\"mocka\",\"subsets\":[{\"labels\":{\"version\":\"base\"},\"name\":\"version-base\"}],\"trafficPolicy\":{\"loadBalancer\":{\"simple\":\"ROUND_ROBIN\"}}}}\n"}}'
  creationTimestamp: "2023-09-12T07:49:15Z"
  generation: 12
  name: dr-mocka
  namespace: demo
  resourceVersion: "98672"
  uid: a6f49044-e889-473c-b188-edbdb8ee347f
spec:
  host: mocka
  subsets:
  - labels:
      version: base
    name: version-base
    # -- lua脚本自动添加的规则
  - labels:
      istio.service.tag: gray
    name: canary
    # --
  trafficPolicy:
    loadBalancer:
      simple: ROUND_ROBIN
---
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"networking.istio.io/v1beta1","kind":"DestinationRule","metadata":{"annotations":{},"name":"dr-mockb","namespace":"demo"},"spec":{"host":"mockb","subsets":[{"labels":{"version":"base"},"name":"version-base"}],"trafficPolicy":{"loadBalancer":{"simple":"ROUND_ROBIN"}}}}
    rollouts.kruise.io/origin-spec-configuration: '{"spec":{"host":"mockb","subsets":[{"labels":{"version":"base"},"name":"version-base"}],"trafficPolicy":{"loadBalancer":{"simple":"ROUND_ROBIN"}}},"annotations":{"kubectl.kubernetes.io/last-applied-configuration":"{\"apiVersion\":\"networking.istio.io/v1beta1\",\"kind\":\"DestinationRule\",\"metadata\":{\"annotations\":{},\"name\":\"dr-mockb\",\"namespace\":\"demo\"},\"spec\":{\"host\":\"mockb\",\"subsets\":[{\"labels\":{\"version\":\"base\"},\"name\":\"version-base\"}],\"trafficPolicy\":{\"loadBalancer\":{\"simple\":\"ROUND_ROBIN\"}}}}\n"}}'
  creationTimestamp: "2023-09-12T07:49:15Z"
  generation: 12
  name: dr-mockb
  namespace: demo
  resourceVersion: "98678"
  uid: 4bd0f6c5-efa1-4558-9e31-6f7615c21f9a
spec:
  host: mockb
  subsets:
  - labels:
      version: base
    name: version-base
    # -- lua脚本自动添加的规则
  - labels:
      istio.service.tag: gray
    name: canary
    # --
  trafficPolicy:
    loadBalancer:
      simple: ROUND_ROBIN

此时运行 curl http://GATEWAY_IP:PORT 可以得到如下结果,所有流量均通过 base 版本服务。

-> mocka(version: base, ip: 10.244.1.36)-> mockb(version: base, ip: 10.244.1.37)

此时运行 curl -H http://GATEWAY_IP:PORT -Hmy-request-id:canary 可以得到如下结果,所有流量均通过 canary 版本服务。

-> mocka(version: canary, ip: 10.244.1.41)-> mockb(version: canary, ip: 10.244.1.42)

此时整个服务的流量可以表示为下图,包含 headermy-request-id=canary 的流量全部走灰度环境,其它流量全部走基线环境:


(可选)利用 EnvoyFilter 进行流量染色

我们可以通过编写 EnvoyFilter 进一步简化流量染色的步骤,在之前的例子中,在请求的时候包含了可以透传的 header my-request-id,如果想要实现更加通用的 header 请求规则,例如包含 agent=pc 的流量全部走灰度环境,其它则走基线环境,则可以通过 EnvoyFilter 在入口网关进行染色。以下定义了一个 EnvoyFilter,该 EnvoyFilter 定义了一个 Lua 脚本,会对包含 agent=pc 的流量染色,为其添加 my-request-id=canary,而其它流量则添加 my-request-id=base。

apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
  name: http-request-labelling-according-source
  namespace: istio-system
spec:
  workloadSelector:
    labels:
      app: istio-ingressgateway
  configPatches:
  - applyTo: HTTP_FILTER
    match:
      context: GATEWAY
      listener:
        filterChain:
          filter:
            name: "envoy.filters.network.http_connection_manager"
            subFilter:
              name: "envoy.filters.http.router"
    patch:
      operation: INSERT_BEFORE
      value:
       name: envoy.lua
       typed_config:
         "@type": "type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua"
         inlineCode: |
           function envoy_on_request(request_handle)
           local header = "agent"
            headers = request_handle:headers()
             version = headers:get(header)
             if (version ~= nil) then
              if (version == "pc") then
                headers:add("my-request-id","canary")
              else
                headers:add("my-request-id","base")
              end
             else
              headers:add("my-request-id","base")
             end
           end

保持其它配置不变,此时运行 curl http://GATEWAY_IP:PORT 可以得到如下结果,所有流量均通过 base 版本服务。

-> mocka(version: base, ip: 10.244.1.36)-> mockb(version: base, ip: 10.244.1.37)

此时运行 curl -H http://GATEWAY_IP:PORT -Hagent:pc 可以得到如下结果,EnvoyFilter 自动为该流量添加 headermy-request-id=canary,因此所有流量均通过新版本服务。

-> mocka(version: canary, ip: 10.244.1.41)-> mockb(version: canary, ip: 10.244.1.42)


完整的全链路灰度方案

Kruise Rollout 除了支持开源的 Istio 实现全链路灰度外,还支持与 MSE 实现完整的全链路灰度方案,我们可以通过如下操作文档[2]快速实现体系化的全链路灰度能力。


MSE 全链路灰度可以有效地控制流量在前端、网关、后端各个微服务等组件中闭环,不仅仅是 RPC/Http 的流量,对于异步调用比如 MQ 流量也支持符合全链路“泳道”调用的规则。通过 Kruise Rollout 跟 MSE 可以帮助我们更加便捷地实现微服务全链路灰度发布,提高微服务场景下发布的效率和稳定性。

MSE 全链路灰度可以有效地控制流量在前端、网关、后端各个微服务等组件中闭环,不仅仅是 RPC/Http 的流量,对于异步调用比如 MQ 流量也支持符合全链路“泳道”调用的规则。通过 Kruise Rollout 跟 MSE 可以帮助我们更加便捷地实现微服务全链路灰度发布,提高微服务场景下发布的效率和稳定性。

加入 OpenKruise 社区

最后,非常欢迎你通过 Github/Slack/钉钉/微信 等方式加入我们来参与 OpenKruise 开源社区。

  • 加入社区 Slack channel (English)
  • 加入社区钉钉群:搜索群号 23330762 (Chinese)
  • 加入社区微信群(新):添加用户 openkruise 并让机器人拉你入群 (Chinese)


相关链接:

[1] Kruise Rollout

https://openkruise.io/rollouts/introduction

[2] 操作文档

https://help.aliyun.com/zh/mse/user-guide/implement-mse-based-end-to-end-canary-release-by-using-kruise-rollouts?spm=a2c4g.11186623.0.0.1d5a79dezV82UH

相关实践学习
深入解析Docker容器化技术
Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。Docker是世界领先的软件容器平台。开发人员利用Docker可以消除协作编码时“在我的机器上可正常工作”的问题。运维人员利用Docker可以在隔离容器中并行运行和管理应用,获得更好的计算密度。企业利用Docker可以构建敏捷的软件交付管道,以更快的速度、更高的安全性和可靠的信誉为Linux和Windows Server应用发布新功能。 在本套课程中,我们将全面的讲解Docker技术栈,从环境安装到容器、镜像操作以及生产环境如何部署开发的微服务应用。本课程由黑马程序员提供。     相关的阿里云产品:容器服务 ACK 容器服务 Kubernetes 版(简称 ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情: https://www.aliyun.com/product/kubernetes
相关文章
|
存储 Kubernetes 监控
Open-Local - 云原生本地磁盘管理系统
Open-Local是由多个组件构成的本地磁盘管理系统,目标是解决当前 Kubernetes 本地存储能力缺失问题。通过Open-Local,使用本地存储会像集中式存储一样简单。
Open-Local - 云原生本地磁盘管理系统
|
资源调度 监控 API
开源API网关APISIX分析与使用
开源API网关APISIX分析与使用
1514 0
|
关系型数据库 MySQL 数据库
n8n自动化工具部署与使用
n8n是一款开源的工作流自动化工具,类似于IFTTT。它的优点是开源、可以自托管、下载安装方便、易于使用,可以互联上百种服务。n8n基于节点能够将任何工具连接在一起,轻松部署不同类型的任务。它可以做很多事情,比如:从数据库中获取数据后下载为excel然后通过邮件发送给其他人。
11048 1
|
10月前
|
人工智能 API
MCP协议的局限性
5年前,我把 AI 比喻为一种智能化的 API 网关,提出一种分治的思想,将一个大问题转换为若干可解的小问题,如今,这种思想正在 mcp 这种协议沿用。但目前来看,它的实现方式还是有点丑陋的,并且有一些问题。
|
9月前
|
人工智能 Java API
MCP客户端调用看这一篇就够了(Java版)
本文详细介绍了MCP(Model Context Protocol)客户端的开发方法,包括在没有MCP时的痛点、MCP的作用以及如何通过Spring-AI框架和原生SDK调用MCP服务。文章首先分析了MCP协议的必要性,接着分别讲解了Spring-AI框架和自研SDK的使用方式,涵盖配置LLM接口、工具注入、动态封装工具等步骤,并提供了代码示例。此外,还记录了开发过程中遇到的问题及解决办法,如版本冲突、服务连接超时等。最后,文章探讨了框架与原生SDK的选择,认为框架适合快速构建应用,而原生SDK更适合平台级开发,强调了两者结合使用的价值。
12372 33
MCP客户端调用看这一篇就够了(Java版)
|
11月前
|
缓存 Ubuntu Linux
Docker Buildx 简介与安装指南
Docker Buildx 是一个强大的工具,提供了多架构构建、并行构建和高级缓存管理等功能。通过正确安装和配置 Buildx,可以显著提升 Docker 镜像的构建效率和灵活性。希望本文能帮助你更好地理解和使用 Docker Buildx,以提高开发和部署的效率。
5596 16
|
Arthas Java 应用服务中间件
我的程序突然罢工了|深入探究HSF调用异常,从死锁到活锁的全面分析与解决
本文详细记录了作者在处理HSF调用异常问题的过程中,从初步怀疑死锁到最终发现并解决活锁问题的全过程。
962 49
|
NoSQL MongoDB 关系型数据库
13个Mongodb GUI可视化管理工具,总有一款适合你
本文介绍了13个好用的MongoDB可视化工具。Robomongo,MongoDB Compass,phpMoAdmin等
115708 0
13个Mongodb GUI可视化管理工具,总有一款适合你
|
Prometheus Cloud Native 调度
Sentinel 新版本发布,提升配置灵活性以及可观测配套
Sentinel 新版本发布,提升配置灵活性以及可观测配套
1681 102