②.kubernetes Pod控制器Deployment DeamonSet

一.Pod控制器

二.ReplicaSet

三.Deployment

四.Deployment场景实践

五.动态扩缩容实践

六.Deployment重建策略

七.Deployment滚动更新

八.Deployment滚动更新策略

九.Deployment实现灰度发布

十.DaemonSet基本概述

十一. DaemonSet部署应用

十二. DaemonSet更细策略

十三. job

十四. job实践

===============================================================================================

一.Pod控制器

1.1 什么是Pod控制器

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

1.2 Pod控制器主要作用

pod的资源出现故障时,会尝试进行重启,当根据重启策略无效,则会重新新建pod的资源。

1.3 pod控制器种类

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

ReplicaSet 主要三个组件组成:

1. 用户期望的pod副本数量
2. 标签选择器,判断哪个pod归自己管理
3. 当现存的pod数量不足,会根据pod资源模板进行新建

帮助用户管理无状态的pod资源,精确反应用户定义的目标数量,但是RelicaSet不是直接使用的控制器,而是使用Deployment。

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

ReplicaSet 与Deployment 这两个资源对象逐步替换之前RC的作用。

  • DaemonSet:用于确保集群中的每一个节点只运行特定的pod副本,通常用于实现系统级后台任务。比如ELK服务
    特性:服务是无状态的
    服务必须是守护进程

  • StatefulSet:管理有状态应用

  • Job:只要完成就立即退出,不需要重启或重建

  • Cronjob:周期性任务控制,不需要持续后台运行

二.ReplicaSet

2.1 传统应用集群

在传统环境中,如果要保证应用的高可用,一般都以集群方式部署,集群中的应用实例至少部署2个以上,这样即使一个应用故障了,另一台应用任然能够对外提供服务,在这种环境下,我们主要依赖前置的负载均衡Nginx,通过手动编辑配置文件的方式来实现。而一旦我们需要对应用进行扩容或缩容,也需要在Nginx上进行手动配置,过程相对繁琐也比较容易出错

2.2 什么是ReplicaSet

在 Kubernetes 环境中,通过 ReplicaSet 这种资源对象就可以来帮助我们实现集群的高可用, ReplicaSet (RS)的主要作用就是维持一组 Pod 副本的运行,保证一定数量的 Pod 在集群中正常运行,ReplicaSet 控制器会持续监听它控制的这些 Pod 的运行状态以及数量,保证应用集群的高可用;

2.3 ReplicaSet组成部分

ReplicaSet控制器包含了3个基本的组成部分:

  • seLector 标签选择器: 匹配并关联Pod对象,并加入控制器的管理中;
  • replicas期望的副本数: 期望在集群中所运行的Pod对象数量;
  • template Pod模板: 实际上就是定义的 Pod 规范,相当于把一个Pod 的描述以模板的形式嵌入到了 ReplicaSet

2.4 ReplicaSet示例配置

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: mall-deploy    # RS控制器名称
  namespace: default   # 命名空间
spec :
  replicas: 3          # 期望的 Pod 副本数量,默认值为1
  selector:            # SeLector,匹配 Pod 模板中的标签
    matchLabeTs:
      app: mall
  template:            # 定义 Pod 模板(内嵌Pod模板不需要apiVersion和kind字段)
    metadata:
      labels:
        app: mall            # 定义 Pod 标签
    spec:
      containers:         #定义 Pod 中的容器信息
      - name: mall-container
        image: nginx
        ports:
        - containerPort: 80

三.Deployment

3.1 什么是Deployment

Deployment (简称为deploy) 是Kubernetes控制器的一种高级别实现,他构建于ReplicaSet控制器之上.
我们只需要描述DepLoyment中的目标Pod期望状态,而DepLoyment控制器以受控速率更改实际状态,使其变为期望状态,也就是说,后期我们部署应用不直接使用Pod和ReplicaSet,而是使用Deployment控制器来调用ReplicaSet来实现,Deployment控制器在ReplicaSet原有基础上,添加了部分特性。

  • 1、事件和状态查看: 可以通过特定的命令查看Deployment对象的更新进度和状态;
  • 2、版本记录: 将Deployment对象的更新操作都进行保存,以便后续执行回滚操作使用;
  • 3、多种更新方案: Recreate重建,可以实现单批次更新所有Pod.RolLingUpdate可以实现多批次逐步替换Pod

3.2 Deployment组成部分

DepLoyment 资源对象的格式和 ReplicaSet 几乎-致,Deployment 控制器也包含了3个基本的组成部分

  • selector 标签选择器: 匹配并关联Pod对象,并对授其管控的Pod对象计数;
  • replicas 期望的副本数: 期望在集群中所运行的Pod对象数量;
  • template Pod模板: 实际上就是定义的 Pod 内容,相当于把一个Pod 的描述以模板的形式嵌入到了 ReplicaSet

3.3 Deployment示例配置

apiVersion: apps/v1
kind: Deployment
metadata:
  name: mall-deploy       #定义deploy资源名称
spec:
  replicas: 3             #定义depLoy控制Pod的副本数
  minReadySeconds:10      #Pod就绪后,多少秒内任一容器无崩溃方视为 “就绪”,默认0s
  selector:
    matchLabels:          #标签选择器,选择 app:mall的标签
      app: mall
  template:               #Pod 模板,申明Pod名称、使用镜像拥有哪些标签等
    metadata:
      labels:             # Pod标签
        app: mall
    spec:                 # Pod的容器详情电明
      containers:
      - name: demoapp-container
        image: oldxu3957/demoapp:v1.0
        ports:
        - containerPort: 80

四.Deployment场景实践

4.1 场景说明

场景说明: 运行一个demoapp的应用,部署3个副本,然后通过service来实现负载均衡;

  • 1、创建 Deployment资源,部署三个副本
  • 2、创建Service资源,通过标签选择器选择对应的Pod,以实现负载均衡;
  • 3、使用 curl命令,或Chrome浏览器验证集群高可用

4.2 创建应用集群

