日本熟妇hd丰满老熟妇,中文字幕一区二区三区在线不卡 ,亚洲成片在线观看,免费女同在线一区二区

基于nginx ingress+云效Appstack實現灰度發布

本文主要介紹如何配置nginx ingress和云效Appstack來實現灰度發布。

背景信息

灰度發布能降低部署風險,提升服務穩定性,尤其適用于快速迭代的軟件研發。相比 k8s 的滾動部署,基于流量特征的灰度發布更精準,風險更低。在云原生場景下,基于 nginx ingress 的灰度發布廣泛使用。該方案在流量入口調配灰度和正常流量,將灰度流量導入新版本服務,驗證通過后再全量部署,驗證不通過時可及時回退,確保用戶服務不間斷。

基本原理

對于常見的 web 服務,ingress 灰度發布的基本邏輯是:將指向同一入口(HOST)的請求,根據特征或流量比例,部分流量被路由到灰度服務中,通過監控和驗證灰度流量,判斷灰度服務是否符合上線標準

根據流量路徑,我們可以繪制 ingress 流量灰度在 k8s 上的架構圖(如下圖):

image

流量從入口的 HOST 進來后,根據 nginx-ingress 的流量標識(定義在 ingress 的 annotation 中),將符合灰度標識的請求路由到灰度環境的 service,再進入工作負載 Pod。

每個環境內部的 service 和 deployment 并不主動感知灰度標識,通常情況下,內部的 rpc 流量不攜帶灰度標識。因此,這種架構主要解決外部流量灰度的問題,適合服務數量不多、服務間調用簡單的場景。

操作步驟

接下來,我們結合云效 Appstack,來看下如何在阿里云 ACK 集群上進行應用的 ingress 灰度發布。

我們首先導入 ACK 集群并創建應用。

高的 - 2024-12-16T163041.584.png

環境管理

  1. 新建環境

    應用交付AppStack首頁,進入目標應用,分別新建灰度環境與生產環境,兩個環境共享同一個 k8s 集群,將灰度環境命名為 grey,生產環境命名為 ack-prod。

    高的 - 2024-12-16T163427.089.png

  2. 編排配置

    單擊設置 > 編排配置,定義部署編排。灰度發布生效的關鍵是 Ingress 中的 canary 注解,需要查看您的 nginx-ingress-controller 版本,確定可以支持的注解。測試的集群上 nginx-ingress-controller 的版本是 0.30,采用 header 來標識灰度流量。

    高的 - 2024-12-16T163940.407.png

    為了做到只在灰度環境中開啟灰度的路由配置,使用了編排模板的條件語句,參見下面的編排示例:

    ---
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: {{ .AppStack.appName }}-{{ .AppStack.envName }}
      namespace: {{ .Values.namespace }}
    {{ if eq .AppStack.envName "grey" }}
      annotations:
        # 開啟Canary。
        nginx.ingress.kubernetes.io/canary: "true"
        # 請求頭為_env。
        nginx.ingress.kubernetes.io/canary-by-header: "_env"
        # 請求頭_env的值為grey時,請求才會被路由到新版本服務中。
        nginx.ingress.kubernetes.io/canary-by-header-value: "grey"
    {{ end }}
    spec:
      rules:
      - host: {{ .Values.host }}
        http:
          paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: {{ .AppStack.appName }}-{{ .AppStack.envName }}
                port:
                  number: 80

    可以看到在 Ingress 的編排中,僅名稱為“grey”的環境,會開啟 canary 的 annotaion,并且將灰度標識設置為通過 _env: grey 的 header 標簽。

    同時在 Ingress 的 rules 配置中,通過變量 host 來指定路由關聯的 HOST,這里 ACK 灰度環境和 ACK 生產環境分別關聯灰度環境變量組和生產環境變量組,這兩個變量組的 host 變量采用相同的值。

    示例:

    高的 - 2024-12-16T164017.469.png

    # 
    namespace = demo-pre
    # 
    host = go.demo.prod
    # 
    namespace = demo-prod
    # 
    host = go.demo.prod

    除了 Ingress 外,還需要配置對應的 Service 和 Deployment。

    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: {{ .AppStack.appName }}-{{ .AppStack.envName }}
      namespace: {{ .Values.namespace }}
    spec:
      selector:
        run: {{ .AppStack.appName }}-{{ .AppStack.envName }}
      ports:
        - protocol: TCP
          port: 80
          targetPort: 8080
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: {{ .AppStack.appName }}-{{ .AppStack.envName }}
      labels:
        run: {{ .AppStack.appName }}-{{ .AppStack.envName }}
      namespace: {{ .Values.namespace }}
    spec:
      replicas: {{ .Values.replicas }}
      selector:
        matchLabels:
          run: {{ .AppStack.appName }}-{{ .AppStack.envName }}
      template:
        metadata:
          labels:
            run: {{ .AppStack.appName }}-{{ .AppStack.envName }}
        spec:
          containers:
            - name: main
              image: {{ .AppStack.image.backend }}
              ports:
                - containerPort: 8080
              resources:
                limits:
                  cpu: {{ .Values.cpuLimit }}
                  memory: {{ .Values.memoryLimit }}
                requests:
                  cpu: {{ .Values.cpuRequest }}
                  memory: {{ .Values.memoryRequest }}

