k8s實現灰度發布


  灰度發布在實際生產部署中是經常被使用的方式,常規的方法是手動從前端LB(負載均衡)上將后端服務器摘掉,然后,停服務,最后上傳代碼,完成軟連接更新。在使用CI/CD工具時,這個過程變得自動化了,我們只需要通過Jenkins這個功能強大的開源持續集成和部署工具,就可以聯合Gitlab 或 Gogs 來實現自動拉取代碼,並根據自己編寫的pipeline腳本,實現自動連接到LB上摘掉后端Server,並自動連接到后端Server上,上傳代碼,並重啟服務,最后通過郵件通知管理員整個過程的結果報告。但今天,K8s的更讓我們看到了一種更便捷高效的灰度發布的實現方法,下面就來說說:

由於本人能力有限,對k8s的理解尚淺,原理部分在后續研究透徹后,在來詳細說明,本編僅供初學者參考

首先需要制作此次實驗的基礎鏡像:
1. Dockerfile的編寫:
  mkdir dockerfile && cd dockerfile
  vim Dockerfile    #注意: Dockerfile的文件名首字母要大寫
    FROM alpine:latest

    MAINTAINER "ZCF <zcf@zczf.com>"

    ENV NGX_DOC_ROOT="/var/lib/nginx/html" HOSTNAME="" IP="" PORT="" INDEX_PAGE=""
    RUN apk --no-cache add nginx && mkdir -p ${NGX_DOC_ROOT}/shop /run/nginx

    COPY chk.html   ${NGX_DOC_ROOT}
    COPY entrypoint.sh /bin

    CMD ["/usr/sbin/nginx","-g","daemon off;"] #定義啟動nginx服務為前端啟動, -g:是global段,中修改daemon off;
    ENTRYPOINT ["/bin/entrypoint.sh"] #將CMD的命令,作為參數傳遞給/bin/entrypoint.sh 腳本.


    #准備Dockerfile配套的基礎文件:
    1) 啟動容器時,執行的腳本文件: entrypoint.sh
      vim entrypoint.sh
        #!/bin/sh

        echo "<h1>WELCOME TO ${HOSTNAME:-www.zcf.com} WEB SITE | `date` | `hostname` | `hostname -i` | -${YOU_INFO:-v1}- | </h1>" > ${NGX_DOC_ROOT}/index.html
        cat > /etc/nginx/conf.d/default.conf <<EOF
        server {
          server_name ${HOSTNAME:-www.zcf.com};
          listen ${IP:-0.0.0.0}:${PORT:-80};
          root ${NGX_DOC_ROOT};
          location / {
            index ${INDEX_PAGE} index.html index.htm;
          }
          location = /404.html {
            internal;
          }
        }
        EOF

        exec "$@"      #它就是來接受CMD傳入的參數的.

  2 ) 給entrypoint.sh 添加執行權限
    chown +x entrypoint.sh

  3) 后期做健康檢查時,使用的html文件:
    echo OK > chk.html

2. 開始制作docker鏡像文件:
  docker build --tag myapp:v1 ./

3. 將制作好的鏡像文件,打上標簽,並上傳到harbor上。
  docker login harbor.zcf.com -u admin -p 123456      #登錄harbor
  docker tag myapp:v1 harbor.zcf.com/k8s/myapp:v1      #先打上harbor倉庫路徑
  docker push harbor.zcf.com/k8s/myapp:v1         #再上傳鏡像到harbor上。

4. 為了方便延時恢復發布的效果,我們還需要在制作一個鏡像
  docker run -d --name ngx1 -e YOU_INFO="DIY-HelloWorld-v2" harbor.zcf.com/k8s/myapp:v1
    #說明: -e 是指定要傳遞給容器的環境變量, 因為我提前在myapp中啟動腳本entrypoint.sh中使用的了YOU_INFO這個環境變量,
    # 因此,這里我可以直接給容器傳遞這個變量,來實現修改nginx首頁的效果.

  docker commit --pause ngx1      #將ngx1暫停,並將當前容器狀態,導出為一個新鏡像。

  docker kill ngx1 && docker rm -fv ngx1  #制作完鏡像,就直接刪除測試ngx1容器.

  root@k8s-n1:~# docker images
    REPOSITORY TAG IMAGE ID CREATED SIZE
    <none> <none> 85355d4af36c 6 seconds ago 7.02MB    #這個就上剛制作的新鏡像.

  #給剛制作好的鏡像打上標簽:harbor.zcf.com/k8s/myapp:v2,便於上傳到harbor上。
  docker tag 85355d4af36c harbor.zcf.com/k8s/myapp:v2

  #測試運行鏡像,若沒有問題,就可以上傳到本地harbor上了。

  docker run -p 83:80 --rm -d --name ngx1 harbor.zcf.com/k8s/myapp:v2

  root@k8s-n1:~# curl http://192.168.111.80:83/    #測試鏡像是否修改了nginx的首頁為YOU_INFO的內容.
  <h1>WERCOME TO www.zcf.com WEB SITE | Fri Jul 19 02:31:13 UTC 2019 | ec4f08f831de | 172.17.0.2 | -DIY-HelloWorld-v2- | </h1>

  docker kill ngx1      #刪除ngx1容器.

  docker push harbor.zcf.com/k8s/myapp:v2     #最后,上傳新鏡像到harbor上.