apiVersion: apps/v1
kind: Deployment
metadata:
  name: demoapp-deploy
spec:
  replicas: 3
  selector:
    matchLabels:
      app: demoapp
  template:
    metadata:
      labels:
        app: demoapp
    spec:
      containers:
      - name: demoapp-container
        image: oldxu3957/demoapp:v1.0
        ports:
        - containerPort: 80

4.3 检查集群状态

1、检查集群的 Deployment:

  • NAME 列出了集群中 DepLoyment 的名称
  • READY 显示应用程序的可用的“副本"数。显示的模式是“就绪个数/期望个数"。
  • UP-TO-DATE 显示为了达到期望状态已经更新的副本数
  • AVAILABLE 显示应用可供用户使用的副本数。
  • AGE 显示应用程序运行的时间。
[root@k8s-240 deployment]# kubectl get deployment
NAME             READY   UP-TO-DATE   AVAILABLE   AGE
demoapp-deploy   3/3     3            3           18s

[root@k8s-240 deployment]# kubectl describe deployment demoapp-deploy 
Conditions:
  Type           Status  Reason
  ----           ------  ------
  Available      True    MinimumReplicasAvailable
  Progressing    True    NewReplicaSetAvailable
OldReplicaSets:  <none>
NewReplicaSet:   demoapp-deploy-7ddd58f7c6 (3/3 replicas created)          #看到replicaSet资源
Events:

注意:期望副本数是根据.spec.replicas 字段设置 3
2、检查集群的 ReplicaSet:

  • NAME 列出名字空间中 ReplicaSet 的名称;
  • DESIRED 显示应用的期望副本个数,即在创建 Deployment 时所定义的值。此为期望状态;
  • CURRENT 显示当前运行状态中的副本个数;
  • READY 显示应用中有多少副本可以为用户提供服务:
  • AGE 显示应用已经运行的时间长度。
    注意 RepLicaSet 的名称被格式化为[Deployment名称]-[随机字符册]
[root@k8s-240 deployment]# kubectl get rs
NAME                        DESIRED   CURRENT   READY   AGE
demoapp-deploy-7ddd58f7c6   3         3         3       5m56s

3.检查集群的Pod,所创建的ReplicaSet确保总是存在三个Pod

[root@k8s-240 deployment]# kubectl get pod
NAME                              READY   STATUS      RESTARTS   AGE
demoapp-deploy-7ddd58f7c6-55c5n   1/1     Running     0          9m55s
demoapp-deploy-7ddd58f7c6-8bfj8   1/1     Running     0          9m55s
demoapp-deploy-7ddd58f7c6-lwtn8   1/1     Running     0          9m55s

4.4 创建Service

[root@master ~]# cat demoapp-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: demoapp-svc
spec:
  selector:          #标签选择器,选择哪些相同的Pod为一组Upstream
    app: demoapp
  ports:
  - name: http
    port: 80          # service对外提供的端口
    targetPort: 80    # Pod的端口

查看对应的service地址

[root@k8s-240 deployment]# kubectl get svc
NAME          TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)        AGE
demoapp-svc   ClusterIP   10.0.0.39    <none>        80/TCP         6s
kubernetes    ClusterIP   10.0.0.1     <none>        443/TCP        35d

4.5 验证集群高可用

[root@k8s-240 deployment]# curl 10.0.0.39/version
demoapp v1.0!! PodIP: 10.244.157.167!
[root@k8s-240 deployment]# curl 10.0.0.39/version
demoapp v1.0!! PodIP: 10.244.149.158!
[root@k8s-240 deployment]# curl 10.0.0.39/version
demoapp v1.0!! PodIP: 10.244.157.168!

4.6 水平伸缩

水平扩展/收缩的功能比较简单,修改replicas对应的副本数即可。比如将 Pod 的副本调整到 5 个,那么 Deployment 所管理的ReplicaSet 则会自动创建一个新的 Pod 出来,这样就水平扩展了
1、命令方式修改

kubectl scale deployment

2、通过yaml来实现

kubectl edit deployment demoapp

4.7 模拟故障

删除Pod,看是否能自动恢复

五.动态扩缩容实践

5.1 什么是HPA

Kubernetes实现Pod的扩缩容需要通过手动来实现,但线上的业务情况比较复杂,依赖于纯手动的方式,不太现实。所以希望系统能自动感知Pod的压力来完成扩缩容,比如: 当Pod的CPU达到了50%则扩容,当Pod的CPU低于50%自动缩容。
为此Kubernetes为我们提供了这样的一个资源对象HPA (horizontal-pod-autoscaler) ,专用来实现Pod的水平自动扩缩容。HPA 通过监控分析一些控制器控制的所有 Pod 的负载变化情况来确定是否需要调整Pod 的副本数量;

5.2 自动扩缩容算法

算法:
副本数 = [当前副本数 * (当前指标 / 期望指标)]
当前指标: 当前Pod已经达到了百分之多少的压力;期望指标: 当Pod达到期望的指标百分比时就要进行扩容;
例如,当前副本为1,当前当前指标值250%,而期望的指标值是50%,则副本数会翻5倍,因为 1 * (250%/50%) = 5

5.3 安装MetricServer

kubectl apply -f https:// inux.oldxu.net/metrics-server.yaml

5.4 动态扩缩容实践

apiVersion: apps/v1
kind: Deployment
metadata:
  name: php-apache
spec:
  selector:
    matchLabels:
      run: php-apache
  replicas: 1
  template:
    metadata:
      labels:
        run: php-apache
    spec:
      containers:
      - name: php-apache
        image: oldxu3957/hpa-example
        ports:
        - containerPort: 80
        resources:
          requests:
            cpu: 200m
          limits:
            cpu: 500m

2.创建负载均衡

apiVersion: v1
kind: Service
metadata:
  name: php-apache
spec:
  selector:
    run: php-apache
  ports:
  - port: 80
    targetPort: 80

获取负载均衡IP

[root@k8s-240 deployment]# kubectl get svc
NAME          TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)        AGE
php-apache    ClusterIP   10.0.0.164   <none>        80/TCP         3s

