系列目录

简介

当kubernetes集群中的某个服务需要升级时,传统的做法是,先将要更新的服务下线,业务停止后再更新版本和配置,然后重新启动并提供服务。如果业务集群规模较大时,这个工作就变成了一个挑战,而且先全部了停止,再逐步升级的方式会导致服务较长时间不可用。kubernetes提供了滚动更新(rolling-update)的方式来解决上述问题。

简单来说,滚动更新就是针对多实例服务的一种不中断服务的更新升级方式。一般情况下,对于多实例服务,滚动更新采用对各个实例逐个进行单独更新而非同一时刻对所有实例进行全部更新的方式。

对于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这些更高级别的抽象来管理的。如下图:

新版本的Kubernetes推荐用Deployment替代ReplicationController,在Deployment这个概念下在保持Pod副本数上实际发挥作用的是隐藏在背后的Replica Set。

因此,我们可以看到Kubernetes上Service的rolling update实质上是对Service所match出来的Pod集合的Rolling update,而控制Pod部署、调度和副本调度的却又恰恰是Deployment和replication controller,因此后两者才是kubernetes service rolling update真正要面对的实体。

使用kubectl rolling-update更新

使用kubectl rolling-update命令的方式,主要是针对使用RC创建的pods。

先来看下面一个示例,创建一个包含4个nginx副本的RC nginx-demo-v1-rc.yml:

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内容如下:

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

原文地址

kubernetes滚动更新的更多相关文章

  1. Kubernetes——滚动更新和数据管理

    k8s——滚动更新滚动更新就是一次只更新一小部分副本,更新成功之后再更新更多的副本,最终完成所有副本的更新.滚动更新最大的好处是零停机,整个更新的过程中始终有副本运行,从而保证了业务的连续性.kube ...

  2. 详谈kubernetes滚动更新-1

    系列目录 这个系列分为两个小节,第一个小节介绍deployment滚动更新时,deployment.replicaset.pod的细节以及创建过程以及deployment版本管理的方式 第二个小节将介 ...

  3. Kubernetes滚动更新介绍及使用-minReadySeconds

    滚动升级Deployment 现在我们将刚刚保存的yaml文件中的nginx镜像修改为 nginx:1.13.3,然后在spec下面添加滚动升级策略:   1 2 3 4 5 6 7 minReady ...

  4. kubernetes 滚动更新发布及回滚

    基本命令 记录历史 --record kubectl  apply -f **** --record 查看当前状态 kubectl rollout status deployment/demo -w ...

  5. Kubernetes集群中Service的滚动更新

    Kubernetes集群中Service的滚动更新 二月 9, 2017 0 条评论 在移动互联网时代,消费者的消费行为已经“全天候化”,为此,商家的业务系统也要保持7×24小时不间断地提供服务以满足 ...

  6. Kubernetes Deloyment实现滚动更新

    目录 滚动更新简介 使用kubectl rolling-update更新RC Deployment的rolling-update 滚动更新简介 当kubernetes集群中的某个服务需要升级时,传统的 ...

  7. Kubernetes Pod应用的滚动更新(八)

    一.环境准备 我们紧接上一节的环境,进行下面的操作,如果不清楚的,可以先查看上一篇博文. 滚动更新是一次只更新一小部分副本,成功后,再更新更多的副本,最终完成所有副本的更新.滚动更新的最大的好处是零停 ...

  8. kubernetes之DaemonSet以及滚动更新

    1.什么是DaemonSet? 1.1DaemonSet是Pod控制器的又一种实现方式,用于在集群中的全部节点上同时运行一份指定的Pod资源副本,后续加入集群的节点也会自动创建一个相关的Pod对象,当 ...

  9. Kubernetes 零宕机滚动更新

    转载自:https://www.qikqiak.com/post/zero-downtime-rolling-update-k8s/ 软件世界的发展比以往任何时候都快,为了保持竞争力需要尽快推出新的软 ...

随机推荐

  1. HDU-1528/1962 Card Game Cheater

    两组牌中两张牌相比能赢的就连,后求最大匹配. #include <cmath> #include <cstdlib> #include <cstdio> #incl ...

  2. outline:0与outline:none区别

    outline:0与outline:none的效果完全一样,用哪个都行,为了少写几个字,提倡用outline:0.具体区别如下: 出处: https://stackoverflow.com/quest ...

  3. 将Linux下python默认版本切换成替代版本

    本文链接自http://www.myhack58.com/Article/48/66/2016/71806.htm 当你安装 Debian Linux 时,安装过程有可能同时为你提供多个可用的 Pyt ...

  4. matlab 中的删除文件

    Matlab中有两种删除文件的方式: 一种是删除文件     delete()函数      //可以使用help  delete命令查询delete()函数的使用方法 delete('p1.jpg' ...

  5. no main manifest attribute, in demo-1.0.jar

    今天想打包一个jar到Linux上运行,发现使用java -jar demo-1.0.jar 运行报错: no main manifest attribute, in demo-1.0.jar 解决方 ...

  6. 怎样抓获或忽略像control-C这样的键盘中断?

    基本步骤是调用signal():#include <signal.h>singal(SIGINT, SIG_IGN); 就可以忽略中断信号, 或者:extern void func(int ...

  7. 【NOIP2016练习】T2 forest (树形DP,数论)

    题意:有一棵N个点的树,每个点上有点权 定义路径长度为所经过的所有点的点权之和,树的直径为一棵树中最大的路径长度 有N次询问,每次询问要求回答所有树的直径之积 每次询问后会删一条边,树的数量会+1 要 ...

  8. es6总结(九)--Iterator & for of

  9. 24深入理解C指针之---指针和数组

    一.指针和数组 #include <stdio.h> int main(int argc, char **argv) { ] = {, , , , ,}; int *ptrVector = ...

  10. hdu 5438(类似拓扑排序)

    Ponds Time Limit: 1500/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Sub ...