溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

如何解決K8s中快速交付應(yīng)用的難題

發(fā)布時(shí)間:2021-11-18 16:54:56 來源:億速云 閱讀:129 作者:柒染 欄目:云計(jì)算

如何解決K8s中快速交付應(yīng)用的難題,針對(duì)這個(gè)問題,這篇文章詳細(xì)介紹了相對(duì)應(yīng)的分析和解答,希望可以幫助更多想解決這個(gè)問題的小伙伴找到更簡(jiǎn)單易行的方法。

前言

軟件技術(shù)更新?lián)Q代很快,但我們追求的目標(biāo)是一直不變的,那就是在安全穩(wěn)定的前提下,增加應(yīng)用的部署頻率,縮短產(chǎn)品功能的迭代周期,這樣的好處就是企業(yè)可以在更短的時(shí)間內(nèi)獲得產(chǎn)品的價(jià)值、更快地獲得客戶反饋和響應(yīng)客戶需求,從而進(jìn)一步提升產(chǎn)品的競(jìng)爭(zhēng)力;除此之外,企業(yè)還可以釋放更多的資源投入到創(chuàng)新業(yè)務(wù)的研發(fā)上,創(chuàng)造更多的價(jià)值,這是一個(gè)良性循環(huán)的過程。

應(yīng)用產(chǎn)品的快速迭代誠然能給我們帶來各種各樣的好處,但挑戰(zhàn)也與其并存。更高頻率的應(yīng)用發(fā)布,意味著線上業(yè)務(wù)有不可預(yù)期故障的風(fēng)險(xiǎn)更大,除了產(chǎn)品上線之前在預(yù)發(fā)測(cè)試環(huán)境中充分測(cè)試驗(yàn)證迭代功能之外,制定最合適的應(yīng)用發(fā)布策略就是另外一個(gè)非常重要的話題,因?yàn)樗梢宰畲笙薅鹊慕档蜆I(yè)務(wù)故障的風(fēng)險(xiǎn)以及帶來的損失。

云原生應(yīng)用交付的關(guān)鍵點(diǎn)

我們說頻繁地進(jìn)行產(chǎn)品迭代意味著更大的故障風(fēng)險(xiǎn),傳統(tǒng)應(yīng)用如此,云原生應(yīng)用更是如此。因?yàn)樵圃鷳?yīng)用通常都是基于云的分布式部署模式,且每個(gè)應(yīng)用可能是由多個(gè)功能組件互相調(diào)用來一起提供完整的服務(wù)的,每個(gè)組件都有自己獨(dú)立的迭代流程和計(jì)劃。在這種情況下,功能組件越多,意味著出錯(cuò)的概率越大。那么如何在應(yīng)用交付層面對(duì)上述這些痛點(diǎn)做出改進(jìn),我們總結(jié)出以下幾個(gè)云原生應(yīng)用交付的關(guān)鍵點(diǎn)。

如何解決K8s中快速交付應(yīng)用的難題

  • 如何充分利用云原生架構(gòu)基礎(chǔ)設(shè)施的優(yōu)勢(shì)。這個(gè)優(yōu)勢(shì)我們可以簡(jiǎn)單總結(jié)為兩點(diǎn):彈性和高可用;

  • 如何具有跨平臺(tái)移植和交付的能力?;A(chǔ)設(shè)施底層的計(jì)算、存儲(chǔ)、網(wǎng)絡(luò)資源有很大的差異化,在以前,基礎(chǔ)架構(gòu)的不同是由上層應(yīng)用決定的,而云原生應(yīng)用的交付需要具有跨平臺(tái)移植和交付的能力;

  • 如何實(shí)現(xiàn)應(yīng)用運(yùn)維自治化。自治化不等于自動(dòng)化,自動(dòng)化是指觸發(fā)一個(gè)流程,流程結(jié)束后能自動(dòng)達(dá)到想要的一個(gè)預(yù)期結(jié)果,而自治化是指應(yīng)用再高可用的運(yùn)行態(tài)時(shí),如果其中某個(gè)功能組件的某個(gè)副本出現(xiàn)故障,應(yīng)用能自動(dòng)移除故障副本并補(bǔ)充新的應(yīng)用副本;

  • 如何讓應(yīng)用變得更具有可預(yù)測(cè)性。應(yīng)用的交付終態(tài),在我們編寫應(yīng)用編排模板的時(shí)候就是可預(yù)測(cè)到的,如果應(yīng)用的交付變得更有可預(yù)測(cè)性,那么風(fēng)險(xiǎn)也會(huì)最大程度地降低;

  • 如何提高應(yīng)用更快的平均恢復(fù)時(shí)間。如果應(yīng)用有超出了應(yīng)用自治的能力范疇之外的故障發(fā)生需要人工介入,那更快的平均恢復(fù)時(shí)間就意味著更低的業(yè)務(wù)損失。

