概述

本文核心问题是:如何升级应用。

对于Pod的更新有两种策略:

  • 一是删除全部旧Pod之后再创建新Pod。好处是,同一时间只会有一个版本的应用存在;缺点是,应用有一段时间不可用。
  • 二是先创建新Pod,再删除旧Pod。可以一次性创建全部,再删除全部,也可以逐渐创建删除。好处是应用一直可用,缺点是要同时支持两个版本。

蓝绿部署

对于应用的版本v1和版本v2:

  • 在运行v1前,流量一直都在v2上
  • 部署v1,然后测试通过后,将流量切换到v2,v2就成为了新的生产环境
  • 一旦v2出现问题,可以在切回v1

金丝雀部署(也称灰度部署)

金丝雀部署一种增量发布,先是在小范围内发布,然后观察测试,如无问题逐渐发布全部。

kubectl rolling-update

因为kubectl rolling-update的方式已经过时,所以只是做一下简介。

假设现在有一个名为test-v1,Pod选择器为app=order的ReplicationController要升级为test-v2,则执行下面命令可升级:

k rolling-update test-v1 test-v2 --image=test:v2

运行此命令后:

  1. 立刻创建一个名为test-v2的ReplicationController,他的Pod模板镜像正是test:v2,并添加一个标签deployment=xxxx
  2. test-v1以及app=order选中的Pod都会被加上一个标签:deployment=yyyy。如此做法是防止Pod的管理混乱。
  3. 先将test-v2的Pod扩展为1,使用更新后的模板创建新Pod;再将test-v1缩小1,如此循环。
  4. 因为在滚动过程中Service的标签选择器一直是app=order,所以新老版本都会接收到流量。

过时的原因是:伸缩的请求时由kubectl发起的,如果因为任何原因丢失了网络连接,升级将处于中间状态。另一个原因是:期望只修改Pod定义中的镜像tag,就能时Kubernetes运行升级工作

使用Deployment声明式的升级

Deployment是一种更高阶的资源,用于部署程序并以声明的方式升级应用,而不是通过ReplicationController或ReplicaSet进行部署。

在使用Deployment时,Pod是由Deployment的ReplicaSet创建的。

准备镜像

将之前的文章(Kubernetes学习笔记(四):服务)里的拿过来做一下微小的改动,生成两个镜像。改动内容就是在输出内容加上版本号。

fmt.Fprintf(w,"this is v1, hostname: %v\n",hostname)
docker push registry.cn-hangzhou.aliyuncs.com/orzi/goweb:v1 fmt.Fprintf(w,"this is v2, hostname: %v\n",hostname)
docker push registry.cn-hangzhou.aliyuncs.com/orzi/goweb:v2

创建Deployment

Deployment与ReplicaSet的配置相似,都含有标签选择器、副本数量和Pod模板。此外Deployment还会包含一个部署策略。

定义Service

定义了一个NodePort类型的Service

# goweb-svc.yaml
apiVersion: v1
kind: Service
metadata:
name: goweb
spec:
type: NodePort
selector:
app: goweb
ports:
- port: 80
targetPort: 8000
nodePort: 31234

定义Deployment

# goweb-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: goweb
spec:
replicas: 3
selector:
matchLabels:
app: goweb
template:
metadata:
labels:
app: goweb
spec:
containers:
- name: goweb
image: registry.cn-hangzhou.aliyuncs.com/orzi/goweb:v1

运行查看

可以看到名为goweb-fdfcfdcc6的RS,有个label是pod-template-hash=fdfcfdcc6,顾名思义,fdfcfdcc6就是pod模板的hash值。

创建Deployment时指定 --record 记录历史版本号,非常有用

-> [root@kube0.vm] [~] k create -f goweb-svc.yaml
service/goweb created -> [root@kube0.vm] [~] k create -f goweb-deployment.yaml --record deployment.apps/goweb created
-> [root@kube0.vm] [~] k get all -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod/goweb-fdfcfdcc6-4wklw 1/1 Running 0 9s 10.244.2.37 kube2.vm <none> <none>
pod/goweb-fdfcfdcc6-bw8c4 1/1 Running 0 9s 10.244.2.36 kube2.vm <none> <none>
pod/goweb-fdfcfdcc6-xjcwf 1/1 Running 0 9s 10.244.1.33 kube1.vm <none> <none> NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
service/goweb NodePort 10.100.193.94 <none> 80:31234/TCP 28s app=goweb
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 54s <none> NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
deployment.apps/goweb 3/3 3 3 9s goweb registry.cn-hangzhou.aliyuncs.com/orzi/goweb:v1 app=goweb NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTOR
replicaset.apps/goweb-fdfcfdcc6 3 3 3 9s goweb registry.cn-hangzhou.aliyuncs.com/orzi/goweb:v1 app=goweb,pod-template-hash=fdfcfdcc6

