k8s

Kruise Rollout+Higress实现灰度发布

上篇文章测试了开源版Higress暂不支持全链路灰度发布的功能,但是基本的灰度发布还是支持的,下面就实际测试一下。

金丝雀发布

部署demo

官方文档:https://higress.cn/docs/latest/user/kruise-rollout/
示例中的镜像registry.cn-hangzhou.aliyuncs.com/mse-ingress/version:v1已经下载不到了,我重新写了一个,程序运行在80端口,访问/version路径会返回version: v1

cat main.go

package main

import (
    "fmt"
    "log"
    "net/http"
)

func versionHandler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintln(w, "version: v1")
}

func main() {
    http.HandleFunc("/version", versionHandler)
    log.Println("Starting server on port 80")
    log.Fatal(http.ListenAndServe(":80", nil))
}

编写Dockerfile。

cat Dockerfile

FROM golang:1.18 as builder
WORKDIR /app
COPY go.mod ./
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -o /app/main .

FROM alpine:latest
WORKDIR /root/
COPY --from=builder /app/main .
EXPOSE 80
CMD ["./main"]

构建镜像。

docker build -t version:v1 .

创建服务。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: demo
spec:
  replicas: 3
  selector:
    matchLabels:
      app: demo
  template:
    metadata:
      labels:
        app: demo
    spec:
      containers:
      - name: main
        image: version:v1
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: demo
spec:
  ports:
  - port: 80
    targetPort: 80
    protocol: TCP
    name: http
  selector:
    app: demo
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: demo
spec:
  ingressClassName: higress
  rules:
  - http:
      paths:
      - backend:
          service:
            name: demo
            port:
              number: 80
        path: /version
        pathType: Exact
    host: demo.com

file

创建rollout

apiVersion: rollouts.kruise.io/v1alpha1
kind: Rollout
metadata:
  name: rollouts-demo
spec:
  objectRef:
    workloadRef:
      apiVersion: apps/v1
      kind: Deployment
      name: demo
  strategy:
    canary:
      steps:
      - weight: 10
        pause: {}
        replicas: 1
      - weight: 30
        pause: {}
        replicas: 2
      trafficRoutings:
      - service: demo
        ingress:
          classType: higress
          name: demo
  • 其中 workloadRef 旁路式的选择需要 Rollout 的 Workload,此处为 Deployment,支持其他 Workload(如CloneSet、DaemonSet)。
  • 其中 canary.Steps 定义了整个 Rollout 过程一共分为3批,其中第一批只灰度一个新版本 Pod,并且 routing 10% 流量到新版本 Pod,并且需要人工确认是否继续发布;第二批只灰度两个新版本 Pod,并且 routing 30%流量到新版本 Pod,并且需要人工确认是否继续发布;最后一批,无需定义,即全量发布。
  • 其中 trafficRoutings 指向了需要感知流量规则的资源,kruise rollout会自动更新相关资源,实时反射目标流量规则。

修改镜像

修改上面的main.go,把version: v1换成version: v2,重新构建镜像版本为version:v2

file

当前执行完第一批发布,并且出于暂停状态,需要人工确认才能继续下一批次发布。并且创建了一个新的deployment demo-ggplk

测试流量。

for i in {1..10}; do curl http://nodeip:31779/version -H "host: demo.com"; done

file

有10%流量访问v2版本。

继续发布

kubectl-kruise rollout approve rollout/rollouts-demo

file

创建了2个新版本pod。

测试流量。

file

全量发布

在新版本pod全部启动后,再删除deployment demo-ggplk,完成发布。

file

流量全部转发至新版本。

file

A/B Test

只有匹配特定规则的请求才会被引流到新版本,常见的做法包括基于Http Header和Cookie。

file

回滚环境

删除上面的rollout,把上面的v2版本回滚到v1版本。

创建rollout

apiVersion: rollouts.kruise.io/v1alpha1
kind: Rollout
metadata:
  name: rollouts-header
spec:
  objectRef:
    workloadRef:
      apiVersion: apps/v1
      kind: Deployment
      name: demo
  strategy:
    canary:
      steps:
      - matches:
        - headers:
          - name: user-agent
            value: android
        pause: {}
        replicas: 1
      trafficRoutings:
      - service: demo
        ingress:
          classType: higress
          name: demo

其中 canary.Steps 定义了整个 Rollout 过程一共分为2批,其中第一批只灰度一个新版本 Pod,并且将带有 HTTP Header user-agent: android (即安卓用户)的流量 routing 到新版本 Pod,并且需要人工确认是否继续发布;最后一批,无需定义,即全量发布。

file

修改镜像

修改镜像版本为v2。

file

测试流量

curl http://nodeip:31779/version -H "host: demo.com" -H "user-agent: android"

file

来自安卓的流量路由到v2版本,非安卓的流量路由到v1版本。

继续发布

file

分类: k8s
0 0 投票数
文章评分
订阅评论
提醒
guest

0 评论
最旧
最新 最多投票
内联反馈
查看所有评论

相关文章

开始在上面输入您的搜索词,然后按回车进行搜索。按ESC取消。

返回顶部
0
希望看到您的想法,请您发表评论x