抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

Kubernetes 基础资源控制器

image-20220525094307190

概述

Pod是kubernetes的最小管理单元,在kubernetes中,按照pod的创建方式可以将其分为两类:

  • 自主式pod:kubernetes直接创建出来的Pod,这种pod删除后就没有了,也不会重建
  • 控制器创建的pod:kubernetes通过控制器创建的pod,这种pod删除了之后还会自动重建

Pod控制器是什么

Pod控制器就是帮助我们自动的调度管理Pod,并满足期望的Pod数量。

​ Pod控制器是用于实现管理pod的中间层,确保pod资源符合预期的状态,pod的资源出现故障时,会尝试 进行重启,当根据重启策略无效,则会重新新建pod的资源。

​ 创建为具体的控制器对象之后,每个控制器均通过API Server提供的接口持续监控相关资源对象的当前状态,并在因故障、更新或其他原因导致系统状态发生变化时,尝试让资源的当前状态想期望状态迁移和逼近。

Pod和Pod控制器

Pod控制器资源通过持续性地监控集群中运行着的Pod资源对象来确保受其管控的资源严格符合用户期望的状态,例如资源副本的数量要精确符合期望等。

通常,一个Pod控制器资源至少应该包含三个基本的组成部分:

  • 标签选择器:匹配并关联Pod资源对象,并据此完成受其管控的Pod资源计数。
  • 期望的副本数:期望在集群中精确运行着的Pod资源的对象数量。
  • Pod模板:用于新建Pod资源对象的Pod模板资源。

控制器的必要性

​ 自主式Pod对象由调度器调度到目标工作节点后即由相应节点上的kubelet负责监控其容器的存活状态,容器主进程崩溃后,kubelet能够自动重启相应的容器。

​ 但对出现非主进程崩溃类的容器错误却无从感知,这便依赖于pod资源对象定义的存活探测,以便kubelet能够探知到此类故障。

​ 但若pod被删除或者工作节点自身发生故障(工作节点上都有kubeletkubelet不可用,因此其健康状态便无法保证),则便需要控制器来处理相应的容器重启和配置。

常见的控制器

Pod控制器由masterkube-controller-manager组件提供,常见的此类控制器有

ReplicationController

比较原始的pod控制器,已经被废弃,由ReplicaSet替代

ReplicaSet

代用户创建指定数量的pod副本数量,确保pod副本数量符合预期状态,并且支持滚动式自动扩容和缩容功能

Deployment

工作在ReplicaSet之上,用于管理无状态应用,目前来说最好的控制器。支持滚动更新和回滚功能,还提供声明式配置。

Horizontal Pod Autoscaler

可以根据集群负载自动水平调整Pod的数量,实现削峰填谷

DaemonSet

用于确保集群中的每一个节点只运行特定的pod副本,常用于实现系统级后台任务,比如ELK服务

Job

它创建出来的pod只要完成任务就立即退出,不需要重启或重建,用于执行一次性任务

Cronjob

它创建的Pod负责周期性任务控制,不需要持续后台运行,用于执行周期性任务

StatefulSet

管理有状态应用

ReplicaSet控制器

replicaset top

ReplicaSet概述

ReplicaSet是取代早期版本中的ReplicationController控制器,其功能基本上与ReplicationController相同

ReplicaSet(简称RS)是Pod控制器类型的一种实现,用于确保由其管控的Pod对象副本数在任意时刻都能精确满足期望的数量。ReplicaSet控制器资源启动后会查找集群中匹配器标签选择器的Pod资源对象,当前活动对象的数量与期望的数量不吻合时,多则删除,少则通过Pod模板创建以补足。

使用场景

假如我们现在有一个 Pod 正在提供线上的服务,我们来想想一下我们可能会遇到的一些场景:

  • 某次运营活动非常成功,网站访问量突然暴增
  • 运行当前 Pod 的节点发生故障了,Pod 不能正常提供服务了

