k8s集群——Deployment

Deployment为Pod和Replica Set(升级版的 Replication Controller)提供声明式更新。

注意:您不该手动管理由 Deployment 创建的 Replica Set,否则您就篡越了 Deployment controller 的职责!

 

Deployment的典型的用例如下:

1、创建一个Deployment对象来生成对应的ReplicaSet,并完成Pod副本的创建过程。

2、检查Deployment的状态来查看部署动作是否完成,Pod副本的数量是否达到预期的值。

3、更新Deployment以创建新的Pod,通过修改Pod-Template-Spec字段来声明Pod的新状态。这会创建一个新的ReplicaSet,Deployment会按照控制的速率将pod从旧的ReplicaSet移动到新的ReplicaSet中。

4、如果当前状态不稳定,则回滚到一个早先的Deployment版本。

5、暂停Deployment,以便于一次性修改多个PodTemplateSpec的配置项,然后再恢复Deployment,进行新的发布。

6、扩容Deployment以满足更高的负载。

7、查看Deployment 的状态,以此作为发布是否成功的指标。

8、清除旧的不必要的 ReplicaSets。

 

(1)创建 Deployment

下面是一个 Deployment 示例,它创建了一个 ReplicaSet 来启动3个 nginx pod。

下载示例文件nginx-deployment.yaml并执行命令:

apiVersion: extensions/v1beta1

kind: Deployment

metadata:

  name: nginx-deployment

  labels:

    app: nginx

spec:

  replicas: 1

  selector:

    matchLabels:

      app: nginx

  template:

    metadata:

      labels:

        app: nginx

    spec:

      containers:

      - name: nginx

        image: nginx:1.7.9

        ports:

        - containerPort: 80

执行创建命令:

[root@gqtest ~]# kubectl create -f nginx-deployment.yaml --record

deployment "nginx-deployment" created

注:--record选项可以记录当前命令执行记录,便于以后查看一个deployment revision中执行了哪些命令。

 

(2)更新Deployment

Deployment的更新(rollout)当且仅当Deployment的pod template中的label发生更新或者镜像发生更改时,才会被触发。像Deployment扩容,不会触发rollout事件。

假如我们现在想要让 nginx pod 使用nginx:1.9.1的镜像来代替原来的nginx:1.7.9的镜像。

[root@gqtest ~]# kubectl set image deployment/nginx-deployment nginx=nginx:1.9.1

deployment "nginx-deployment" image updated

 

或者可以使用edit命令来编辑 Deployment,修改 .spec.template.spec.containers[0].image ,将nginx:1.7.9 改写成 nginx:1.9.1。

[root@gqtest ~]# kubectl edit deployment/nginx-deployment

 

(3)回退Deployment

可以通过设置.spec.revisonHistoryLimit项来指定 deployment 最多保留多少 revision 历史记录。默认的会保留所有的 revision;如果将该项设置为0,Deployment就不允许回退了。

 

只要 Deployment 的 rollout 被触发就会创建一个 revision。也就是说当且仅当 Deployment 的 Pod template(如.spec.template)被更改,例如更新template 中的 label 和容器镜像时,就会创建出一个新的 revision。

 

我们先故意执行一个有错误的Deployment任务:

[root@gqtest ~]# kubectl set image deployment/nginx-deployment nginx=nginx:1.99

deployment "nginx-deployment" image updated

我们故障写了一个不存在的镜像文件版本,Deployment rollout任务会补卡住,如下所示:

可以看到pod的状态处于"ImagePullBackOff"的错误状态:

[root@gqtest ~]# kubectl get pods

NAME                               READY     STATUS             RESTARTS   AGE

mysql-mn49n                        1/1       Running            1          3d

myweb-k6fp0                        1/1       Running            1          3d

myweb-m9nv9                        1/1       Running            1          3d

nginx-deployment-538426637-g55n4   0/1       ImagePullBackOff   0          3m

注:Deployment controller会自动停止坏的 rollout,并停止扩容新的 ReplicaSet。

我们需要回退到稳定版本的Deployment revision。

先查看一下Deployment的revision记录:

[root@gqtest ~]# kubectl rollout history deployment/nginx-deployment

deployments "nginx-deployment"

REVISION    CHANGE-CAUSE

1        kubectl create -f nginx-deployment.yaml --record

2        kubectl set image deployment/nginx-deployment nginx=nginx:1.9.1

3        kubectl set image deployment/nginx-deployment nginx=nginx:1.99