Kubernetes 是一個(gè)可移植的,可擴(kuò)展的開源平臺(tái),用于管理容器化的工作負(fù)載和服務(wù),可促進(jìn)聲明式配置和自動(dòng)化。它自身的平臺(tái)能力已經(jīng)滿足了我們前面提到的大部分需求。Kubernetes 使用容器技術(shù)部署應(yīng)用,這樣的好處包括但不限于:

  • 應(yīng)用程序創(chuàng)建和部署更敏捷

  • 可移植性

  • 環(huán)境一致性

  • 松耦合和分布式

  • 資源隔離

  • 高效率和高密度的資源利用

如何解決K8s中快速交付應(yīng)用的難題

Kubernetes 還提供了應(yīng)用管理、調(diào)度、監(jiān)控和運(yùn)維的強(qiáng)大能力:

  • 服務(wù)發(fā)現(xiàn)和負(fù)載均衡能力

  • 應(yīng)用的自動(dòng)部署和回滾能力

  • 應(yīng)用的自治修復(fù)能力

  • 存儲(chǔ)編排能力

  • 密鑰和配置管理能力

但 Kubernetes 它也有很多功能是不提供但允許擴(kuò)展的部分,比如日志采集、監(jiān)控報(bào)警等能力。下面這張圖就是阿里云容器服務(wù)是在支持標(biāo)準(zhǔn) Kubernetes 的基礎(chǔ)上,對(duì)與用戶息息相關(guān)的能力做了增強(qiáng)和提升后的架構(gòu)大圖,包括提供最大的彈性化與低廉成本的全球化接入能力,強(qiáng)大的安全架構(gòu)支撐能力,深度整合阿里云基礎(chǔ)資源服務(wù)的能力,并經(jīng)過 雙11 驗(yàn)證和沉淀了海量用戶經(jīng)驗(yàn),同時(shí)支持專有、托管、無服務(wù)化、邊緣和神龍裸金屬等多種產(chǎn)品形態(tài),我們今天后面的所有演示就是在此平臺(tái)上做的。

如何解決K8s中快速交付應(yīng)用的難題

應(yīng)用交付的邊界

在 Kubernetes 中應(yīng)用交付的邊界是什么?

從簡(jiǎn)單處入手,我們可以認(rèn)為應(yīng)用的交付就是它的網(wǎng)絡(luò)服務(wù)模式,服務(wù)的的后端資源以及業(yè)務(wù)數(shù)據(jù)的持久化存儲(chǔ),這些資源被分別抽象成 service、deployment/pod,volume 資源等。

如何解決K8s中快速交付應(yīng)用的難題