​ 第一种情况,可能比较好应对,活动之前我们可以大概计算下会有多大的访问量,提前多启动几个 Pod 副本,活动结束后再把多余的 Pod 杀掉,虽然有点麻烦,但是还是能够应对这种情况的。

​ 第二种情况,可能某天夜里收到大量报警说服务挂了,然后起来打开电脑在另外的节点上重新启动一个新的 Pod,问题可以解决。

​ 但是如果我们都人工的去解决遇到的这些问题,似乎又回到了以前刀耕火种的时代了是吧?如果有一种工具能够来帮助我们自动管理 Pod 就好了,Pod 挂了自动帮我在合适的节点上重新启动一个 Pod,这样是不是遇到上面的问题我们都不需要手动去解决了。

​ 而 ReplicaSet 这种资源对象就可以来帮助我们实现这个功能,ReplicaSet(RS) 的主要作用就是维持一组 Pod 副本的运行,保证一定数量的 Pod 在集群中正常运行,ReplicaSet 控制器会持续监听它所控制的这些 Pod 的运行状态,在 Pod 发送故障数量减少或者增加时会触发调谐过程,始终保持副本数量一定。

ReplicaSet功能

ReplicaSet的主要作用是保证一定数量的pod正常运行,它会持续监听这些Pod的运行状态,一旦Pod发生故障,就会重启或重建。同时它还支持对pod数量的扩缩容镜像版本的升降级,同时ReplicaSet能够实现以下功能:

精确反应期望值

ReplicaSet需要确保由其控制运行的Pod副本数量精确吻合配置中定义的期望值,否则就会自动补足所缺或终止所余。

保证高可用

​ 探测到由其管控的Pod对象因其所在的工作节点故障而不可用时,自动请求由调度器于其他工作节点创建缺失的Pod副本。

弹性伸缩

​ 可通过ReplicaSet控制器动态扩容或者缩容Pod资源对象的数量。必要时还可以通过HPA控制器实现Pod资源规模的自动伸缩。

使用案例

下面我们就结合一个案例来说明ReplicaSet的使用

创建资源清单

我们创建一个ReplicaSet的资源清单

1
vi nginx-rs.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
apiVersion: apps/v1  #api版本定义
kind: ReplicaSet #定义资源类型为ReplicaSet
metadata: #元数据定义
name: nginx-rs
namespace: default
spec: #ReplicaSet的规格定义
replicas: 2 #定义副本数量为2个
selector: #标签选择器,定义匹配Pod的标签
matchLabels:
app: nginx
template: #Pod的模板定义
metadata: #Pod的元数据定义
name: nginx-pod #自定义Pod的名称
labels: #定义Pod的标签,需要和上面的标签选择器内匹配规则中定义的标签一致,可以多出其他标签
app: nginx
spec: #Pod的规格定义
containers: #容器定义
- name: nginx #容器名称
image: nginx:1.12 #容器镜像
imagePullPolicy: IfNotPresent #拉取镜像的规则
ports: #暴露端口
- name: http #端口名称
containerPort: 80
资源清单解析

如上资源清单可以分为三个部分

image-20220530142346777

  • 第1部分是RS本身的信息,比如版本号、类型、元数据(里面有名称、命名空间、标签);
  • 第2部分是设置副本数量和选择器配置,用于选定RS来管理哪些Pod,第3部分来设置Pod标签,然后第2部分标签选择器来选择,比如第2部分的app:nginx-pod和第3部分的app:nginx进行标签匹配;
  • 第3部分是Pod的配置,用户创建pod时的创建模板;
核心属性

在这里面,需要新了解的配置项就是spec下面几个选项:

字段值 类型 描述
replicas Integer 指定期望的Pod对象副本数量
selector Object 当前控制器匹配Pod对象副本的标签选择器,支持matchLabels和matchExpressions两种匹配机制
template Object 用于定义Pod时的Pod资源信息
minReadySeconds Integer 用于定义Pod启动后多长时间为可用状态,默认为0秒