3.创建hpa 设定cpu超过50%,则触发自动创建Pod副本

# kubectl autoscale deployment php-apache --min=1 --max=10 --cpu-percent=50
[root@master ~]# cat php-apache-hpa.yaml
apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
  name: php-apache
spec:
  minReplicas: 1         # 最少启动1个Pod
  maxReplicas: 10        # 最多扩展10个Pod
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: php-apache
  targetCPUUtilizationPercentage: 50     # cpu达到50%

4.模拟增加负载

while sleep 0.01;do curl http://10.0.0.164;done
当前副本为1,当前压力达到了250%,而CPU只要超过50%就会扩容,需要扩容5个副本来分担压力。1 * (250%/5%) = 5

六.Deployment重建策略

6.1 什么是Recreate

重建 (Recreate)当更新策略设定为 Recreate ,在更新镜像时它会先杀死正在运行的Pod,等彻底杀死后,重新创建新的RS,然后启动对应的Pod,那么在这个更新过程中,会造成服务一段时间无法提供服务;

  • 第一步: 同时杀死所有旧版本的Pod,此时Pod无法正常对外提供服务;
  • 第二步: 创建新的RS,启动新的Pod;
  • 第三步: 等待Pod就绪,对外提供服务

6.2 Recreate实践

[root@master deployment]# cat demoapp-deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: demoapp-deploy
spec:
  replicas: 3
  strategy:
    type: Recreate   # 重建
  selector:
    matchLabels:
      app: demoapp
  template:
    metadata:
      labels:
        app: demoapp
    spec:
      containers:
      - name: demoapp-container
        image: oldxu3957/demoapp:v1.1# 将v1.0 修改为 v1.1 版本
        ports:
        - containerPort: 80

2.观察更新过程

[root@k8s-240 deployment]# kubectl get pod
NAME                              READY   STATUS    RESTARTS   AGE
demoapp-deploy-5f5b6fbb97-7qlr2   1/1     Running   0          15s
demoapp-deploy-5f5b6fbb97-9wgrl   1/1     Running   0          15s
demoapp-deploy-5f5b6fbb97-flpbl   1/1     Running   0          15s

3.创建新的RS,然后期望运行Pod为3,就绪3

[root@k8s-240 deployment]# kubectl get rs
NAME                        DESIRED   CURRENT   READY   AGE
demoapp-deploy-5bd8c99dc6   3         3         0       9m48s
demoapp-deploy-7ddd58f7c6   0         0         0       46h

七.Deployment滚动更新

7.1 什么是滚动更新

滚动更新 (RolLingUpdate) ,一次仅更新一批Pod,当更新的Pod就绪后,在更新另一批,直到全部更新完成为止,该策略实现了不间断服务的目标,在更新过程中可能会出现不同的应用版本并存且,同时提供服务的情况。

  • 第一步: 创建新的ReplicaSet,然后根据新的镜像运行新的Pod;
  • 第二步:删除旧的Pod,启动新的Pod,新Pod就绪后,继续删除旧Pod,启动新Pod;
  • 第三步: 持续第二步过程,一直到所有Pod都被更新成功。

7.2 滚动更新实践

1.准备yaml文件

apiVersion: apps/v1
kind: Deployment
metadata:
  name: demoapp-deploy
spec:
  replicas: 3
  strategy:
    type: RollingUpdate
  selector:
    matchLabels:
      app: demoapp
  template:
    metadata:
      labels:
        app: demoapp
    spec:
      containers:
      - name: demoapp-container
        image: oldxu3957/demoapp:v1.1
        ports:
        - containerPort: 80

2.观察更新过程

[root@k8s-240 deployment]# kubectl apply -f deployment_rollout.yaml 
deployment.apps/demoapp-deploy configured
[root@k8s-240 deployment]# kubectl rollout status deployment demoapp-deploy
Waiting for deployment "demoapp-deploy" rollout to finish: 1 out of 3 new replicas have been updated...
Waiting for deployment "demoapp-deploy" rollout to finish: 1 out of 3 new replicas have been updated...
Waiting for deployment "demoapp-deploy" rollout to finish: 1 out of 3 new replicas have been updated...
Waiting for deployment "demoapp-deploy" rollout to finish: 2 out of 3 new replicas have been updated...
Waiting for deployment "demoapp-deploy" rollout to finish: 2 out of 3 new replicas have been updated...
Waiting for deployment "demoapp-deploy" rollout to finish: 1 old replicas are pending termination...
Waiting for deployment "demoapp-deploy" rollout to finish: 1 old replicas are pending termination...
deployment "demoapp-deploy" successfully rolled out

3.通过浏览器访问,会发现新老版本存在交替,但并不会初心服务不可用状态

7.3 应用回退实践

有时,你可能想要回滚 Deployment; 例如,当 Deployment 不稳定进入反复崩溃状态。 默认情况下,Deployment 的所有上线记录都保留在系统中,以便可以随时回滚。 (你可以通过修改 revisionHistoryLimit 调整保留的数量,默认10条)
1.首先,检查 Deployment 上线的历史版本

[root@master deployment]# kubectl rollout history deployment demoapp-deploy
deployment.apps/demoapp-deploy
REVISION CHANGE-CAUSE
1        <none>      # 历史版本,demoapp:v1.0<none>
2        <none>      # 当前正在使用的版本,demoapp:v1.1

2.也可以查看每个REVISION对应的具体信息

[root@master deployment]# kubectl rollout historydeployment demoapp-deploy --revision=1
deployment.apps/demoapp-deploy with revision #2
Pod Template:
  Labels: app=demoapp
  pod-template-hash=697dcf98
  Containers:
   demoapp-container:
    Image: oldxu3957/demoapp:v1.0 # 可以看到当前的镜像版本
    Port: 80/TCP
    Host Port:  0/TCP
    Environment:<none>
    Mounts: <none>
Volumes :<none>