注:因为我们创建 Deployment 的时候使用了--recored参数可以记录命令,我们可以很方便的查看每次 revision 的变化。

查看单个revision 的详细信息:

[root@gqtest ~]# kubectl rollout history deployment/nginx-deployment --revision=2

 

回退到历史版本

回退到上一个版本:

[root@gqtest ~]# kubectl rollout undo deployment/nginx-deployment

deployment "nginx-deployment" rolled back

回退到一个指定的版本:

# kubectl rollout undo deployment/nginx-deployment --to-revision=2

deployment "nginx-deployment" rolled back

 

可以通过设置.spec.revisonHistoryLimit项来指定 deployment 最多保留多少 revision 历史记录。默认的会保留所有的 revision;如果将该项设置为0,Deployment就不允许回退了。

 

(4)Deployment 扩容

使用以下命令将nginx-deployment扩容为3副本:

[root@gqtest ~]# kubectl scale deployment nginx-deployment --replicas 3

deployment "nginx-deployment" scaled

 

查看该Deployment的事件记录:

[root@gqtest ~]# kubectl describe deployment nginx-deployment

 

注:假如集群中启用了horizontal pod autoscaling,您可以给 Deployment 设置一个 autoscaler,基于当前 Pod的 CPU 利用率选择最少和最多的 Pod 数。

 

关于Deployment的比例扩容:

RollingUpdate Deployment 支持同时运行一个应用的多个版本。或者 autoscaler 扩 容 RollingUpdate Deployment 的时候,正在中途的 rollout(进行中或者已经暂停的),为了降低风险,Deployment controller 将会平衡已存在的活动中的 ReplicaSet(有 Pod 的 ReplicaSet)和新加入的 replica。这被称为比例扩容。

 

(5)暂停和恢复Deployment

可以在发出一次或多次更新前暂停一个 Deployment,然后再恢复它。这样您就能多次暂停和恢复 Deployment,在此期间进行一些修复工作,而不会发出不必要的 rollout。

[root@gqtest ~]# kubectl rollout pause deployment/nginx-deployment

deployment "nginx-deployment" paused

[root@gqtest ~]# kubectl set image deploy/nginx-deployment nginx=nginx:1.9.2

deployment "nginx-deployment" image updated

即使执行了上面的镜像更改命令,也没有触发任何Deployment rollout的事件。而且可以继续做更多的修改,例如:

[root@gqtest ~]# kubectl set resources deployment nginx-deployment -c=nginx --limits=cpu=200m,memory=256Mi

deployment "nginx-deployment" resource requirements updated

注:-c选项的作用是指定容器唯一标识名

当各种变更都准备妥当后,我们恢复该deployment:

[root@gqtest ~]# kubectl rollout resume deploy nginx-deployment

deployment "nginx-deployment" resumed

查看一下deployment处理结果,使用-w选项(watch)跟踪输出如下所示:

[root@gqtest ~]# kubectl get rs -w

 

(6)Deployment 状态

Deployment 在生命周期中有多种状态。在创建一个新的 ReplicaSet 的时候它可以是 progressing 状态, complete 状态,或者 fail to progress 状态。

进行中的 Deployment

Kubernetes 将执行过下列任务之一的 Deployment 标记为 progressing 状态:

Deployment 正在创建新的ReplicaSet过程中。

Deployment 正在扩容一个已有的 ReplicaSet。

Deployment 正在缩容一个已有的 ReplicaSet。

有新的可用的 pod 出现。

可以使用kubectl rollout status命令监控 Deployment 的进度。

 

完成的 Deployment

Kubernetes 将包括以下特性的 Deployment 标记为 complete 状态:

Deployment 最小可用。最小可用意味着 Deployment 的可用 replica 个数等于或者超过 Deployment 策略中的期望个数。

所有与该 Deployment 相关的replica都被更新到了指定版本,也就说更新完成。

该 Deployment 中没有旧的 Pod 存在。

可以用kubectl rollout status命令查看 Deployment 是否完成。如果 rollout 成功完成,kubectl rollout status将返回一个0值的 Exit Code。

[root@gqtest ~]# kubectl rollout status deploy/nginx-deployment

deployment "nginx-deployment" successfully rolled out

[root@gqtest ~]# echo $?

0

 

版本记录的清理策略

可以设置 Deployment 中的 .spec.revisionHistoryLimit 项来指定保留多少旧的 ReplicaSet。 余下的将在后台被当作垃圾收集。默认的,所有的 revision 历史就都会被保留。在未来的版本中,将会更改为2。

