k8s指南-工作负载(4)

2023-11-03

目录:
(1)k8s指南-概述
(2)k8s指南-架构
(3)k8s指南-工作负载(1)
(4)k8s指南-工作负载(2)
(5)k8s指南-工作负载(3)
(6)k8s指南-工作负载(4)
(7)k8s指南-Service
(8)k8s指南-Ingress
(9)k8s指南-DNS与服务发现
(10)k8S指南-平滑升级与自动扩缩容


批处理工作负载包括Job和CronJob,前者用于处理一次性任务,后者处理定时任务。

Job

Job会创建一个或多个Pod,并将执行这些创建的pod,直到所有的pod成功终止。

删除Job的操作会清除所创建的全部pod,挂起Job的操作会删除Job的所有活跃Pod,直到Job被再次恢复执行。

示例Job

下面是一个Job配置示例,负责计算圆周率小数点后的2000位,并将结果打印出来。

apiVersion: batch/v1
kind: Job
metadata:
  name: pi
spec:
  template:
    spec:
      containers:
      - name: pi
        image: perl:5.34.0
        command: ["perl",  "-Mbignum=bpi", "-wle", "print bpi(2000)"]
      restartPolicy: Never
  backoffLimit: 4

你可以通过以下命令来运行此示例:

kubectl apply -f https://kubernetes.io/examples/controllers/job.yaml

通过describe或者get命令可以看到该工作负载或Pod的状态。查看pod的日志:

kubectl logs pi-8ldmv
3.1415926535897932384626433832795028841971...

Job规约

与Kubernetes中其他资源类似,Job也需要 apiVersion, kindmetadata 字段。Job的名字必须是合法的DNS子域名。另外还需要.spec节区。

Pod模板

Job的.spec中只有.spec.template是必需的字段。
除了作为pod所必需的字段之外,Job中的pod模板必须设置合适的标签和重启策略,重启策略只能为NeverOnFailure(当设置为OnFailure时,需要考虑重启是否会带来幂等性问题)。

字段.spec.selector是可选的,在绝大多数场合都不需要为其赋值。

Job的并行执行

适合以Job形式来运行的任务主要有三种:

非并行运行Job

  • 通常只启动一个Pod,除非该pod失败
  • 当pod成功终止时,立即视Job为完成状态

完成计数的并行Job

  • .spec.completions字段设置为非0的正数值
  • Job用来代表整个任务,当成功的pod个数达到.spec.completions时,Job被视为完成。
  • 当使用.spec.completionMode="Indexed"时,每个pod都会获得一个不同的索引值,介于0和.spec.completions-1之间。

工作队列的并行Job

  • 不设置.spec.completions,默认值为.spec.parallelism
  • 多个pod之间必须互相协调,或者借助外部服务确定每个pod要处理哪个工作项。例如,任一pod都可以从工作队列中取走最多N个工作项。
  • 每个pod都可以独立确定是否其他pod均已完成,进而确定Job是否完成。
  • 当Job中任何pod成功终止,不再创建新pod。
  • 一旦至少一个pod成功完成,并且所有pod均已终止,即可宣告Job成功完成。
  • 一旦任何pod成功退出,任何其他pod都不应再对此任务执行任何操作或生成任何输出,所有pod都应启动退出过程。

对于非并行的Job,你可以不设置.spec.completions.spec.parallelism。这两个属性都不设置时,默认为1。

对于完成计算类型的Job,应该设置.spec.completions为需要的完成个数,.spec.parallelism可以设置也可以不设置,默认值为1。

对于一个工作队列Job,可以不设置.spec.completions,但必须设置.spec.parallelism

并行性请求(.spec.parallelism)可以设置为任何非负整数,如果为0,则Job相当于启动后便暂停,直到此值被增加。
实际并行性(即任意时刻处于运行状态的pod个数)可能比并行性请求略大或略小。

处理Pod和容器失效

Pod中的容器可能因为多种不同原因失效,例如因为其中的进程退出时返回值非0,或者容器因为超出内存约束而被杀死。如果发生这类事件,并且重启策略为OnFailure,Pod会继续保留,但容器会被重启。
因此你的程序需要能够处理重启的情况,或者设置重启策略为Never

除了容器外,Pod也可能会失败。例如当Pod启动时,节点失效(被重启,被升级或删除等),或者pod中的容器失败而不重启(重启策略为Never)。当Pod失败时,Job控制器会启动一个新的pod。这意味着,你的应用需要处理在一个新的pod中被重启的情况,尤其是应用需要处理之前运行所产生的临时文件、锁、不完整输出等问题。

