Kubernetes 实战 —— 04. 副本机制和其他控制器:部署托管的 pod

本文深入探讨了Kubernetes中的副本机制和控制器,包括存活探测器的使用,如HTTP GET、TCP Socket和Exec探测器。通过示例展示了如何创建基于HTTP的存活探测器,以及如何配置和管理Deployment以确保pod的稳定运行。文中还讨论了如何应对节点故障,如通过Deployment自动创建新pod,以及如何水平扩展和缩小pod规模。此外,还涉及了ReplicaSet和DaemonSet的使用场景,以及如何使用更复杂的标签选择器。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

保持 pod 健康

只要 pod 调度到某个节点,该节点上的 Kubelet 就会运行 pod 的容器,从此只要该 pod 存在,就会保持运行。如果容器的主进程奔溃, Kubelet 就会自动重启容器;如果应用程序奔溃, Kubelet 就会自动重启应用程序。

应用程序也可能因为无限循环或死锁等情况而停止响应。为确保应用在这种情况下可以重新启动,必须从外部检查应用程序的运行状况,而不是依赖于应用的内部检测。

介绍存活探测器

Kubernetes 可以通过存活探测器 (liveness probe) 检查容器是否还在运行。可以为 pod 中的每个容器单独指定存活探测器。 Kubernetes 将定期执行探测器,如果探测失败,就会自动重启容器。

注意:Kubernetes 还支持就绪探测器 (readiness probe) ,两者适用于两种不同的场景。

Kubernetes 有三种探测容器的机制:

HTTP GET 探测器:对容器的 IP 地址(指定的端口和路径)执行 HTTP GET 请求。如果探测器收到响应,并且响应状态码不代表错误(状态码为 2xx 或 3xx ),则认为探测成功。如果服务器返回错误响应状态码或者没有响应,那么探测就被认为是失败的,容器将被重启。
TCP Socket探测器:尝试与容器指定端口建立 TCP 连接。如果连接成功建立,则探测成功。否则,容器将被重启。
Exec 探测器:在容器内执行任意命令,并检查命令的退出状态码。如果状态码是 0 ,则探测成功。所有其他状态码都被认为失败,容器将被重启。

创建基于 HTTP 的存活探测器

为了让 HTTP GET 探测器探测失败,我们需要修改 kubia 源码,使得其从第五次访问之后开始一直返回 500 状态码 (Internal Server Error) 。
然后我们可以通过以下描述文件 kubia-liveness-probe.yaml 创建一个包含 HTTP GET 存活探测器的 pod 。

# 遵循 v1 版本的 Kubernetes API
apiVersion: v1
# 资源类型为 Pod
kind: Pod
metadata://加入Java开发交流君样:756584822一起吹水聊天
  # pod 的名称
  name: kubia-liveness
spec:
  containers:
    # 创建容器所使用的镜像
    - image: idealism/kubia-unhealthy
      # 容器的名称
      name: kubia
      ports:
        # 应用监听的端口
        - containerPort: 8080
          protocol: TCP
      # 开启一个存活探测器
      livenessProbe:
        # 存活探测器的类型为 HTTP GET
        httpGet:
          # 探测器连接的网络端口
          port: 8080
          # 探测器请求的路径
          path: /
          

使用存活探测器

使用 kubectl create -f kubia-liveness-probe.yaml 创建完 pod 后,等待一段时间后,容器将会重启。可以通过 kubectl get pod kubia-liveness 看到容器会重启,并且无限循环下去:

NAME             READY   STATUS    RESTARTS   AGE
kubia-liveness   1/1     Running   2          4m9s
kubectl logs kubia-liveness --previous: 查看前一个容器的日志,可以了解前一个容器停止的原因

kubectl describe pod kubia-liveness: 查看 pod 详情。可以发现在 Containers 和 Events 里面有终止的相关信息。

Containers:
  kubia:
    ...//加入Java开发交流君样:756584822一起吹水聊天
    State:          Running  # 容器目前正常运行
      Started:      Sun, 07 Jun 2020 17:59:35 +0800
    Last State:     Terminated  # 前一个容器由于错误被终止,错误码是 137
      Reason:       Error
      Exit Code:    137
      Started:      Sun, 07 Jun 2020 17:57:44 +0800
      Finished:     Sun, 07 Jun 2020 17:59:27 +0800
    Ready:          True
    Restart Count:  2  # 该容器已被重启 2 次
    Liveness:       http-get http://:8080/ delay=0s timeout=1s period=10s #success=1 #failure=3