Pod 模板这个概念非常重要,因为后面我们讲解到的大多数控制器,都会使用 Pod 模板来统一定义它所要管理的 Pod,更有意思的是,我们还会看到其他类型的对象模板,比如Volume 的模板等。

应用配置

我们创建完成资源清单后就可以应用配置

1
2
kubectl apply -f nginx-rs.yml
kubectl get pod -o wide

我们就可以看到我们创建的两个pod了

image-20220530142819361

查看ReplicaSet

因为我们创建了ReplicaSet所以我们还可以查看ReplicaSet的情况

1
kubectl get rs

image-20220530143015263

显示的几列描述信息如下

  • DESIRED:期望副本数量

  • CURRENT:当前副本数量*

  • READY:已经准备好提供服务的副本数量

破坏性测试

ReplicaSet的最大作用是让运行在K8s中的POD符合期望值,我们删除一个POD,ReplicaSet可以帮我们自动创建新的POD

根据标签删除pod

我们根据标签删除POD,删除后k8s会帮我们自动创建

1
2
3
kubectl get pod -o wide
kubectl delete pod -l app=nginx
kubectl get pod -o wide

我们发现我们删除POD后,自动帮我们创建了,满足我们的期望值

image-20220530144354040

扩缩容

可以直接通过vim 编辑清单文件修改replicas字段,也可以通过kubect edit 命令去编辑

kubectl还提供了一个专用的子命令scale用于实现应用规模的伸缩,支持从资源清单文件中获取新的目标副本数量,也可以直接在命令行通过“--replicas”选项进行读取。

scale命令扩容

命令扩容一般用于短期的临时性扩容,应付完成后要记得缩容到原来水平

查看容量

可看到当前的nginx-rs设置的期望值是2,并且当前的值也是2

1
kubectl get rs nginx-rs -o wide

image-20220530144728066

执行扩容

使用scale命令可以对集群进行扩缩容

1
2
kubectl scale replicasets nginx-rs --replicas=4
kubectl get rs nginx-rs -o wide

现在通过扩容命令将nginx-rs扩容到4个副本,我们发现已经扩容完成了

image-20220530144938161

查看Pod情况

我们可以通过命令查看Pod的情况

1
kubectl get pods -o wide

我们发现已经扩容到了4个副本了

image-20220530145127558

配置文件缩容

配置文件扩容一般用于初始容量变更,长期进行扩容

查看容量

可看到当前是四个节点

1
kubectl get pods -o wide

image-20220530145127558

应用配置

因为我们没有更改配置文件,所以配置文件现在的副本数还是2,所以应用配置后可以直接进行缩容

1
2
kubectl apply -f nginx-rs.yml
kubectl get rs nginx-rs -o wide

我们发现nginx-rs已经还原到了最初的状态

image-20220530145448930

查看Pod情况

我们可以查看POD的情况

1
kubectl get pods -o wide

我们发现现在只有两个节点了,说明我们已经缩容成功了

image-20220530145553565

更新控制器

replicaset还有一个很重要的功能就是应用更新,更新我们可以直接修改资源清单然后应用即可

更新资源清单

下面修改上面创建的replicaset示例文件,将镜像nginx:1.12改为1.20版本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
apiVersion: apps/v1  #api版本定义
kind: ReplicaSet #定义资源类型为ReplicaSet
metadata: #元数据定义
name: nginx-rs
namespace: default
spec: #ReplicaSet的规格定义
replicas: 2 #定义副本数量为2个
selector: #标签选择器,定义匹配Pod的标签
matchLabels:
app: nginx
template: #Pod的模板定义
metadata: #Pod的元数据定义
name: nginx-pod #自定义Pod的名称
labels: #定义Pod的标签,需要和上面的标签选择器内匹配规则中定义的标签一致,可以多出其他标签
app: nginx
spec: #Pod的规格定义
containers: #容器定义
- name: nginx #容器名称
image: nginx:1.20 #容器镜像
imagePullPolicy: IfNotPresent #拉取镜像的规则
ports: #暴露端口
- name: http #端口名称
containerPort: 80
应用更新