3.确认要回退的REVISION,然后执行回退命令即可。
按照下面的步骤将 Deployment 从当前版本 (即版本2) 回滚到以前的版本 (即版本 1)。
3.1.通过使用 --to-revision 来回滚到特定修订版本:

[rootmaster ~]# kubectl rollout undo deployment  demoapp-deploy --to-revision=1
deployment.apps/demoapp-deploy rolled back

3.2.测试访问站点

# 访问站点
[root@master ~]# cur 10.96.8.44:8888
iKubernetes demoapp v1.1 !!
[root@master ~]# cur 10.96.8.44:8888
iKubernetes demoapp v1.0 !!
[root@master ~]# curl 10.96.80.44:8888
iKubernetes demoapp v1.1 !!
[root@master ~]# cur 10.96.8.44:8888
iKubernetes demoapp v1.0 !!
[root@master ~]# curl 10.96.80.44:8888
iKubernetes demoapp v1.0 !!

八.Deployment滚动更新策略

Deployment 会在 .spec .strategy.type=RollingUpdate 时采取滚动更新的方式更新 Pods。可以指定 maxUnavailable 和maxSurge 来控制滚动更新过程。

  • maxSurge 最大可用Pod
    • 用来指定可以创建超出期望Pod个数的 Pod数量。可以是数字也可以是百分比 (例如10%) 此字段的默认值为25%.
    • 例如,当此值为 20% 时,启动滚动更新后,会立即对新的RepLicaSet 扩容,同时保证新旧 Pod 的总数不超过所需Pod 总数的 120%。一旦日 Pods 被杀死,新的RepLicaSet 可以进一步扩容,同时确保更新期间的任何时候运行中的 Pods 总数最多为所需 Pods 总数的 120%。 计算公式: 10+(10x20%)=12
  • maxUnavailable 最大不可用Pod
    • 用来指定更新过程中不可用的 Pod 的个数上限。可以是数字也可以是百分比 例如10%) 此字段的默认值为25%。
    • 例如,当此值设置为 20% 时,滚动更新开始时会立即将旧RepLicaSet 缩容到期望 Pod 个数的70%。新 Pod 准备就绪后,继续缩容旧有的 ReplicaSet,然后对新的ReplicaSet 扩容,确保在更新期间可用的 Pods 总数在任何时候都是所需的 Pod 个数的 70%。 计算公式: 1-(10x20%)=8
  • maxSurge 和 maxUnavailable 两个属性协同工作,可组合定义出3中不同的策略完成多批次的应用更新。
    • 先增新,后减旧: 将maxSurge设置为30%,将maxUnavailable的值设为0;
    • 先减日,后增新: 将maxUnavailable设置为30%,将maxSurge的值设为0;
    • 同时增减,将maxSurge和maxUnavailable分别设定为2%;期望是12Pod,至少就绪8个Pod

8.1 maxSurge

指定升级期间存在的总Pod对象数量最多可超出期望值的个数,可以是0,也可以是整数,也可以是一个百分比。例如: 期望的的值为10,maxSurge属性为2,则表示Pod对象总数不能超过12个。 计算公式: 10+(10x2%)=12

示例配置:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: demoapp-deploy
spec:
  replicas: 10
  strategy:
    rollingUpdate:
      maxSurge: 20%            #最大可用20%
      maxUnavailable: 0        #不可用状态设定为0
  selector:
    matchLabels:
      app: demoapp
  template:
    metadata:
      labels:
        app: demoapp
    spec:
      containers:
      - name: demoapp-container
        image: registry.cnhuhehaote.aliyuncs.com/oldxu3957/demoapp:v1.0       #调整版本触发更新
        ports:
        - containerPort: 80
#可以通过如下命令实时查看更新策略是否与图中一致:
watch -n 1 kubectl get rs

8.2 maxUnavailable

升级期间不可用的Pod副本数 (包括新版本),最多不能低于期望的个数,默认为1。
例如: 期望的值为10,maxunavailable属性为2,则表示Pod处于正常状态至少 有8个。计算公式: 10-(10x20%)=8

示例配置:

[root@master deployment]# cat demoapp-deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata :
  name: demoapp-deploy
spec:
  replicas: 5
  strategy:
    rollingUpdate:
      maxSurge: 0          # 最大可用0
      maxUnavailable: 20%  # 不可用Pod副本最低20%
  selector:
    matchLabels:
      app: demoapp
  template:
    metadata:
      labels:
        app: demoapp
    spec:
      containers:
      - name: demoapp-container
        image: registry.cn-huhehaote.aliyuncs.com/oldxu3957/demoapp:v1.0 # 调整版本触发更新
        ports
        - containerPort: 80

可以通过如下命令实时查看更新策略是否与描述的一致

watch -n 1 kubectl get rs

8.3 maxSurge & maxUnavailable

同时设定 maxSurge 以及 maxUnavailable

[root@master deployment]# cat demoapp-deploy .yaml
apiVersion: apps/1
kind: Deployment
metadata :
  name: demoapp-deploy
spec:
  replicas: 5
  strategy:
    rollingUpdate :
      maxSurge: 20%             # 最大可用0
      maxUnavailable: 20%       # 不可用Pod副本最低20%
  selector:
    matchLabels:
      app: demoapp
  template:
    metadata :
      labels:
        app: demoapp
    spec :
      containers:
      - name: demoapp-container
        image: registry.cn-huhehaote.aliyuncs.com/oldxu3957/demoapp:v1.0 # 调整版本触发更新
        ports:
        - containerPort: 80

8.4 minReadySeconds

Deployment支持使用 spec.minReadySeconds 字段来控制滚动更新的速度,默认值为0,表示新建的Pod对象一旦“就绪”将立即被视作可用,随后即可开始下一轮更新过程。如果设定了spec.minReadySeconds: 3 及表示新建的Pod对象至少要成功运行多久才会被视作可用,即就绪之后还要等待指定的 3s 才能开始下一批次的更新。在一个批次内新建的所有Pod就绪后在转为可用状态前,更新操作会被阻塞,并且任何一个Pod就绪探测失败,都会导致滚动更新被终止。
因此,为minReadySeconds设定一个合理的值,不仅能够减缓更新的速度,还能够让Deployment提前发现一部分程序因为Bug导致的升级故障

