Kubernetes学习笔记(八):Deployment--声明式的升级应用
概述
本文核心问题是:如何升级应用。
对于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
运行此命令后:
- 立刻创建一个名为test-v2的ReplicationController,他的Pod模板镜像正是test:v2,并添加一个标签
deployment=xxxx。 - test-v1以及
app=order选中的Pod都会被加上一个标签:deployment=yyyy。如此做法是防止Pod的管理混乱。 - 先将test-v2的Pod扩展为1,使用更新后的模板创建新Pod;再将test-v1缩小1,如此循环。
- 因为在滚动过程中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--声明式的升级应用的更多相关文章
- k8s之Deployment 声明式地升级应用(五)
Deployment 声明式地升级应用 现在你已经知道如何将应用程序组件打包进容器,将他们分组到pod中,并为它们提供临时或者持久存储,将密钥或配置文件注入,并可以使pod之间互相通信.这就是微服务化 ...
- 吴裕雄--天生自然JAVA SPRING框架开发学习笔记:Spring声明式事务管理(基于Annotation注解方式实现)
在 Spring 中,除了使用基于 XML 的方式可以实现声明式事务管理以外,还可以通过 Annotation 注解的方式实现声明式事务管理. 使用 Annotation 的方式非常简单,只需要在项目 ...
- Struts2学习第八课 声明式异常处理
异常处理:exception-mapping元素 exception-mapping元素:配置当前的action的声明式异常处理 exception-mapping元素有两个属性: --excepti ...
- deployment:声明式的升级应用
9.1.使用RC实现滚动升级 #kubectl rolling-update kubia-v1 kubia-v2 --image=luksa/kubia:v2 使用kubia-v2版本应用来替换运行着 ...
- Kubernetes 学习笔记(一):基础概念
个人笔记,仅本人查阅使用,不保证正确. 零.微服务 微服务架构专注于应用解耦合,通过将应用彻底地组件化和服务化,每个微服务只包含一个非常小的功能,比如权限管理.日志收集等等.由这一组微服务组合起来,提 ...
- Learning ROS forRobotics Programming Second Edition学习笔记(八)indigo rviz gazebo
中文译著已经出版,详情请参考:http://blog.csdn.net/ZhangRelay/article/category/6506865 Learning ROS forRobotics Pro ...
- python3.4学习笔记(八) Python第三方库安装与使用,包管理工具解惑
python3.4学习笔记(八) Python第三方库安装与使用,包管理工具解惑 许多人在安装Python第三方库的时候, 经常会为一个问题困扰:到底应该下载什么格式的文件?当我们点开下载页时, 一般 ...
- Go语言学习笔记八: 数组
Go语言学习笔记八: 数组 数组地球人都知道.所以只说说Go语言的特殊(奇葩)写法. 我一直在想一个人参与了两种语言的设计,但是最后两种语言的语法差异这么大.这是自己否定自己么,为什么不与之前统一一下 ...
- 【opencv学习笔记八】创建TrackBar轨迹条
createTrackbar这个函数我们以后会经常用到,它创建一个可以调整数值的轨迹条,并将轨迹条附加到指定的窗口上,使用起来很方便.首先大家要记住,它往往会和一个回调函数配合起来使用.先看下他的函数 ...
随机推荐
- 数学--数论--整除分块(巨TM详细,学不会,你来打我)
1.概念 从一道例题说起 在介绍整除分块之前,我们先来看一道算数题:已知正整数n,求∑i=1n⌊ni⌋已知正整数n,求∑i=1n⌊ni⌋在介绍整除分块之前,我们先来看一道算数题: 已知正整数n,求∑i ...
- js世家委托详解
事件原理 通过div0.addElementListener来调用:用法:div0.addElementListener(事件类型,事件回调函数,是否捕获时执行){}.1.事件类型(type):必须是 ...
- Spring Boot Actuator H2 RCE复现
0x00 前言 Spring Boot框架是最流行的基于Java的微服务框架之一,可帮助开发人员快速轻松地部署Java应用程序,加快开发过程.当Spring Boot Actuator配置不当可能造成 ...
- TCP 可靠传输
TCP报文段首部 序号: TCP是面向字节流的.在一个TCP连接中传送的字节流中的每一个字节都按顺序编号.整个要传送的字节流的起始序号必须在连接建立时设置.首部中的序号字段值则指的是本报文段所发送的数 ...
- Educational Codeforces Round 83 E. Array Shrinking
E. Array Shrinking 题目大意: 给你一个大小是n的序列,相邻的序列如果相等,则可以合并,合并之后的值等于原来的值加1. 求:合并之后最小的序列的和. 题解: 这个数据范围和这个相邻的 ...
- spring的后台数据校验
数据校验对于开发项目来说是必须的.校验一般分为前台校验和后台校验,前台校验是必须要做的,后台校验是可选的.后台校验相对前台校验来说配置起来一般更复杂.前台校验通过js做,前台校验一般非常容易绕过.sp ...
- 12_JavaScript基础入门(2)
运算符 运算符(Operators,也翻译为操作符),是发起运算的最简单形式. 运算符的分类见仁见智,我们的课程对运算符进行如下分类: 数学运算符(Arithmetic operators) ...
- layui里面的layer模块弹窗,强制居中的方法!!!
每次调用layer弹窗做动态展示的时候,只要内容不固定或者需要二次渲染 比如layui.form.render()进行渲染的时候 由于弹窗已经出来了,只是content部分的结构改变了宽度或者高度,l ...
- ARM-Linux Gcc 交叉编译环境搭建
1 NFS网络文件系统搭建 测试宿主机与目标板ping通 目标板上某个文件夹(例如mnt)挂载到宿主机(192.168.1.111)的/home/nfs_dir文件夹下 mount –t nfs –o ...
- [CodeForces 344D Alternating Current]栈
题意:两根导线绕在一起,问能不能拉成两条平行线,只能向两端拉不能绕 思路:从左至右,对+-号分别进行配对,遇到连续的两个“+”或连续的两个“-”即可消掉,最后如果全部能消掉则能拉成平行线.拿两根线绕一 ...