我们现在应用资源清单来完成更新

1
2
kubectl apply -f nginx-rs.yml
kubectl get rs -o wide

我们看到nginx-rs已经被更新了

image-20220530150457072

查看POD版本

我们再来检查以下POD的版本

1
kubectl get pods -o custom-columns=Name:metadata.name,Image:spec.containers[0].image

我们发现k8s只更新了RS控制器但是并没有更新pod的nginx版本号

image-20220530150625045

删除POD

这里虽然重载了,但是已有的pod所使用的镜像仍然是1.12版本的,只是新建pod时才会使用1.20版本,这里测试先手动删除已有的pod

1
2
kubectl delete pods -l app=nginx
kubectl get pods -o custom-columns=Name:metadata.name,Image:spec.containers[0].image

最终我们发现这里的POD已经被更新了,使用RS控制器需要注意更新版本需要删除应用

image-20220530150832105

删除replicaset控制器

使用Kubectl delete命令删除ReplicaSet对象时默认会一并删除其管控的各Pod对象,有时,考虑到这些Pod资源未必由其创建,或者即便由其创建也并非自身的组成部分,这时候可以添加“--cascade=false”选项,取消级联关系。

查看集群情况

我们可以先看下RS集群的情况

1
2
kubectl get rs -o wide
kubectl get pods -o wide

我们发现POD都正常运行

image-20220530151136275

删除replicaset

删除replicaset我们可以通过命令直接删除

直接删除
1
2
3
kubectl delete replicasets nginx-rs
kubectl get rs -o wide
kubectl get pods -o wide

我们发现直接删除后,K8s还会将replicaset以及POD全部删除

image-20220530151407279

只删除replicaset

有时候可以通过参数cascade=false设置不删除pod,测试前我们先应用nginx-rs

1
2
kubectl apply -f nginx-rs.yml
kubectl get rs

image-20220530151534300

只删除RS

1
2
3
kubectl delete replicasets nginx-rs --cascade=false
kubectl get rs -o wide
kubectl get pods -o wide

我们发现删除了RS后,POD没有被删除

image-20220530151705572

删除POD

1
2
kubectl delete pod -l app=nginx
kubectl get pods -o wide

image-20220530151805386

Deployment控制器

image-20211110225019376

Deployment概述

​ 只需要在 Deployment 中描述想要的目标状态是什么,Deployment controller 就会帮您将 Pod 和ReplicaSet 的实际状态改变到您的目标状态。也可以定义一个全新的 Deployment 来创建 ReplicaSet 或者删除已有的 Deployment 并创建一个新的来替换。

img

什么是Deployment

Deployment为Pod和Replica Set(下一代Replication Controller)提供声明式更新

​ 前面我们学习了 ReplicaSet 控制器,了解到该控制器是用来维护集群中运行的 Pod 数量的,但是往往在实际操作的时候,我们反而不会去直接使用 RS,而是会使用更上层的控制器Deployment

​ Deployment 一个非常重要的功能就是实现了 Pod 的滚动更新,比如我们应用更新了,我们只需要更新我们的容器镜像,然后修改 Deployment 里面的 Pod 模板镜像,那么 Deployment 就会用滚动更新(Rolling Update)的方式来升级现在的 Pod,这个能力是非常重要的。因为对于线上的服务我们需要做到不中断服务,所以滚动更新就成了必须的一个功能。

​ 而 Deployment 这个能力的实现,依赖的就是ReplicaSet 这个资源对象,实际上我们可以通俗的理解就是每个 Deployment 就对应集群中的一次部署,这样就更好理解了

Deployment特性

Deployment控制器资源的主要职责是为了保证Pod资源的健康运行,其大部分功能均可通过调用ReplicaSet实现,同时还增添部分特性。

  • 事件和状态查看:必要时可以查看Deployment对象升级的详细进度和状态。
  • 回滚:升级操作完成后发现问题时,支持使用回滚机制将应用返回到前一个或由用户指定的历史记录中的版本上。
  • 版本记录:对Deployment对象的每一个操作都予以保存,以供后续可能执行的回滚操作使用。
  • 暂停和启动:对于每一次升级,都能够随时暂停和启动。
  • 多种自动更新方案:一是Recreate,即重建更新机制,全面停止、删除旧有的Pod后用新版本替代;另一个是RollingUpdate,即滚动升级机制,逐步替换旧有的Pod至新的版本。