準備示例代碼并關聯到應用中

可從 atomgit 上下載實例代碼,路徑為:https://atomgit.com/feiyuw/demo-go-echo.git

將代碼導入到云效代碼管理 Codeup,然后關聯到應用中。

高的 - 2024-12-16T164053.254.png

定義灰度發布的流程

接下來,我們通過云效 AppStack 的研發流程,定義灰度發布的整個過程,見下圖:

image.jpeg

在該流程中,每次執行,我們都會從 master 分支拉取代碼進行鏡像構建,構建完成后會轉交運維進行審批,審批通過后即開始部署過程。

部署過程包含灰度部署、灰度驗證、生產部署和灰度清理四個步驟。

  • 灰度部署步驟會將前面構建出來的鏡像更新到 ACK 灰度環境,此時通過在請求中攜帶 _env:grey 的 header 就可進行灰度驗證。

  • 灰度驗證是一個人工卡點,用于對灰度環境的觀測和驗證,如果驗證通過即自動進行生產環境的部署,如果驗證失敗,則跳過生產部署,執行灰度清理。

  • 生產部署步驟會將鏡像更新到 ACK 生產環境,此時新的服務版本將對普通用戶可見。注意,這里為了降低風險,生產部署的策略被設置為了分批,且首批暫停的模式,保證線上仍然是逐步放量的,且有機會快速回退。

  • 灰度清理步驟主要是清理灰度環境的資源,一方面節約資源,另一方面避免灰度驗證不通過時對線上的影響。

在 云效 AppStack 上相關應用的設置中,進行研發流程設置(如果僅是體驗灰度發布,可僅配置生產階段)。

高的 - 2024-12-16T164130.200.png

上述流程可以參考下面的流水線 YAML 來定義,請注意將其中的acr_docker_build_step 步驟的鏡像地址和服務連接修改為實際的值,并把grey_validate 和 ops_validate 包含的 userId 替換為自己的阿里云賬號 ID。