8.5 revisionHistoryLimit

Deployment保留一部分更新历史中旧版本的 ReplicaSet 对象,当我们执行回滚操作的时候,就直接使用旧版本的 ReplicaSet,在Deployment 资源保存历史版本数量有spec.revisionHistoryLimit 属性进行定义

kubectl rollout history deployment

8.6 progressDeadlineSeconds

滚动更新故障超时时长,默认为600秒,k8s 在升级过程中有可能由于各种原因升级卡住(这个时候还没有明确的升级失败) ,比如在拉取被墙的镜像,权限不够等错误。如果配置 progressDeadlineSeconds,当达到了时间如果还卡着,则会上报这个异常情况,这个时候这个Deployment 状态就被标记为 False,并且注明原因。但是它并不会阻止 Deployment 继续进行卡住后面的升级操作。

九.Deployment实现灰度发布

灰度发布 (又名金丝雀发布) 是指黑与白之前,能够平滑过度的一种发布方式,在上面可以进行A/B Testing

  • 1、首先: 让一部分用户继续使用产品特性A (旧版本)
  • 2、其次: 让一部分用户开始使用产品特性B (新版本)
  • 3、最后: 如果用户对产品特性B没有反对意见,那么逐步扩大反问将用户的流量迁移到B上面来。
    使用灰度发布的模式,可以及时发现问题,调整问题,以减少影响的速度,保证整体系统的稳定运行。

    如果新版本没有问题,那么逐步扩大新版本的访问流量,然后减少就版本的访问流量。

    最后删除旧版本的Deployment,或者讲replicaset副本数设定为0,至此所有的流量都进入新版本

9.1 部署1.0版本应用

1.编写yaml

[root@master tmp]# cat demoapp-version10.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: demoapp-version-10-prod
spec:
  replicas: 3
  selector:
    matchLabels:
      app: demoapp
      version: V1.
  template:
    metadata:
      labels:
        app: demoapp
        version: V1.0
    spec:
      containers:
      - name: demoapp
        image: oldxu3957/demoapp:v1.0

2.检查部署结果

[root@master tmp]# kubectl get pod
NAME                                       READY    STATUS      RESTARTS  AGE 
demoapp-version-10-prod-5499c6ddc7-q84z8    1/1   Running         0       5s
demoapp-version-10-prod-5499c6ddc7-t7qk7    1/1   Running         0       5S
demoapp-version-10-prod-5499c6ddc7-vdpvs    1/1   Running         0       5s

9.2 部署service实现负载均衡

1.编写负载均衡yaml,它会通过标签选择留选择app=demoapp的Pod

[rootomaster ~]# cat demoapp-service .yaml
apiversion: V1
kind: Service
metadata:
  name : demoapp-service
spec:
  selector:
    app: demoapp
  ports:
  - name: http
    port: 80
    targetPort: 80

2.获取Service的IP

[root@master tmp]# kubectl get service
NAME                TYPE     CLUSTER-IP     EXTERNAL-IP PORT(S)     AGE
demoapp-service   ClusterIp  10.96.54.90      <none>     88/TCP      4S

3.访问v1.日应用

[rootmaster *]# curl 18.96.54.90/version
demoapp V1.8 !!
[rootomaster *]# curl 18.96.54.98/version
demoapp V1.8 !!
[rootomaster *]# curl 10.96.54.90/version
demoapp v1.8 !!

9.3 部署1.1版本应用

[root@master tmp]# cat demoapp-version11.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: demoapp-version-11-prod
spec:
  replicas: 1    # 部署一个副本作为灰度应用
  selector:
    matchLabels:
      app: demoapp
      version: V1.1
  template:
    metadata:
      labels:
        app: demoapp
        version: v1.1
    spec :
      containers:
      - name: demoapp
        image: oldxu3957/demoapp:v1.1

9.4 测试新老版本共存

[root@master ~]# curl 10.96.54.90/version
demoapp v1.0 !!
[root@master ~]# curl 10.96.54.90/version
demoapp v1.0 !!
[root@master ~]# curl 10.96.54.90/version
demoapp v1.1 !!
[root@master ~]# curl 10.96.54.90/version
demoapp v1.0 !!
[root@master ~]# curl 10.96.54.90/version
demoapp v1.1 !!

9.5 控制新老版本流量

1、逐步增加1.1版本的流量

[root@master tmp]# vim demoapp-version11.yaml
spec:
  replicas: 3# 增加副本数量,这样就能接收更大比例的流量

2、逐步减少1.0版本的流量

[root@master tmp]# vim demoapp-version10.yaml
spec:
  replicas: 0# 副本数调为0,或者删除Deployment

十.DaemonSet基本概述

10.1 什么是DaemonSet

DaemonSet 控制器是用来保证在所有节点上运行一个Pod的副本。当有节点加入集群中,也会为新节点增加一个DaemonSet类型Pod,当有系欸但从集群种一出时,改Pod也会被回收。删除DaemonSet将会删除它创建的所有Pod。

10.2 DaemonSet使用场景

  • 在每个节点上运行集群存储守护进程,如:Gluster、Ceph
  • 在每个节点上运行日志收集守护进程,如: fluentd、Filebeat.Logstash
  • 在每个节点上运行监控守护进程,如: Prometheus NodeExporter、
  • 在每个节点上运行网络插件为Pod提供网络服务,如: fanneL、calico

10.3 DaemonSet编写示例

DaemonSet是标准的API资源类型,它在spec字段中嵌套字段有seLector、tempalte,与DepLoyment用法基本相同,但DaemonSet 不管理 Replicas,因为 DaemonSet不是基于期望的副本数,而是 基于节点数量来控制Pod数量

apiVersion: apps/v1       # API群组及版本
kind: DaemonSet           # 资源类型表示
metadata:
  name: <string>          # 资源名称
  namespace: <string>     # 名称空间: DaemonSet资源隶属于名称空间级别
