Hi~朋友,关注置顶防止错过消息
什么是控制器 控制器种类 Deployment作用 资源定义 PodTemplate pod-temaplte-hash标签 滚动更新 更新回退 水平扩展/收缩 更新暂停/恢复 更新失败原因
什么是控制器
控制器是指可以对Pod进行管理的一些工作负载,他们可以按照用户的期待来完成一系列Pod的操作。
控制器的种类
Deployment和ReplicaSet:用来管理你的集群上的无状态应用,所有Pod都是相互等价的,并且在需要的时候被换掉 StatesulSet:运行一个或者多个以某种方式跟踪应用状态的Pods DaemonSet:定义提供节点本地支撑设施的Pod,每次你向集群中添加一个新节点时,如果该节点与某DaemonSet的规约匹配,则控制面会为该DaemonSet调度一个Pod到该新节点上运行 Job和CronJob:定义一些一直运行到结束并停止的任务。Job用来表达的是一次性的任务,而CronJob会根据其时间规划反复运行。
Deployment作用
为Pod和ReplicaSet提供更新能力 为应用提供水平扩展和收缩的功能 为应用提供滚动更新的功能
Deployment资源定义
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
# 上半部分是Deployment控制器定义
# 下半部分是被控制对象的定义(这里也就是Pod)
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
spec.replicas: 用来定义Pod的数量 spec.selector:用来查找被Deployment控制器管理的Pod
上述示例就是我们定义的nginx-deployment控制器,会确保携带了app=nginx标签的Pod个数永远为3。
PodTemplate
Deployment中spec.template字段被称为PodTemplate。
控制循环
控制循环所有控制器公用的逻辑,大体逻辑如下:
for {
实际状态 := 获取集群中对象X的实际状态(Actual State)
期望状态 := 获取集群中对象X的期望状态(Desired State)
if 实际状态 == 期望状态{
什么都不做
} else {
执行编排动作,将实际状态调整为期望状态
}
}
实际状态通常来源于Kubernetes集群本身 期望状态通常是用户提交的Deployment的YAML文件中定义的,比如Deployment中的spec.replicas字段。
创建Deployment控制器
$ kubectl apply -f deployment.yaml
查看一些Deployment和Pod相关信息
$ kubectl get deployments
$ kubectl describe deployment nginx-deployment
$ kubectl get pods -o wide

在Deployment中的简要信息中,主要有以下信息:
Name:Deployment的名称 REDAY:应用程序的可用副本数,显示模式是"就绪个数/期望个数" UP-TO-DATE:为了达到期望已经更新的副本数 AVAILABLE:可供用户使用的副本数 AGE:应用程序的运行时间
什么是pod-template-hash标签?
pod-template-hash标签是根据PodTemplate生成的Hash值,该标签会被加在被Deployment创建的ReplicaSet和Pod上,同时ReplicaSet的名称格式是[DeploymentName]-[template-hash哈希值]
$ kubectl get rs
$ kubectl describe rs nginx-deployment-9456bbbf9

$ kubectl get pods --show-labels

Delpoyment其实不会直接控制Pod,而是借助ReplicaSet操作Pod,ReplicaSet后续说。
如何进行Deployment滚动更新
仅当Deployment的Pod模板(即.spec.template)发生改变时,才会触发 Deployment上线,其他更新(如对Deployment执行扩缩容的操作)不会触发上线动作。
$ kubectl edit deployment/nginx-deployment
查看上线运行状态
$ kubectl rollout status deployment/nginx-deployment
$ kubectl get rs


从上图可以看出Deployment通过创建了新的ReplicaSet,并且将其中的Pod副本扩展成3个,老的ReplicaSet的Pod副本收缩为0,完成Deployment的更新。
何为滚动更新?
$ kubectl describe deployments nginx-deployment

从上图可以看出,Kubernetes在进行更新时并不是粗暴将原来的ReplicaSet直接下线,创建新的ReplicaSet,而是通过对新ReplicaSet的扩容、老ReplicaSet的缩容逐步完成。
Deployment在更新时可以确保仅关闭一定数量的Pod,默认情况下会确保75%的Pod处于运行状态 Deployment在更新时可以确保创建的Pod数量期望的值高,默认情况下比期望个数可以多25%
上述两个规则可以在图片中RollingUpdateStrategy字段中看出。
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3
strategy:
# 定义策略为为滚动更新
type: RollingUpdate
rollingUpdate:
maxUnavailable: 25%
maxSurge: 25%
.spect.strategy有两种值:
RollingUpdate:就是我们说的滚动更新,也是默认值 Recreate:重新创建,该策略下,如果Deployment发生更新,在创建新Pod之前会杀死所有的旧Pod