以一個(gè) wordpress 應(yīng)用為例,它包括兩個(gè)功能組件:前端組件處理用戶請(qǐng)求,后端組件存儲(chǔ)數(shù)據(jù)。前端組件包括一個(gè) frontend service 和 3 個(gè) pod,后端組件包括一個(gè) backend service 和一個(gè) pod 組件,所以這個(gè) wordpress 應(yīng)用交付的資源就是 2 個(gè) service 和總共 4 個(gè)后端 pod。這個(gè)后端的 pod 資源我們?cè)?Kubernetes 中通過 deployment 來統(tǒng)一管理,service 資源相當(dāng)于一個(gè)負(fù)載均衡器,把請(qǐng)求路由到后端 pod 上,它涉及集群內(nèi)各個(gè)組件之間調(diào)用以及外部用戶訪問集群內(nèi)服務(wù),所以有不同的種類劃分。

如何解決K8s中快速交付應(yīng)用的難題

根據(jù)服務(wù)暴露的方式不同,可以分為以下幾種:

ClusterIP

通過為 Kubernetes 的 Service 分配一個(gè)集群內(nèi)部可訪問的固定虛擬 IP(Cluster IP),實(shí)現(xiàn)集群內(nèi)的訪問。為最常見的方式。

apiVersion: v1
kind: Service
metadata:
  name: wordpress
spec:
  type: ClusterIP      # 默認(rèn)的service類型,服務(wù)僅暴露為集群內(nèi)部可訪問
  ports:
    - port: 80         # 暴露給集群內(nèi)部的服務(wù)端口
      targetPort: 80   # 容器監(jiān)聽的服務(wù)端口
      protocol: TCP
  selector:
    app: wordpress     # 轉(zhuǎn)發(fā)請(qǐng)求到有相同標(biāo)簽的后端pod

NodePort

NodePort 是把 service 的 port 映射到集群節(jié)點(diǎn)的一個(gè)端口上,如果你不指定這個(gè)端口,系統(tǒng)將選擇一個(gè)隨機(jī)端口。大多數(shù)時(shí)候我們應(yīng)該讓 Kubernetes 來選擇端口,用戶自己來選擇可用端口代價(jià)太大。

apiVersion: v1
kind: Service
metadata:
  name: wordpress
spec:
  type: NodePort       # NodePort service類型,服務(wù)暴露一個(gè)固定的靜態(tài)端口用于集群外部訪問
  ports:
    - port: 80         # 暴露給集群內(nèi)部的服務(wù)端口
      targetPort: 80   # 容器監(jiān)聽的服務(wù)端口
      protocol: TCP
      nodePort: 31570  # 集群外部可以通過此端口訪問服務(wù)
  selector:
    app: wordpress     # 轉(zhuǎn)發(fā)請(qǐng)求到有相同標(biāo)簽的后端pod

NodePort 的方式雖然可以把服務(wù)暴露給集群外訪問,但是也有很多缺點(diǎn):

  • 每個(gè)端口只能是一種服務(wù)

  • 端口范圍有限制,一般是 30000-32767

  • 如果節(jié)點(diǎn)的 IP 地址變化了的話,你需要做一些變更操作去適配

所以在生產(chǎn)中一般不推薦這種方式,但如果你的應(yīng)用對(duì)成本比較敏感又能容忍服務(wù)有不可用窗口期的話,是可以使用這種方式的。

如何解決K8s中快速交付應(yīng)用的難題

LoadBalancer

LoadBalancer 是服務(wù)暴露到集群外或者公網(wǎng)上的標(biāo)準(zhǔn)方式,但它依賴 cloud provider 提供的一個(gè)負(fù)載均衡器的能力,負(fù)載均衡器會(huì)單獨(dú)分配一個(gè) ip 地址并監(jiān)聽后端服務(wù)的指定端口,請(qǐng)求的流量會(huì)通過指定的端口轉(zhuǎn)發(fā)到后端對(duì)應(yīng)的服務(wù)。

apiVersion: v1
kind: Service
metadata:
  name: wordpress