5. 現在已經有了,myapp:v1 和 myapp:v2 那就可以開始K8s的灰度發布測試了。

  #先創建三個pod,一個Client,兩個Nginx
  #1. 先創建 Client
    kubectl run client --image=harbor.zcf.com/k8s/alpine:v1 --replicas=1
    #注意: alpine:是一個最小化的Linux系統,很多開源鏡像站都可以下載到.
    kubectl get pods -o wide      #查看Pod的創建詳情.

  #2. 創建Nginx
  kubectl run nginx --image=harbor.zcf.com/k8s/myapp:v1 --port=80 --replicas=2

  kubectl get deployment -w      #watch着監控k8s幫我們創建2個pod的過程.

  kubectl get pod -o wide

  #3. 登錄Client,測試訪問Nginx
  root@k8s-m1:/etc/ansible# kubectl get pod
    NAME READY STATUS RESTARTS AGE
    client-f5cdb799f-2wsmr 1/1 Running 2 16h
    nginx-6d6d8b685-7t7xj 1/1 Running 0 99m
    nginx-6d6d8b685-xpx5r 1/1 Running 0 99m

  kubectl exec -it client-f5cdb799f-2wsmr sh
  / # ip addr
  / # for i in `seq 1000`; do wget -O - -q http://nginx/ ; sleep 1; done
  / #    #說明: 若你的kube-dns沒有部署成功,這里的nginx可換成Service的IP.
  / #    #   kubectl get svc |grep nginx    #這個就是Nginx的Service的集群IP.

  #4. 以上測試可看到,已經能夠實現負載均衡的效果了。
    接着,開始進行灰度發布測試
    #更新myapp的鏡像為myapp:v2
    kubectl set image --help
    kubectl set image deployment myapp myapp=harbor.zcf.com/k8s/myapp:v2    #升級myapp的鏡像為myapp:v2

  #上面執行命令時,就可以看着,另一個終端中Client的訪問變化情況,你可以發現,訪問逐漸從 v1 變成 DIY-HelloWorld-v2了。

  #5.測試動態調整nginx Pod的數量
    kubectl scale --replicas=5 deployment nginx    #修改nginx的Pod副本數量為5個.
    kubectl get pods

  #接着在到Client所在的終端上,查看變化,你會發現,主機名和IP部分開始有更多變化了。

  #6. 查看nginx鏡像升級狀態,是否成功
    kubectl rollout status deployment nginx

  #7. 再查看myapp的鏡像是否已經升級為最新的了
    kubectl describe pods nginx-xxx-xx

  #8. 將myapp回滾到之前的版本,即v1版本
    kubectl rollout undo --help
    kubectl rollout undo deployment nginx

6. 測試K8s集群外部訪問nginx
  #修改 myapp service的類型,讓它能被集群外部的客戶端訪問.
    kubectl edit svc myapp
      #type: ClusterIP 把它修改為 type:NodePort

  #查看svc的更新信息:
    kubectl get svc #這里就可以看到,myap service的端口將動態增加一個. 如:80:30020/TCP,注意:30020是隨機分配的。
             #它的范圍是,你在使用kubeasz部署時,設置 NODE_PORT_RANGE="30000-60000"中隨機選的.

  #接着就可以在集群外部的客戶端去訪問myapp了
    http://Master或Node的物理IP:30020/

#好了,以上測試結果,我就不截圖了,想看到結果的道友們要多多動手測試,然后多多總結,多多思考,就可以看到,並且明白了。




免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM