Kubernetes - 处理无限数量的工作项

标签 kubernetes

我需要从工作队列中获取一个工作项,然后顺序运行一系列容器来处理每个工作项。这可以使用 initContainers ( https://stackoverflow.com/a/46880653/94078 ) 来完成

重新启动流程以获得下一个工作项的推荐方法是什么?

  • 作业看起来很理想,但似乎不支持无限/不确定的完成次数。
  • 使用单个 Pod 不起作用,因为 initContainer 不会重新启动 ( https://github.com/kubernetes/kubernetes/issues/52345 )。
  • 我希望避免 argo 或 brigade 等系统的维护/学习开销。

谢谢!

最佳答案

作业应该用于处理工作队列。使用工作队列时,您不应设置 .spec.comletions (或将其设置为null)。在这种情况下,Pod 将不断创建,直到其中一个 Pod 成功退出。故意以失败状态退出(主)容器有点尴尬,但这就是规范。无论此设置如何,您都可以根据自己的喜好设置.spec.parallelism;我已将其设置为 1,因为您似乎不需要任何并行性。

在你的问题中,你没有指定如果工作队列变空你想要做什么,所以我将给出两种解决方案,一种是如果你想等待新项目(无限),另一种是如果你想结束工作,如果工作队列变空(项目数量有限,但不确定)。

两个示例都使用 Redis,但您可以将此模式应用于您最喜欢的队列。请注意,从队列中弹出项目的部分并不安全;如果您的 Pod 在弹出某个项目后由于某种原因死亡,则该项目将保持未处理或未完全处理的状态。请参阅reliable-queue pattern寻求适当的解决方案。

对我使用过的每个工作项实现顺序步骤 init containers 。请注意,这确实是一个原始的解决方案,但如果您不想使用某些框架来实现适当的管道,那么您的选择有限。

There is an asciinema if any would like to see this at work without deploying redis, etc.

Redis

要测试这一点,您至少需要创建一个 redis Pod 和一个服务。我正在使用 fine parallel processing work queue 中的示例。您可以通过以下方式部署它:

kubectl apply -f https://rawgit.com/kubernetes/website/master/docs/tasks/job/fine-parallel-processing-work-queue/redis-pod.yaml
kubectl apply -f https://rawgit.com/kubernetes/website/master/docs/tasks/job/fine-parallel-processing-work-queue/redis-service.yaml

此解决方案的其余部分要求您在与作业相同的命名空间中拥有一个名为 redis 的服务,并且不需要身份验证和一个名为 redis-master 的 Pod .

插入项目

要在工作队列中插入一些项目,请使用此命令(您需要 bash 才能使其工作):

echo -ne "rpush job "{1..10}"\n" | kubectl exec -it redis-master -- redis-cli

无限版本

如果队列为空,此版本将等待,因此它永远不会完成。

apiVersion: batch/v1
kind: Job
metadata:
  name: primitive-pipeline-infinite
spec:
  parallelism: 1
  completions: null
  template:
    metadata:
      name: primitive-pipeline-infinite
    spec:
      volumes: [{name: shared, emptyDir: {}}]
      initContainers:
      - name: pop-from-queue-unsafe
        image: redis
        command: ["sh","-c","redis-cli -h redis blpop job 0 >/shared/item.txt"]
        volumeMounts: [{name: shared, mountPath: /shared}]
      - name: step-1
        image: busybox
        command: ["sh","-c","echo step-1 working on `cat /shared/item.txt` ...; sleep 5"]
        volumeMounts: [{name: shared, mountPath: /shared}]
      - name: step-2
        image: busybox
        command: ["sh","-c","echo step-2 working on `cat /shared/item.txt` ...; sleep 5"]
        volumeMounts: [{name: shared, mountPath: /shared}]
      - name: step-3
        image: busybox
        command: ["sh","-c","echo step-3 working on `cat /shared/item.txt` ...; sleep 5"]
        volumeMounts: [{name: shared, mountPath: /shared}]
      containers:
      - name: done
        image: busybox
        command: ["sh","-c","echo all done with `cat /shared/item.txt`; sleep 1; exit 1"]
        volumeMounts: [{name: shared, mountPath: /shared}]
      restartPolicy: Never

有限版本

如果队列为空,此版本将停止作业。请注意弹出初始化容器检查队列是否为空的技巧,如果队列确实为空,则所有后续初始化容器主容器立即退出 - 这是向 Kubernetes 发出作业已执行的信号的机制已完成,无需为其创建新的 Pod。

apiVersion: batch/v1
kind: Job
metadata:
  name: primitive-pipeline-finite
spec:
  parallelism: 1
  completions: null
  template:
    metadata:
      name: primitive-pipeline-finite
    spec:
      volumes: [{name: shared, emptyDir: {}}]
      initContainers:
      - name: pop-from-queue-unsafe
        image: redis
        command: ["sh","-c","redis-cli -h redis lpop job >/shared/item.txt; grep -q . /shared/item.txt || :>/shared/done.txt"]
        volumeMounts: [{name: shared, mountPath: /shared}]
      - name: step-1
        image: busybox
        command: ["sh","-c","[ -f /shared/done.txt ] && exit 0; echo step-1 working on `cat /shared/item.txt` ...; sleep 5"]
        volumeMounts: [{name: shared, mountPath: /shared}]
      - name: step-2
        image: busybox
        command: ["sh","-c","[ -f /shared/done.txt ] && exit 0; echo step-2 working on `cat /shared/item.txt` ...; sleep 5"]
        volumeMounts: [{name: shared, mountPath: /shared}]
      - name: step-3
        image: busybox
        command: ["sh","-c","[ -f /shared/done.txt ] && exit 0; echo step-3 working on `cat /shared/item.txt` ...; sleep 5"]
        volumeMounts: [{name: shared, mountPath: /shared}]
      containers:
      - name: done
        image: busybox
        command: ["sh","-c","[ -f /shared/done.txt ] && exit 0; echo all done with `cat /shared/item.txt`; sleep 1; exit 1"]
        volumeMounts: [{name: shared, mountPath: /shared}]
      restartPolicy: Never

关于Kubernetes - 处理无限数量的工作项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49568337/

相关文章:

nginx - 尝试为 Rancher 2.X 配置 Nginx - 从 Rancher 1.x 迁移

kubernetes - Azure Kubernetes 服务 (AKS) : How to enable HTTPS between Nginx Kubernetes Ingress Controller & Asp.Net Core 6.0 WebAPI POD?

deployment - 如何在 kubernetes 中使用 yaml 文件删除和重新创建 pod

kubernetes - GKE 负载均衡器 - 入口 - 服务 - session 亲和性(粘性 session )

kubernetes - 您可以在 GKE 集群之间共享 pod 和服务 secondary_ip_range 吗?

docker - 如何最好地在多台物理机上部署一个kubernetes集群?

Kubernetes 中的 dockerhub 给出未经授权的 : incorrect username or password with right credentials

scheduling - Kubernetes DNS Pod在追风场景中竞赛用户级别Pod

linux - 如何更改我的 Kubernetes 版本

kubernetes - 如何通过iptables从外部控制对某些Nodeport的访问