渐进式交付实践:通过 Argo Rollouts 和 FSM Gateway 实现金丝雀发布

发布于:2024-04-19 ⋅ 阅读:(24) ⋅ 点赞:(0)

渐进式交付(Progressive delivery)是一种软件发布策略,旨在更安全、更可控地将新版本软件逐步推出给用户。它是持续交付的进一步提升,允许开发团队在发布新版本时拥有更细粒度的控制,例如可以根据用户反馈、性能指标和其他关键数据来调整发布过程。渐进式交付通过利用一系列现代部署方案如蓝绿部署(Blue-Green Deployments)、金丝雀发布(Canary Releases)等让开发团队能够更灵活地管理风险,同时加快新功能的发布速度。

Argo Rollouts 包括一个 Kubernetes控制器 和一组 CRD,提供如蓝绿色、金丝雀、金丝雀分析、体验等高级部署功能和 Kubernetes 的渐进交付功能。

之前曾分享过 使用 Argo Rollouts 和服务网格实现自动可控的金丝雀发布(彼时的服务网格现已更名为 FSM),这是通过服务网格技术实现了东西向流量的金丝雀发布。虽然以此可以确保内部服务之间的平滑过渡,但这并不足以保证最终用户体验的质量。我们还需要手段来控制新版本对最终用户的可变性及影响,因此对于南北向流量 – 入口的网络流量 – 金丝雀发布变得不可或缺。

对于 Kubernetes 的入口流量管理,常见的有如 Ingress ControllerGateway API。作为服务网格 FSM 组件之一的 FSM Gateway 是一个开源的 Kubernetes Gateway API 实现,它使用可编程应用引擎 Pipy 作为代理配置路由和策略来管理入口流量。关于 FSM Gateway 的使用,可以查看之前的 系列文章

rollouts-plugin-trafficrouter-gatewayapi 是 Argo Rollouts 的一个插件它实现了 Kubernetes Gateway API 规范。使用它可以使用 FSM Gateway 实现渐进式的交付,当然你可以使用其他的实现。

今天就以 FSM Gateway 为例介绍如何使用 Argo Rollouts 进行南北向流量的金丝雀发布。

前置条件

  • Kubernetes 集群,最低版本 1.23
  • kubectl cli

准备环境

安装 FSM Gateway

我们可以通过 FSM CLI 来安装 FSM Gateway,参考 文档 下载并安装 FSM CLI,当前最新的版本为 1.2.3。

system=$(uname -s | tr '[:upper:]' '[:lower:]')
arch=$(uname -m | sed -E 's/x86_/amd/' | sed -E 's/aarch/arm/')
release=v1.2.3
curl -L https://github.com/flomesh-io/fsm/releases/download/$release/fsm-$release-$system-$arch.tar.gz | tar -vxzf -
./$system-$arch/fsm version
cp ./$system-$arch/fsm /usr/local/bin/fsm

使用下面的命令安装 FSM Gateway,作为 服务网格 FSM 的众多组件之一,FSM Gateway 的运行会由 FSM 控制器管理。

fsm install \
    --set=fsm.fsmGateway.enabled=true

如果你已经安装了 FSM,可以通过下面的命令来启用网关。

fsm gateway enable

在成功安装 FSM Gateway 之后,可以看到 gateway class fsm-gatweay-cls 已经就绪。

kubectl get gatewayclass
NAME              CONTROLLER                      ACCEPTED   AGE
fsm-gateway-cls   flomesh.io/gateway-controller   True       2m35s

与 FSM Gateway 一同安装的还有 Gateway API 的 CRD

创建 Gateway 对象

安装了 FSM Gateway 并不意味着马上可以开始接管流量,我们还需要创建 Gateway 对象

kubectl apply -n default -f - <<EOF
apiVersion: gateway.networking.k8s.io/v1beta1
kind: Gateway
metadata:
  name: simple-fsm-gateway
spec:
  gatewayClassName: fsm-gateway-cls
  listeners:
    - protocol: HTTP
      port: 80
      name: http
      allowedRoutes:
        namespaces:
          from: Same
EOF

获取 Gateway 的 IP 地址。

export GATEWAY_IP=$(kubectl get svc -n default -l app=fsm-gateway -o jsonpath='{.items[0].status.loadBalancer.ingress[0].ip}')

安装 Argo Rollouts

使用下面的命令在集群中安装最新的 Argo Rollouts,其运行在命名空间 argo-rollouts 中。

kubectl create namespace argo-rollouts
kubectl apply -n argo-rollouts -f https://github.com/argoproj/argo-rollouts/releases/latest/download/install.yaml

为了 Argo Rollouts 能够通过修改路由来控制流量,需要为其创建 ClusterRoleClusterRoleBinding。(这个操作在每个集群只需一次即可)

kubectl apply -f - <<EOF
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: gateway-controller-role
  namespace: argo-rollouts
rules:
  - apiGroups:
      - "*"
    resources:
      - "*"
    verbs:
      - "*"
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: gateway-admin
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: gateway-controller-role
subjects:
  - namespace: argo-rollouts
    kind: ServiceAccount
    name: argo-rollouts
EOF
安装 kubectl argo 插件

使用 kubectl argo 插件可以通过命令行对发布进行操作。

在 macOS 下,其他平台参考 官方安装文档

brew install argoproj/tap/kubectl-argo-rollouts