spec:
  type: LoadBalancer       # LoadBalancer service類型,一般依賴于公共云廠商供的負(fù)載均衡能力
  ports:
    - port: 80         # 暴露給集群內(nèi)部的服務(wù)端口
      targetPort: 80   # 容器監(jiān)聽的服務(wù)端口
      protocol: TCP
  selector:
    app: wordpress     # 轉(zhuǎn)發(fā)請(qǐng)求到有相同標(biāo)簽的后端pod

如何解決K8s中快速交付應(yīng)用的難題

Ingress

ClusterIP 服務(wù)類型僅限集群內(nèi)通信,NodePort 可以實(shí)現(xiàn)暴露服務(wù)訪問入口,但每個(gè)節(jié)點(diǎn)都會(huì)占用一個(gè)端口,會(huì)增加端口管理的復(fù)雜性,LoadBalancer 通常需要第三方云提供商支持,有一定的約束性。而 Ingress 這個(gè)服務(wù)類型跟我們前面的三種服務(wù)類型不一樣,它實(shí)際上不是一種服務(wù)類型,而是類似一種集群服務(wù)入口的存在,它可以基于你配置的不同路徑或者子域名把流量路由到對(duì)應(yīng)的后端服務(wù),更像是一個(gè)“智能路由”服務(wù)。

如何解決K8s中快速交付應(yīng)用的難題

前面介紹了一些應(yīng)用發(fā)布涉及到的資源類型,以及 service 資源類型的幾種模式,那 service 如何找到對(duì)應(yīng)的后端 pod 呢,這個(gè)就是標(biāo)簽的作用,我們可以把每個(gè)應(yīng)用的 pod 和 service 都打上同樣的標(biāo)簽,這個(gè)標(biāo)簽的機(jī)制就是我們后面要講的幾種應(yīng)用發(fā)布策略的關(guān)鍵點(diǎn)了。

如何解決K8s中快速交付應(yīng)用的難題

應(yīng)用的發(fā)布策略

在 Kubernetes 集群中,除了根據(jù)業(yè)務(wù)需求選定服務(wù)暴露方式外,為了讓應(yīng)用在升級(jí)期間依然平穩(wěn)提供服務(wù),選擇一個(gè)正確的發(fā)布策略就非常重要了。

滾動(dòng)發(fā)布

第一種應(yīng)用發(fā)布策略就是滾動(dòng)發(fā)布,這也是比較常見的策略。它是通過逐個(gè)替換實(shí)例來逐步部署新版本的應(yīng)用,直到所有實(shí)例都被替換完成為止。

如下圖所示,當(dāng)前我的應(yīng)用提供的服務(wù)版本是 v1, 這個(gè)服務(wù)的后端有 3 個(gè)副本, 但我更新版本 v2 的時(shí)候,它是一個(gè)副本一個(gè)副本地開始替換,直到最終服務(wù)的后端全部替換成 v2 版本。

如何解決K8s中快速交付應(yīng)用的難題

一個(gè)應(yīng)用示例的編排文件如下所示:

  • go-demo-v1.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: go-demo
spec:
  replicas: 3
  selector:
    matchLabels:
      app: go-demo
  template:
    metadata:
      labels:
        app: go-demo
    spec:
      containers:
      - name: go-demo
        image: registry.cn-hangzhou.aliyuncs.com/haoshuwei24/go-demo:v1
        imagePullPolicy: Always
        ports:
        - containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
  name: go-demo
spec:
  ports:
  - port: 80
    targetPort: 8080
    name: go-demo
  selector:
    app: go-demo
  type: ClusterIP
  • 部署版本 v1

$ kubectl apply -f go-demo-v1.yaml
  • 查看 pod 運(yùn)行狀態(tài)

$ kubectl get po
NAME                       READY   STATUS    RESTARTS   AGE
go-demo-78bc65c564-2rhxp   1/1     Running   0          19s
go-demo-78bc65c564-574z6   1/1     Running   0          19s
go-demo-78bc65c564-sgl2s   1/1     Running   0          19s
  • 訪問應(yīng)用服務(wù)

