等待 K8S 作业完成

Waiting for K8S Job to finish

我正在寻找一种方法来等待作业在部署后成功完成执行。

正在通过 AWS 上 K8S 上的 CD 从 Azure DevOps 部署作业。这是 运行 一次增量数据库迁移,每次部署时使用 Fluent migrations。我需要阅读 pod.status.phase 字段。

如果字段是“Succeeded”,那么CD会继续。如果是“Failed”,CD停止。

有人知道如何实现吗?

我们可以使用 K8S Rest 查看 Pod 状态 API。

为了连接到 API,我们需要获得一个令牌: https://kubernetes.io/docs/tasks/administer-cluster/access-cluster-api/#without-kubectl-proxy

# Check all possible clusters, as you .KUBECONFIG may have multiple contexts:
kubectl config view -o jsonpath='{"Cluster name\tServer\n"}{range .clusters[*]}{.name}{"\t"}{.cluster.server}{"\n"}{end}'

# Select name of cluster you want to interact with from above output:
export CLUSTER_NAME="some_server_name"

# Point to the API server refering the cluster name
APISERVER=$(kubectl config view -o jsonpath="{.clusters[?(@.name==\"$CLUSTER_NAME\")].cluster.server}")

# Gets the token value
TOKEN=$(kubectl get secrets -o jsonpath="{.items[?(@.metadata.annotations['kubernetes\.io/service-account\.name']=='default')].data.token}"|base64 -d)

从上面的代码我们获得了TOKENAPISERVER地址。

在 Azure DevOps 上,在您的目标版本上,在代理作业上,我们可以添加 Bash 任务:


#name of K8S Job object we are waiting to finish
JOB_NAME=name-of-db-job
APISERVER=set-api-server-from-previous-code
TOKEN=set-token-from-previous-code

#log APISERVER and JOB_NAME for troubleshooting
echo API Server: $APISERVER
echo JOB NAME: $JOB_NAME

#keep calling API until you get status Succeeded or Failed.
while true; do

  #read all pods and query for pod containing JOB_NAME using jq.
  #note that you should not have similar pod names with job name otherwise you will get mutiple results. This script is not expecting multiple results.
  res=$(curl -X GET $APISERVER/api/v1/namespaces/default/pods/ --header "Authorization: Bearer $TOKEN" --insecure | jq --arg JOB_NAME "$JOB_NAME" '.items[] | select(.metadata.name | contains($JOB_NAME))' | jq '.status.phase')

  if (res=="Succeeded"); then
   echo Succeeded
   exit 0
  elif (res=="Failed"); then
    echo Failed
    exit 1
  else    
    echo $res
  fi
  sleep 2
done

如果 Failed,脚本将以代码 1 退出并且 CD 将停止(如果以这种方式配置)。
如果 Succeeded,存在代码 0,CD 将继续。

在最终设置中: - 脚本是工件的一部分,我在 Agent Job 的 Bash 任务中使用它。 - 我已将 JOB_NAME 放入任务环境中。 Vars 以便它可以用于多个数据库迁移。 - 令牌和 API 服务器地址在全局级别的变量组中。

待办事项:

    如果 URL 无效,则
  • curl 不存在,代码为 0。它需要 --fail 标志,但仍然存在 0.
  • "Unknown" Pod 状态也应该被处理

我认为最好的方法是使用 kubectl wait 命令:

Wait for a specific condition on one or many resources.

The command takes multiple resources and waits until the specified condition is seen in the Status field of every given resource.

只有在Job完成(或达到超时)时才会return:

kubectl wait --for=condition=complete job/myjob --timeout=60s

如果不设置--timeout,默认等待30秒。


注意: kubectl wait 是在 Kubernetes v1.11.0 上引入的。如果您使用的是旧版本,则可以使用 kubectl get--field-selector:

创建一些逻辑

kubectl get pod --field-selector=status.phase=Succeeded