即使将Job的重启策略设置为Never,同一程序也可能因为pod重启而被执行两次。

Pod的回退失效策略

在有些情况下,你可能希望执行Job的pod在经历若干次失败后,Job直接进入失败状态,比如Job有配置错误。为了实现这一点,可以设置.spec.backoffLimit参数,表示失败次数限制,默认为6。

计算重试次数有以下两种方法:

  • 计算.status.phase = "Failed" 的pod数量
  • 当pod的重启策略为OnFailure时,针对.status.phase等于pendingrunning的pod,计算其中所有容器的重启次数。

两种方式中其中一个的值达到失败次数限制时,Job就会被判定为失败。

如果你的Job的重启策略为OnFailure,则pod不会重启,但任务容器会重启,在达到Job失败次数限制时pod会被自动删除,其中的日志会丢失。如下所示:

Events:
  Type     Reason                Age   From            Message
  ----     ------                ----  ----            -------
  Normal   SuccessfulCreate      98s   job-controller  Created pod: pi-gddcd
  Normal   SuccessfulDelete      5s    job-controller  Deleted pod: pi-gddcd
  Warning  BackoffLimitExceeded  5s    job-controller  Job has reached the specified backoff limit

如果你的Job的重启策略为Never,则容器不会被重启。每次失败时,Job-controller都会创建一个新的pod来重试Job,直到达到失败次数限制。失败的pod不会被删除,其中的日志也会保留。如下所示:

Events:
  Type    Reason            Age   From            Message
  ----    ------            ----  ----            -------
  Normal  SuccessfulCreate  2m9s  job-controller  Created pod: pi-8whm8
  Normal  SuccessfulCreate  2m5s  job-controller  Created pod: pi-lnnps
  Normal  SuccessfulCreate  110s  job-controller  Created pod: pi-bvw9t
  Normal  SuccessfulCreate  85s   job-controller  Created pod: pi-422xk
  Normal  SuccessfulCreate  41s   job-controller  Created pod: pi-86x4z

因此建议将Job的重启策略设置为Never比较好。

activeDeadlineSeconds
除了Job执行结束与失败次数超限会导致Job终止外,还可以通过配置活跃期限(.spec. activeDeadlineSeconds )来自动停止Job任务。

我们可以为 Job 的 .spec.activeDeadlineSeconds 设置一个秒数值。该值适用于 Job 的整个生命期,无论 Job 创建了多少个 Pod。 一旦 Job 运行时间达到 activeDeadlineSeconds 秒,其所有运行中的 Pod 都会被终止, 并且 Job 的状态更新为 type: Failedreason: DeadlineExceeded

.spec. activeDeadlineSeconds的优先级高于.spec.backoffLimit,也就是说,即使失败次数未达到限制,只要Job活跃时间限制到了,该Job也会被终止。

注意,Job规约和Job的pod模板规约中都有activeDeadlineSeconds 字段,不要设置错了。

重启策略对应的是pod,而不是Job本身。一旦job状态变为失败状态,这就是一个最终状态。
也就是说,由.spec.activeDeadlineSeconds.spec.backoffLimit 所触发的Job终止机制会导致Job永久性的失败,而这类状态都需要人工干预才能解决。

Job自动清理

已完成的Job通常不需要留存在系统中,一直保留它们会给API服务器带来额外的压力。

如果Job由某种更高级的控制器如CronJob来管理,则Job可以被CronJob基于特定的清理策略清理掉。否则的话,就需要指定其过期机制。

Job的TTL机制
特性版本:Kubernetes v1.23 [stable]。
可以通过设置Job的.spec.ttlSecondsAfterFinished字段来自动清理已完成的Job(状态为CompletedFailed)。
例如:

apiVersion: batch/v1
kind: Job
metadata:
  name: pi-with-ttl
spec:
  ttlSecondsAfterFinished: 100
  template:
    spec:
      containers:
      - name: pi
        image: perl:5.34.0
        command: ["perl",  "-Mbignum=bpi", "-wle", "print bpi(2000)"]
      restartPolicy: Never

该Job会在结束后的100秒被清理。如果ttl字段设置为0则表示在结束之后立即清理。没有设置则不会被清理。

CronJob

一个CronJob对象就像是一个Linux环境的crontab文件一样,它会在给定的调度周期(crontab格式)内定期的创建一些job。

注意:所有的定时任务的调度周期都基于kube-controller-manager的时区。

通常情况下,CronJob对于创建定期和重复的任务非常有用,比如定期的备份和邮件发送之类的任务场景。