$ while sleep 0.1; do curl http://172.19.15.25; done
Version: v1
Version: v1
Version: v1
Version: v1
Version: v1
Version: v1
  • 更新 go-demo-v1.yamlgo-demo-v2.yaml 并更新鏡像 tag

...
registry.cn-hangzhou.aliyuncs.com/haoshuwei24/go-demo:v2
...
  • 部署版本 v2

$ kubectl apply -f go-demo-v2.yaml
  • 可以查看 pod 會(huì)被新版本 pod 逐個(gè)替換

$kubectl get po -w
NAME                                READY   STATUS              RESTARTS   AGE
application-demo-8594ff4967-85jsg   1/1     Running             0          3m24s
application-demo-8594ff4967-d4sv8   1/1     Terminating         0          3m22s
application-demo-8594ff4967-w6lpz   0/1     Terminating         0          3m20s
application-demo-b98d94554-4mwqd    1/1     Running             0          3s
application-demo-b98d94554-ng9wx    0/1     ContainerCreating   0          1s
application-demo-b98d94554-pmc5g    1/1     Running             0          4s
  • 訪問服務(wù)會(huì)發(fā)現(xiàn)在應(yīng)用滾動(dòng)升級(jí)過程中,版本 v1 和 v2 都會(huì)被訪問到,這個(gè)時(shí)間的長(zhǎng)短取決于應(yīng)用的啟動(dòng)速度

$ while sleep 0.1; do curl http://172.19.15.25; done
Version: v1
Version: v2
Version: v1
Version: v1
Version: v2
Version: v1
Version: v1
Version: v2

滾動(dòng)發(fā)布優(yōu)點(diǎn)就是它比較簡(jiǎn)單,而且不會(huì)占用太多的計(jì)算資源。缺點(diǎn)是:

  • 版本在實(shí)例之間緩慢替換

  • 這個(gè)滾動(dòng)發(fā)布可能需要一定時(shí)間

  • 無法控制流量

從應(yīng)用在集群中的終態(tài)上來說,集群中要么只有版本 1 的應(yīng)用后端,要么只有版本 2 的后端;如果版本 2 有缺陷,那么線上服務(wù)應(yīng)用到的就是整體用戶, 雖然我們有機(jī)制可以快速回滾,但涉及到整體用戶使用故障的代價(jià)還是太大。

藍(lán)綠發(fā)布

第二種就是藍(lán)綠發(fā)布,藍(lán)/綠發(fā)布是應(yīng)用版本 1 與版本 2 的后端 pod 都部署在環(huán)境中,通過控制流量切換來決定發(fā)布哪個(gè)版本。與滾動(dòng)發(fā)布相比,藍(lán)綠發(fā)布策略下的應(yīng)用終態(tài),是可以同時(shí)存在版本 1 和版本 2 兩種 pod 的,我們可以通過 service 流量的切換來決定當(dāng)前服務(wù)使用哪個(gè)版本的后端。

如何解決K8s中快速交付應(yīng)用的難題

一個(gè)應(yīng)用示例的編排文件如下所示。

  • go-demo-v1.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: go-demo-v1
spec:
  replicas: 4
  selector:
    matchLabels:
      app: go-demo
      version: v1
  template:
    metadata:
      labels:
        app: go-demo
        version: v1
    spec:
      containers:
      - name: go-demo
        image: registry.cn-hangzhou.aliyuncs.com/haoshuwei24/go-demo:v1
        imagePullPolicy: Always
        ports:
        - containerPort: 8080
  • go-demo-v2.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: go-demo-v2
spec:
  replicas: 4
  selector:
    matchLabels:
      app: go-demo
      version: v2
  template:
    metadata:
      labels:
        app: go-demo
        version: v2
    spec:
      containers:
      - name: go-demo
        image: registry.cn-hangzhou.aliyuncs.com/haoshuwei24/go-demo:v2
        imagePullPolicy: Always
        ports:
        - containerPort: 8080
  • service.yaml