升级Deployment

只要修改Deployment的Pod模板定义,Kubernetes会自动的将实际状态收敛为修改后的状态。对于升级,只需要修改Pod中镜像的tag。

升级策略由deployment.spec.strategy.type定义,值是Recreate或RollingUpdate,默认RollingUpdate。

kubectl patch及minReadySeconds

使用kubectl patch定义deployment.spec.minReadySeconds来减慢滚动升级时间,以便观察升级过程

-> [root@kube0.vm] [~] k patch deployment goweb -p '{"spec":{"minReadySeconds":5}}'
deployment.apps/goweb patched

循环请求服务

在执行升级前新开窗口,运行下面的命令查看输出

-> [root@kube0.vm] [~] while true; do curl http://192.168.199.231:31234/ ; sleep 1; done
this is v1, hostname: goweb-fdfcfdcc6-pw7b4
this is v1, hostname: goweb-fdfcfdcc6-pw7b4
this is v1, hostname: goweb-fdfcfdcc6-x8n7h
this is v1, hostname: goweb-fdfcfdcc6-pw7b4
this is v1, hostname: goweb-fdfcfdcc6-x8n7h
this is v1, hostname: goweb-fdfcfdcc6-j4mz8
this is v1, hostname: goweb-fdfcfdcc6-j4mz8
# 以上是升级之前的输出、以下是开始升级后的
this is v1, hostname: goweb-fdfcfdcc6-x8n7h
this is v1, hostname: goweb-fdfcfdcc6-pw7b4
this is v1, hostname: goweb-fdfcfdcc6-pw7b4
this is v1, hostname: goweb-fdfcfdcc6-j4mz8
this is v2, hostname: goweb-65cc575865-25988
this is v2, hostname: goweb-65cc575865-25988
this is v1, hostname: goweb-fdfcfdcc6-x8n7h
this is v1, hostname: goweb-fdfcfdcc6-j4mz8
this is v2, hostname: goweb-65cc575865-bfd98
this is v2, hostname: goweb-65cc575865-bfd98
this is v2, hostname: goweb-65cc575865-25988
this is v2, hostname: goweb-65cc575865-25988
this is v2, hostname: goweb-65cc575865-25988
# 这之后就是升级完成了

kubectl set

使用 kubectl set image 更新任何包含容器资源的镜像。

-> [root@kube0.vm] [~] k set image deployment goweb goweb=registry.cn-hangzhou.aliyuncs.com/orzi/goweb:v2
deployment.apps/goweb image updated

kubectl rollout

查看升级状态信息。执行完kubectl set image,立刻执行下面的命令。手速得快,不然赶不上热乎的。

-> [root@kube0.vm] [~] k rollout status deployment goweb
Waiting for deployment "goweb" rollout to finish: 1 out of 3 new replicas have been updated...
Waiting for deployment "goweb" rollout to finish: 1 out of 3 new replicas have been updated...
Waiting for deployment "goweb" rollout to finish: 1 out of 3 new replicas have been updated...
Waiting for deployment "goweb" rollout to finish: 2 out of 3 new replicas have been updated...
Waiting for deployment "goweb" rollout to finish: 2 out of 3 new replicas have been updated...
Waiting for deployment "goweb" rollout to finish: 2 out of 3 new replicas have been updated...
Waiting for deployment "goweb" rollout to finish: 1 old replicas are pending termination...
Waiting for deployment "goweb" rollout to finish: 1 old replicas are pending termination...
Waiting for deployment "goweb" rollout to finish: 1 old replicas are pending termination...
deployment "goweb" successfully rolled out

修改Deployment或其他资源的方式