spec :
  minReadySeconds: <integer>       # Pod就绪后多少秒内任容器无崩溃方视为“就绪”
  selector: <object>               # 标签选择器,必须匹配template字段中Pod模板的标签
  revisionHistoryLimit: <integer>  # 滚动更新历史记录数量,默认为10
  updateStrategy: <Object>         # 滚动更新策略
    type: <string>                 # 滚动更新类型,可用值有OnDelete和RollingUpdate
    rollingUpdate: <Object>        # 滚动更新参数,专用于RollingUpdate类型
      maxSurge: <string>           # 滚动更新参数,更新期间存在的总Pod对象数量最多可超出期望值的个数
      maxUnavailable : <string>    # 滚动更新参数,升级期间不可用的Pod副本数
  template: <0bject>             # Pod模板
    metadata: <0bject>             # Pod名称
    spec: <0bject>                 # Pod详情

十一. DaemonSet部署应用

11.1 DaemonSet部署实例

cat nginx-DaemonSet.yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: nginx-ds
  namespace: default
spec:
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx:1.16
          ports:
            - name: http
              containerPort: 80
          livenessProbe:
            tcpSocket:
              port: 80
            initialDelaySeconds: 3
          readinessProbe:
            httpGet:
              path: "/u"
              port: 80
              scheme: HTTP
            initialDelaySeconds: 5

11.2 DaemonSet部署node_exporter

1.为每个节点都运行一份node_exporter,采集当前节点的信息:

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: node-exporter-ds
  namespace: default
spec:
  selector:
    matchLabels:
      app: node-exporter
  template:
    metadata:
      labels:
        app: node-exporter
    spec:
      containers:
        - name: prometheus-node-exporter
          image: prom/node-exporter:v0.18.8
          ports:
            - name: node-ex-http
              containerPort: 9188
              hostPort: 9100
          livenessProbe:
            tcpSocket:
              port: node-ex-http
            initialDelaySeconds: 3
          readinessProbe:
            httpGet:
              path: "/metrics"
              port: node-ex-http
              scheme: HTTP
            initialDelaySeconds: 5
          hostNetwork: true  # 共享主机网络
          hostPID: true      # 获取主机 PID
          #nodeSelector:     #节点选择器 选择那些节点部署Ingress,默认所有
            #type: ssd       #如果节点有type=ssd 标签则部署

2.输出Pod对象状态

[root@master ~]# kubectl describe daemonsets.appsnode-exports-ds
Desired Number of Nodes Scheduled: 3
Current Number of Nodes Scheduled: 3
Number of Nodes Scheduled with Up-to-date Pods: 3
Number of Nodes Scheduled with Available Pods: 3
Number of Nodes Misscheduled: 0
Pods Status:  3 Running / 0  Waiting / 0 Succeeded / 0 Failed

3.node_exporter默认监听在TCP的9100端口上,我们可以向任何一台节点IP发起访问,进行验证。

[root@master ~]# curl -s 10..0.204:9100/metrics |grep Toad15
# HELP node_Load15 15m Load average.# TYPE node_load15 gaugenode load15 0.27
[root@master ~]# curl -s 10.0.0.205:910/metrics |grep load15
# HELP node_load15 15m Toad average.# TYPE node_load15 gaugenode load15 0.18

十二. DaemonSet更细策略

DaemonSet也支持更新策略,它支持 OnDelete 和 RollingUpdate两种

  • OnDeLete: 是在相应节点的Pod资源被删除后重建为新版本,从而允许用户手动编排更新过程。
  • RollingUpdate: 滚动更新,工作逻辑和Deployment滚动更新类似;

12.1 RollingUpdate

1.将此前创建的node-expoter中的pod模板镜像修改为 prom/nodeexporter:v0.18.1,便能测试其更新过程.

cat node_exporter.yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: node-exporter-ds
  namespace: default
spec:
  minReadySeconds: 3
  revisionHistoryLimit: 20
  updateStrategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 1
  selector:
    matchLabels:
      app: node-exporter
  template:
    metadata:
      labels:
        app: node-exporter
    spec:
      containers:
      - name: prometheus-node-exporter
        image: prom/node-exporter:v0.18.1
        ports:
        - name: node-ex-http
          containerPort: 910
          hostPort: 910
        livenessProbe:
          tcpSocket:
            port: node-ex-http
          initialDelaySeconds: 5
        readinessProbe:
          httpGet:
            path: '/metrics'
            port: node-ex-http
            scheme: HTTP
          initialDelaySeconds: 5
      hostNetwork: true
      hostPID: true

2.安装默认的 RollingUpdate 策略, node-exports-ds 资源将采用一次更新一个Pod对象,待新建Pod的对象就绪后,在更新下一个Pod对象,直到全部完成。

[rootmaster daemonset]# kubectl describedaemonsets.apps node-exports-ds
Events:
Type                 Reason              Age         From
Message
------------------
Normal SuccessfulDelete 96s daemonset-controller Deleted pod: node-exports-ds-p9w52
Normal SuccessfulCreate 95s daemonset-controller Created pod: node-exports-ds-hcbfn
Normal SuccessfulDelete 62s daemonset-controller Deleted pod: node-exports-ds-fjc6x
Normal SuccessfulCreate 61s daemonset-controller Created pod: node-exports-ds-Igtsc

12.2 OnDelete

1.将此前创建的node-expoter中的pod模板镜像更新为 prom/nodeexporter:v1.3.1,由于升级版本跨度过大,无法确保升级过程中的科定性,我们就不得不使用 0nDeLete 策略来替换默认的RolTingUpdate 策略.

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: node-exporter-ds
  namespace: default
spec:
  minReadySeconds: 3
  revisionHistoryLimit: 20
  updateStrategy:
    type: OnDelete
  selector:
    matchLabels:
      app: node-exporter
  template:
    metadata:
      labels:
        app: node-exporter
    spec:
      containers:
      - name: prometheus-node-exporter
        image: prom/mode exporter:v1.3.1
        ports:
        - name: node-ex-http
          containerPort: 9100
          hostPort: 9100
        livenessProbe:
          tcpSocket:
            port: node-ex-http
          initialDelaySeconds: 3
        readinessProbe:
          httpGet:
            path: "/metrics"
            port: node-ex-http
            scheme: HTTP
          initialDelaySeconds: 5
      hostNetwork: true
      hostPID: true

