【问题标题】:Monitoring a kubernetes job监控 Kubernetes 作业
【发布时间】:2017-01-01 22:53:51
【问题描述】:

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

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

问题是在我在 kubernetes 中提交部署作业的 java 测试中,即使作业完成的时间少于该作业,我也要等待 8 分钟,因为我没有办法监控作业的状态来自 java 测试。

【问题讨论】:

    标签: kubernetes kubernetes-health-check


    【解决方案1】:
    $ kubectl wait --for=condition=complete --timeout=600s job/myjob
    

    【讨论】:

    • 作业可能会失败并且永远不会完成...在这种情况下,您的命令将卡住几分钟(超时 = 600 秒)而不是返回。
    【解决方案2】:
    <kube master>/apis/batch/v1/namespaces/default/jobs 
    

    endpoint 列出作业的状态。我已经解析了这个 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 编写,这里是定期获取工作列表的 golang 示例:

      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...
          }
      }
      

      【讨论】:

        【解决方案4】:

        我发现在使用 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());
        

        希望对你有帮助

        【讨论】:

          【解决方案5】:

          您没有提及实际检查作业完成的内容,但与其盲目等待并希望最好的结果,不如继续在循环中轮询作业status,直到它变为“已完成”。

          【讨论】:

          • 抱歉,我应该在问题中提到我想从 Java 测试中监控这一点。将编辑问题。
          • 我不知道你使用的是什么客户端库,但是测试的逻辑应该和我解释的一样:轮询作业状态,检查 Json 响应中的作业状态,重试直到此状态等于“已完成”。
          • 你是对的。我已采纳您的建议,在下方详细说明了我的解决方案。
          【解决方案6】:

          既然你说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");
            }
          });
          

          【讨论】:

            【解决方案7】:

            我不知道你在说什么类型的任务,但我们假设你正在运行一些 pod

            你可以的

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

            kubectl get pods -w
            

            这当然不是全名,因为大多数时候,如果您正在运行 nginx 副本或部署,您的 pod 会得到随机名称,您的 pod 最终会得到类似 nginx-1696122428-ftjvy 的名称,所以您会想要这样做

            watch 'kubectl get pods | grep nginx'
            

            您可以将 pods 替换为您正在做的任何工作,即(rc、svc、deployments....)

            【讨论】:

            • 你可以更好地使用标签:watch 'kubectl get pods -l job=foobar'kubectl get -w pods -l job=foobar
            • 如果我连接到盒子这很好,但是我试图从 java 测试中获取工作的状态。抱歉,我应该在问题中提到这一点。现在已经编辑过了。
            • 我正在考虑以某种方式 ssh 进入 kube 框,然后查看作业的状态。但是,如果有人知道一个端点可以被监控以查看尚未完成的作业状态,那么知道那将是很棒的。
            • 抱歉来晚了,我就像@trial999一样告诉你关于api的事情,而且你不需要ssh到kube box,只需配置kubectl连接到你的master
            • kubernetes 作业是一类特殊的工作,类似于 pod,但作用域不同。我相信作者在问工作(kubernetes.io/docs/tasks/job
            猜你喜欢
            • 2011-09-11
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多