Events:

  Type     Reason     Age                  From                   Message
  ----     ------     ----                 ----                   -------
  Normal   Scheduled  <unknown>            default-scheduler      Successfully assigned default/kubia-liveness to minikube-m02
  Warning  Unhealthy  48s (x6 over 2m58s)  kubelet, minikube-m02  Liveness probe failed: HTTP probe failed with statuscode: 500  # 发现容器不健康
  Normal   Killing    48s (x2 over 2m38s)  kubelet, minikube-m02  Container kubia failed liveness probe, will be restarted  # 终止该容器

错误码 137 是两个数字的总和: 128 + x , x 是终止进程的信号编号。

x=9 表示是 SIGKILL 的信号编号,意味着这个进程被强行终止,这个信号不能被捕获或忽略,并且在接收过程中不能执行任何清理在接收到该信号
x=15 表示是 SIGTERM 的信号编号,意味着这个进程被终止,先进行询问进程终止,让其清理文件和关闭,可以被捕获和解释或忽略
底部列出的事件显示了 Kubernetes 发现容器不健康,所以终止并重新创建。

注意:当容器被强行终止时,会创建一个全新的容器,而不是重启原来的容器。

配置存活探测器的附加属性
可以使用 kubectl explain pod.spec.containers.livenessProbe 查看存活探测器能使用的自定义附加参数。

基于 kubia-liveness-probe.yaml 创建一个新的描述文件 kubia-liveness-probe-initial-delay.yaml ,并添加 pod.spec.containers.livenessProbe.initialDelaySeconds 属性,值为 15 ,表示在第一次探测器等待 15 秒。

spec:
  containers:
    # 创建容器所使用的镜像
    - image: idealism/kubia-unhealthy
      ...
      # 开启一个存活探测器
      livenessProbe:
        ...
        # 第一次探测前等待 15 秒
        initialDelaySeconds: 15

这样可以在应用程序准备好之后再进行探测,以免应用程序启动时间过长导致一直探测失败而无限重启。

创建有效的存活探测器

存活探测器应该检查什么:简易的存活探测器可以仅检查服务器是否响应,但为了更好地进行存活检查,需要将探测器配置为请求特定的 URL 路径(如 /health ),并让应用从内部对内部运行的所有重要组件执行状态检查,以确保它们都没有终止或停止响应。
确保 /health 不需要认证,否则探测会一直失败,导致容器无限重启
检查应用的内部,检查结果不能受任何外部因素的影响。例如数据库连不上时,存活探测器不应该返回失败,如果问题在数据库,那么重启容器不会解决问题。

保持探测器轻量

不应消耗太多计算资源
运行不应花太长时间。默认情况下,探测器执行的频率相对较高,必须在一秒之内执行完毕
无须在探测器中实现重试:探测器的失败阈值是可配置的,并且通常在容器被终止之前探测器必须失败多次
存活探测器小结:存活探测由 pod 上的 Kubelet 执行, Kubernetes 控制面板不会参与。因此节点奔溃时,控制面板会为所有随节点停止运行的 pod 创建替代者,但不会为直接创建的 pod 创建替代者,因为这些 pod 只被节点上的 Kubelet 管理。为了避免这种情况发生,我们应该使用控制器或类似机制管理 pod

了解 Deployment

注:本节中提到的 pod 受 Deployment 管理等说法为简化说法,实际上 pod 由受 Deployment 管理创建的 ReplicaSet 进行管理创建。

Deployment 是一种 Kubernetes 资源,可确保它的 pod 始终保持运行状态。如果 pod 因为任何原因消失(例如节点从集群中消失或由于该 pod 已从节点中逐出),则 Deployment 会注意到缺少了 pod 并创建替代者

