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

先决条件

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

演示

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

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

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

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

  1. 启用宽松模式

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

    1. # Create the curl namespace
    2. kubectl create namespace curl
    3. # Add the namespace to the mesh
    4. osm namespace add curl
    5. # Deploy curl client in the curl namespace
    6. kubectl apply -f https://raw.githubusercontent.com/openservicemesh/osm-docs/release-v1.2/manifests/samples/curl/curl.yaml -n curl

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

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

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

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

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

    1. 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
    2. HTTP/1.1 200 OK
    3. pod: httpbin-v1-77c99dccc9-q2gvt
    4. HTTP/1.1 200 OK
    5. pod: httpbin-v1-77c99dccc9-q2gvt
    6. HTTP/1.1 200 OK
    7. pod: httpbin-v1-77c99dccc9-q2gvt
    8. HTTP/1.1 200 OK
    9. pod: httpbin-v1-77c99dccc9-q2gvt
    10. HTTP/1.1 200 OK
    11. pod: httpbin-v1-77c99dccc9-q2gvt
    12. HTTP/1.1 200 OK
    13. pod: httpbin-v1-77c99dccc9-q2gvt
    14. HTTP/1.1 200 OK
    15. pod: httpbin-v1-77c99dccc9-q2gvt
    16. HTTP/1.1 200 OK
    17. pod: httpbin-v1-77c99dccc9-q2gvt
    18. HTTP/1.1 200 OK
    19. pod: httpbin-v1-77c99dccc9-q2gvt
    20. HTTP/1.1 200 OK
    21. pod: httpbin-v1-77c99dccc9-q2gvt

    上面的输出表明:全部 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 的选择器。

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

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

    1. $ 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
    2. HTTP/1.1 200 OK
    3. pod: httpbin-v2-6b48697db-cdqld
    4. HTTP/1.1 200 OK
    5. pod: httpbin-v1-77c99dccc9-q2gvt
    6. HTTP/1.1 200 OK
    7. pod: httpbin-v1-77c99dccc9-q2gvt
    8. HTTP/1.1 200 OK
    9. pod: httpbin-v1-77c99dccc9-q2gvt
    10. HTTP/1.1 200 OK
    11. pod: httpbin-v2-6b48697db-cdqld
    12. HTTP/1.1 200 OK
    13. pod: httpbin-v2-6b48697db-cdqld
    14. HTTP/1.1 200 OK
    15. pod: httpbin-v1-77c99dccc9-q2gvt
    16. HTTP/1.1 200 OK
    17. pod: httpbin-v2-6b48697db-cdqld
    18. HTTP/1.1 200 OK
    19. pod: httpbin-v2-6b48697db-cdqld
    20. HTTP/1.1 200 OK
    21. pod: httpbin-v1-77c99dccc9-q2gvt

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