本指南演示如何使用 SMI 流量拆分配置执行金丝雀部署。

先决条件

  • Kubernetes 集群版本 v1.19.0 或者更高。
  • 已安装 osm-edge。
  • 使用 kubectl 与 API server 交互。
  • 已安装 osm 命令行工具,用于管理服务网格。

演示

在此演示中,我们将部署一个 HTTP 应用程序并执行金丝雀发布,其中会部署新版本的应用程序,以对一定百分比的流量提供服务。

为了拆分流量到多个服务后端,需要使用 SMI 流量拆分 API 。关于 API 使用的更多说明,可以查看 流量拆分指南。为了将客户端流量透明地拆分到多个服务后端,需要注意客户端需要使用 TrafficSplit 资源中指定的根服务的 FQDN 来发送流量。在该演示中,curl 客户端发送流量到根服务 httpbin.org,该服务初始有 v1 版本的服务,然后执行金丝雀发布将部分流量定向到 v2 版本的服务中。

以下步骤演示了金丝雀发布的部署策略。

注意:启用宽松流量策略模式 无需显式地创建访问控制策略。

  1. 启用宽松模式

    osm_namespace=osm-system # Replace osm-system with the namespace where osm-edge is installed
    kubectl patch meshconfig osm-mesh-config -n "$osm_namespace" -p '{"spec":{"traffic":{"enablePermissiveTrafficPolicyMode":true}}}'  --type=merge
    
  2. curl 命名空间下部署 curl 客户端,并将命名空间纳入网格管理。

    # Create the curl namespace
    kubectl create namespace curl
    
    # Add the namespace to the mesh
    osm namespace add curl
    
    # Deploy curl client in the curl namespace
    kubectl apply -f https://raw.githubusercontent.com/flomesh-io/osm-edge-docs/release-v1.1/manifests/samples/curl/curl.yaml -n curl
    

    确认 curl 客户端 pod 启动并运行。

    $ kubectl get pods -n curl
    NAME                    READY   STATUS    RESTARTS   AGE
    curl-54ccc6954c-9rlvp   2/2     Running   0          20s
    
  3. 为客户端的访问创建根 service httpbin,service 选择器使用 app: httpbin

    # Create the httpbin namespace
    kubectl create namespace httpbin
    
    # Add the namespace to the mesh
    osm namespace add httpbin
    
    # Create the httpbin root service and service account
    kubectl apply -f https://raw.githubusercontent.com/flomesh-io/osm-edge-docs/release-v1.1/manifests/samples/canary/httpbin.yaml -n httpbin
    
  4. 部署 httpbin 服务的 v1 版本。该 service httpbin-v1 使用选择器 app: httpbin, version: v1,该 deployment httpbin-v1 有标签 app: httpbin, version: v1 ,其匹配了根 service httpbin 和 service httpbin-v1 的选择器。

    kubectl apply -f https://raw.githubusercontent.com/flomesh-io/osm-edge-docs/release-v1.1/manifests/samples/canary/httpbin-v1.yaml -n httpbin
    
  5. 创建 SMI TrafficSplit 资源将流量定向到 httpbin-v1

    kubectl apply -f - <<EOF
    apiVersion: split.smi-spec.io/v1alpha2
    kind: TrafficSplit
    metadata:
      name: http-split
      namespace: httpbin
    spec:
      service: httpbin.httpbin.svc.cluster.local
      backends:
      - service: httpbin-v1
        weight: 100
    EOF
    
  6. 确认发往根 service FQDN httpbin.httpbin.svc.cluster.local 的所有流量都被路由到 httpbin-v1 pod。可以通过检查 HTTP 响应头、确认请求成功和响应 pod httpbin-v1 的相关信息。

    for i in {1..10}; do kubectl exec -n curl -ti "$(kubectl get pod -n curl -l app=curl -o jsonpath='{.items[0].metadata.name}')" -c curl -- curl -sI http://httpbin.httpbin:14001/json | egrep 'HTTP|pod'; done
    HTTP/1.1 200 OK
    pod: httpbin-v1-77c99dccc9-r78z7
    HTTP/1.1 200 OK
    pod: httpbin-v1-77c99dccc9-r78z7
    HTTP/1.1 200 OK
    pod: httpbin-v1-77c99dccc9-r78z7
    HTTP/1.1 200 OK
    pod: httpbin-v1-77c99dccc9-r78z7
    HTTP/1.1 200 OK
    pod: httpbin-v1-77c99dccc9-r78z7
    HTTP/1.1 200 OK
    pod: httpbin-v1-77c99dccc9-r78z7
    HTTP/1.1 200 OK
    pod: httpbin-v1-77c99dccc9-r78z7
    HTTP/1.1 200 OK
    pod: httpbin-v1-77c99dccc9-r78z7
    HTTP/1.1 200 OK
    pod: httpbin-v1-77c99dccc9-r78z7
    HTTP/1.1 200 OK
    pod: httpbin-v1-77c99dccc9-r78z7
    

    上面的输出表明全部 10 个请求都返回了 HTTP 200 OK,这是 httpbin-v1 pod 的响应。

  7. 部署 httpbinv2 版本准备金丝雀发布。该 service httpbin-v2 使用选择器 app: httpbin, version: v2,该 deployment 的标签 app: httpbin, version: v2 匹配根 service httpbin 和 service httpbin-v2 的选择器。

    kubectl apply -f https://raw.githubusercontent.com/flomesh-io/osm-edge-docs/release-v1.1/manifests/samples/canary/httpbin-v2.yaml -n httpbin
    
  8. 执行金丝雀发布,通过更新 SMI TrafficSplit 资源拆分发往 FQDN httpbin.httpbin.svc.cluster.local 的流量到 httpbin-v1httpbin-v2 service,分别对应 httpbinv1v2 版本。。

    kubectl apply -f - <<EOF
    apiVersion: split.smi-spec.io/v1alpha2
    kind: TrafficSplit
    metadata:
      name: http-split
      namespace: httpbin
    spec:
      service: httpbin.httpbin.svc.cluster.local
      backends:
      - service: httpbin-v1
        weight: 50
      - service: httpbin-v2
        weight: 50
    EOF
    
  9. 确认流量按照后端服务指定的权重比例拆分。由于 v1v2 都是 50 的权重,请求应该像下面一样负载均衡到两个版本。

    for i in {1..10}; do kubectl exec -n curl -ti "$(kubectl get pod -n curl -l app=curl -o jsonpath='{.items[0].metadata.name}')" -c curl -- curl -sI http://httpbin.httpbin:14001/json | egrep 'HTTP|pod'; done
    HTTP/1.1 200 OK
    pod: httpbin-v2-6b48697db-hh4vz
    HTTP/1.1 200 OK
    pod: httpbin-v1-77c99dccc9-r78z7
    HTTP/1.1 200 OK
    pod: httpbin-v2-6b48697db-hh4vz
    HTTP/1.1 200 OK
    pod: httpbin-v1-77c99dccc9-r78z7
    HTTP/1.1 200 OK
    pod: httpbin-v2-6b48697db-hh4vz
    HTTP/1.1 200 OK
    pod: httpbin-v1-77c99dccc9-r78z7
    HTTP/1.1 200 OK
    pod: httpbin-v2-6b48697db-hh4vz
    HTTP/1.1 200 OK
    pod: httpbin-v1-77c99dccc9-r78z7
    HTTP/1.1 200 OK
    pod: httpbin-v2-6b48697db-hh4vz
    HTTP/1.1 200 OK
    pod: httpbin-v1-77c99dccc9-r78z7
    

上面的结果显示所有 10个请求都收到 HTTP 200 OK 的响应,基于 TrafficSplit 中配置的权重 httpbin-v1httpbin-v2 各响应了 5个请求。