上图就是当我们把更新策略修改为Recreate以后,如果Deployment发生更新时的变更情况,可以发现旧的所有Pod都被杀死,然后重新创建新的Pod。
当.spect.strategy=RollingUpdate时,也就是更新策略为滚动更新时,主要有两个参数:
.spec.strategy.rollingUpdate.maxUnavailable:更新过程中最大不可用的Pod的上线,这里可以写固定的数值,也可以是百分比,默认值为25%(百分比算出来以后会去除小数)。 .spec.strategy.rollingUpdate.maxSurge:用来指定创建超出期望的Pod的上限,可以写固定的数值,也是百分比,默认值是25%(百分比算出来会向上取整)。
我们尝试将maxUnavailable改为90%,然后再对Deployment的PodTemplate进行更新(只有PodTemplate的变更才会触发更新),可以看到以下效果图:

从上图中我们可以看出,maxUnavailable已被修改为90%,同时在对老的Pod节点进行收缩时直接收缩到只有1个可用(3 * 0.9 = 2.7 = 2(去除小数))
如何进行回滚?
当我们发布的版本或者发布出问题时,我们需要对Deployment进行回滚,下面我们可以将nginx镜像改成一个1.161,故意模拟失败的情况,然后看
$ kubectl describe deployment nginx-deployment

从上图中,可以看到我们老的ReplicaSet被收缩为至1个Pod,新的ReplicaSet中创建了3个Pod,下面我再看一下Pod的情况:
$ kubectl get pods --show-labels

从上图中可以看出我们新创建的3个Pod一直处于拉取镜像阶段,同时老的Pod也被收缩到只剩1个。
查看滚动更新的状态
$ kubectl rollout status deployment/nginx-deployment

从上图可以看出,我们滚动更新处于pending中,还未结束,此时因为我们已经发现问题了,需要对此次部署回滚,可以使用以下命令版本:
$ kubectl rollout undo deployment/nginx-deployment
$ kubectl rollout status deployment/nginx-deployment

通过查看更新状态,我们可以看到Deployment被我们成功回滚,你可以再观察一下Pod、ReplicaSet和Deployment发现都回到发布前的状态。
如何选择版本进行回退?
在实际的生产环境中,我们可以能不仅需要回退到上一个版本中,有可能需要回退到上上个版本或者特定的版本,Kubernetes会为我们保存一些更新记录,此时这些记录就派上用场,我们可以通过这些记录可以回滚到特定版本。
$ kubectl rollout history deployment/nginx-deployment

可以看到,Kubernetes默认为我们保存了最近的3次发布历史,其中CHANGE-CAUSE相当于发布的描述,那么如何为我们的发布记录设置描述?主要有以下两种方式:
$ kubectl annotate deployment/nginx-deployment kubernetes.io/change-cause="回滚发布"
$ kubectl rollout history deployment/nginx-deployment

可以看到我们最近的那一次回滚发布已经加上了描述信息。
方式二是通过修改资源清单的方式如下:
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
kubernetes.io/change-cause: 设置Nginx镜像为1.14.1
查看发布历史的详细信息
$ kubectl rollout history deployment/nginx-deployment --revision=6

保存的发布历史版本的个数我们可以通过.spec.revisionHistoryLimit进行修改,超过该数量的旧的ReplicaSet将会被清理,如下:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3
revisionHistoryLimit: 5
$ kubectl set image deployment/nginx-deployment nginx=nginx:1.21.6
$ kubectl annotate deployment/nginx-deployment kubernetes.io/change-cause="设置Nginx镜像为1.21.6"
$ kubectl set image deployment/nginx-deployment nginx=nginx:1.21
$ kubectl annotate deployment/nginx-deployment kubernetes.io/change-cause="设置Nginx镜像为1.21"

从上图可以看出,历史版本现在数量已经由3个变为5个。
如何回退到指定版本?
上面我们已经知道了如何查看发布历史,那么如何回退到指定版本呢?
$ kubectl rollout undo deployment/nginx-deployment --to-revision=6
$ kubectl rollout status deployment/nginx-deployment
$ kubectl rollout history deployment/nginx-deployment

如何进行手动进行水平扩展/收缩?
$ kubectl scale deployment/nginx-deployment --replicas=5

$ kubectl get rs
$ kubectl get pods --show-labels

可以看出Pod的数量被成功从3个水平扩展到了5个。
如何自动进行水平扩展和收缩?
自动进行水平扩展/收缩主要依赖HorizontalPodAutoscaler(HPA)来实现,HPA会综合评估所有Pod负载来决定是扩展还是收缩。使用HPA的前置条件必须要安装Metric-Server,如果启用HPA,不要设置.spec.replicas。
创建HPA
$ kubectl autoscale deployment/nginx-deployment --min=2 --max=8 --cpu-percent=80

如何暂停/恢复Deployment更新?
对于Deployment有时候我们会多次进行更新,但是这些更新我们并不想触发Deployment的更新操作,此时可以使用下面的命令对Deployment进行暂停:
$ kubectl rollout pause deployment/nginx-deployment

当我们在多次修改以后,可以对Deployment进行恢复,这期间的修改都会合并成一个版本进行更新:
$ kubectl rollout resume deployment/nginx-deployment
Delpoyment部署失败的几个原因?
常见的原因有:
配额不足 就绪探针(Readiness Probe)失败 镜像拉取错误 权限不足 应用程序运行时错误
本期Kubernetes Deployment控制器就到这,扫码关注,更多内容我们下期再见!