使用案例

配置资源清单

Deployment 资源对象的格式和 ReplicaSet 几乎一致,如下资源对象就是一个常见的 Deployment 资源类型:

1
vi nginx-deployment.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 2 #期望的Pod副本数量
selector: #label selector
matchLabels:
app: nginx
template: #Pod模板
metadata:
labels: #一定要和上面的selector 保持一致
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80
配置项说明
  • 我们定义了一个Deployment,名字叫nginx-deployment;
  • 通过spec.replicas字段定义了Pod的副本数是2;
  • 通过spec.selector字段定义了被打上app: nginx的标签的Pod才会被管理;
  • tmplate字段定义了这个Deployment管理的Pod应该是怎样的,具有怎样的属性;
创建控制器
1
2
kubectl apply -f nginx-deployment.yml
kubectl get deployment -o wide

这样我们就创建了一个deployment

image-20220530153509359

显示的几列描述信息如下

  • READY:当前可用pod数/总pod数

  • UP-TO-DATE:最新版本的pod的数量

  • AVAILABLE:当前可用的pod的数量

查看replicaset

ReplicaSet是一个副本控制器,ReplicaSet可以用selector来控制Pod的数量,而Deployments是一个更高层次的概念,它管理ReplicaSets,并提供对pod的声明性更新以及许多其他的功能。

1
kubectl get rs -o wide

image-20220530153854077

通过查看资源对象可以看出,Deployment会自动创建相关的ReplicaSet控制器资源,并以”[DEPLOYMENT-name]-[POD-TEMPLATE-HASH-VALUE]”格式为其命名,其中的hash值由Deployment自动生成,而Pod名则是以ReplicaSet控制器的名称为前缀,后跟5位随机字符。

扩缩容

scale命令扩容

命令扩容一般用于短期的临时性扩容,应付完成后要记得缩容到原来水平

查看当前容量

我们可以使用如下命令来查看deployment详情

1
kubectl get deployment -o wide

我们发现当前的pod数量是2

image-20220530154222804

执行扩容

使用scale命令可以对集群进行扩缩容,扩充到4个节点

1
2
kubectl scale deployment nginx-deployment --replicas=4
kubectl get deployment -o wide

我们发现deployment已经更新完成了,并且是4个POD

image-20220530154350993

查看POD情况
1
kubectl get pod -o wide

image-20220530154457525

查看RS情况
1
kubectl get rs -o wide

我们发现扩容后只是在原来的RS集群上面增加了两个节点

image-20220530154554682

配置文件缩容

配置文件扩缩容一般用于初始容量变更,长期进行扩缩容

查看当前容量

我们可以使用如下命令来查看deployment详情

1
2
kubectl get deployment -o wide
kubectl get pod -o wide

我们发现当前的pod数量是4

image-20220530154740863

应用配置文件

因为我们没有更改配置文件,直接应用配置文件即可

1
2
kubectl apply -f nginx-deployment.yml
kubectl get deployment -o wide

我们发现已经缩容完成了

image-20220530154854054

查看POD情况
1
kubectl get pod -o wide

我们看到POD的数量已经变为了2

image-20220530154930557

查看RS情况
1
kubectl get rs -o wide

我们发现扩容后只是在原来的RS集群上面减少了两个节点

image-20220530155051277

更新控制器

​ ReplicaSet控制器的应用更新需要手动分成多步并以特定的次序进行,过程繁杂且容易出错,而Deployment却只需要由用户指定在Pod模板中要改动的内容,(如镜像文件的版本),余下的步骤便会由其自动完成。Pod副本数量也是一样。

更新策略

