为Kubernetes作业处理长时间运行的initContainers

olmpazwi  于 2023-08-03  发布在  Kubernetes
关注(0)|答案(1)|浏览(135)

在最近升级到GKE 1.26之后,我开始遇到一个与Kubernetes作业相关的问题,该作业在历史上一直运行得很顺利。
作业本身包含两个组件:

  • 一个简单的initContainer,只是对API/服务进行健康检查,有时在启动时需要一些时间来响应(有时大约10分钟)
  • 处理逻辑和对所述API服务的各种调用的脚本

简单地说,它看起来像以下内容(为了简洁起见,省略了一些内容):

apiVersion: batch/v1
kind: Job
metadata:
  name: my-job-{{ now | date "20060102150405" }}
  labels:
    app: my-job
spec:
  backoffLimit: 0
  template:
    metadata:
      labels:
        app: my-job
      annotations:
        "cluster-autoscaler.kubernetes.io/safe-to-evict": "true"
    spec:
      restartPolicy: Never
      ...
      initContainers:
      - name: wait-service
        ...
        command: ['bash', '-c', 'while [[ "$(curl -s -o /dev/null -w ''%{http_code}'' http://someService/api/v1/status)" != "200" ]]; do echo waiting for service; sleep 2s; done']
      containers:
        - name: run-job
          ...
      volumes:
          ...
      tolerations: 
          ...

字符串

**我遇到的问题是,在部署后约5分钟,当initContainer正在运行并等待服务时,Kubernetes将创建作业的新示例(包括自己的initContainer等)**这是有问题的,主要是因为在主容器(run-job)中运行的脚本的两个示例很容易导致其中的操作失去同步/进入不良状态(脚本涉及通过API以特定顺序暂停和恢复各种服务)。

我可以在原始作业的日志中验证这一点:

│ wait-service waiting for service 
| failed container "run-job" in pod "my-job-20230721165715-rh6s2" is waiting to start: PodInitializing for .../my-job-20230721165715-rh6s2 (run-job)                            
| wait-service waiting for service


因此,在这个作业的新部署大约5分钟后,我运行了它的两个示例(与上面失败的容器消息一致)。这通常以它们中的一个或两个处于不良状态而结束。
我尝试了一些配置更改,但收效甚微,我想知道处理此问题的最佳方法是什么?本质上,我需要为initContainer提供足够的容忍度,这样它就不会触发上述故障并重新创建一个新的作业(而是继续使用原始示例)。

yi0zb3m4

yi0zb3m41#

由于您使用helm,并且您已经使用时间戳名称(my-job-{{ now | date "20060102150405" }})命名了作业,因此每次安装helm时都会创建一个新的作业,但这与升级时可能正在运行或未运行的现有作业没有任何联系。
如果要确保在部署时终止现有作业,则应考虑在应用升级之前使用升级前挂接删除应用程序命名空间中的任何现有作业。
更新1
我已经启动了一个1.26集群,并使用了您的示例(为了让它运行,做了一些调整),让它运行了10分钟,没有得到额外的job或pod。
然而,与此同时,您可以做的是向后跟踪Pod,以找出是什么“拥有”它们。如果你输入kubectl describe {pod},你会在输出中看到一阅读“Controlled by”。举例来说:

Controlled By:  Job/example-service-deploy-jobs-20230722170514

字符串
如果您看到两个Pod,请描述这两个Pod并查看是否引用了相同的作业。如果两个pod都指向同一个作业,那么这个作业就产生了两个pod--这通常意味着它认为第一个pod失败了,并产生了第二个pod来重试。
如果您看到引用的其他作业,则表示已部署了另一个作业,而未删除第一个作业。
描述这些作业,看看它们也有一个“受控者”字段(如果它们是由Helm安装的,或者使用kubectl apply或类似的手动部署的,它们不应该这样做)--我进行这个检查的原因是查看是否有东西(比如cronjob)正在触发一个作业。
单独提问:您的群集是如何托管的,是裸机还是托管的(AKS、EKS、GKE等?)
另一种可能性,如果您运行在托管上,则是您运行在Spot/Preemptible示例上,或者节点有其他问题。您可以在监视init容器的同时监视节点(watch kubectl get nodes)以查看它们中是否有任何一个终止--如果它们终止了,您可以开始调查节点终止的原因。
简而言之,问题不是作业本身,而是围绕它(或集群中)的其他东西。

相关问题