kubernete编排技术二:deployment
kubernete中的控制器模式,是指用一种对象来控制另一种对象,这个控制器是由组件kube-controller-manager来实现的。deployment就是一种控制器,用来控制pod的创建、水平扩展收缩、滚动更新。deployment是kubernete中一个对无状态pod的控制器,本文来介绍一下。
deployment简介
先回顾一下我们之前定义的yaml文件,这个文件定义了2个pod副本(replicas: 2),这个deployment的编排逻辑就是带app: springboot-mybatis这个label的数量只能有2个,超过就需要删除,少了就需要创建。
apiVersion: apps/v1
kind: Deployment
metadata:
name: springboot-mybatis-deployment
spec:
selector:
matchLabels:
app: springboot-mybatis
replicas: 2
template:
metadata:
labels:
app: springboot-mybatis
spec:
containers:
- name: spingboot-mybatis
imagePullPolicy: IfNotPresent
image: zjj2006forever/springboot-mybatis:1.2
ports:
- containerPort: 8300
上面yaml文件中的template,被称作pod模板,而template上面的代码部分,就是控制器的定义。这儿的控制器其实就是上面的控制器部分对下面pod模板的控制。创建时,控制器会从etcd查找label是springboot-mybatis的pod个数,因为是0,所以会创建2个;如果运行过程中,有一个pod挂了,会再创建一个。
pod水平扩展和收缩
上一节的yaml文件定义了一个2个pod的deployment控制器,这样会生成2个pod。在我们实际工作中,有时会遇到突增流量,比如促销活动之类的,这时候我们可以用增加pod来应对。最直接的方式就是修改replicas,比如改为replicas: 4。但是生成环境中,这样效率太低了,我们可以执行如下命令:
kubectl scale deployment springboot-mybatis-deployment --replicas=4
之后我们查看集群上的pod,这2个AGE=10s的pod就是后来扩展出来的。
[root@master k8s]# kubectl get pods
NAME READY STATUS RESTARTS AGE
springboot-mybatis-deployment-5b78f66997-d5fk9 1/1 Running 0 61s
springboot-mybatis-deployment-5b78f66997-hcmm4 1/1 Running 0 10s
springboot-mybatis-deployment-5b78f66997-k5xw8 1/1 Running 0 61s
springboot-mybatis-deployment-5b78f66997-pvfdv 1/1 Running 0 11s
我们查看其中一个新pod的状态,跟之前的pod创建过程完全一样。
[root@master k8s]# kubectl describe pod springboot-mybatis-deployment-5b78f66997-hcmm4
Name: springboot-mybatis-deployment-5b78f66997-hcmm4
Namespace: default
Priority: 0
Node: worker1/192.168.59.141
Start Time: Wed, 08 Jul 2020 06:01:08 -0400
Labels: app=springboot-mybatis
pod-template-hash=5b78f66997
Annotations: <none>
Status: Running
IP: 10.244.1.25
IPs:
IP: 10.244.1.25
Controlled By: ReplicaSet/springboot-mybatis-deployment-5b78f66997
Containers:
spingboot-mybatis:
Container ID: docker://ef433a219549b32e1d01899ea6ac581c1bfffa7d01e1c165647be52f9f79ff5b
Image: zjj2006forever/springboot-mybatis:1.2
Image ID: docker-pullable://zjj2006forever/springboot-mybatis@sha256:bf43bc9d1d4bdb33d82a206282c8f82be3679847d1011806b72e3634ebe67564
Port: 8300/TCP
Host Port: 0/TCP
State: Running
Started: Wed, 08 Jul 2020 06:01:11 -0400
Ready: True
Restart Count: 0
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from default-token-qk5nc (ro)
Conditions:
Type Status
Initialized True
Ready True
ContainersReady True
PodScheduled True
Volumes:
default-token-qk5nc:
Type: Secret (a volume populated by a Secret)
SecretName: default-token-qk5nc
Optional: false
QoS Class: BestEffort
Node-Selectors: <none>
Tolerations: node.kubernetes.io/not-ready:NoExecute for 300s
node.kubernetes.io/unreachable:NoExecute for 300s
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled <unknown> default-scheduler Successfully assigned default/springboot-mybatis-deployment-5b78f66997-hcmm4 to worker1
Normal Pulled 107s kubelet, worker1 Container image "zjj2006forever/springboot-mybatis:1.2" already present on machine
Normal Created 106s kubelet, worker1 Created container spingboot-mybatis
Normal Started 106s kubelet, worker1 Started container spingboot-mybatis
查看replicas
[root@master k8s]# kubectl get rs
NAME DESIRED CURRENT READY AGE
springboot-mybatis-deployment-5b78f66997 4 4 4 3m59s
检测一下应用运行正常
[root@worker1 ~]# curl http://10.244.1.24:18082/actuator/info
{"app":{"name":"springboot-mybatis","description":"two-datasource-test","version":"1.0","spring-boot-version":"2.1.6"}}
如果流量降下来了,我们可以收缩pod数量,执行命令
kubectl scale deployment nginx-deployment --replicas=2
查看pod数量,后来扩展的2个pod被删除了
[root@master k8s]# kubectl get pods
NAME READY STATUS RESTARTS AGE
springboot-mybatis-deployment-5b78f66997-d5fk9 1/1 Running 0 11m
springboot-mybatis-deployment-5b78f66997-k5xw8 1/1 Running 0 11m
可以看出,这种控制器模式,是由deployment控制ReplicaSet,ReplicaSet控制pod。
滚动更新
在实际开发工作中,升级服务上线是经常的事情。以本文中的应用为例,之前的deployment使用的镜像是zjj2006forever/springboot-mybatis:1.2,如果我们升级镜像版本到1.3,需要怎么操作呢?
注:镜像的升级版本我已经打好并且发布到dockerhub,感兴趣的同学自行拉取测试。
这个升级操作我们可以直接修改yaml文件,也可以执行如下命令进行修改,这个命令的原理是直接编辑etcd里面的springboot-mybatis-deployment控制器对象,可以跟编辑文件一样进行编辑
kubectl edit deployment/springboot-mybatis-deployment
编辑完成保存后,就会触发滚动更新。执行下面命令查看滚动更新的日志。
[root@master ~]# kubectl rollout status deployment/springboot-mybatis-deployment
Waiting for deployment "springboot-mybatis-deployment" rollout to finish: 1 out of 2 new replicas have been updated...
Waiting for deployment "springboot-mybatis-deployment" rollout to finish: 1 out of 2 new replicas have been updated...
Waiting for deployment "springboot-mybatis-deployment" rollout to finish: 1 out of 2 new replicas have been updated...
Waiting for deployment "springboot-mybatis-deployment" rollout to finish: 1 old replicas are pending termination...
Waiting for deployment "springboot-mybatis-deployment" rollout to finish: 1 old replicas are pending termination...
deployment "springboot-mybatis-deployment" successfully rolled out
这时我们再次查看pod,发现新的pod已经创建出来了
[root@master k8s]# kubectl get pods
NAME READY STATUS RESTARTS AGE
springboot-mybatis-deployment-69787d89c4-8kplf 1/1 Running 0 30s
springboot-mybatis-deployment-69787d89c4-hv4zl 1/1 Running 0 3m11s
从下面springboot-mybatis-deployment的描述Events中可以看出滚动更新的过程
[root@master ~]# kubectl describe deployment springboot-mybatis-deployment
Name: springboot-mybatis-deployment
Namespace: default
CreationTimestamp: Wed, 08 Jul 2020 06:00:17 -0400
Labels: <none>
Annotations: deployment.kubernetes.io/revision: 2
kubectl.kubernetes.io/last-applied-configuration:
{"apiVersion":"apps/v1","kind":"Deployment","metadata":{"annotations":{},"name":"springboot-mybatis-deployment","namespace":"default"},"sp...
Selector: app=springboot-mybatis
Replicas: 2 desired | 2 updated | 2 total | 2 available | 0 unavailable
StrategyType: RollingUpdate
MinReadySeconds: 0
RollingUpdateStrategy: 25% max unavailable, 25% max surge
Pod Template:
Labels: app=springboot-mybatis
Containers:
spingboot-mybatis:
Image: zjj2006forever/springboot-mybatis:1.3
Port: 8300/TCP
Host Port: 0/TCP
Environment: <none>
Mounts: <none>
Volumes: <none>
Conditions:
Type Status Reason
---- ------ ------
Available True MinimumReplicasAvailable
Progressing True NewReplicaSetAvailable
OldReplicaSets: <none>
NewReplicaSet: springboot-mybatis-deployment-69787d89c4 (2/2 replicas created)
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ScalingReplicaSet 30m deployment-controller Scaled up replica set springboot-mybatis-deployment-5b78f66997 to 2
Normal ScalingReplicaSet 29m deployment-controller Scaled up replica set springboot-mybatis-deployment-5b78f66997 to 4
Normal ScalingReplicaSet 19m deployment-controller Scaled down replica set springboot-mybatis-deployment-5b78f66997 to 2
Normal ScalingReplicaSet 6m18s deployment-controller Scaled up replica set springboot-mybatis-deployment-69787d89c4 to 1
Normal ScalingReplicaSet 3m37s deployment-controller Scaled down replica set springboot-mybatis-deployment-5b78f66997 to 1
Normal ScalingReplicaSet 3m37s deployment-controller Scaled up replica set springboot-mybatis-deployment-69787d89c4 to 2
Normal ScalingReplicaSet 3m32s deployment-controller Scaled down replica set springboot-mybatis-deployment-5b78f66997 to 0
上面event中最后4行就是滚动更新的过程。很明显,滚动更新过程是创建一个新的pod,删除一个旧的pod,直到新的pod全部创建,旧的pod的全部删除。可以"滚动更新"这个词非常形象。滚动更新有如下优势:
1.新pod启动失败整个过程就会停止,剩下的旧pod依然可以提供服务。
2.为了保证服务不中断,deployment控制器会保证一次删除pod的比例和一次创建的pod的比例,默认都是yaml中replicas的25%。
3.这2个比例也可以通过参数来配置,看下面的yaml。maxSurge指每次滚动过程中可以创建多少个pod,maxUnavailable指一次更新中可以删除几个pod,这2个参数值也可以用百分数表示,指的是滚动过程中一次创建或删除的pod数量占replicas配置的pod的比例。
apiVersion: apps/v1
kind: Deployment
metadata:
name: springboot-mybatis-deployment
spec:
selector:
matchLabels:
app: springboot-mybatis
replicas: 2
template:
metadata:
labels:
app: springboot-mybatis
spec:
containers:
- name: spingboot-mybatis
imagePullPolicy: IfNotPresent
image: zjj2006forever/springboot-mybatis:1.3
ports:
- containerPort: 8300
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 1
失败回滚
如果我们升级应用的过程中,pod启动失败,这时候我们为了不中断服务,必须回滚。比如之前的yaml文件中,我们定义的springboot-mybatis镜像版本是1.3,如果我们改成1.4版本,dockerhub上并没有这个版本,拉取失败导致pod启动失败。修改yaml文件中镜像版本到1.4后,执行更新命令
kubectl apply -f springboot-mybatis.yaml
这时deployment就会触发滚动更新,但是这时因为镜像拉取失败,pod创建失败,如下结果中第4行
[root@master ~]# kubectl get rs
NAME DESIRED CURRENT READY AGE
springboot-mybatis-deployment-5b78f66997 0 0 0 15h
springboot-mybatis-deployment-69787d89c4 2 2 2 14h
springboot-mybatis-deployment-7d6fc78b87 1 1 0 80s
我们再查看deployment的状态,如下,镜像版本是1.4,这时我们可以触发回滚操作。
[root@master ~]# kubectl describe deployment springboot-mybatis-deployment
Name: springboot-mybatis-deployment
Namespace: default
CreationTimestamp: Wed, 08 Jul 2020 06:00:17 -0400
Labels: <none>
Annotations: deployment.kubernetes.io/revision: 3
kubectl.kubernetes.io/last-applied-configuration:
{"apiVersion":"apps/v1","kind":"Deployment","metadata":{"annotations":{},"name":"springboot-mybatis-deployment","namespace":"default"},"sp...
Selector: app=springboot-mybatis
Replicas: 2 desired | 1 updated | 3 total | 2 available | 1 unavailable
StrategyType: RollingUpdate
MinReadySeconds: 0
RollingUpdateStrategy: 25% max unavailable, 25% max surge
Pod Template:
Labels: app=springboot-mybatis
Containers:
spingboot-mybatis:
Image: zjj2006forever/springboot-mybatis:1.4
Port: 8300/TCP
Host Port: 0/TCP
Environment: <none>
Mounts: <none>
Volumes: <none>
Conditions:
Type Status Reason
---- ------ ------
Available True MinimumReplicasAvailable
Progressing True ReplicaSetUpdated
OldReplicaSets: springboot-mybatis-deployment-69787d89c4 (2/2 replicas created)
NewReplicaSet: springboot-mybatis-deployment-7d6fc78b87 (1/1 replicas created)
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ScalingReplicaSet 14h deployment-controller Scaled up replica set springboot-mybatis-deployment-69787d89c4 to 1
Normal ScalingReplicaSet 14h deployment-controller Scaled down replica set springboot-mybatis-deployment-5b78f66997 to 1
Normal ScalingReplicaSet 14h deployment-controller Scaled up replica set springboot-mybatis-deployment-69787d89c4 to 2
Normal ScalingReplicaSet 14h deployment-controller Scaled down replica set springboot-mybatis-deployment-5b78f66997 to 0
Normal ScalingReplicaSet 3m3s deployment-controller Scaled up replica set springboot-mybatis-deployment-7d6fc78b87 to 1
下面命令可以查看deployment的升级历史
[root@master k8s]# kubectl rollout history deployment/springboot-mybatis-deployment
deployment.apps/springboot-mybatis-deployment
REVISION CHANGE-CAUSE
1 <none>
2 <none>
3 <none>
从上面的deployment的describe中我们可以看出目前revision是3(deployment.kubernetes.io/revision: 3),我们应该恢复到2,如下命令
kubectl rollout undo deployment/springboot-mybatis-deployment --to-revision=2
执行之后,再看deployment状态,镜像版本已经恢复到zjj2006forever/springboot-mybatis:1.3
[root@master k8s]# kubectl describe deployment
Name: springboot-mybatis-deployment
Namespace: default
CreationTimestamp: Wed, 08 Jul 2020 06:00:17 -0400
Labels: <none>
Annotations: deployment.kubernetes.io/revision: 4
kubectl.kubernetes.io/last-applied-configuration:
{"apiVersion":"apps/v1","kind":"Deployment","metadata":{"annotations":{},"name":"springboot-mybatis-deployment","namespace":"default"},"sp...
Selector: app=springboot-mybatis
Replicas: 2 desired | 2 updated | 2 total | 2 available | 0 unavailable
StrategyType: RollingUpdate
MinReadySeconds: 0
RollingUpdateStrategy: 25% max unavailable, 25% max surge
Pod Template:
Labels: app=springboot-mybatis
Containers:
spingboot-mybatis:
Image: zjj2006forever/springboot-mybatis:1.3
Port: 8300/TCP
Host Port: 0/TCP
Environment: <none>
Mounts: <none>
Volumes: <none>
Conditions:
Type Status Reason
---- ------ ------
Available True MinimumReplicasAvailable
Progressing True NewReplicaSetAvailable
OldReplicaSets: <none>
NewReplicaSet: springboot-mybatis-deployment-69787d89c4 (2/2 replicas created)
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ScalingReplicaSet 14h deployment-controller Scaled up replica set springboot-mybatis-deployment-69787d89c4 to 1
Normal ScalingReplicaSet 14h deployment-controller Scaled down replica set springboot-mybatis-deployment-5b78f66997 to 1
Normal ScalingReplicaSet 14h deployment-controller Scaled up replica set springboot-mybatis-deployment-69787d89c4 to 2
Normal ScalingReplicaSet 14h deployment-controller Scaled down replica set springboot-mybatis-deployment-5b78f66997 to 0
Normal ScalingReplicaSet 15m deployment-controller Scaled up replica set springboot-mybatis-deployment-7d6fc78b87 to 1
Normal ScalingReplicaSet 35s deployment-controller Scaled down replica set springboot-mybatis-deployment-7d6fc78b87 to 0
最后,从replicas的结果中我们可以看出,每次无论升级成功失败都会有一个replicas创建出来,为了限制保留的历史版本个数,可以通过参数spec.revisionHistoryLimit来进行设置。
[root@master k8s]# kubectl get rs
NAME DESIRED CURRENT READY AGE
springboot-mybatis-deployment-5b78f66997 0 0 0 15h
springboot-mybatis-deployment-69787d89c4 2 2 2 14h
springboot-mybatis-deployment-7d6fc78b87 0 0 0 14m
总结
deployment是kubernete中非常重要的一个编排技术,不过它有一个局限,只能编排无状态的pod,比如一个应用的集群,集群中的节点都是平等的,不存在主备关系。但是我们日常的开发中,好多pod是有状态的,比如一个部署在kubernete中的redis集群,会存在主从节点,这样启动的时候pod就存在顺序,deployment就不能满足了。
- python数据科学-数据预处理
- python3 邮箱相关邮箱的服务
- 谈一谈Python中str()和repr()的区别
- TensorFlow从0到1 - 15 - 重新思考神经网络初始化
- python2.7搬运--->TensorFlow - 深度学习破解验证码
- 来学习几个简单的Hive函数啦
- 推荐系统实战-基于用户的协同过滤
- 素数的筛法
- 听说GAN很高大上,其实就这么简单
- python3 解码base64遇到的问题与解决
- TensorFlow从0到1 - 16 - L2正则化对抗“过拟合”
- 使用虚拟环境,搭建python3+scrapy
- Matplotlib基础全攻略
- Python 小爬虫 - 爬取今日头条街拍美女图
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- linux文件管理命令实例分析【显示、查看、统计等】
- linux用户和组命令实例分析【切换、添加用户、权限控制等】
- Linux中Bash环境变量的配置方法
- Linux 中的防火墙 ufw 简介
- linux下如何实现快速拷贝大文件
- Linux硬链接与软链接原理及用法解析
- Linux通用java程序启动脚本代码实例
- 如何解决Ubuntu18.04循环登录/卡在开机界面/无法进入图形界面的问题
- CentOS7连接XShell与网络配置的方法
- 如何监控 Linux 服务器状态的方法
- Linux 文件系统的操作实现
- win10系统下安装superset的步骤
- Ubuntu下使用python3中的venv创建虚拟环境
- vsftpd配置虚拟用户登录的方法
- Linux 删除特殊字符文件名或目录的方法