k8s工作负载资源之deployment

2021年9月23日 8点热度 0条评论 来源: iqsing

首先我们要理解:一个应用跑在k8s集群上了,那么这个应用就是一个工作负载(workloads)。

在k8s中会用pod的来承载这个应用,那么负责管理这个pod的东西就叫工作负载资源(workload resources

我们可以简单理解为是这样的:

工作负载资源又支持jj自定义或使用第三方资源,这里我们先认识内置的,k8s内置工作负载资源包含如下:

  • deployment
  • replicaset
  • statefulset
  • daemonset
  • jobs
  • cronjob
  • TTL Controller for Finished Resources
  • ReplicationController (逐步被ReplicaSet替代)

那让我们从最常用的deployment开始吧。

一个 Deployment 为 Pods和 ReplicaSets提供声明式的更新能力,我们从下面几个方面开始上手:

  1. 创建 Deployment 将 ReplicaSet 上线。 ReplicaSet 在后台创建 Pods。 检查 ReplicaSet 的上线状态,查看其是否成功。
  2. **通过更新 Deployment 的 Pod模板(TemplateSpec),声明 Pod 的新状态 。 **新的 ReplicaSet 会被创建,Deployment 以受控速率将 Pod 从旧 ReplicaSet 迁移到新 ReplicaSet。 每个新的 ReplicaSet 都会更新到 Deployment 的修订版本。
  3. 如果 Deployment 与你的预期不符,可以回滚到较早的 Deployment 版本。 每次回滚都会更新到 Deployment 修订的新版本。
  4. 通过Deployment 扩大应用规模承担更多负载
  5. 暂停 Deployment ,对 PodTemplateSpec 做修改然后恢复执行,让pod更新到新版本。

deployment创建

说了这么多还不如手动写一个deployment的yml声明实在(如果你喜欢json也可以是json格式,本质上还是将yml转换为json格式请求的api)。

下面deployment创建了一个replicaset,这个replicaset将会启动三个nginx的pod:

nginx-deployment.yml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx-web
        image: nginx:latest
        ports:
        - containerPort: 80

通过kubectl apply 将声明文件转换为api提交给apiserver

$ kubectl apply -f nginx-deployment.yml 
deployment.apps/nginx-deployment created

查看deployment资源创建的对象nginx-deployment(这里的对象与编程语言中对象同义)

$ kubectl get deployment
NAME               READY   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment   3/3     3            3           67m

查看nginx-deplyment创建的replicat对象nginx-deployment-767cf44bff

$kubectl get rs
NAME                          DESIRED   CURRENT   READY   AGE
nginx-deployment-767cf44bff   3         3         3       68m

最后是nginx-deployment-767cf44bff创建的三个pod对象

$ kubectl get pod 

NAMESPACE     NAME                                READY   STATUS    RESTARTS   AGE
default       nginx-deployment-767cf44bff-9fj8q   1/1     Running   0          13m
default       nginx-deployment-767cf44bff-f746l   1/1     Running   0          13m
default       nginx-deployment-767cf44bff-ktbzl   1/1     Running   0          13m

也可以通过rollout status 查看 Deployment 上线状态。

$kubectl rollout status deployment/nginx-deployment
deployment "nginx-deployment" successfully rolled out

这就是deployment资源创建对象的关系图:

现在我们主要来看一下创建的这个nginx-deployment声明。

我们把yml文件分为两个大部分(红色):

  • 属性。

    • apiVersion - 创建该对象所使用的 Kubernetes API 的版本
    • kind - 想要创建的对象的类别
    • metadata - 帮助唯一性标识对象的一些数据,包括一个 name 字符串、UID 和可选的 namespace
  • 规格 spec(specification)

    • replicas - 期望的pod副本数量
    • selector - pod标签选择器
    • template - pod模板

    我们在selector中匹配包含app=nginx标签的pod,pod模板中又为新创建的pod打上app=nginx的标签,这样就形成了控制闭环。

我们通过可以show-labels查看pod的标签

$ kubectl get pod  --show-labels
NAME                                READY   STATUS    RESTARTS   AGE   LABELS
nginx-deployment-767cf44bff-9fj8q   1/1     Running   0          81m   app=nginx,pod-template-hash=767cf44bff
nginx-deployment-767cf44bff-f746l   1/1     Running   0          81m   app=nginx,pod-template-hash=767cf44bff
nginx-deployment-767cf44bff-ktbzl   1/1     Running   0          81m   app=nginx,pod-template-hash=767cf44bff

为什么pod中又有一个pod-template-hash标签?

eployment 控制器将 pod-template-hash 标签添加到 Deployment 所创建的每一个 ReplicaSet 中。我们来看一下rs的selector描述:

$ kubectl describe rs
Name:           nginx-deployment-767cf44bff
Namespace:      default
Selector:       app=nginx,pod-template-hash=767cf44bff

pod-template-hash 标签是通过对 ReplicaSet 的 PodTemplate 进行哈希处理,此标签可确保 Deployment 的子 ReplicaSets 不冲突,所生成的哈希值被添加到 ReplicaSet的selector、Pod 模板labels、以及 ReplicaSet 旗下的任何 Pod 中。这样deployment下的replicaset只能控制自己的pod。恩,妙哉。

不同工作负载资源所创建的对象,spec是不同的。比如在Deployment中spec可以包含如下字段,这个可以在Kubernetes API中找到。

大多数字段都包含了一个默认值,除非有特殊需求,大多数时候很难被用到。如果需要的时候你再谷歌一下也不迟。到这里deployment工作负载的第一个用例已经成了。

deployment更新

仅当 Deployment Pod 模板(即 .spec.template字段)发生改变时,例如模板的标签或容器镜像被更新, 才会触发 Deployment 上线。

其他更新(如对 Deployment 执行扩缩容的操作)不会触发上线动作。

  1. 我们可以通过kubectl set 命令更新现有工作负责资源
$ kubectl set image deployment/nginx-deployment nginx-web=nginx:1.17 --record
deployment.apps/nginx-deployment image updated

--record 用于记录kubectl对资源的操作。便于后期需要时回滚。下面会说到。

kubectl set -h 查询set支持更新的内容。

Available Commands:

  • env Update environment variables on a pod template
  • image Update image of a pod template
    resources Update resource requests/limits on objects with pod templates
  • selector Set the selector on a resource
  • serviceaccount Update ServiceAccount of a resource
  • subject Update User, Group or ServiceAccount in a RoleBinding/ClusterRoleBinding
  1. 使用kubectl edit编辑deployment后自动更新
$ kubectl edit deployment/nginx-deployment --record
deployment.apps/nginx-deployment edited
  1. 直接更新deployment yml文件

个人觉得最好的方式是更新yml声明文件,通过kubectl apply 应用即可,这样你只要管理好你的的nginx-deployment.yml做到心中有数

当我们更新后查看rs状态,此时deployment 创建了一个新的nginx-deployment replicaset并投入使用。

$ kubectl get rs
NAME                          DESIRED   CURRENT   READY   AGE
nginx-deployment-64f9765d86   4         4         4       4h11m
nginx-deployment-6cf9cc9c9d   0         0         0       5h6m

这里顺便看一下deployment中pod滚动更新策略

我们可以通过kubectl describe deployment 查看RollingUpdateStrategy字段,即在滚动更新时最大不可用pod数为1/4,最大可用pod数为期望副本数1.25倍(多25%)。

RollingUpdateStrategy: 25% max unavailable, 25% max surge

假如我们将 deployment_A 中4个副本(pod)更新到deployment_B(也是4副本),其中的某个数据pod状态如下

$ kubectl get pod 
NAME                                READY   STATUS              RESTARTS   AGE
nginx-deployment-64f9765d86-c9rlj   0/1     ContainerCreating   0          2s
nginx-deployment-64f9765d86-wngmx   0/1     ContainerCreating   0          2s
nginx-deployment-7fcdcb4b75-lmsmm   1/1     Running             0          4h6m
nginx-deployment-7fcdcb4b75-m99tx   1/1     Terminating         0          4h5m
nginx-deployment-7fcdcb4b75-tghb2   1/1     Running             0          4h5m
nginx-deployment-7fcdcb4b75-xfs2m   1/1     Running             0          4h6m

即只有1个在停止,正在创建2个新pod(即将有5个可用),详细滚动过程可通过kubectl descibe deployment中events查看。

尽量不要更新模板中labels,会造成pod孤立。在某些API版本已经被禁止了。

deployment回滚

deployment回滚和更新一样,Pod 模板部分会被回滚。

我们通过 rollout history 来查看某个deployment的历史版本。即之前通过--record所记录的。

$ kubectl  rollout history   deployment/nginx-deployment 
deployment.apps/nginx-deployment 
REVISION  CHANGE-CAUSE
1         <none>
2         <none>
3         kubectl apply --filename=nginx-deployment.yml --record=true
4         kubectl apply --filename=nginx-deployment.yml --record=true
5         kubectl set image deployment/nginx-deployment nginx-web=nginx:1.17 --record=true
9         kubectl edit deployment/nginx-deployment --record=true
10        kubectl edit deployment/nginx-deployment --record=true

回滚到第5个版本。

$ kubectl rollout undo deployment/nginx-deployment --to-revision=5
deployment.apps/nginx-deployment rolled back

或者直接回滚到上一个版本。

$ kubectl rollout undo deployment/nginx-deployment

还是如前面所说,回滚只一种更工程化的说法,其实回滚也是一种更新,yml声明依然是核心。所以我们更应该关注的对deployment的yml文件的版本控制。

deployment缩放

缩放控制的是.spec.replicas,也可通过scale命令操作。

$ kubectl scale deployment/nginx-deployment --replicas=6
deployment.apps/nginx-deployment scaled

水平自动缩放本为暂不涉及,后面文章会详细讨论。可以参考:Horizontal Pod Autoscaler

deployment暂停与恢复

我们可以在触发更新之前暂停 Deployment,然后做多个修改之后再恢复,进行一次性上线。

还是我们之前的deployment

$ kubectl get deploy
NAME               READY   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment   4/4     4            4           30m

$ kubectl get rs
NAME                          DESIRED   CURRENT   READY   AGE
nginx-deployment-64f9765d86   4         4         4       30m

暂停deployment

$ kubectl rollout pause deployment/nginx-deployment
error: deployments.apps "nginx-deployment" is already paused

对nginx-deployment做一些更新

  1. 直接修改yml文件,更新镜像为nginx:1.17,并通过kubectl apply应用更改。
  2. 通过set做资源限制。
$ kubectl set resources deployment/nginx-deployment -c=nginx-web --limits=cpu=50m,memory=100Mi
deployment.apps/nginx-deployment resource requirements updated

此时我们查看rs副本状态,查看deployment版本信息

$ kubectl get rs 
NAME                          DESIRED   CURRENT   READY   AGE
nginx-deployment-64f9765d86   4         4         4       40m

$ kubectl rollout history deployment/nginx-deployment
deployment.apps/nginx-deployment 
REVISION  CHANGE-CAUSE
1         <none>

可以看到还是之前的rs,deployment并没有将我们的修改应用到对象中。

现在我们将deployment通过Resume恢复

$ kubectl rollout resume deployment/nginx-deployment
deployment.apps/nginx-deployment resumed

查看rs状态

$ kubectl get rs 
NAME                          DESIRED   CURRENT   READY   AGE
nginx-deployment-64f9765d86   3         3         3       41m
nginx-deployment-7f4447656b   2         2         0       4s

这会deployment已恢复,并应用了对资源对象的更新。

参考:

k8s官方文档Deployment

    原文作者:iqsing
    原文地址: https://www.cnblogs.com/qsing/p/15321541.html
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系管理员进行删除。