方法 作用
kubectl edit 使用编辑器打开资源配置
kubectl patch 在命令行以merge的方式修改配置
kubectl apply 通过yaml或者json文件,修改新改动的值。如果指定的对象不存在则创建。
kubectl replace 使用yaml或者json文件替换一个必须已存在的对象配置。
kubectl set image 修改镜像

回滚

使用kubectl rollout undo 回滚到上一个版本

-> [root@kube0.vm] [~] k rollout undo deployment goweb
deployment.apps/goweb rolled back

使用 kubectl rollout history 查看版本记录

-> [root@kube0.vm] [~] k rollout history deployment goweb
deployment.apps/goweb
REVISION CHANGE-CAUSE
6 kubectl create --filename=goweb-deployment.yaml --record=true
7 kubectl create --filename=goweb-deployment.yaml --record=true

回滚到特定版本

-> [root@kube0.vm] [~] k rollout undo deployment goweb --to-revision=5
error: unable to find specified revision 5 in history -> [root@kube0.vm] [~] k rollout undo deployment goweb --to-revision=7
deployment.apps/goweb skipped rollback (current template already matches revision 7) -> [root@kube0.vm] [~] k rollout undo deployment goweb --to-revision=6
deployment.apps/goweb rolled back

通过deployment.spec.revisionHistoryLimit指定历史版本个数,默认为2。也就是当前和上一个版本。

控制滚动升级速率

deployment.spec.strategy.rollingUpdate下有两个字段,用来控制升级速率

  • maxSurge:超出期望副本数的Pod实例的比例或个数。默认25%,转换成绝对值后四舍五入,也可以直接指定为绝对值。
  • maxUnavailable:滚动升级时,最多允许有多少实例不可用,默认25%,转换成绝对值后四舍五入,也可以直接指定为绝对值。

暂停、恢复升级

  • 使用kubectl rollout pause暂停升级
  • 使用kubectl rollout resume取消暂停

阻止出错版本的滚动升级

  • minReadySeconds:指定新创建的Pod至少要运行多久才视为可用。
  • 配置就绪探针
  • 为滚动升级配置progressDeadlineSeconds

小结

  • kubectl rolling-update 过时的原因:伸缩的请求时由kubectl发起的,如果因为任何原因丢失了网络连接,升级将处于中间状态
  • Deployment是一种更高阶的资源,用于部署程序并以声明的方式升级应用,而不是通过ReplicationController或ReplicaSet进行部署。
  • 创建Deployment时指定 --record 记录历史版本号
  • Deployment下的ReplicaSet命名是DeploymentName+Pod模板Hash,而ReplicaSet下的Pod是在此基础拼接个随机字符串。
  • 升级策略由deployment.spec.strategy.type定义,值是Recreate或RollingUpdate,默认RollingUpdate。
  • 定义deployment.spec.minReadySeconds来减慢滚动升级时间
  • maxSurge与maxUnavailable控制滚动升级速率
  • 命令:patch、set、rollout
  • kubectl rollout:status、undo、pause、resume、history。

Kubernetes学习笔记(八):Deployment--声明式的升级应用的更多相关文章

  1. k8s之Deployment 声明式地升级应用(五)

    Deployment 声明式地升级应用 现在你已经知道如何将应用程序组件打包进容器,将他们分组到pod中,并为它们提供临时或者持久存储,将密钥或配置文件注入,并可以使pod之间互相通信.这就是微服务化 ...

  2. 吴裕雄--天生自然JAVA SPRING框架开发学习笔记:Spring声明式事务管理(基于Annotation注解方式实现)

    在 Spring 中,除了使用基于 XML 的方式可以实现声明式事务管理以外,还可以通过 Annotation 注解的方式实现声明式事务管理. 使用 Annotation 的方式非常简单,只需要在项目 ...

  3. Struts2学习第八课 声明式异常处理

    异常处理:exception-mapping元素 exception-mapping元素:配置当前的action的声明式异常处理 exception-mapping元素有两个属性: --excepti ...

  4. deployment:声明式的升级应用

    9.1.使用RC实现滚动升级 #kubectl rolling-update kubia-v1 kubia-v2 --image=luksa/kubia:v2 使用kubia-v2版本应用来替换运行着 ...

  5. Kubernetes 学习笔记(一):基础概念

    个人笔记,仅本人查阅使用,不保证正确. 零.微服务 微服务架构专注于应用解耦合,通过将应用彻底地组件化和服务化,每个微服务只包含一个非常小的功能,比如权限管理.日志收集等等.由这一组微服务组合起来,提 ...

  6. Learning ROS forRobotics Programming Second Edition学习笔记(八)indigo rviz gazebo

    中文译著已经出版,详情请参考:http://blog.csdn.net/ZhangRelay/article/category/6506865 Learning ROS forRobotics Pro ...

  7. python3.4学习笔记(八) Python第三方库安装与使用,包管理工具解惑

    python3.4学习笔记(八) Python第三方库安装与使用,包管理工具解惑 许多人在安装Python第三方库的时候, 经常会为一个问题困扰:到底应该下载什么格式的文件?当我们点开下载页时, 一般 ...

  8. Go语言学习笔记八: 数组

    Go语言学习笔记八: 数组 数组地球人都知道.所以只说说Go语言的特殊(奇葩)写法. 我一直在想一个人参与了两种语言的设计,但是最后两种语言的语法差异这么大.这是自己否定自己么,为什么不与之前统一一下 ...

  9. 【opencv学习笔记八】创建TrackBar轨迹条

    createTrackbar这个函数我们以后会经常用到,它创建一个可以调整数值的轨迹条,并将轨迹条附加到指定的窗口上,使用起来很方便.首先大家要记住,它往往会和一个回调函数配合起来使用.先看下他的函数 ...

