等待 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)
从上面的代码我们获得了TOKEN和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 放入任务环境中。 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
我正在寻找一种方法来等待作业在部署后成功完成执行。
正在通过 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)
从上面的代码我们获得了TOKEN和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 放入任务环境中。 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