注意: 将该值设置为0,将导致所有的 Deployment 历史记录都会被清除,该 Deployment 就无法再回退了。

 

(7)编写 Deployment Spec

在所有的 Kubernetes 配置中,Deployment 也需要apiVersion,kind和metadata这些配置项。

Deployment也需要 .spec section.

Pod Template

.spec.template 是 .spec中唯一要求的字段。

.spec.template 是 pod template. 它跟 Pod有一模一样的schema,除了它是嵌套的并且不需要apiVersion 和 kind字段。

为了划分Pod的范围,Deployment中的pod template必须指定适当的label(不要跟其他controller重复了)和适当的重启策略。

.spec.template.spec.restartPolicy 可以设置为 Always , 如果不指定的话这就是默认配置。

Replicas

.spec.replicas 是可以选字段,指定期望的pod数量,默认是1。

Selector

.spec.selector是可选字段,用来指定 label selector ,圈定Deployment管理的pod范围。

如果被指定, .spec.selector 必须匹配 .spec.template.metadata.labels,否则它将被API拒绝。如果 .spec.selector 没有被指定, .spec.selector.matchLabels 默认是 .spec.template.metadata.labels。

在Pod的template跟.spec.template不同或者数量超过了.spec.replicas规定的数量的情况下,Deployment会杀掉label跟selector不同的Pod。

注意: 不应该再创建其他label跟这个selector匹配的pod,或者通过其他Deployment,或者通过其他Controller,例如ReplicaSet和ReplicationController。否则该Deployment会被把它们当成都是自己创建的。Kubernetes不会阻止这么做。如果有多个controller使用了重复的selector,controller们就会互相打架并导致不正确的行为。

策略

.spec.strategy 指定新的Pod替换旧的Pod的策略。 .spec.strategy.type 可以是"Recreate"或者是 "RollingUpdate"(按比例更新)。"RollingUpdate"是默认值。

Recreate Deployment,.spec.strategy.type==Recreate时,在创建出新的Pod之前会先杀掉所有已存在的Pod。

Rolling Update Deployment,.spec.strategy.type==RollingUpdate时,Deployment使用rolling update 的方式更新Pod 。可以指定maxUnavailable 和 maxSurge 来控制 rolling update 进程。

Max Unavailable,.spec.strategy.rollingUpdate.maxUnavailable 是可选配置项,用来指定在升级过程中不可用Pod的最大数量。该值可以是一个绝对值(例如5),也可以是期望Pod数量的百分比(例如10%)。通过计算百分比的绝对值向下取整。例如,该值设置成30%,启动rolling update后旧的ReplicatSet将会立即缩容到期望的Pod数量的70%。新的Pod ready后,随着新的ReplicaSet的扩容,旧的ReplicaSet会进一步缩容,确保在升级的所有时刻可以用的Pod数量至少是期望Pod数量的70%。

Max Surge,.spec.strategy.rollingUpdate.maxSurge 是可选配置项,用来指定可以超过期望的Pod数量的最大个数。该值可以是一个绝对值(例如5)或者是期望的Pod数量的百分比(例如10%)。当MaxUnavailable为0时该值不可以为0。通过百分比计算的绝对值向上取整。默认值是1。例如,该值设置成30%,启动rolling update后新的ReplicatSet将会立即扩容,新老Pod的总数不能超过期望的Pod数量的130%。旧的Pod被杀掉后,新的ReplicaSet将继续扩容,旧的ReplicaSet会进一步缩容,确保在升级的所有时刻所有的Pod数量和不会超过期望Pod数量的130%。

Progress Deadline Seconds

.spec.progressDeadlineSeconds 是可选配置项,用来指定在系统报告Deployment的failed progressing——表现为resource的状态中type=Progressing、Status=False、 Reason=ProgressDeadlineExceeded前可以等待的Deployment进行的秒数。Deployment controller会继续重试该Deployment。未来,在实现了自动回滚后, deployment controller在观察到这种状态时就会自动回滚。

如果设置该参数,该值必须大于 .spec.minReadySeconds。

Min Ready Seconds

.spec.minReadySeconds是一个可选配置项,用来指定没有任何容器crash的Pod并被认为是可用状态的最小秒数。默认是0(Pod在ready后就会被认为是可用状态)。

Rollback To

.spec.rollbackTo 是一个可以选配置项,用来配置Deployment回退的配置。设置该参数将触发回退操作,每次回退完成后,该值就会被清除。

Revision

.spec.rollbackTo.revision是一个可选配置项,用来指定回退到的revision。默认是0,意味着回退到历史中最老的revision。