Cron时间表语法

 ┌───────────── 分钟 (0 - 59)
 │ ┌───────────── 小时 (0 - 23)
 │ │ ┌───────────── 月的某天 (1 - 31)
 │ │ │ ┌───────────── 月份 (1 - 12)
 │ │ │ │ ┌───────────── 周的某天 (0 - 6)(周日到周一;在某些系统上,7 也是星期日)
 │ │ │ │ │                          或者是 sun,mon,tue,web,thu,fri,sat
 │ │ │ │ │
 │ │ │ │ │
 * * * * *
输入 描述 相当于
@yearly (or @annually) 每年 1 月 1 日的午夜运行一次 0 0 1 1 *
@monthly 每月第一天的午夜运行一次 0 0 1 * *
@weekly 每周的周日午夜运行一次 0 0 * * 0
@daily (or @midnight) 每天午夜运行一次 0 0 * * *
@hourly 每小时的开始一次 0 * * * *

例如,下面这行指出必须在每个星期五的午夜以及每个月 13 号的午夜开始任务:

0 0 13 * 5

要生成 CronJob 时间表表达式,你还可以使用crontab.guru之类的 Web 工具。

时区

对于没有指定时区的CronJob,kube-controller-manager基于本地时区解释排期表(Schedule)。

功能特性: Kubernetes v1.25 [beta]。
如果启用了 CronJobTimeZone 特性门控, 你可以为 CronJob 指定一个时区(如果你没有启用该特性门控,或者你使用的是不支持试验性时区功能的Kubernetes版本,集群中所有CronJob的时区都是未指定的)。

启用该特性后,你可以将 spec.timeZone 设置为有效时区名称。 例如,设置 spec.timeZone: "Etc/UTC" 指示 Kubernetes采用UTC来解释排期表。

Go 标准库中的时区数据库包含在二进制文件中,并用作备用数据库,以防系统上没有可用的外部数据库。

Cronjob调度丢失

一个Cronjob每执行一次调度就会创建一个Jobs对象。大概是因为有时候可能会有两个job被创建,或者没有任务创建。官方尝试去解决这个问题,但是目前仍然无法避免。因此在设计过程中,所有的Job都应该是幂等性的(idempotent)。

如果CronJob未能在预定时间创建,则该任务将被视为错过调度。对于每一个Cronjob来说,CronJob控制器会检查从上一次调度时间到现在的持续时间内它错过了多少个调度,如果错过调度100次,它将不再执行调度,并且会有如下相关异常:

Cannot determine if job needs to be started. Too many missed start time (> 100). Set or decrease .spec.startingDeadlineSeconds or check clock skew.

值得注意的是,如果设置了startingDeadlineSeconds参数(不为空),控制器统计错过的调度次数将不再是从最后一次调度时间,而是按startingDeadlineSeconds的值统计。比如,如果设置startingDeadlineSeconds:200,控制器会统计在最后200秒内错过了的调度次数。

当设置concurrencyPolicy: Forbid时,如果前一个任务还在运行时,CronJob尝试再次被调度,此时会被forbid掉,也会被记录为错过一次调度。

假设一个定时任务被设置在08:30:00开始每一分钟执行一次,并且startingDeadlineSeconds:200。如果CronJob控制器在8:30-10:30时间段故障了,Job将会在10:30:00开始继续执行。 因为控制器仅会计算在过去的200秒内,错过调度的次数,这远远小于100次,所有定时任务会在控制器恢复后继续调度,而不会影响正常的任务。

另外需要注意的是,CronJob仅负责调度和创建匹配的Jobs,而由Jobs真正去管理真正执行任务的Pods。

Cronjob参数详情

  • spec.startingDeadlineSeconds: 表示统计错过调度次数(100次)的开始时间,默认从最后一次调度时间开始统计错过调度次数(超过100不再调度)。
  • spec.concurrencyPolicy: 并发调度策略,可选值:{“Allow”:“允许并发”,“Forbid”:“不允许”,“Replace”:“调度覆盖”}。Allow: 注意:当设置为Allow时,需要考虑到任务执行时间和调度周期,因为可能上个任务没执行成功,下个任务就到执行时间了,如此下来可能会有多个相同的任务在同时执行,造成资源浪费或者并发安全问题;Replace: 当使用Replace遇到上述情况,后个任务会将前一个任务替换掉,如此一来所有的任务可能都不会完整执行;Forbid: 不允许并发调度,也即当前任务未完成时,即使到了下一个调度周期,调度任务也不会执行。此种情况下可能出现任务异常阻塞。如果此时startingDeadlineSeconds参数也没有设置,就可能会出现经过100个调度周期后,该任务不再调度。
  • spec.schedule: 调度周期,格式为标准的crontab格式[分 时 日 月 周]。
  • spec.failedJobsHistoryLimit: 历史失败的任务数限制(通常可以保留1-2个,用于查看失败详情,以调整调度策略)。
  • spec.successfulJobsHistoryLimit: 历史成功的任务数限制(可以自己决定保留多少个成功任务)。
  • spec.jobTemplate: 标准的pod运行的模板(容器运行时的相关参数)。
  • spec.suspend: 可选参数,如果设置为true,所有后续的任务都会被暂停执行,该参数不适用于已经运行的任务,默认为False。