apiVersion: v1
kind: Service
metadata:
  name: go-demo
spec:
  ports:
  - port: 80
    targetPort: 8080
    name: go-demo
  selector:
    app: go-demo
    version: v1
  type: ClusterIP
  • 部署以上 3 個(gè)資源

$ kubectl apply -f go-demo-v1.yaml -f go-demo-v2.yaml -f service.yaml
  • 訪問服務(wù)可以看到目前只訪問到版本 1 的服務(wù)

$ while sleep 0.1; do curl http://172.19.8.137; done
Version: v1
Version: v1
Version: v1
Version: v1
Version: v1
  • 修改 service.yaml 的 spec.selector 下 version=v2

apiVersion: v1
kind: Service
metadata:
  name: go-demo
spec:
  ports:
  - port: 80
    targetPort: 8080
    name: go-demo
  selector:
    app: go-demo
    version: v2
  type: ClusterIP
  • 重新部署

$ kubectl apply -f service.yaml
  • 重新訪問服務(wù)可以看到很快切換到了版本 2 上

$ [root@iZbp13u3z7d2tqx0cs6ovqZ blue-green]# while sleep 0.1; do curl http://172.19.8.137; done
Version: v2
Version: v2
Version: v2

我們剛才說到滾動(dòng)升級(jí)有一個(gè)過程需要時(shí)間,即使回滾,它也需要一定的時(shí)間才能回滾完畢,在新版本應(yīng)用有缺陷的情況下,藍(lán)綠發(fā)布的策略可以快速在 v1 和 v2 兩個(gè)版本之前切流量,所以這個(gè)切換流量的時(shí)間跟滾動(dòng)升級(jí)相比就縮短了很多了,但藍(lán)綠發(fā)布的缺點(diǎn)跟滾動(dòng)發(fā)布相同的就是這個(gè)缺陷會(huì)影響到整體用戶,服務(wù)要么百分百切換到版本 2 上,要么百分百切換到版本 1 上,這是個(gè)非 0 即 100 的操作,即使藍(lán)綠發(fā)布策略可以大大縮短故障恢復(fù)時(shí)間,但在某些場(chǎng)景下也是不可接受的。 而且集群環(huán)境中同時(shí)存在兩個(gè)版本的 pod 副本,資源占用的話相比滾動(dòng)發(fā)布是 2 倍的。

金絲雀發(fā)布(灰度發(fā)布)

第三種要介紹的發(fā)布策略是金絲雀發(fā)布,金絲雀部署是應(yīng)用版本 1 和版本 2 同時(shí)部署在環(huán)境中,并且用戶請(qǐng)求有可能會(huì)路由到版本 1 的后端,也可能會(huì)路由到版本 2 的后端,從而達(dá)到讓一部分新用戶訪問到版本 2 的應(yīng)用。 這種發(fā)布策略下,我們可以通過調(diào)整流量百分比來逐步控制應(yīng)用向新的版本切換,它與藍(lán)綠部署相比,不僅繼承了藍(lán)綠部署的優(yōu)點(diǎn),而且占用資源優(yōu)于藍(lán)綠部署所需要的 2 倍資源,在新版本有缺陷的情況下只影響少部分用戶,把損失降到最低。

如何解決K8s中快速交付應(yīng)用的難題

對(duì)于灰度發(fā)布的概念來說,有人認(rèn)為它跟金絲雀發(fā)布講的是一個(gè)東西,有人認(rèn)為它們不同。它跟金絲雀發(fā)布的過程是相同的,但目的有所不同:

  • 金絲雀發(fā)布更傾向于能快速獲取用戶的一些反饋,比如我可能不確定我的這個(gè)新版本功能的用戶體驗(yàn)是否能被大眾很好的接受,我期望能得到線上用戶的一些及時(shí)反饋,在產(chǎn)品側(cè)做功能體驗(yàn)調(diào)整之后再迭代 v3 版本;

  • 而灰度發(fā)布則是我的產(chǎn)品功能已經(jīng)設(shè)計(jì)并開發(fā)的很完善了,現(xiàn)在就是要逐步替換線上的舊版本,但是要控制發(fā)布可能帶來的風(fēng)險(xiǎn),所以要灰度發(fā)布。

