kubernetes滾動更新

系列目錄html

簡介nginx

當kubernetes集羣中的某個服務須要升級時,傳統的作法是,先將要更新的服務下線,業務中止後再更新版本和配置,而後從新啓動並提供服務。若是業務集羣規模較大時,這個工做就變成了一個挑戰,並且先所有了中止,再逐步升級的方式會致使服務較長時間不可用。kubernetes提供了滾動更新(rolling-update)的方式來解決上述問題。api

簡單來講,滾動更新就是針對多實例服務的一種不中斷服務的更新升級方式。通常狀況下,對於多實例服務,滾動更新採用對各個實例逐個進行單獨更新而非同一時刻對全部實例進行所有更新的方式。bash

對於k8s集羣部署的service來講,rolling update就是指一次僅更新一個pod,並逐個進行更新,而不是在同一時刻將該service下面的全部pod shutdown,避免業務中斷。網絡

Service、Deployment、RS、RC和Pod之間的關係

對於咱們要部署的應用來講,通常是由多個抽象的service組成。在kubernetes中,一個service經過label selector match出一個pods集合,這些Pods做爲service的endpoint,是真正承載業務的實體。而pod在集羣內的部署、調度、副本數則是經過Deployment或者RC這些更高級別的抽象來管理的。以下圖:app

avatar

新版本的Kubernetes推薦用Deployment替代ReplicationController,在Deployment這個概念下在保持Pod副本數上實際發揮做用的是隱藏在背後的Replica Set。3d

所以,咱們能夠看到Kubernetes上Service的rolling update實質上是對Service所match出來的Pod集合的Rolling update,而控制Pod部署、調度和副本調度的卻又偏偏是Deployment和replication controller,所以後二者纔是kubernetes service rolling update真正要面對的實體。code

使用kubectl rolling-update更新

使用kubectl rolling-update命令的方式,主要是針對使用RC建立的pods。
先來看下面一個示例,建立一個包含4個nginx副本的RC nginx-demo-v1-rc.yml:server

apiVersion: v1
kind: ReplicationController
metadata:
  name: nginx-demo-v1
spec:
  replicas: 4
  selector:
    app: nginx-demo
    ver: v1
  template:
    metadata:
      labels:
        app: nginx-demo
        ver: v1
    spec:
      containers:
        - name: nginx-demo
          image: nginx:1.10.1
          ports:
            - containerPort: 80
              protocol: TCP
          env:
            - name: NGX_DEMO_VER
              value: v1

建立一個service,nginx-demo-svc.yml內容以下:htm

apiVersion: v1
kind: Service
metadata:
  name: nginx-demo-svc
spec:
  ports:
  - port: 80
    protocol: TCP
  selector:
    app: nginx-demo

建立rc和service:

kubectl create -f nginx-demo-v1-rc.yml
kubectl create -f nginx-demo-svc.yml

建立完成之後,能夠經過訪問任一Pod的環境變量查看NGX_DEMO_VER的值,爲v1

如今咱們建立一個nginx-demo-v2-rc.yml的文件,來升級現有的pod:

apiVersion: v1
kind: ReplicationController
metadata:
  name: nginx-demo-v2
spec:
  replicas: 4
  selector:
    app: nginx-demo
    ver: v2
  template:
    metadata:
      labels:
        app: nginx-demo
        ver: v2
    spec:
      containers:
        - name: nginx-demo
          image: nginx:1.11.9
          ports:
            - containerPort: 80
              protocol: TCP
          env:
            - name: NGX_DEMO_VER
              value: v2

執行更新操做:

kubectl rolling-update nginx-demo-svc -f nginx-demo-v2-rc.yml

須要注意的是,在執行滾動升級時,兩個版本的yml文件區別:

  • RC的名字不能與舊的RC名字相同
  • 在selector中應至少有一個label與舊的RC的label不一樣,以標識其爲新的RC。

咱們能夠經過以下操做來查看更新的完整過程:

kubectl rolling-update nginx-demo-v1 --udpate-period=10s -f nginx-demo-v2-rc.yml

當全部舊的pod被新的Pod替換完成之後,更新完成。

使用kubectl rolling-update實現滾動更新的不足:

  • rolling-update的邏輯是由kubectl發出N條命令到APIServer完成的,極可能由於網絡緣由致使update中斷

  • 須要建立一個新的rc,名字與要更新的rc不能同樣

  • 回滾還須要執行rolling-update,只是用老的版本替換新的版本

  • service執行的rolling-update在集羣中沒有記錄,後續沒法跟蹤rolling-update歷史

現現在,RC的方式已經被Deployment替代。

Deployment的rolling-update

kubernetes的Deployment是一個更高級別的抽象。Deployment會建立一個Replica Set,用來保證Deployment中的Pod的副本數。要rolling-update deployment中的Pod,只須要修改Deployment本身的yml文件並應用便可。這個修改會建立一個新的Replica Set,在增長這個新RS的pod數的同時,減小舊RS的pod,直至徹底升級。而這一切都發生在Server端,並不須要kubectl參與。

建立一個Deployment yml文件nginx-demo-dm.yml:

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: nginx-demo
spec:
  replicas: 4
  selector:
    matchLabels:
      app: nginx-demo
  minReadySeconds: 10
  template:
    metadata:
      labels:
        app: nginx-demo
        version: v1
    spec:
      containers:
        - name: deployment-demo
          image: nginx:1.10.1
          ports:
            - containerPort: 80
              protocol: TCP

建立該deployment:

kubect create -f nginx-demo-dm.yml --record

而後咱們能夠直接修改該deployment文件,以下 :

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: nginx-demo
spec:
  replicas: 4
  selector:
    matchLabels:
      app: nginx-demo
  minReadySeconds: 10
  template:
    metadata:
      labels:
        app: nginx-demo
        version: v2
    spec:
      containers:
        - name: deployment-demo
          image: nginx:1.11.9
          ports:
            - containerPort: 80
              protocol: TCP

一共就改了兩個地方,將version改成了v2,將nginx鏡像從1.10.1改到了1.11.9,執行以下操做應用更改:

kubectl apply -f nginx-demo-dm.yml --record

這個時候,咱們能夠經過執行kubectl get rs來查看到rs的變化,以確認是否在執行升級。也能夠經過kubectl describe deployment nginx-demo來查看詳細的rolling-update的過程。還能夠經過kubectl rollout status deployment/nginx-demo來查看更新狀態。

除了使用apply方式來應用更改之外,還有另一種方式能夠直接升級。就是經過kubectl edit nginx-demo-dm.yml來編輯deployment文件,保存之後,不須要執行apply,就會自動完成升級。

咱們能夠注意到,在執行deployment的操做時,使用了一個--record參數,這個參數是用來告訴apiserver記錄update的歷史。能夠經過以下命令來查看update歷史:

kubectl rollout history deployment nginx-demo

查看指定revision的詳細信息:

kubectl rollout history deployment hello-deployment --revision=2

須要說明的是,在升級完成之後,舊的RS也不會被刪除,這些信息都會存儲到server端,以方便回滾。
deployment下的pod的回滾操做至關簡單,直接執行rollout undo便可將deployment回滾到record中記錄的上一個revision:

kubectl rollout undo deployment nginx-demo

執行以下操做,回滾到指定版本:

kubectl rollout undo deployment hello-deployment --to-version=2

原文地址

相關文章
相關標籤/搜索