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

原文地址

相关文章
相关标签/搜索