deployment支持两种更新策略:**重建更新滚动更新**

重建更新

​ 先删除所有的Pod再根据新的模板创建新的Pod,中间会导致服务的不可用,用户要么使用的是新版本,要么就是旧版本

滚动更新

滚动更新是默认的更新策略,它在删除一些旧版本的Pod的同时补充创建一些新的Pod,更新期间服务不会中断。

​ 滚动更新指先删除一部分老版本的Pod,再去重建一部分新版本的Pod,然后再去删除一部分老版本Pod,再去重建一部分新版本的Pod,以此类推,直至全部更新成新版本,在这个过程中老版本Pod和新版本Pod是同时存在的;

滚动更新参数

滚动更新期间,应用升级期间还要确保可用的Pod对象数量不低于某些阈值,确保可以持续处理客户端请求,变动的方式和Pod对象的数量范围将通过maxSurgemaxunavailable两个属性协同进行定义

  • maxSurge:指定升级期间存在的总Pod对象数量最多以超出期望值的个数,其值可以为0或者正整数,也可以是一个期望值的百分比:例如如果期望值是3,当前的属性值为1,则表示Pod对象的总数不能超过4个。
  • maxUnavailable:升级期间正常可用的Pod副本数(包括新旧版本)最多不能低于期望的个数、其值可以是0或者正整数。也可以是一个期望值的百分比,默认值为1;该值意味着如果期望值是3,那么在升级期间至少要有两个Pod对象处于正常提供服务的状态

maxSurge和maxUnavailable的数量不能同时为0,否则Pod对象的复本数量在符合用户期望的数量后无法做出合理变动以进行滚动更新操作。

命令更新

命令扩容一般用于短期的临时性扩容,应付完成后要记得缩容到原来水平,默认情况下使用的是滚动更新策略

查看版本

通过命令查看当前deployment镜像的版本号以及POD的版本号

1
2
kubectl get deployment -o wide
kubectl get pods -o custom-columns=Name:metadata.name,Image:spec.containers[0].image

我们发现镜像的版本号符合预期,都是1.7.9

image-20220530160318833

执行更新命令

我们可以通过命令直接进行更新

1
kubectl set image deployment/nginx-deployment nginx=nginx:1.12

执行命令后就开始进行更新了

image-20220530160656720

查看更新过程

我们可以通过命令来查看更新的过程

1
kubectl get deployment nginx-deployment -o wide -w

我们发现更新的过程中没有出现服务不可用的情况,这种就是滚动更新

image-20220530160753800

查看版本

通过命令查看更新后的deployment镜像的版本号以及POD的版本号

1
2
kubectl get deployment -o wide
kubectl get pods -o custom-columns=Name:metadata.name,Image:spec.containers[0].image

我们发现镜像的版本号符合预期,都是1.12

image-20220530160934011

查看RS情况
1
kubectl get rs -o wide

我们发现更新后新建了一个RS,并且保留原来的RS但是节点数为0用来回滚

image-20220530161014377

配置重建更新

我们更多的情况下是使用配置文件进行更新,配置文件更新适合于长期以及永久更新,我们使用配置文件进行重建更新

配置解释

可以通过strategy指定策略类型,支持两个属性

1
2
3
4
5
6
7
strategy:指定新的Pod替换旧的Pod的策略, 支持两个属性:
type:指定策略类型,支持两种策略
Recreate:重建更新,在创建出新的Pod之前会先杀掉所有已存在的Pod
RollingUpdate:滚动更新,就是杀死一部分,就启动一部分,在更新过程中,存在两个版本Pod
rollingUpdate:当type为RollingUpdate时生效(如果是重建更新则不需要此参数),用于为RollingUpdate设置参数,支持两个属性:
maxUnavailable:用来指定在升级过程中不可用Pod的最大数量,默认为25%。即如果有8个Pod,先干掉8x25%=2个。
maxSurge: 用来指定在升级过程中可以超过期望的Pod的最大数量,默认为25%。即如果有8个Pod,先升级8x25%=2个。
编辑资源清单

