<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Ingress企業(yè)實戰(zhàn):金絲雀與藍綠發(fā)布篇

          共 11450字,需瀏覽 23分鐘

           ·

          2023-08-31 08:11

          背景

          現(xiàn)如今,越來越多的應(yīng)用采用了微服務(wù)架構(gòu),這也導(dǎo)致了應(yīng)用數(shù)量相比傳統(tǒng)模式更多,管理更加復(fù)雜,發(fā)布更加頻繁,如果直接將新版本上線發(fā)布給全部用戶。一旦遇到線上事故(或BUG),對用戶的影響極大,解決問題周期較長,甚至有時不得不回滾到前一版本,嚴重影響了用戶體驗。為了保證整體系統(tǒng)的穩(wěn)定,風險降到最低,我們可以采用灰度發(fā)布與藍綠發(fā)布等不同的發(fā)布方式。

          什么是金絲雀發(fā)布

          金絲雀發(fā)布,又稱灰度發(fā)布,是指通過讓小部份用戶流量引入的新版本進行測試,如果一切順利,則可以增加(可能逐漸增加)百分比,逐步替換舊版本。如在過程中出現(xiàn)任何問題,則可以中止并快速回滾到舊版本。最簡單的方式是隨機選擇百分比請求到金絲雀版本,但在更復(fù)雜的方案下,則可以基于請求的內(nèi)容、特定范圍的用戶或其他屬性等。

          什么是藍綠發(fā)布

          藍綠發(fā)布,提供了一種零宕機的部署方式,是一種以可觀測的方式發(fā)布應(yīng)用的方式,目的減少發(fā)布過程中停止時間。在保留老版本的同時部署新版本,將兩個版本同時在線,新版本和老版本相互熱備,通過切換路由權(quán)重的方式(非0即100)實現(xiàn)應(yīng)用的不同版本上線或者下線,如果有問題可以快速地回滾到老版本。這樣做的好處是無需停機,并且風險較小。

          示例應(yīng)用部署

          部署示例版本:

          $ cat demo.yml
          apiVersion: apps/v1
          kind: Deployment
          metadata:
            name: demo
            labels:
              app: demo
          spec:
            replicas: 1
            selector:
              matchLabels:
                app: demo
            template:
              metadata:
                labels:
                  app: demo
              spec:
                containers:
                - name: demo
                  imagePullPolicy: Always
                  image: registry.cn-shanghai.aliyuncs.com/kubesre01/demo:v1
                  ports:
                  - containerPort: 8080
          ---
          apiVersion: v1
          kind: Service
          metadata:
            name: demo-svc
          spec:
            type: ClusterIP
            selector:
              app: demo
            ports:
              - port: 8080
                targetPort: 8080
          $ kubectl apply -f demo.yml
          deployment.apps/demo created

          部署新版本:

          $ cat demo_new.yml
          apiVersion: apps/v1
          kind: Deployment
          metadata:
            name: demo-new
            labels:
              app: demo-new
          spec:
            replicas: 1
            selector:
              matchLabels:
                app: demo-new
            template:
              metadata:
                labels:
                  app: demo-new
              spec:
                containers:
                - name: demo-new
                  imagePullPolicy: Always
                  image: registry.cn-shanghai.aliyuncs.com/kubesre01/demo:v2
                  ports:
                  - containerPort: 8080
          ---
          apiVersion: v1
          kind: Service
          metadata:
            name: demo-new-svc
          spec:
            type: ClusterIP
            selector:
              app: demo-new
            ports:
              - port: 8080
                targetPort: 8080

          $
           kubectl apply -f demo_new.yml
          deployment.apps/demo_new created

          創(chuàng)建Ingress記錄:

          $ cat demo-ingress.yml
          apiVersion: networking.k8s.io/v1
          kind: Ingress
          metadata:
            name: demo
          spec:
            rules:
            - host: demo.kubesre.com
              http:
                paths:
                - path: /info
                  pathType: Prefix
                  backend:
                    service:
                      name: demo-svc 
                      port:
                        number: 8080
            ingressClassName: nginx

          $
           kubectl apply -f demo-ingress.yml
          ingress.networking.k8s.io/demo-ingress created

          #
           訪問如下內(nèi)容說明部署成功!
          $ curl  http://demo.kubesre.com/info
          {"message":"云原生運維圈!"}

          到此為止,示例應(yīng)用與新版本已部署完畢!

          基于客戶端請求頭的流量切分

          假設(shè)線上已運行了一套對外提供的七層demo應(yīng)用,此時開發(fā)了一些新的功能,需要上線新版本demo應(yīng)用,但是又不想直接替換成新版本demo應(yīng)用,而是希望將請求頭包含user=kubesre的客戶端請求轉(zhuǎn)發(fā)到新版本demo應(yīng)用中,進行驗證測試新版本demo應(yīng)用,等測試驗證通過并穩(wěn)定后,可將所有流量從老版本demo應(yīng)用切換到新版本demo應(yīng)用中,再平滑地將老版本demo應(yīng)用下線。創(chuàng)建新版本Ingress:

          $ cat demo-new-canary.yml
          apiVersion: networking.k8s.io/v1
          kind: Ingress
          metadata:
            name: demo-new-canary
            annotations:
              # 開啟Canary。
              nginx.ingress.kubernetes.io/canary: "true"
              # 請求頭為user
              nginx.ingress.kubernetes.io/canary-by-header: "user"
              # 請求頭user的值為kubesre時,請求才會被路由到新版本服務(wù)new-new中。
              nginx.ingress.kubernetes.io/canary-by-header-value: "kubesre"

          spec:
            rules:
            - host: demo.kubesre.com
              http:
                paths:
                - path: /info
                  pathType: Prefix
                  backend:
                    service:
                      name: demo-new-svc
                      port:
                        number: 8080
            ingressClassName: nginx

          $
           kubectl apply -f demo-new-canary.yml
          ingress.networking.k8s.io/demo-new-canary created

          測試驗證:

          # 請求頭為user: kubesre,訪問到新的版本
          $ curl -H "user: kubesre" http://demo.kubesre.com/info
          {"message":"云原生運維圈!新版本"}

          #
           其他則訪問到老的版本
          $ curl  http://demo.kubesre.com/info
          {"message":"云原生運維圈!"}

          基于客戶端來源IP的流量切分

          假設(shè)線上已運行了一套對外提供的七層demo應(yīng)用,此時開發(fā)了一些新的功能,需要上線新版本demo應(yīng)用,又不想直接替換成新版本demo應(yīng)用,而是只希望公司內(nèi)部人員能訪問到新版本demo應(yīng)用中,進行測試驗證新版本demo應(yīng)用,非公司內(nèi)部人員訪問還是訪問到老版本應(yīng)用中。等公司內(nèi)部人員測試驗證通過并穩(wěn)定后,可將所有流量從老版本demo應(yīng)用切換到新版本demo應(yīng)用中,再平滑地將老版本demo應(yīng)用下線。創(chuàng)建新版本Ingress:

          $ cat demo-new-canary.yml
          apiVersion: networking.k8s.io/v1
          kind: Ingress
          metadata:
            name: demo-new-canary
            annotations:
              nginx.ingress.kubernetes.io/canary: "true"
              nginx.ingress.kubernetes.io/canary-by-header: "X-Forwarded-For"
              # 假設(shè)客戶端來源IP為123.456.789.123
              nginx.ingress.kubernetes.io/canary-by-header-value: "123.456.789.123"
              
          spec:
            rules:
            - host: demo.kubesre.com
              http:
                paths:
                - path: /info
                  pathType: Prefix
                  backend:
                    service:
                      name: demo-new-svc
                      port:
                        number: 8080
            ingressClassName: nginx

          $
           kubectl apply -f demo-new-canary.yml
          ingress.networking.k8s.io/demo-new-canary created

          測試驗證:

          # 通過請求頭模擬來源IP,真實環(huán)境不需要
          $ curl -H "X-Forwarded-For:123.456.789.123" http://demo.kubesre.com/info
          {"message":"云原生運維圈!新版本"}

          #
           其他則訪問到老的版本
          $ curl  http://demo.kubesre.com/info
          {"message":"云原生運維圈!"}

          基于服務(wù)權(quán)重的流量切分

          假設(shè)線上已運行了一套對外提供的七層demo應(yīng)用,此時修復(fù)了一些問題,需要上線新版本demo應(yīng)用,又不想直接替換成新版本demo應(yīng)用,而是希望將20%的流量切換新版本。待運行一段時間穩(wěn)定后,可將所有流量從老版本demo應(yīng)用切換到新版本demo應(yīng)用中,再平滑地將老版本demo應(yīng)用下線。創(chuàng)建新版本Ingress:

          $ cat demo-new-canary.yml
          apiVersion: networking.k8s.io/v1
          kind: Ingress
          metadata:
            name: demo-new-canary
            annotations:
              nginx.ingress.kubernetes.io/canary: "true"
              nginx.ingress.kubernetes.io/canary-by-header: "X-Forwarded-For"
              # 將20%的流量轉(zhuǎn)發(fā)到新版本
              nginx.ingress.kubernetes.io/canary-weight: "20"
              
          spec:
            rules:
            - host: demo.kubesre.com
              http:
                paths:
                - path: /info
                  pathType: Prefix
                  backend:
                    service:
                      name: demo-new-svc
                      port:
                        number: 8080
            ingressClassName: nginx

          $
           kubectl apply -f demo-new-canary.yml
          ingress.networking.k8s.io/demo-new-canary created

          測試驗證:

          # 可以看出,有4/20的幾率由新版本服務(wù)響應(yīng),符合20%服務(wù)權(quán)重的設(shè)置。
          $ for i in {1..20}; do curl http://demo.kubesre.com/info; done;
          {"message":"云原生運維圈!"}
          {"message":"云原生運維圈!"}
          {"message":"云原生運維圈!"}
          {"message":"云原生運維圈!"}
          {"message":"云原生運維圈!新版本"}
          {"message":"云原生運維圈!"}
          {"message":"云原生運維圈!"}
          {"message":"云原生運維圈!新版本"}
          {"message":"云原生運維圈!"}
          {"message":"云原生運維圈!新版本"}{
          "message":"云原生運維圈!新版本"}
          {"message":"云原生運維圈!"}
          {"message":"云原生運維圈!"}
          {"message":"云原生運維圈!"}
          {"message":"云原生運維圈!"}
          {"message":"云原生運維圈!"}
          {"message":"云原生運維圈!"}
          {"message":"云原生運維圈!"}
          {"message":"云原生運維圈!"}
          {"message":"云原生運維圈!"}

          注解說明

          Nginx Ingress支持通過配置注解(Annotations)來實現(xiàn)不同場景下的發(fā)布和測試,可以滿足灰度發(fā)布、藍綠發(fā)布、A/B測試等業(yè)務(wù)場景。具體實現(xiàn)過程如下:為服務(wù)創(chuàng)建兩個Ingress,一個為常規(guī)Ingress,另一個為帶nginx.ingress.kubernetes.io/canary: "true"注解的Ingress,稱為Canary Ingress;為Canary Ingress配置流量切分策略Annotation,兩個Ingress相互配合,即可實現(xiàn)多種場景的發(fā)布和測試。Nginx Ingress的Annotation支持以下幾種規(guī)則:

          • nginx.ingress.kubernetes.io/canary-by-header基于Header的流量切分,適用于灰度發(fā)布。如果請求頭中包含指定的header名稱,并且值為“always”,就將該請求轉(zhuǎn)發(fā)給Canary Ingress定義的對應(yīng)后端服務(wù)。如果值為“never”則不轉(zhuǎn)發(fā),可用于回滾到舊版本。如果為其他值則忽略該annotation,并通過優(yōu)先級將請求流量分配到其他規(guī)則。
          • nginx.ingress.kubernetes.io/canary-by-header-value必須與canary-by-header一起使用,可自定義請求頭的取值,包含但不限于“always”或“never”。當請求頭的值命中指定的自定義值時,請求將會轉(zhuǎn)發(fā)給Canary Ingress定義的對應(yīng)后端服務(wù),如果是其他值則忽略該annotation,并通過優(yōu)先級將請求流量分配到其他規(guī)則。
          • nginx.ingress.kubernetes.io/canary-by-header-pattern與canary-by-header-value類似,唯一區(qū)別是該annotation用正則表達式匹配請求頭的值,而不是某一個固定值。如果該annotation與canary-by-header-value同時存在,該annotation將被忽略。
          • nginx.ingress.kubernetes.io/canary-by-cookie基于Cookie的流量切分,適用于灰度發(fā)布。與canary-by-header類似,該annotation用于cookie,僅支持“always”和“never”,無法自定義取值。
          • nginx.ingress.kubernetes.io/canary-weight基于服務(wù)權(quán)重的流量切分,適用于藍綠部署。表示Canary Ingress所分配流量的百分比,取值范圍[0-100]。例如,設(shè)置為100,表示所有流量都將轉(zhuǎn)發(fā)給Canary Ingress對應(yīng)的后端服務(wù)。

          以上注解規(guī)則會按優(yōu)先級進行評估,優(yōu)先級為:canary-by-header -> canary-by-cookie -> canary-weight。

          總結(jié)

          本文介紹了金絲雀發(fā)布與藍綠發(fā)布,并以企業(yè)案例的方式講解了不同的場景使用什么樣的發(fā)布方式,下一章將介紹Ingress 證書管理與雙向認證,請敬請期待!

          添加??下面微信,拉你進群與大佬一起探討云原生!


          瀏覽 467
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  天天射天天日天天干 | 日韩欧美动作影片 | 蜜臀av秘 一区二区三区 | 另类TS人妖一区二区三区牧瑶 | 特级毛片操逼 |