随机推荐

  1. 数学--数论--整除分块(巨TM详细,学不会,你来打我)

    1.概念 从一道例题说起 在介绍整除分块之前,我们先来看一道算数题:已知正整数n,求∑i=1n⌊ni⌋已知正整数n,求∑i=1n⌊ni⌋在介绍整除分块之前,我们先来看一道算数题: 已知正整数n,求∑i ...

  2. js世家委托详解

    事件原理 通过div0.addElementListener来调用:用法:div0.addElementListener(事件类型,事件回调函数,是否捕获时执行){}.1.事件类型(type):必须是 ...

  3. Spring Boot Actuator H2 RCE复现

    0x00 前言 Spring Boot框架是最流行的基于Java的微服务框架之一,可帮助开发人员快速轻松地部署Java应用程序,加快开发过程.当Spring Boot Actuator配置不当可能造成 ...

  4. TCP 可靠传输

    TCP报文段首部 序号: TCP是面向字节流的.在一个TCP连接中传送的字节流中的每一个字节都按顺序编号.整个要传送的字节流的起始序号必须在连接建立时设置.首部中的序号字段值则指的是本报文段所发送的数 ...

  5. Educational Codeforces Round 83 E. Array Shrinking

    E. Array Shrinking 题目大意: 给你一个大小是n的序列,相邻的序列如果相等,则可以合并,合并之后的值等于原来的值加1. 求:合并之后最小的序列的和. 题解: 这个数据范围和这个相邻的 ...

  6. spring的后台数据校验

    数据校验对于开发项目来说是必须的.校验一般分为前台校验和后台校验,前台校验是必须要做的,后台校验是可选的.后台校验相对前台校验来说配置起来一般更复杂.前台校验通过js做,前台校验一般非常容易绕过.sp ...

  7. 12_JavaScript基础入门(2)

    运算符 运算符(Operators,也翻译为操作符),是发起运算的最简单形式. 运算符的分类见仁见智,我们的课程对运算符进行如下分类: 数学运算符(Arithmetic operators)      ...

  8. layui里面的layer模块弹窗,强制居中的方法!!!

    每次调用layer弹窗做动态展示的时候,只要内容不固定或者需要二次渲染 比如layui.form.render()进行渲染的时候 由于弹窗已经出来了,只是content部分的结构改变了宽度或者高度,l ...

  9. ARM-Linux Gcc 交叉编译环境搭建

    1 NFS网络文件系统搭建 测试宿主机与目标板ping通 目标板上某个文件夹(例如mnt)挂载到宿主机(192.168.1.111)的/home/nfs_dir文件夹下 mount –t nfs –o ...

  10. [CodeForces 344D Alternating Current]栈

    题意:两根导线绕在一起,问能不能拉成两条平行线,只能向两端拉不能绕 思路:从左至右,对+-号分别进行配对,遇到连续的两个“+”或连续的两个“-”即可消掉,最后如果全部能消掉则能拉成平行线.拿两根线绕一 ...