监控Kubernetes Job

16

我有一些Kubernetes作业,需要不同的时间才能完成,大约在4到8分钟之间。是否有方法可以知道作业何时完成,而不是等待8分钟假设是最坏情况。我有一个测试用例,执行以下操作:

1) Submits the kubernetes job.
2) Waits for its completion.
3) Checks whether the job has had the expected affect.

问题是,在我的Java测试中,我提交了在Kubernetes中部署作业的任务,即使作业完成所需时间少于8分钟,我仍需要等待8分钟,因为我没有办法从Java测试中监视作业的状态。

7个回答

14
$ kubectl wait --for=condition=complete --timeout=600s job/myjob

3
工作可能会失败并永远无法完成......在这种情况下,您的命令将会被卡住数分钟(timeout = 600秒),而不是返回结果。 - collimarco

7
<kube master>/apis/batch/v1/namespaces/default/jobs 

端点列表显示作业的状态。我已经解析了这个JSON并检索出以“deploy…”开头的最新正在运行的作业的名称。

然后我们可以访问

<kube master>/apis/batch/v1/namespaces/default/jobs/<job name retrieved above>

当作业成功时,请监视以下状态字段值。
"status": {
    "conditions": [
      {
        "type": "Complete",
        "status": "True",
        "lastProbeTime": "2016-09-22T13:59:03Z",
        "lastTransitionTime": "2016-09-22T13:59:03Z"
      }
    ],
    "startTime": "2016-09-22T13:56:42Z",
    "completionTime": "2016-09-22T13:59:03Z",
    "succeeded": 1
  }

所以我们会不断轮询此端点,直到其完成。希望这能帮助到某些人。

3
你可以使用NewSharedInformer方法来监视作业的状态。如果不确定如何在Java中编写它,这里是一个Go语言示例,以便定期获取作业列表:
type ClientImpl struct {
    clients *kubernetes.Clientset
}

type JobListFunc func() ([]batchv1.Job, error)

var (
    jobsSelector = labels.SelectorFromSet(labels.Set(map[string]string{"job_label": "my_label"})).String()
)


func (c *ClientImpl) NewJobSharedInformer(resyncPeriod time.Duration) JobListFunc {
    var once sync.Once
    var jobListFunc JobListFunc

    once.Do(
        func() {
            restClient := c.clients.BatchV1().RESTClient()
            optionsModifer := func(options *metav1.ListOptions) {
                options.LabelSelector = jobsSelector
            }
            watchList := cache.NewFilteredListWatchFromClient(restClient, "jobs", metav1.NamespaceAll, optionsModifer)
            informer := cache.NewSharedInformer(watchList, &batchv1.Job{}, resyncPeriod)

            go informer.Run(context.Background().Done())

            jobListFunc = JobListFunc(func() (jobs []batchv1.Job, err error) {
                for _, c := range informer.GetStore().List() {
                    jobs = append(jobs, *(c.(*batchv1.Job)))
                }
                return jobs, nil
            })
        })

    return jobListFunc
}

然后在您的显示器上,您可以通过排列作业列表来检查其状态:

func syncJobStatus() {
    jobs, err := jobListFunc()
    if err != nil {
        log.Errorf("Failed to list jobs: %v", err)
        return
    }

    // TODO: other code

    for _, job := range jobs {
        name := job.Name
        // check status...
    }
}

2
我发现在使用job.getStatus()进行轮询时,JobStatus没有得到更新。 即使在使用kubectl从命令提示符中检查时状态更改了。
为了解决这个问题,我重新加载了作业处理程序。
client.extensions().jobs()
                   .inNamespace(myJob.getMetadata().getNamespace())
                   .withName(myJob.getMetadata().getName())
                   .get();

我的循环检查工作状态的代码如下:
KubernetesClient client = new DefaultKubernetesClient(config);
Job myJob = client.extensions().jobs()
                  .load(new FileInputStream("/path/x.yaml"))
                  .create();
boolean jobActive = true;
while(jobActive){
    myJob = client.extensions().jobs()
            .inNamespace(myJob.getMetadata().getNamespace())
            .withName(myJob.getMetadata().getName())
            .get();
    JobStatus myJobStatus = myJob.getStatus();
    System.out.println("==================");
    System.out.println(myJobStatus.toString());
         
    if(myJob.getStatus().getActive()==null){
        jobActive = false;
    }
    else {
        System.out.println(myJob.getStatus().getActive());
        System.out.println("Sleeping for a minute before polling again!!");
        Thread.sleep(60000);
    }
}

System.out.println(myJob.getStatus().toString());

希望这能有所帮助。

1

您没有提到实际检查作业完成情况的方式,但是不要盲目等待并希望一切顺利,应该在循环中不断轮询作业状态,直到它变为“已完成”。


抱歉,我在问题中应该提到我想从Java测试中监控它。我会编辑问题的。 - trial999
1
我不知道你使用的客户端库是什么,但测试的逻辑应该与我解释的相同:轮询作业状态,在Json响应中检查作业状态,重试直到此状态等于“已完成”。 - Antoine Cotten
你说得对。我采纳了你的建议,并在下面详细说明了我的解决方案。 - trial999

1

既然你说是Java,你可以使用fabric8的Kubernetes Java绑定来启动作业并添加一个监视器:

KubernetesClient k = ...
k.extensions().jobs().load(yaml).watch (new Watcher <Job>() {
    
  @Override
  public void onClose (KubernetesClientException e) {}
      
  @Override
  public void eventReceived (Action a, Job j) {
    if(j.getStatus().getSucceeded()>0)
      System.out.println("At least one job attempt succeeded");
    if(j.getStatus().getFailed()>0)
      System.out.println("At least one job attempt failed");
  }
});

0

我不知道你在谈论什么类型的任务,但假设你正在运行一些容器。

你可以进行以下操作:

watch 'kubectl get pods | grep <name of the pod>'

或者

kubectl get pods -w

当然它不会是完整的名称,因为大多数情况下,如果您运行nginx副本或部署,您的pod将以类似nginx-1696122428-ftjvy的某个名称结尾,所以您需要执行的操作是:

watch 'kubectl get pods | grep nginx'

您可以将pods替换为您正在进行的任何工作,例如(rc、svc、deployments等)


1
甚至更好的是,您可以使用标签:watch 'kubectl get pods -l job=foobar'kubectl get -w pods -l job=foobar - Tim Hockin
这很好,如果我连接到盒子,但是我正在尝试从Java测试中获取作业的状态。抱歉,我应该在问题中提到它。现在已经编辑过了。 - trial999
我正在考虑以某种方式ssh进入kube盒子,然后观察作业的状态。但如果有人知道可以监视作业状态的端点,即使作业尚未完成,那就太好了。 - trial999
抱歉来晚了,我本来就想像@trial999一样告诉你有关API的事情,而且你不需要SSH到kube盒子,只需配置kubectl连接到你的主节点即可。 - Ahmad Aabed
1
Kubernetes任务是一种特殊类型的工作,类似于Pod但具有不同的范围。我相信作者正在询问任务(https://kubernetes.io/docs/tasks/job/)。 - cgseller

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接