---
stages:
  build:
    name: "構建"
    jobs:
      go_build:
        name: "Go 鏡像構建"
        steps:
          golang_build_step:
            name: "Golang 構建"
            step: "GolangBuild"
            with:
              goVersion: "1.20.x"
              run: |
                export GOPROXY=https://goproxy.cn
                make build
          upload_step:
            step: "ArtifactUpload"
            name: "構建物上傳"
            with:
              serviceConnection: "wtdbdh89rrfdsod6"
              repo: "flow_generic_repo"
              artifact: "demo-go-echo"
              version: "prod-${CI_COMMIT_ID}.${DATETIME}"
              filePath:
              - "demo-go-echo"
              - "deploy.sh"
          acr_docker_build_step:
            name: "鏡像構建并推送至阿里云鏡像倉庫個人版"
            step: "ACRDockerBuild"
            with:
              artifact: "image"
              dockerfilePath: "Dockerfile"
              dockerRegistry: "registry.cn-zhangjiakou.aliyuncs.com/docker007/demo-go-echo"
              dockerTag: "prod-${CI_COMMIT_ID}.${DATETIME}"
              region: "cn-zhangjiakou"
              serviceConnection: "<connectionId>"
  approve:
    name: "部署審核"
    jobs:
      ops_validate:
        name: "運維審批"
        component: "ManualValidate"
        with:
          validatorType: "users"
          validators:
          - <userId>
  grey:
    name: "灰度驗證"
    jobs:
      grey_deploy_job:
        name: "ACK灰度部署"
        component: "AppStackFlowDeploy"
        with:
          application: "demo-go-echo"
          environment: "grey"
          artifacts:
          - label: "backend"
            value: "$[stages.build.go_build.acr_docker_build_step.artifacts.image.dockerUrl]"
          autoDeploy: true
      grey_validate:
        name: "灰度驗證"
        component: "ManualValidate"
        needs:
        - "grey_deploy_job"
        with:
          validatorType: "users"
          validators:
          - <userId>
  deploy:
    name: "部署"
    jobs:
      ack_deploy_job:
        name: "ACK生產部署"
        component: "AppStackFlowDeploy"
        condition: |
          succeed('grey.grey_validate')
        with:
          application: "demo-go-echo"
          environment: "ack-prod"
          artifacts:
          - label: "backend"
            value: "$[stages.build.go_build.acr_docker_build_step.artifacts.image.dockerUrl]"
          autoDeploy: true
  cleanup:
    name: "清理環境"
    jobs:
      cleanup_grey_env_job:
        name: "清理灰度環境"
        component: "AppStackCleanEnv"
        needs:
        - "grey.grey_validate"
        - "deploy.ack_deploy_job"
        condition: |
          failed('grey.grey_validate') || succeed('deploy.ack_deploy_job')
        with:
          application: "demo-go-echo"
          environment: "grey"
          deleteEnv: "cleanEnv"

驗證灰度發布流程

我們假設研發流程僅包含生產階段,先運行一次生產階段,將應用部署到灰度和生產環境中,注意:環境第一次部署可能需要手動創建部署單。

修改代碼,將 routes.go 里面的版本號修改為新的值,再次執行生產階段,直到灰度驗證步驟,此時生產環境與灰度環境運行不同的版本。

通過 kubectl get ing -A 獲取 Ingress 的出口 IP,在本地/etc/hosts 中將其綁定到 go.demo.prod 中,如:

127.0.0.1   go.demo.prod  # 將127.0.0.1修改為正確的出口IP

打開終端,通過 httpie 或者 curl 請求/version 接口,以 httpie 為例,請求命令為:

http -v http://go.demo.prod/version    # 請求正式環境
http -v http://go.demo.prod/version _env:grey    # 請求灰度環境

常見問題

  1. 有了灰度環境,生產環境部署的時候還需要分批嗎?

    建議在生產環境部署的時候仍然開啟分批,因為灰度環境雖然驗證通過了,但受到數據量等影響,生產環境仍然不建議全量一起上線,通過分批,可以把風險控制在小范圍內,避免大的故障的發生。

  2. 如何在研發流程上整合配置變更和數據變更?

    可以將配置變更和數據變更作為研發階段的步驟,編排到研發流程的流水線 YAML 中,通常建議在應用部署前執行數據變更,部署后執行配置變更。同時,對應于 K8s 上的灰度環境,如果采用了類似 Nacos 這樣的配置中心,也應當由對應的灰度 namespace,從而避免直接修改生產配置。

  3. 灰度環境包含多個應用,如何保證其內部服務間調用也是走的灰度環境?

    完整的方案建議參考 MSE 等產品。

    如果應用數量比較少,鏈路比較簡單,且接受基于 K8s 的簡單方案,可以為每個應用都定義一個灰度環境,共享同一個集群和 namespace,應用間通過 Service 進行調用。此時,由于 namespace 的隔離,灰度環境內的應用互相調用只會調用同 namespace 下的其它應用的灰度版本。

    這種方案需要保證各應用灰度環境的長期可用,因此研發流程最后的清理環境步驟需要被移除。

  4. 如何在流程中關聯其它類型的發布如函數計算?

    可以在函數計算的相關步驟編排到研發流程的流水線 YAML 中,從而實現雙方的聯動。

其他相關