等待K8S作业完成

时间:2019-09-10 13:29:49

标签: amazon-web-services kubernetes azure-devops continuous-deployment kubernetes-pod

我正在寻找一种方法,等待Job部署完成后成功完成。

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

如果字段为“ Succeeded”,则CD将继续。如果它是“ Failed,则CD停止。

有人知道如何实现这一目标吗?

2 个答案:

答案 0 :(得分:1)

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

为了连接到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)

通过以上代码,我们获得了令牌 APISERVER 地址。

在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放入Task Env。 Vars,因此可以用于多个数据库迁移。 -令牌和API服务器地址在全局级别的“变量”组中。

待办事项:

    如果URL无效,则
  • curl不存在,代码为0。它需要--fail标志,但行上方仍存在0。
  • “未知”豆荚状态也应得到处理

答案 1 :(得分:1)

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

  

等待一种或多种资源的特定条件。

     

该命令占用多个资源,并等待直到指定   每个给定资源的“状态”字段中都可以看到这种情况。

仅在作业完成(或达到超时)时返回:

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