CronJob示例

下面是一个定时任务示例:

apiVersion: batch/v1beta1
kind: CronJob
metadata:
  labels:
    run: dnsall
  name: dnsall
  namespace: myapp
spec:
  # 强烈建议设置并发策略,根据调度周期和任务特性进行设置
  concurrencyPolicy: Forbid
  # 强烈建议设置失败任务数,用于排查任务失败根因,以优化任务
  failedJobsHistoryLimit: 1
  successfulJobsHistoryLimit: 3
  # 强烈建议设置错过调度的计算时间
  startingDeadlineSeconds: 600
  # 调度周期
  schedule: '05,15,25,35,45,55 */1 * * *'
  suspend: false
  jobTemplate:
    metadata:
    spec:
      template:
        metadata:
          labels:
            run: dnsall
        spec:
          imagePullSecrets:
          - name: mydocker
          containers:
          - args:
            - -cmdbtype
            - dns
            image: harbor.bgbiao.top/cron-job:2019-12-04
            imagePullPolicy: Always
            name: dnsall
            resources: {}
            terminationMessagePath: /dev/termination-log
            terminationMessagePolicy: File
          dnsPolicy: ClusterFirst
          # 强烈建议设置任务的重启策略(任务的失败会触及到Jobs控制器中的Backofflimit参数,导致job失败)
          restartPolicy: OnFailure
          schedulerName: default-scheduler
          securityContext: {}
          terminationGracePeriodSeconds: 30

查看调度任务:

$ kubectl  get cronjob -n myapp
NAME             SCHEDULE                      SUSPEND   ACTIVE   LAST SCHEDULE   AGE
dnsall           05,15,25,35,45,55 */1 * * *   False     0        8m41s           23h

cronjob其实定期的创建了job,因此具体的任务pod其实是由job控制器来维护的。
这里可以看到,上面的cronjob保存的三个执行成功的任务

$ kubectl  get jobs -n myapp  | grep dns
dnsall-1577597100           1/1           23s        22m
dnsall-1577597700           1/1           24s        12m
dnsall-1577598300           1/1           24s        2m22s

再查看一个job真正管理的pod任务的执行(任务已经已完成,所以期望值为1,当前值为0):

$ kubectl  get pods -n myapp | grep dnsall-1577598300
dnsall-1577598300-hdl4z           0/1     Completed   0          3m29s

参考资料

[1]. https://kubernetes.io/zh/docs/concepts/overview/
[2]. https://blog.csdn.net/weichuangxxb/article/details/103754021

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

k8s指南-工作负载(4) 的相关文章