现在我们编辑配置文件设置重建更新

1
vi nginx-deployment.yml

我们使用重建更新将nginx版本改为1.15版本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
strategy: #镜像更新策略
type: Recreate #重建更新策略
replicas: 2 #期望的Pod副本数量
selector: #label selector
matchLabels:
app: nginx
template: #Pod模板
metadata:
labels: #一定要和上面的selector 保持一致
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.15 #重建更新为1.15版本
ports:
- containerPort: 80
应用更新

我们可以直接应用配置文件来进行配置更新

1
kubectl apply -f nginx-deployment.yml

image-20220530162441523

查看更新过程

我们可以通过命令来查看更新的过程

1
kubectl get deployment nginx-deployment -o wide -w

我们发现更新的过程有一段时间服务是不可用的,这种就属于重建更新,速度快但是服务有中断的情况

image-20220530162722254

查看版本

通过命令查看更新后的deployment镜像的版本号以及POD的版本号

1
2
kubectl get deployment -o wide
kubectl get pods -o custom-columns=Name:metadata.name,Image:spec.containers[0].image

我们发现镜像的版本号符合预期,都是1.15

image-20220530162845063

查看RS情况
1
kubectl get rs -o wide

我们发现更新后新建了一个RS,并且保留原来的RS但是节点数为0用来回滚

image-20220530162922031

配置滚动更新

使用重建更新可能导致服务不可用,K8s默认采用的就是滚动更新

编辑资源清单

现在我们编辑配置文件设置重建更新

1
vi nginx-deployment.yml

我们使用重建更新将nginx版本改为1.20版本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
strategy: #镜像更新策略
type: RollingUpdate #滚动更新策略
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
replicas: 2 #期望的Pod副本数量
selector: #label selector
matchLabels:
app: nginx
template: #Pod模板
metadata:
labels: #一定要和上面的selector 保持一致
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.20 #重建更新为1.20版本
ports:
- containerPort: 80
应用更新

我们可以直接应用配置文件来进行配置更新

1
kubectl apply -f nginx-deployment.yml

我们将配置文件更新为1.20版本

image-20220530163555196

查看更新过程

我们可以通过命令来查看更新的过程

1
kubectl get deployment nginx-deployment -o wide -w

我们发现更新的过程中没有出现服务不可用的情况,这种就是滚动更新

image-20220530163453225

查看版本

通过命令查看更新后的deployment镜像的版本号以及POD的版本号

1
2
kubectl get deployment -o wide
kubectl get pods -o custom-columns=Name:metadata.name,Image:spec.containers[0].image

我们发现镜像的版本号符合预期,都是1.20

image-20220530163616016

查看RS情况
1
kubectl get rs -o wide

我们发现更新后新建了一个RS,并且保留原来的RS但是节点数为0用来回滚

image-20220530163649159

版本回退

deployment支持版本升级过程中的暂停、继续功能以及版本回退等诸多功能,下面具体来看

回滚选项

kubectl rollout: 版本升级相关功能,支持下面的选项:

  • status 显示当前升级状态
  • history 显示 升级历史记录
  • pause 暂停版本升级过程
  • resume 继续已经暂停的版本升级过程
  • restart 重启版本升级过程
  • undo 回滚到上一级版本(可以使用–to-revision回滚到指定版本)
直接回滚
查看版本

通过命令查看当前deployment镜像的版本号以及POD的版本号

1
2
kubectl get deployment -o wide
kubectl get pods -o custom-columns=Name:metadata.name,Image:spec.containers[0].image

我们发现镜像的版本号都是1.20

image-20220530164057415

查看RS情况
1
kubectl get rs -o wide

image-20220530164149602

执行回滚命令

我们直接执行回滚命令

1
kubectl rollout undo deployment nginx-deployment

这样我们就完成了一次回滚

image-20220530164308185

查看回滚过程

我们查看下回顾的过程

1
kubectl get deployment nginx-deployment -o wide -w

我们发现本次回滚是使用滚动更新来完成的

