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
相关文章
|
人工智能 安全 Apache
QwenPaw:你的私人 AI 助理 —— 数据归你、记忆进化、多端触达的开源个人智能体
QwenPaw 是一款开源、本地优先的AI个人智能体(Apache 2.0),数据归属用户、记忆自主进化、支持钉钉/飞书/微信等多端触达。3行命令即可部署,内置Coding IDE、Persona人格、定时任务、MCP工具生态与多Agent协作,真正属于你的私有AI助理。
QwenPaw:你的私人 AI 助理 —— 数据归你、记忆进化、多端触达的开源个人智能体
|
6月前
|
人工智能 Kubernetes 机器人
一键部署 OpenClaw:基于 ACS Agent Sandbox 构建企业级 AI Agent 应用
本文将详细介绍如何基于 ACS Agent Sandbox 一键部署 OpenClaw,实现按需休眠与秒级唤醒,并介绍其与钉钉等应用的集成方法。
1806 7
|
7月前
|
人工智能 自然语言处理 API
n8n:流程自动化、智能化利器
流程自动化助你在重复的业务流程中节省时间,可通过自然语言直接创建工作流啦。
1505 9
n8n:流程自动化、智能化利器
|
11月前
|
人工智能 运维 安全
阿里云函数计算 AgentRun 全新发布,构筑智能体时代的基础设施
云原生应用平台 Serverless 计算负责人杨皓然在云栖大会发表主题演讲“Serverless Agent 基础设施:助力大规模 Agent 部署与运维”。本议题深入介绍了阿里云以函数计算为核心打造的 Agent 基础设施——AgentRun,阐述其如何通过创新的运行时、模型服务、网关及可观测体系,为企业构筑坚实、高效、安全的 Agent 时代基石。
|
人工智能 监控 负载均衡
一文详述:AI 网关与 API 网关到底有什么区别?
近年来,AI发展迅猛,大模型成为推动业务创新的关键力量。企业面临如何安全管理和部署AI应用的挑战,需设计既能满足当前需求又可适应未来发展的基础架构。AI网关应运而生,在集成、管理和优化AI应用中扮演重要角色。本文探讨AI网关与API网关的区别,分析AI系统为何需要专门网关,并提供选择合适AI网关的建议。AI网关不仅支持多种模型,还具备高级安全性和性能优化功能,有助于企业在复杂环境中灵活应用AI技术。
1137 2
|
Kubernetes Cloud Native Java
灰度发布、蓝绿部署、金丝雀都是啥?
在滚动部署中,应用的新版本逐步替换旧版本。实际的部署发生在一段时间内。在此期间,新旧版本会共存,而不会影响功能和用户体验。这个过程可以更轻易的回滚和旧组件不兼容的任何新组件。
灰度发布、蓝绿部署、金丝雀都是啥?
|
运维 Kubernetes Perl
在K8S中,节点故障pod驱逐pod过程,时间怎么定义的?
在K8S中,节点故障pod驱逐pod过程,时间怎么定义的?
|
Kubernetes jenkins 持续交付
jenkins学习笔记之二十一:k8s部署jenkins及动态slave
jenkins学习笔记之二十一:k8s部署jenkins及动态slave
2006 0
|
Kubernetes 数据库 容器
k8s快速部署xxl-job
k8s快速部署xxl-job
2299 3