在这里插入图片描述
上图的节点 1 有两个节点, Pod A 是被直接创建的,而 Pod B 由 Deployment 管理。节点异常退出后, Deployment 会创建一个新的 Pod B2 来替换减少的 Pod B ,而 Pod A 由于没有东西负责重建而完全丢失。

Deployment 的操作
Deployment 会持续监控正在运行的 pod 列表,并保证匹配标签选择器(

介绍控制器的协调流程

Deployment 的工作是确保 pod 数量始终与其标签选择器匹配
!在这里插入图片描述

了解 Deployment 的三部分

  • 标签选择器 (label selector) :用于确定 Deployment 作用域中有哪些 pod
  • 副本个数 (replica count) :指定应运行的 pod 数量
  • pod 模版 (pod template) :用于创建新的 pod 副本
    处。

在这里插入图片描述
Deployment 的副本个数、标签选择器和 pod 模版都可以随时修改,但只有副本数目但变更会影响现有的 pod 。

更改控制器的标签选择器或 pod 模版的效果

更改标签选择器和 pod 模版对现有的 pod 没有影响。更改标签选择器会使现有的 pod 脱离 Deployment 的范围,因此控制器会停止关注它们。更改模版仅影响由此 Deployment 创建的新 pod 。

使用 Deployment 的好处

确保 pod 持续运行:在现有 pod 丢失时启动一个新
集群节点发生故障时,为故障节点上运行的受 Deployment 管理的所有 pod 创建替代副本
轻松实现 pod 水平伸缩——手动和自动都可以
注意: pod 实例永远不会重新安置到另一个节点。 Deployment 会创建一个全新的 pod 实例,它与正在替换的实例无关。

创建一个 Deployment
我们可以通过以下描述文件 kubia-deployment.yaml 创建一个 Deployment ,它确保符合标签选择器 app=kubia 的 pod 实例始终是三个。

# 遵循 v1 版本的 Kubernetes API
apiVersion: apps/v1
# 资源类型为 Deployment
kind: Deployment
metadata://加入Java开发交流君样:756584822一起吹水聊天
  # Deployment 的名称
  name: kubia
spec:
  # 指定与标签选择器匹配的 pod 数目为 3
  replicas: 3
  # 指定 Deployment 操作对象
  selector:
    # 需要匹配以下指定的标签
    matchLabels:
      app: kubia
  # 启动 pod 使用的模版(可以发现模版内容与 kubia-manual.yaml 对应部分一致)
  template:
    metadata:
      # 指定标签为 app=kubia
      labels:
        app: kubia
    spec:
      containers:
        # 容器的名称
        - name: kubia
          # 创建容器所使用的镜像
          image: idealism/kubia
          # 应用监听的端口
          ports:
            - containerPort: 8080
              protocol: TCP

模版中的 pod 标签必须和 Deployment 的标签选择器匹配, API 服务器会校验 Deployment 的定义,不会接受错误配置。

若不指定选择器,它会自动根据 pod 模版中的标签自动配置,这样可以让描述文件更简洁。 P93

使用 Deployment

kubectl create -f kubia-deployment.yaml 会创建一个名为 kubia 的 Deployment ,它会根据 pod 模版启动三个新 pod 。

kubectl get pods 可以查看当前创建的所有 pod :

NAME                    READY   STATUS             RESTARTS   AGE
kubia-9495d9bf5-5dwj7   1/1     Running            0          3m53s
kubia-9495d9bf5-5j6zr   1/1     Running            0          3m53s
kubia-9495d9bf5-w98f6   1/1     Running            0          3m53s

查看 Deployment 对已删除的 pod 的响应 P94

kubectl delete pod kubia-9495d9bf5-5dwj7 会删除一个 pod ,然后再次查看当前所有 pod ,可以发现会有 4 个 pod ,因为删除的 pod 正在终止,并且正在创建一个新的 pod : P94

NAME                    READY   STATUS              RESTARTS   AGE
kubia-9495d9bf5-5dwj7   1/1     Terminating         0          24m
kubia-9495d9bf5-5j6zr   1/1     Running             0          24m
kubia-9495d9bf5-kxcw5   0/1     ContainerCreating   0          9s
kubia-9495d9bf5-w98f6   1/1     Running             0          24m

控制器如何创建新的 pod

控制器通过创建一个新的替代 pod 来响应 pod 的删除操作。但它并没有对删除本身作出反应,而是针对由此产生对状态—— pod 数量不足作出反应

在这里插入图片描述

应对节点故障

接下来我们将关闭一个节点的网络接口来模拟节点故障。

  • minikube ssh --node=‘m02’: 进入节点内部
  • sudo ifconfig eth0 down: 关闭该节点的网络接口
  • kubectl get nodes: 发现节点 minikube-m02 的状态为未就绪 (NotReady)
  • kubectl get pods: 可能仍然会看到与之前相同的三个 pod ,因为 Kubernetes 在重新调度 pod 之前会等待一段时间(如果节点因临时网络故障或 Kubelet 重启而无法访问)。如果节点在几分钟内无法访问, Deployment 会立即启动一个新的 pod 。

将 pod 移入/移出 Deployment 的作用域

由 Deployment 创建的 pod 并不是绑定到 Deployment 。在任何时刻, Deployment 管理与标签选择器匹配的 pod 。通过更改 pod 的标签,可以将它从 Deployment 的作用域中添加或删除。

尽管一个 pod 没有绑定到一个 Deployment 拥有的 ReplicaSet ,但该 pod 在 metadata.ownerReferences 中存储它属于哪一个 ReplicaSet 。

给 Deployment 管理的 pod 加标签

kubectl label pod kubia-9495d9bf5-5mmhb type=special: 给 pod 添加其他标签不会影响 Deployment 的管理范围,它只关心该 pod 是否具有标签选择器中引用的所有标签。

更改已托管的 pod 的标签

kubectl label pod kubia-9495d9bf5-5mmhb app=foo --overwrite: 更改其中一个 pod 的标签将使其不再与 Deployment 的标签选择器相匹配,并不再由 Deployment 管理,只剩下两个匹配的 pod 。因此, Deployment 会启动一个新的 pod ,将数目恢复为三

在这里插入图片描述

更改 Deployment 的标签选择器

更改 Deployment 的标签选择器会让所有的 pod 脱离 Deployment 的管理,导致它创建三个新的 pod 。你永远不会修改控制器的标签选择器,但会时不时地更改它的 pod 模版。

修改 pod 模版

Deployment 的 pod 模版可以随时修改,可以使用 kubectl edit deployment kubia 编辑 Deployment 。更改后会重新创建一个新的 ReplocaSet ,并使原有的 ReplocaSet 的副本数变为 0 。因此,使用 kubectl get pods 将发现有 6 个 pod ,pod 的前缀是对应的 ReplocaSet 的名称。

//加入Java开发交流君样:756584822一起吹水聊天
NAME                    READY   STATUS        RESTARTS   AGE
kubia-9495d9bf5-kxcw5   1/1     Terminating   0          78m
kubia-9495d9bf5-w98f6   1/1     Terminating   0          102m
kubia-9495d9bf5-xn67d   1/1     Terminating   0          29m
kubia-bc974964b-bp4l2   1/1     Running       0          22s
kubia-bc974964b-r29j2   1/1     Running       0          39s
kubia-bc974964b-xl677   1/1     Running       0          14s

若通过 kubectl edit replicaset kubia-bc974964b 直接修改 Deployment 拥有的 ReplicaSet 实例。这样效果和直接修改 Deployment 类似,也会创建一个新的 ReplicaSet ,并使原有的 ReplocaSet 的副本数变为 0 。这样修改不会将新的 pod 模版同步回原有的 Deployment ,但删除 Deployment 时仍然会删除所有相关的 ReplocaSet 及其管理的 pod 。

水平缩放 pod

kubectl scale deployment kubia --replicas=10: 可以修改 Deployment 需要保持的 pod 实例的数量(02. 开始使用 Kubernetes 和 Docker中介绍过使用该命令进行伸缩)

也可以通过 kubectl edit deployment kubia 修改 spec.replicas 的数量,从而更改需要保持的 pod 实例的数量。

删除一个 Deployment

当通过 kubectl delete deployment kubia 删除 Deployment 时,对应的 ReplicaSet 和 pod 都会被删除。

而通过 kubectl delete replicaset kubia-bc974964b 删除 ReplicaSet 时,对应的 pod 会被删除,但由于 Deployment 会重新创建一个 Replicaset ,所以又会自动创建对应数量的 pod 。
在这里插入图片描述
当通过 kubectl delete deployment kubia --cascade=false 删除 Deployment 时,会保留对应的 ReplicaSet 和 pod ,这样ReplicaSet 不再受管理,但是 pod 仍然受 ReplicaSet 管理。当重新创建符合要求的 Deployment 时, ReplicaSet 又会受到管理。

同样地,通过 kubectl delete replicaset kubia-bc974964b --cascade=false 删除 ReplicaSet 时,也会保留对应的 pod 。这样 pod 不再受管理。当创建符合要求的 ReplicaSet 时,这些 pod 又会受到管理。

使用 ReplicaSet

注:书中原本上一节讲得是 ReplicationController ,但我直接使用 Deployment 进行实践,并依照现在的结果进行了修改。目前推荐使用 Deployment ,并且 ReplicaSet 是受 Deployment 管理的,所以不再详细实践本节内容。

使用更富有表达力的标签选择器

基于 kubia-deployment.yaml 创建一个新的描述文件 kubia-deployment-matchexpressions.yaml ,并将 spec.selector.matchLabels 属性替换为 spec.selector.matchExpressions :

spec:

  # 指定 Deployment 操作对象
  selector:
    # 需要匹配满足以下要求的标签
    matchExpressions:
      # 标签名为 app 的值在 ["kubia"]- app: app
        operator: In
        values:
          - kubia

matchExpressions 运行给选择器添加额外的表达式。每个表达式都必须包含一个 key 、一个 operator ,并且可能还有一个 values 的列表(取决于 operator )。共有四个有效的运算符:

  • In: 标签的值必须与其中一个指定的 values 匹配
  • NotIn: 标签的值与任何指定的 values 都不匹配
  • Exists: pod 必须包含一个指定名称的标签(不关心值)。使用此运算符时,不应指定 values 字段
  • DoesNotExist: pod 不得包含指定名称的标签。使用此运算符时,不应指定 values 字段

如果指定了多个表达式,则所有这些表达式都必须为 true 才能使选择器与 pod 匹配。如果同时指定 matchLabels 和 matchExpressions ,则所有标签都必须匹配,且所有表达式都必须为 true 才能使选择器与 pod 匹配。

使用 DaemonSet 在每个节点上运行一个 pod
DaemonSet 可以让 pod 在集群中的每个节点上运行,并且每个节点正好有一个运行的 pod 实例。

在这里插入图片描述
使用 DaemonSet 在每个节点上运行一个 pod
DaemonSet 没有副本数的概念,它确保创建足够的 pod ,并在每一个节点上部署一个 pod 。如果节点下线, DaemonSet 不会重新创建 pod ;但新节点添加到集群中,它会立刻部署一个新的 pod 实例到该节点。 P108

使用 DaemonSet 只在特定的节点上运行 pod
DaemonSet 将 pod 部署到集群的所有节点上,除非通过 pod 模版中的 spec.nodeSelector 属性指定这些 pod 只在部分节点上运行。

注意:节点可以被设置为不可调度,防止 pod 被部署到节点上。但 DaemonSet 会将 pod 部署到这些节点上,因为无法调度但属性只会被调度器使用,而 DaemonSet 的目的是运行系统服务,即使在不可调度的节点上,系统服务通常也需要运行。

用一个例子来解释 DaemonSet

假设有一个名为 ssd-monitor 的守护进程,它需要在包含 SSD 的所有节点上运行。包含 SSD 的节点已被添加了 disk=ssd 标签,所以我们需要创建一个 DaemonSet ,它只在拥有上述标签的节点上运行守护进程。

在这里插入图片描述
创建一个 DaemonSet 描述文件 P110

为了模拟 ssd-monitor 的监控程序,我们将使用以下 Dockerfile 创建一个每 5 秒中打印 SSD OK 的镜像。

FROM busybox
ENTRYPOINT while true; do echo 'SSD OK'; sleep 5; done
为了将 ssd-monitor 部署到符合要求的每个节点上,我们还需要使用以下 ssd-monitor-daemonset.yaml 描述文件进行部署。

# 遵循 apps/v1 版本的 Kubernetes API
apiVersion: apps/v1
# 资源类型为 DaemonSet
kind: DaemonSet
metadata:
  # DaemonSet 的名称
  name: ssd-monitor
spec:
  # 指定 DaemonSet 操作对象
  selector:
    # 需要匹配以下指定的标签
    matchLabels:
      app: ssd-monitor
  # 启动 pod 使用的模版
  template:
    metadata:
      # 指定标签为 app=ssd-monitor
      labels:
        app: ssd-monitor
    spec:
      # 指定选择具有 disk=ssd 标签的节点部署
      nodeSelector:
        disk: ssd
      containers:
        # 容器的名称
        - name: main
          # 创建容器所使用的镜像
          image: idealism/ssd-monitor

实践

kubectl create -f ssd-monitor-daemonset.yaml: 按照指定的描述文件创建一个 DaemonSet
kubectl get daemonsets: 可以发现所有的值都是 0 ,因为目前还没有节点拥有 disk=ssd 标签
kubectl get pods: 可以发现目前还没有 pod
kubectl label node minikube-m03 disk=ssd: 给节点 minikube-m03 打上标签 disk=ssd
kubectl get pods: 可以发现刚刚启动了一个 pod

NAME                    READY   STATUS              RESTARTS   AGE
ssd-monitor-bbqbp       0/1     ContainerCreating   0          2s
kubectl label node minikube-m03 disk=hdd --overwrite: 将节点 minikube-m03 的标签 disk=ssd 修改为 disk=hdd
kubectl get pods: 可以发现刚刚启动的 pod 正在终止

NAME                    READY   STATUS        RESTARTS   AGE
ssd-monitor-bbqbp       1/1     Terminating   0          2m37s

运行执行单个任务的 pod

介绍 Job 资源

Kubernetes 通过 Job 资源支持运行一种 pod ,该 pod 子啊内部进程成功结束时,不重启容器。一旦任务完成, pod 就被认为处于完成状态。
在节点发生故障时,该节点上由 Job 管理的 pod 将被重新安排到其他节点。如果进程本身异常退出(进程返回错误退出码时),可以将 Job 配置为重新启动容器。

在这里插入图片描述
定义 Job 资源
为了模拟耗时的任务,我们将使用以下 Dockerfile 创建一个调用 sleep 120 命令的镜像。

FROM busybox
ENTRYPOINT echo “ ( d a t e ) B a t c h j o b s t a r t i n g " ; s l e e p 120 ; e c h o " (date) Batch job starting"; sleep 120; echo " (date)Batchjobstarting";sleep120;echo"(date) Finished succesfully”
为了管理部署 batch-job ,我们还需要使用以下 batch-job.yaml 描述文件进行部署。

# 遵循 batch/v1 版本的 Kubernetes API
apiVersion: batch/v1
# 资源类型为 Job
kind: Job
metadata:
  # Job 的名称
  name: batch-job
spec://加入Java开发交流君样:756584822一起吹水聊天
  # 启动 pod 使用的模版
  template:
    metadata:
      # 指定标签为 app=batch-job
      labels:
        app: batch-job
    spec:
      # Job 不能使用 Always 为默认的重启策略
      restartPolicy: OnFailure
      containers:
        # 容器的名称
        - name: main
          # 创建容器所使用的镜像
          image: idealism/batch-job

设置 Job 的重启策略为 OnFailure 或 Never 可以防止容器在完成任务时重新启动。 P114

Job 运行一个 pod P114
kubectl create -f batch-job.yaml: 根据描述文件创建指定的 Job
kubectl get jobs: 查看 job ,可以发现刚刚创建的 Job

NAME        COMPLETIONS   DURATION   AGE
batch-job   0/1           5s         5s

kubectl get pods: 查看 pod ,可以发现 Job 创建的 pod 正在运行

NAME                    READY   STATUS        RESTARTS   AGE
batch-job-d59js         1/1     Running       0          10s

kubectl get pods: 等两分钟后再查看 pod ,可以发现 Job 创建的 pod 状态已经变为 Completed ,即任务已经完成。 pod 未被删除,所以我们可以查看 pod 的日志

NAME                    READY   STATUS        RESTARTS   AGE
batch-job-d59js         0/1     Completed     0          2m56s

kubectl logs pod batch-job-d59js: 查看 pod 的日志

Sun Jun  7 22:36:04 UTC 2020 Batch job starting
Sun Jun  7 22:38:04 UTC 2020 Finished succesfully

kubectl get jobs: 再次查看 job ,可以发现需要运行的 1 个 pod 已经完成

NAME        COMPLETIONS   DURATION   AGE
batch-job   1/1           2m45s      6m25s

在 Job 中运行多个 pod 实例
在 Job 配置中设置 spec.completions 和 spec.parallelism 可以让 Job 创建多个 pod 实例,并允许以并行的方式运行它们。
基于 batch-job.yaml 创建一个新的描述文件 multi-completion-parallel-batch-job.yaml ,并添加 spec.completions 和 spec.parallelism 属性,指定需要成功运行完成 5 个 pod ,最多 2 个 pod 并行运行 : P115

spec:
  # 必须确保 5 个 pod 运行完成
  completions: 5
  # 最多 2 个 pod 可以并行运行
  parallelism: 2

kubectl create -f multi-completion-parallel-batch-job.yaml: 根据描述文件创建指定的 Job

kubectl get pods: 查看运行的 pod ,可以发现共有两个 pod 正在运行。只要一个 pod 运行完成, Job 将运行下一个 pod ,直至 5 个 pod 都成功完成


NAME                                        READY   STATUS        RESTARTS   AGE
multi-completion-parallel-batch-job-fpwv5   1/1     Running       0          37s
multi-completion-parallel-batch-job-m4cqw   1/1     Running       0          37s

限制 Job pod 完成任务的时间
Pod.spec.activeDeadlineSeconds: 可以指定一个 pod 最长存活时间,超时则终止 pod 并标记 Job 失败,可以用来限制 pod 完成任务的时间
Job.spec.backoffLimit: 可以配置一个 Job 在被标记为失败前最多尝试的次数,默认为 6 次
安排 Job 定期运行或在将来运行一次
创建一个 CronJob
为了每 15 分钟运行一次前面的任务,我们需要创建以下 cronjob.yaml 描述文件:

# 遵循 batch/v1beta1 版本的 Kubernetes API
apiVersion: batch/v1beta1
# 资源类型为 CronJob
kind: CronJob
metadata:
  # Job 的名称
  name: batch-job-every-fifteen-minutes
spec:
  # Cron 表达式表明当前任务在每天每小时的 0, 15, 30, 45 分运行
  schedule: "0,15,30,45 * * * *"
  # 指定最迟必须在预定时间后 15 秒内开始运行,否则就标记为一次失败的 `Job`
  startingDeadlineSeconds: 15
  # 创建 Job 使用的模版(可以发现和 batch-job.yaml 的 spec 部分基本一致)
  jobTemplate:
    spec:
      # 启动 pod 使用的模版
      template://加入Java开发交流君样:756584822一起吹水聊天
        metadata:
          # 指定标签为 app=periodic-batch-job
          labels:
            app: periodic-batch-job
        spec:
          # Job 不能使用 Always 为默认的重启策略
          restartPolicy: OnFailure
          containers:
            # 容器的名称
            - name: main
              # 创建容器所使用的镜像
              image: idealism/batch-job

kubectl get cronjobs: 可以查看所有的 CronJob

NAME                              SCHEDULE             SUSPEND   ACTIVE   LAST SCHEDULE   AGE
batch-job-every-fifteen-minutes   0,15,30,45 * * * *   False     0        <none>          8s

CronJob 总是为计划中配置的每个执行创建一个 Job ,但可能会有以下两种问题:

同时创建两个 Job :保证任务是幂等的
没有创建 Job :保证下一个任务能运行完成错过的任何工作

image

最新2020整理收集的一些高频面试题(都整理成文档),有很多干货,包含mysql,netty,spring,线程,spring cloud、jvm、源码、算法等详细讲解,也有详细的学习规划图,面试题整理等,需要获取这些内容的朋友请加Q君样:756584822

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值