示例應(yīng)用 1 如下, 這個(gè)示例中我們通過 pod 的數(shù)量來控制流量比例。

  • go-demo-v1.yaml 設(shè)定副本數(shù)為 9

apiVersion: apps/v1
kind: Deployment
metadata:
  name: go-demo-v1
spec:
  replicas: 9
  selector:
    matchLabels:
      app: go-demo
      version: v1
  template:
    metadata:
      labels:
        app: go-demo
        version: v1
    spec:
      containers:
      - name: go-demo
        image: registry.cn-hangzhou.aliyuncs.com/haoshuwei24/go-demo:v1
        imagePullPolicy: Always
        ports:
        - containerPort: 8080
  • go-demo-v2.yaml 設(shè)定副本數(shù)為 1

apiVersion: apps/v1
kind: Deployment
metadata:
  name: go-demo-v2
spec:
  replicas: 1
  selector:
    matchLabels:
      app: go-demo
      version: v2
  template:
    metadata:
      labels:
        app: go-demo
        version: v2
    spec:
      containers:
      - name: go-demo
        image: registry.cn-hangzhou.aliyuncs.com/haoshuwei24/go-demo:v2
        imagePullPolicy: Always
        ports:
        - containerPort: 8080
  • service.yaml

apiVersion: v1
kind: Service
metadata:
  name: go-demo
spec:
  ports:
  - port: 80
    targetPort: 8080
    name: go-demo
  selector:
    app: go-demo
  type: ClusterIP
  • 部署以上 3 個(gè)資源

$ kubectl apply -f go-demo-v1.yaml -f go-demo-v2.yaml -f service.yaml
  • 訪問服務(wù)可以看到基本上是 10% 的流量切換到版本 2 上

$ while sleep 0.1; do curl http://172.19.8.248; done
Version: v1
Version: v2
Version: v1
Version: v1
Version: v1
Version: v1
Version: v1
Version: v1
Version: v1
Version: v1
Version: v1

另外我們可以使用 nginx ingress controller 來控制流量切換,這個(gè)方式要更精準(zhǔn)。

  • go-demo-v1.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: go-demo-v1
spec:
  replicas: 3
  selector:
    matchLabels:
      app: go-demo
      version: v1
  template:
    metadata:
      labels:
        app: go-demo
        version: v1
    spec:
      containers:
      - name: go-demo
        image: registry.cn-hangzhou.aliyuncs.com/haoshuwei24/go-demo:v1
        imagePullPolicy: Always
        ports:
        - containerPort: 8080
  • go-demo-v2.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: go-demo-v2
spec:
  replicas: 1
  selector:
    matchLabels:
      app: go-demo
      version: v2
  template:
    metadata:
      labels:
        app: go-demo
        version: v2
    spec:
      containers:
      - name: go-demo
        image: registry.cn-hangzhou.aliyuncs.com/haoshuwei24/go-demo:v2
        imagePullPolicy: Always
        ports:
        - containerPort: 8080
  • service-v1.yaml

apiVersion: v1
kind: Service
metadata:
  name: go-demo-v1
spec:
  ports:
  - port: 80
    targetPort: 8080
    name: go-demo
  selector:
    app: go-demo
    version: v1
  type: ClusterIP
  • service-v2.yaml

apiVersion: v1
kind: Service
metadata:
  name: go-demo-v2