2.由于 0nDelete 并非自动完成升级,它需要管理员手动删除Pod,然后重新拉起新的Pod,才能完成更新。 (对于升级有着先后顺序的软件这种方法就非常的有用,)

[root@master ~]# kubectl delete pod node-exports-ds-sg756 node-exports-ds-lgtsc
pod "node-exports-ds-sg756" deleted
pod "node-exports-ds-lgtsc" deleted

3.检查Pod是否正常运行

[root@master ~]# kubectl get pod
NAME                    READY         STATUS               RESTARTS                      AGE
node-exports-ds-8bx4j   1/1           Running                0                           68s
node-exports-ds-mdm2s   1/1           Running                0                           68s

4.检查Pod中使用的镜像是否更新为新版本

[root@master ~]# kubectl get pod node-exports-ds-8bx4j -o yam
containers:
- image: prom/node-exporter:v1.3.1

十三. job

13.1 job控制器特性

Job 控制器常用于管理那些运行一段时间就能够“完成” 的任务,例如离线数据分析,数据备份等,当任务完成后,由Job控制器将该Pod对象置于 Complete 完成状态,在完成一定时间后,当达到了用户指定的生存周期,由系统自动删除该任务。
如果,容器中的进程因 “错误” 而终止,则需要依赖 RestartPoticy配置来确定是否重启,如果是因为 节点故障造成 Pod意外终止的话,会被重新创建起来继续运行。

  • 1、Pod执行,退出状态码为0,则表示执行成功,而后将该Pod状态置于Complete;
  • 2、Pod执行,退出状态码为非0,检查restartpolicy为Never,表示永不重启,而后将该Pod状态置于Failure;
  • 3、Pod执行,退出状态码为非0,检查restartpolicy为OnFailure表示退出状态码如果不为@时重启该Pod,所以会尝试重新拉取Pod,直到执行成功为止;

13.2 job工作方式

在实际生产环境中,有些任务可能需要运行不止一次,用户可以配置他们以串行或并行方式运行起来。

  • 串行Job: 将一个作业串行执行多次直到满足期望的次数;
  • 并行Job: 设定工作队列数,同时运行,而每个队列仅运行一个作业;
    注意: 对于有严格次序要求的作业,只能选择串行执行,而没有严格次序要求的可以选择并行来提升运行的效率和速度;

13.3 job基础资源

apiVersion: batch/v1       # API群组及版本
kind: Job                  # 资源类型
metadata:
  name: <string>           # 源名称
  namespace: <string>      # 名称空间
spec:
  selector: <0bject>       # 标签选择器
  completions: <integer>   # 期望成功完成作业的次数
  parallelism: <integer>   # 作业的最大并行度,默认为1
  backoffLimit: <integer>  # 将作业标记为Failed之前的重试次数,默认为6
  activeDeadlineSeconds: <integer>     # 作业启动后可处于活动状态的时长,超出则会被标记为Faited
  ttlSecondsAfterFinished: <integer>   # 作业的最大生存时长,超期将被删除,@表示立即删除
  template: <0bject>       # Pod模板
    spec: <Object>
      container: <0bject>  # Pod容器详情
      restartpolicy: <string>          #Pod重启策略,默认的ALways并不适应,因此必须单独指定

13.4 job示例代码

[root@master job]# cat job-demo.yaml
apiVersion: batch/v1
kind: Job
metadata:
  name: job-demo
spec:
  completions: 5      # 需要成功运行5次
  parallelism: 1      # 并行执行为1
  backoffLimit: 2     # 失败后,允许重试 2 次
  activeDeadlineSeconds: 120    # 总活跃时间为120s,包含运行Pod时间+异常重试次数时间
  ttlSecondsAfterFinished: 100  # Job-demo在结束100秒之后,会被系统自动删除 (无论执行成功或失败)
  template:
    spec:
      containers:
      - name: myjob
        image: alpine:latest
        command: ["/bin/sh","-c","sleep 3"]
      restartPolicy: OnFailure

十四. job实践

本例中,我们会运行包含多个并行工作进程的 Kubernetes Job。文档
本例中,每个Pod一旦被创建,会立即从任务队列中取走一个消息,然后将消息从队列中删除并退出本次任务
下面是本次示例的主要步骤:

  • 1、启动一个消息队列服务: 我们使用 RabbitMQ。
  • 2、创建一个队列,放上消息数据: 每个消息表示一个要执行的任务。
  • 3、启动一个Job,该Job启动多个 Pod : 每个Pod从消息队列中取走一个任务,处理它,然后重复执行,直到队列的队尾。

14.1 创建Rabbitmq服务

1.部署rabbitmq消息队列服务

cat rabbitmq-deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: rabbitmq-controller
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mq
  template:
    metadata:
      labels:
        app: mq
    spec:
      containers:
      - name: rabbitmq-server
        image: rabbitmq
        ports:
        - containerPort: 5672
      resources:
        limits:
          cpu: 100m

2.部署service,使得集群内Pod可以通过servicename访问该服务

[root@master ~]# cat rabbitmg-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: rabbitmq-service
spec:
  selector:
    app: mq
  ports:
  - port: 5672

14.2 消息发布者User

1.启动临时容器测试