image-20220530164408420

查看RS情况
1
kubectl get rs -o wide

我们对比下上面的RS,发现回滚就是将上一个版本的RS给启用了

image-20220530164459966

再次回滚

我们再次回滚一次看看会发生什么

1
kubectl rollout undo deployment nginx-deployment

image-20220530164632418

查看版本

通过命令查看当前deployment镜像的版本号以及POD的版本号

1
2
kubectl get deployment -o wide
kubectl get pods -o custom-columns=Name:metadata.name,Image:spec.containers[0].image

我们发现镜像的版本号全部又回到了1.20的版本,说明直接回滚只会在最近的两个版本之间互相回滚

image-20220530164711365

回滚指定版本

直接回滚只在最近的两个版本之间来回回滚,不会回滚到在上一个版本,如果想要跨版本回滚怎么办呢

查看版本记录

我们可以通过rollout history命令来查看回滚的版本记录

1
kubectl rollout history deployment nginx-deployment

该命令可以限制版本变更历史

image-20220530165021969

历史版本内容

通过指定版本号来查看变更内容,找到需要回滚的版本,我们可以通过以下命令进行查看,这里我会回滚到最早版本nginx:1.12

1
kubectl rollout history deployment nginx-deployment --revision=2

我们找到了需要回滚的版本是2

image-20220530165402687

执行回滚命令

写入我们需要回滚到的指定版本2

1
kubectl rollout undo deployment nginx-deployment --to-revision=2

这样我们就可以完成指定版本的回滚

image-20220530165427888

查看版本

通过命令查看当前deployment镜像的版本号以及POD的版本号

1
2
kubectl get deployment -o wide
kubectl get pods -o custom-columns=Name:metadata.name,Image:spec.containers[0].image

我们发现镜像的版本号全部又回到了1.12的版本,说明我们已经完成了指定版本的回滚

image-20220530165529488

金丝雀发布

Deployment控制器支持控制更新过程中的控制,如“暂停(pause)”或“继续(resume)”更新操作

什么是金丝雀发布

​ 比如有一批新的Pod资源创建完成后立即暂停更新过程,此时,仅存在一部分新版本的应用,主体部分还是旧的版本

​ 然后,再筛选一小部分的用户请求路由到新版本的Pod应用,继续观察能否稳定地按期望的方式运行,确定没问题之后再继续完成余下的Pod资源滚动更新,否则立即回滚更新操作。这就是所谓的金丝雀发布。

准备工作
编辑配置文件
1
vi nginx-canary.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 2 #期望的Pod副本数量
selector: #label selector
matchLabels:
app: nginx
template: #Pod模板
metadata:
labels: #一定要和上面的selector 保持一致
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.7.9 #重建更新为1.15版本
ports:
- containerPort: 80
应用配置
1
2
kubectl apply -f nginx-deployment.yml
kubectl get deployment -o wide

image-20220530171518372

发布示例

下面我们演示下如何使用金丝雀发布

执行更新命令

更新deployment的版本,并配置暂停deployment

1
kubectl set image deployment nginx-deployment nginx=nginx:1.12 && kubectl rollout pause deployment nginx-deployment

该命令是先执行更新,接着马上就暂停更新

image-20220530172106518

查看RS状态

观察RS的状态信息

1
kubectl get rs -o wide

我们看到当前的RS中1.12有一个实例,而原有的1.7.9还有两个实例

image-20220530172239713

查看更新状态

通过如下命令可以查看更新状态

1
kubectl rollout status deploy nginx-deployment

处于正在等待更新状态,而且目前已经有1个更新完毕,一共有2个需要更新,这时候就会有一部分流量往完成更新的pod上访问

image-20220530172553037

恢复更新

如果测试没有问题就可以继续进行更新,完成更新操作

1
kubectl rollout resume deploy nginx-deployment

image-20220530172714574

查看RS状态
1
kubectl get rs -o wide

我们发现当前节点都已经更新到了最新版本了

image-20220530172806415

评论