暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Kubernetes Deployment控制器

788



Hi~朋友,关注置顶防止错过消息


  1. 什么是控制器
  2. 控制器种类
  3. Deployment作用
  4. 资源定义
  5. PodTemplate
  6. pod-temaplte-hash标签
  7. 滚动更新
  8. 更新回退
  9. 水平扩展/收缩
  10. 更新暂停/恢复
  11. 更新失败原因

什么是控制器

控制器是指可以对Pod进行管理的一些工作负载,他们可以按照用户的期待来完成一系列Pod的操作。

控制器的种类

  • Deployment和ReplicaSet:用来管理你的集群上的无状态应用,所有Pod都是相互等价的,并且在需要的时候被换掉
  • StatesulSet:运行一个或者多个以某种方式跟踪应用状态的Pods
  • DaemonSet:定义提供节点本地支撑设施的Pod,每次你向集群中添加一个新节点时,如果该节点与某DaemonSet的规约匹配,则控制面会为该DaemonSet调度一个Pod到该新节点上运行
  • Job和CronJob:定义一些一直运行到结束并停止的任务。Job用来表达的是一次性的任务,而CronJob会根据其时间规划反复运行。

Deployment作用

  1. 为Pod和ReplicaSet提供更新能力
  2. 为应用提供水平扩展和收缩的功能
  3. 为应用提供滚动更新的功能

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控制器就到这,扫码关注,更多内容我们下期再见!



文章转载自程序员修炼笔记,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论