spec:
  ports:
  - port: 80
    targetPort: 8080
    name: go-demo
  selector:
    app: go-demo
    version: v2
  type: ClusterIP
  • ingress.yaml, 設(shè)置 nginx.ingress.kubernetes.io/service-weight: | go-demo-v1: 100, go-demo-v2: 0, 版本1 - 100% 流量, 版本2 - 0% 流量

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  annotations:
    nginx.ingress.kubernetes.io/service-weight: |
        go-demo-v1: 100, go-demo-v2: 0
  name: go-demo
  labels:
    app: go-demo
spec:
  rules:
    - host: go-demo.example.com
      http:
        paths:
          - path: /
            backend:
              serviceName: go-demo-v1
              servicePort: 80
          - path: /
            backend:
              serviceName: go-demo-v2
              servicePort: 80
  • 部署以上 4 個(gè)資源

$ kubectl apply -f go-demo-v1.yaml -f go-demo-v2.yaml -f service-v1.yaml -f service-v2.yaml -f nginx.yaml
  • 訪問服務(wù)可以看到流量 100% 到版本 1 上

$ while sleep 0.1; do curl http://go-demo.example.com; done
Version: v1
Version: v1
Version: v1
Version: v1
Version: v1
Version: v1
  • 更新 ingress.yaml, 設(shè)置流量比為 50:50

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  annotations:
    nginx.ingress.kubernetes.io/service-weight: |
        go-demo-v1: 50, go-demo-v2: 50
  name: go-demo
  labels:
    app: go-demo
spec:
  rules:
    - host: go-demo.example.com
      http:
        paths:
          - path: /
            backend:
              serviceName: go-demo-v1
              servicePort: 80
          - path: /
            backend:
              serviceName: go-demo-v2
              servicePort: 80
  • 訪問服務(wù)可以看到流量 50% 到版本 1 上, 50% 到版本 2 上

$ while sleep 0.1; do curl http://go-demo.example.com; done
Version: v2
Version: v1
Version: v1
Version: v1
Version: v2
Version: v2
Version: v1
Version: v1
Version: v2
Version: v2
  • 更新 ingress.yaml, 設(shè)置流量比為 0:100

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  annotations:
    nginx.ingress.kubernetes.io/service-weight: |
        go-demo-v1: 0, go-demo-v2: 100
  name: go-demo
  labels:
    app: go-demo
spec:
  rules:
    - host: go-demo.example.com
      http:
        paths:
          - path: /
            backend:
              serviceName: go-demo-v1
              servicePort: 80
          - path: /
            backend:
              serviceName: go-demo-v2
              servicePort: 80
  • 訪問服務(wù)可以看到流量 100% 到版本 2 上

$ while sleep 0.1; do curl http://go-demo.example.com; done
Version: v2
Version: v2
Version: v2
Version: v2
Version: v2
Version: v2
Version: v2
Version: v2
Version: v2
Version: v2

不管是金絲雀發(fā)布還是灰度發(fā)布,缺點(diǎn)就是發(fā)布周期相對(duì)來說要慢很多。

在這些發(fā)布策略當(dāng)中,

  • 當(dāng)你在開發(fā)測(cè)試環(huán)境中對(duì)應(yīng)用做更新發(fā)布的話,用滾動(dòng)發(fā)布;

  • 在生產(chǎn)環(huán)境,滾動(dòng)更新或者藍(lán)綠發(fā)布在新版本已經(jīng)提前測(cè)試充分的情況下可以用;

  • 如果對(duì)新版本的應(yīng)用的更新需要最大限度地控制風(fēng)險(xiǎn),降低故障對(duì)用戶的影響的話,那就使用金絲雀發(fā)布或灰度發(fā)布。

以上就是我們?cè)?Kubernetes 當(dāng)中常用的幾種發(fā)布策略的介紹。

關(guān)于如何解決K8s中快速交付應(yīng)用的難題問題的解答就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關(guān)注億速云行業(yè)資訊頻道了解更多相關(guān)知識(shí)。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

k8s
AI