通过下面的命令启动 Argo Rollouts Dashboard,在浏览器中打开 [http://localhost:3100/rollouts](http://localhost:3100/rollouts) 就可访问 Dashboard。

kubectl argo rollouts dashboard

安装 Rollouts Gateway API 插件

安装 Gateway API 插件需要在 Configmap 中指定插件的下载地址,执行下面的命令后 Rollouts 的控制面会从该地址下载并安装。截止本文发布,插件的最新版本是 0.2.0

注意,请安装对应平台的插件。

kubectl apply -f - <<EOF
apiVersion: v1
kind: ConfigMap
metadata:
  name: argo-rollouts-config # must be so name
  namespace: argo-rollouts # must be in this namespace
data:
  trafficRouterPlugins: |-
    - name: "argoproj-labs/gatewayAPI"
      location: "https://github.com/argoproj-labs/rollouts-plugin-trafficrouter-gatewayapi/releases/download/v0.2.0/gateway-api-plugin-linux-amd64"
EOF

创建 Service

创建两个 Service argo-rollouts-stable-serviceargo-rollouts-canary-service,这两个 Service 将作为 Gateway 的后端服务,由 Rollouts 控制到各个 Service 的流量权重。

kubectl apply -n default -f - <<EOF
apiVersion: v1
kind: Service
metadata:
  name: argo-rollouts-stable-service
spec:
  ports:
    - port: 80
      targetPort: http
      protocol: TCP
      name: http
  selector:
    app: rollouts-demo
---
apiVersion: v1
kind: Service
metadata:
  name: argo-rollouts-canary-service
spec:
  ports:
    - port: 80
      targetPort: http
      protocol: TCP
      name: http
  selector:
    app: rollouts-demo
EOF

创建 HTTP 路由

有了服务之后,就是在 Gateway 创建对应的 HTTPRoute 配置路由,默认将所有的流量都代理到稳定版。

kubectl apply -n default -f - <<EOF
kind: HTTPRoute
apiVersion: gateway.networking.k8s.io/v1beta1
metadata:
  name: argo-rollouts-http-route
spec:
  parentRefs:
    - name: simple-fsm-gateway
      port: 80
  hostnames:
  - "demo.example.com"
  rules:
  - matches:
    - path:
        type: PathPrefix
        value: /  
    backendRefs:
    - name: argo-rollouts-stable-service
      kind: Service
      port: 100
    - name: argo-rollouts-canary-service
      kind: Service
      port: 0
EOF

创建 Rollout

创建资源 Rollout:

  • 使用策略 canary
  • 指定创面创建的两个 Service 分别作为 stableServicecanaryService
  • 流量路由使用插件 argoproj-labs/gatewayAPI,以及操作的 HTTPRouteargo-rollouts-http-route
  • 指定发布的流程 steps
  • 最终要的就是 template 中配置我们的应用,也就是稳定版,与 Deployment 的 template 一致。
kubectl apply -n default -f- <<EOF
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
  name: rollouts-demo
spec:
  replicas: 3
  strategy:
    canary:
      canaryService: argo-rollouts-canary-service # our created canary service
      stableService: argo-rollouts-stable-service # our created stable service
      trafficRouting:
        plugins:
          argoproj-labs/gatewayAPI:
            httpRoute: argo-rollouts-http-route # our created httproute
            namespace: default
      steps:
      - setWeight: 30
      - pause: { duration: 30s }
      - setWeight: 60
      - pause: { duration: 30s }
      - setWeight: 100
      - pause: { duration: 30s }
  revisionHistoryLimit: 2
  selector:
    matchLabels:
      app: rollouts-demo
  template:
    metadata:
      labels:
        app: rollouts-demo
    spec:
      containers:
        - name: rollouts-demo
          image: kostiscodefresh/summer-of-k8s-app:v1
          ports:
            - name: http
              containerPort: 8080
              protocol: TCP
          resources:
            requests:
              memory: 32Mi
              cpu: 5m
EOF

创建完成后便通过命令行访问示例应用了。

curl -H "host: demo.example.com" $GATEWAY_IP/callme

此时会看到如下的结果,说明正在运行的 1.0 版本。

<div class='pod' style='background:#44B3C2'> ver: 1.0
 </div>

执行金丝雀发布

接着我们修改 Rollout,将示例应用的镜像更新为 2.0 版本。

kubectl patch rollout rollouts-demo -n default \
  --type='json' -p='[{"op": "replace", "path": "/spec/template/spec/containers/0/image", "value":"kostiscodefresh/summer-of-k8s-app:v2"}]'

可以通过下命令持续查看示例应用的运行。

while true; do curl -H "host: demo.example.com" $GATEWAY_IP/callme; done

当然,在 Argo Rollouts 的 Dashboard 中我们可以更加直观地看到 Rollout 的执行流程。

最终,rollouts-demo 完成升级,旧版本的实例完全退出。

关于 Flomesh

Flomesh(易衡科技)成立于 2018 年,自主研发并开源了高性能可编程代理 Pipy(https://github.com/flomesh-io/pipy)。以 Pipy 为基础,Flomesh 研发了软件负载均衡、服务网格两款软件产品。为工信部认证的可信云产品、可信开源项目。

Flomesh 核心竞争力来自完全自研的核心组件 Pipy,该组件高性能、高可靠、低延迟、可编程、可扩展、低依赖,采用 C++ 开发,内置自研的 JS 引擎,支持适用 JS 脚本做扩展开发。支持包括 x86、arm、龙芯、海光等硬件 CPU 架构;支持 Linux、FreeBSD、macOS、Windows、OpenWrt 等多种核心的操作系统。

Flomesh 成立以来,以技术为根基、以客户为导向,产品被应用在头部股份制商业银行总行、大型保险公司、运营商总部以及研究院等众多客户和多个场景。

在这里插入图片描述