# 启动ubuntu18:04镜像,然后安装一些工具
[root@master ~]# kubectl run -i --tty temp --imageubuntu:18 .04
[root@temp-Loe07:/# apt-get update
[root@temp-loe07:/# apt-get install -y curl ca-certificates amqp-tools python dnsutils
# 如果觉得安装过于耗时,可以启动我已安装好工具的镜像
[root@master ~]# kubectl run -i --tty temp --image oldxu3957/mgtoos:latest

2.验证rabbitmg服务

# rabbitmg-service 可以通过dns解析到对应的serviceIP
[root@temp-loe07:/# export BROKER_URL=amqp://guest:guest@rabbitmq-service:5672

# 创建队列:
[root@temp-Toe07:/# /usr/bin/amqp-declare-queue --url=$BROKER_URL -q foo

# 向它推送一条消息:
[root@temp-loe07:/# /usr/bin/amqp-publish --url=$BROKER_URL -r foo -p -b oldxu

# 然后取回它
[root@temp-loe07:/# /usr/bin/amgp-consume --url=$BROKER_URL -q foo -c 1 cat && echo 
oldxu

3.为队列增加任务,创建一个job1的队列,然后给队列中填充了8个消息

export BROKER_URL=amqp://guest:guest@rabbitmq-service:5672
/usr/bin/amqp-declare-queue --urL=$BROKER_URL -q job1
for f in aa bb cc dd ee ff gg hh
do
  /usr/bin/amqp-publish --url=$BROKER_URL -r job1 -p -b $f
done

14.3 消息订阅者(job)

现在我们可以创建镜像,获取数据,然后以Job方式运行起来。
14.3.1 编写获取队列程序

# 获取队列数据,然后等待10S,结束
[root@node1 work-queue]# cat worker.py
#!/usr/bin/env python
# Just prints standard out and sleeps for 10seconds .
import sys
import time
print("Processing "+ sys.stdin.readlines()[0])time.sleep(10)

14.3.2 编写Dockerfile
编写Dockerfile文件,制作为镜像,然后推送到自己的仓库; (注意镜像中需要传递的变量)

[root@node1 work-queue]# cat Dockerfile
# Specify BROKER_URL and QUEUE when running
FROM ubuntu:18.04
RUN apt-get update && 
    apt-get install -y curl ca-certificates amqp-tools python  --no-install-recommends && rm -rf /var/lib/apt/lists/*
COPY ./worker.py /worker.py
RUN chmod +x /worker.py
CMD /usr/bin/amqp-consume --urL=$BROKER_URL -q $QUEUE -c 1 /worker.py

14.3.3 编写Job任务
编写Job任务,每个 Pod 使用队列中的一个消息然后退出。这样,Job的完成计数就代表了完成的工作项的数量。

[root@master job]# cat rabbitmg-consumer.yaml
apiVersion: batch/v1
kind: Job
metadata:
  name: rabbitmg-consumer
spec:
  completions: 8       # 总共运行8次,因为队列中有8条消息
  parallelism: 2       # 并行执行2个任务
  ttTSecondsAfterFinished: 100   # 结束后1000s删除
  template:
    spec:
      containers:
      - name : mq-consumer-work
        image: oldxu3957/rabbit-mg-consumer-job
        env:
        - name: BROKER URL
          value: amqp://guest:guest@rabbitmq-service:5672
        - name: QUEUE
          value : job1
      restartPolicy: OnFailure

14.3.4 检查Job

[root@master job]#kubectl describe jobs rabbitmq-consumer
Name :             rabbitmq-consumer
Namespace :        default
Selector:          controller-uid=efc03e23-cfcf-4197-9f5a-273962524b3a
Labels:            controller-uid=efc03e23-cfcf-4197-9f5a-273962524b3a
                   job-name=rabbitmq-consumer
Annotations:       <none>
Parallelism:       2 
Completions:       8
Completion :       Mode:NonIndexed
Start Time:        Sat, 16 Apr 2022 20:04:22 +0800
Completed At:      Sat, 16 Apr 2022 20:04:22 +0800
Duration:          50s
Pods Statuses:     0 Running / 8 Succeeded / 0 Failed
Pod Template:
Labels:            controller-uid=efc03e23-cfcf-4197-9f5a-273962524b3a
                   job-name=rabbitmg-consumer
Containers:
mg-consumer-work:
Image:             registry.cn-huhehaote.aliyuncs.com/oldxu3957/rabbit-mq-consumerjob
Port:              <none>
Host Port:         <none>
Environment:
BROKER_URL: amqp://guest:guest@rabbitmq-service:5672
   QUEUE:          job1
  Mounts:          <none>
 Volumes:          <none> 
Events:
    Type     Reason    Age     From                Message
------------------------------------------------------------------------------------
SuccessfulCreate 2m4s job-controllerNormaTCreated pod: rabbitmg-consumer--1-vk2c9Normal SuccessfulCreate 2m4s job-controllerCreated pod: rabbitmg-consumer--1-b78f8
Normal SuccessfulCreate 112s job-controllerCreated pod: rabbitmg-consumer--1-9mxc4
Normal SuccessfulCreate 112s job-controllerCreated pod: rabbitmg-consumer--1-s4sz5
Normal SuccessfulCreate 99s job-controllerCreated pod: rabbitmg-consumer--1-5nxb9
Normal SuccessfulCreate 98s job-controllerCreated pod: rabbitmg-consumer--1-bf9xs

14.3.5 检查Pod

# 通过检查Pod的Logs,可以看到消息被取走了
[root@master job]# kubectl logs rabbitmg-consumer--1-28pkc
Processing aa
[root@master job]# kubectl logs rabbitmq-consumer-1-5nxb9
Processing ff
[root@master job]# kubectl logs rabbitmq-consumer--1-8tk9j
xuliang
Processing dd
......

14.3.6 注意事项
如果设置的完成数量小于队列中的消息数量,会导致一部分消息项不会被执行。
如果设置的完成数量大于队列中的消息数量,当队列中所有的消息都处理完成后, Job 也会显示为未完成。Job 将创建 Pod 并阻塞等待消息输入。
当发生下面两种情况时,即使队列中所有的消息都处理完了,Job 也不会显示为完成状态:

  • 在 amqp-consume 命令拿到消息和容器成功退出之间的时间段内,执行杀死容器操作;
  • 在 kubelet 向 api-server 传回 Pod 成功运行之前,发生节点崩
posted @ 2021-07-20 13:25  老夫聊发少年狂88  阅读(249)  评论(0编辑  收藏  举报