随机推荐

  • text段、data段和bss段知识介绍

    一 总体概述 1 bss 可读可写 bss是英文Block Started by Symbol的简称 通常是指用来存放程序中未初始化的全局变量的一块内存区域 在程序载入时由内核清0 BSS段属于静态内存分配 它的初始值也是由用户自己定义的连
  • go语言基础2——流程控制if、for、switch、goto、break、continue

    目录 if else 分支结构 if条件判断基本写法 if条件判断特殊写法 for 循环结构 无限循环 for range 键值循环 switch case goto 跳转到指定标签 break 跳出循环 continue 继续下次循环 练
  • html手风琴效果代码,一款漂亮的纯CSS手风琴效果代码

    本文分享了纯css实现的手风琴 喜欢的朋友可以看看 源码CSS部分 accordionMenu width 500px margin 0 auto padding 10px background size fff color 424242
  • 前端代码深浅拷贝四种方式

    今天公司的实习生有问我代码怎么深拷贝 下面我就给大家整理四种前端代码深拷贝的四种方式 前端数据分为基本数据类型和引用数据类型 当我们拷贝引用数据类型的时候 我们希望改变新数组 对象 不改变原本的数组 对象 我们往往会深拷贝数据 下面是四种深
  • Python paramiko文件传输显示上传下载进度条源码 - stdout

    本文Python Code基于chatGPT的推荐 并修改调试实际运行通过 供学习参考 通过使用python paramiko库 实现文件传输 包括上传和下载 并且同步显示上传和下载进度条信息 实时获取传输进度 避免print方式频繁刷屏困
  • Spring Boot 配置多数据源

    Spring Boot 配置多数据源 作者 Grey 原文地址 博客园 Spring Boot 配置多数据源 CSDN Spring Boot 配置多数据源 说明 本文主要介绍了 Spring Boot 下如何配置多数据源 环境和版本 Ja
  • 静态路由综合实验

    目录 实验要求 实验步骤 1 子网划分 2 配置IP和环回 3 配置静态路由 实现全网可达 4 配置缺省路由 使R1 R4可以访问5 5 5 5 24 5 配置空接口防环 6 ping测试 实验要求 1 除R5的环回地址固定以外 整个其他所
  • 10个最好的 jQuery 视频插件

    在这篇文章中已经收集了10个最佳的jQuery视频插件 帮助开发人员容易地实现网站播放影片功能 可以显示视频和视频播放列表 1 Bigvideo js BigVideo js 是一个jQuery插件能够 让你很方便将视频作为网站的背景 它可
  • FCM算法的matlab实现(Fuzzy C-means 算法)

    FCM算法 F C M FCM FCM算法简介 F C M FCM FCM算法原理 F C M FCM FCM算法实现 m a t l a b matlab matlab F C M FCM FCM算法简介 F C M FCM FCM算法属
  • `com.mysql.jdbc.Driver‘. This is deprecated. The new driver class is `com.mysql.cj.jdbc.Driver‘的解决办法

    com mysql jdbc Driver This is deprecated The new driver class is com mysql cj jdbc Driver 的解决办法 说多了都是泪 搭建这个项目遇到的问题太多了 cs
  • Tensorflow中问题总结

    1 ValueError Variable bar v does not exist or was not created with tf get variab le Did you mean to set reuse None in Va
  • 基于Tensorflow卷积神经网络(CNN)的人脸年龄和性别检测系统

    文件大小 150M 开发环境 Python3 7 OpenCV4 0 1 24 Tensorflow1 13 1 PyCharm2020 点击下载 点击下载 简要概述 基于Tensorflow卷积神经网络 CNN 的人脸年龄和性别检测系统
  • Unity BRDF公式解析

    根据BRDF公式 高光项部分 只能物体的表面的粗糙度有关 Roughness有关 大部分公式都是 根据Cook Torrance 的微表面高光BRDF公式 我们把高光分成三项 D项 Normal Distribution Function
  • 正则表达式如何同时添加左右括号 sub_python小课堂24 - 正则表达式(二)

    python小课堂24 正则表达式 二 前言 今天继续来介绍一下python的正则表达式 回顾一下上次介绍的re模块整篇文章围绕着re findall 来进行实例的讲解 也就是所谓的查询操作 为了便于回顾 这里给出链接 python小课堂2
  • 加密文件

    记得不要抄 问题描述 有一种加密方法为 其使用一个字母串 可以含重复字母 字母个数不超过50 作为密钥 假定密钥单词串为feather 则先去掉密钥单词中的重复字母得到单词串feathr 然后再将字母表中的其它字母以反序追加到feathr的
  • Intellij IDEA Diagrams找不到

    问题 利用spring integration配置了并行调用 想利用Intellij IDEA的Diagrams功能生成可视化效果图 但是怎么也找不到Diagrams这个功能 查询了很多解决方法 如添加插件 Settings中设置 利用快捷
  • Jmeter-plugins-manager下载安装和使用

    一 Jmeter plugins manager下载 官网下载地址 Install JMeter Plugins org 点击plugins manager jar就可以下载安装包了 然后把下载的包放入jmeter下面的 lib ext目录
  • matlab中complex的详细用法,Matlab基本函数-complex函数

    1 complex函数 创建复数 2 用法说明 1 z complex x y 函数创建复数z 输入的x y必须同为变量或维数相同 相同数据类型的向量 矩阵或者多维数组 输出的结果跟输入的维数相同 返回值为a b i 2 y complex
  • dubbo提供者源码解析

    一 dubbo配置解析 DubboBeanDefinitionParser类 会解析xml或者注解配置的类 public DubboBeanDefinitionParser Class
  • k8s指南-工作负载(4)

    目录 1 k8s指南 概述 2 k8s指南 架构 3 k8s指南 工作负载 1 4 k8s指南 工作负载 2 5 k8s指南 工作负载 3 6 k8s指南 工作负载 4 7 k8s指南 Service 8 k8s指南 Ingress 9 k