Revision History Limit

Deployment revision history存储在它控制的ReplicaSets中。

.spec.revisionHistoryLimit 是一个可选配置项,用来指定可以保留的旧的ReplicaSet数量。该理想值取决于心Deployment的频率和稳定性。如果该值没有设置的话,默认所有旧的Replicaset或会被保留,将资源存储在etcd中,是用kubectl get rs查看输出。每个Deployment的该配置都保存在ReplicaSet中,然而,一旦删除了旧的RepelicaSet,该Deployment就无法再回退到那个revison了。

如果将该值设置为0,所有具有0个replica的ReplicaSet都会被删除。在这种情况下,新的Deployment rollout无法撤销,因为revision history都被清理掉了。

Paused

.spec.paused是可以可选配置项,boolean值。用来指定暂停和恢复Deployment。Paused和没有paused的Deployment之间的唯一区别就是,所有对paused deployment中的PodTemplateSpec的修改都不会触发新的rollout。

Deployment被创建之后默认是非paused。

(8)、Horizontal Pod Autoscaler

横向自动扩容功能,简称HPA,也是k8s系统中的一种资源对象。在v1.1版本中首次发布,在v1.2版本中升级为稳定版。在v1.6版本之前,仅支持使用CPU负载作为是否扩容的判定条件;自v1.6版本开始提供了根据应用自定义指标进行自动扩容和缩容的功能,不过目前仍为实验性质。

 

可以通过yaml文件定义一个HPA对象,或者直接使用命令创建一个HPA对象。

yaml文件定义的样例:

apiVersion: autoscaling/v1

kind: HorizontalPodAutoscaler

metadata:

  name: php-apache

  namespace: default

spec:

  maxReplicas: 10

  minReplicas: 1

  scaleTargetRef:

    kink: Deployment

    name: php-apache

  targetCPUUtilizationPercentage: 90

注:当名为php-apache的deployment的Pods副本的CPU使用率超过90%时,会触发自动扩容行为。但扩容或缩容都必须满足的约束条件是Pod的副本数量要在1~10之间。

以上为命令行方式创建一个HPA:

[root@gqtest ~]# kubectl autoscale deployment nginx-deployment --min=1 --max=5 --cpu-percent=80

deployment "nginx-deployment" autoscaled

 

(9)、StatefulSet

StatefulSet(有状态系统服务设计)在k8s v1.5中引入,在Kubernetes 1.7中还是beta特性。

现实中很多服务是有状态的,如MySQL集群、kafka集群、ZooKeeper集群等,这些应用集群有以下特点:

每个节点都有固定的身份ID,通过这个ID,集群中的成员可以相互发现和通信;

集群的规模是相对固定的,且不能随意变动;

集群里每个节点都是有状态的,通常会持久化数据到永久存储中;

如果磁盘损坏导致集群里某个节点无法正常运行,则集群功能会部分受损;

StatefulSet是Deployment/RC的一个特殊变种,有如下特性:

StatefulSet里每个Pod都有稳定、唯一的网络标识,可以用来发现集群内其他成员。假设StatefulSet名字叫kafka,那么第1个Pod会命名为kafka-0,第2个Pod叫kafka-1,以此类推。

StatefulSet控制的Pod副本的启停顺序是受控的,操作第n个Pod时,前n-1个Pod已经是运行且准备好的状态。

StatefulSet里的Pod采用稳定的持久化存储卷,通过PV/PVC实现,删除Pod时默认不会删除与StatefulSet相关的存储卷。

StatefulSet需要与Headless Service配合使用,需要在每个StatefulSet的定义中声明它属于哪个Headless Service。

Headless Service没有Cluster IP,当解析Headless Service的DNS域名时,得到的是该Service对应的全部Pod的Endpoint列表。StatefulSet在Headless Service的基础上,又为受Headless Service控制的每个Pod实例创建了一个DNS域名,格式为:$(podname).$(headless service name)。

样例:一个3节点的kafka的StatefulSet集群

该应用集群的headless service名称定义为kafka

该应用集群的StatefulSet名字为kafka,则StatefulSet里的3个Pod的名称分别为:kafka-0,kafka-1,kafka-2

该应用集群的StatefulSet中3个Pod的DNS名称应该是:kafka-0.kafka,kafka-1.kafka,kafka-2.kafka

可以在该应用集群的配置文件中直接使用上述DNS名称来代表相应的Pod。

你可能感兴趣的:(『,OpenShift&K8S,』)