如何使用kubectl启动容器并返回退出码?不使用kubectl exec。

15
我的CI工具使用生命周期,所以如果开发部署成功,它就会进入QA。
我有一个端到端测试容器,想在Kubernetes中运行,但是如何从容器中获取退出代码?
是否可以通过一条命令运行容器并返回退出代码? kubectl run -it 看起来无法获得退出代码,并且在容器完成后有一些额外的信息。

你有检查过我的答案吗?它对你有帮助吗?如果是的话,请考虑接受并点赞,这样它就可以在未来帮助其他人。 - Mark Watney
没有一个答案真正帮助启动Pod,只是获取退出代码。 - tekno45
我需要一种方法来提交一个作业/ pod 并获取退出代码。但是部署和 pod 似乎会获得随机名称。我该如何获取刚刚启动的那个? - tekno45
如果您运行 kubectl run --image=busybox --attach=true --restart=Never sleep -- /bin/sh -c "sleep 10",然后再运行 echo $?,将返回 0,它指的是 pod 的执行。如果您运行 kubectl run --image=busybox --attach=true --restart=Never sleep -- /bin/sh -c "none",然后运行 echo $? 将返回 127(命令未找到)。如果这对您有帮助,请告诉我,我可以更新我的答案,包括关于此的文档参考。 - Mark Watney
6个回答

7

要从Pod(容器)获取退出代码,您可以使用以下命令获取Pod的详细信息:

kubectl get pod termination-demo --output=yaml

输出:

apiVersion: v1
kind: Pod
...
    lastState:
      terminated:
        containerID: ...
        exitCode: 0
        finishedAt: ...
        message: |
          Sleep expired
        ...

要了解更多信息,请查看文档。

如您所愿,为了简化操作,可以运行:

kubectl get pod busybox-term -ojson | jq .status.containerStatuses[].lastState.terminated.exitCode

或者如果你不想安装jq,你可以运行:

kubectl get pod busybox-term --output="jsonpath={.status.containerStatuses[].lastState.terminated.exitCode}"

3

此方法之前由mWatney提到,因此我在此处添加了一些额外的细节:

使用此方法可以从Pod返回退出代码0-255(超过255后重新开始,256==0)。

-it--restart=Never是必需的,--rm是可选的,但有助于删除失败的Pod。
--restart=Never告诉生成器创建一个Pod对象而不是Deployment。

$ kubectl run -it --rm exitcode --image=nginx --restart=Never -- bash -c "exit 0"
pod "exitcode" deleted
$ echo $?
0

$ kubectl run -it --rm exitcode --image=nginx --restart=Never -- bash -c "exit 1"
pod "exitcode" deleted
pod default/exitcode terminated (Error)
$ echo $?
1

$ kubectl run -it --rm exitcode --image=nginx --restart=Never -- bash -c "exit 8"
pod "exitcode" deleted
pod default/exitcode terminated (Error)
$ echo $?
8

$ kubectl run -it --rm exitcode --image=nginx --restart=Never -- bash -c "exit 250"
pod "exitcode" deleted
pod default/exitcode terminated (Error)
$ echo $?
250

$ kubectl run -it --rm exitcode --image=nginx --restart=Never -- bash -c "exit 255"
pod "exitcode" deleted
pod default/exitcode terminated (Error)
$ echo $?
255

$ kubectl run -it --rm exitcode --image=nginx --restart=Never -- bash -c "exit 256"
pod "exitcode" deleted
$ echo $?
0

# exit code can also be assigned to a variable
$ kubectl run -it --rm exitcode --image=nginx --restart=Never -- bash -c "exit 255" ; a=$? && echo $a
pod "exitcode" deleted
pod default/exitcode terminated (Error)
255

为 LoganMzz 进行更新:

$ kubectl run -it --rm --image=busybox --restart=Never foobar -- ash -c 'exit 10'; echo rc=$?
pod "foobar" deleted
pod default/foobar terminated (Error)
rc=10

$ kubectl version
Client Version: version.Info{Major:"1", Minor:"18", GitVersion:"v1.18.5", GitCommit:"e6503f8d8f769ace2f338794c914a96fc335df0f", GitTreeState:"clean", BuildDate:"2020-06-26T03:47:41Z", GoVersion:"go1.13.9", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"18", GitVersion:"v1.18.5", GitCommit:"e6503f8d8f769ace2f338794c914a96fc335df0f", GitTreeState:"clean", BuildDate:"2020-06-26T03:39:24Z", GoVersion:"go1.13.9", Compiler:"gc", Platform:"linux/amd64"}

$ kubectl get nodes -o wide
NAME         STATUS   ROLES    AGE    VERSION   INTERNAL-IP   EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION      CONTAINER-RUNTIME
10.10.0.21   Ready    master   2d1h   v1.18.5   10.10.0.21    <none>        Ubuntu 16.04.6 LTS   4.4.0-184-generic   docker://18.9.7
10.10.0.22   Ready    <none>   2d1h   v1.18.5   10.10.0.22    <none>        Ubuntu 16.04.6 LTS   4.4.0-184-generic   docker://18.9.7

使用 kubectl run -it --rm --image=busybox --restart=Never foobar -- ash -c 'exit 10'; echo rc=$?' 命令,我得到了 pod "foobar" deleted+Error from server (NotFound): pods "foobar" not found+rc=1` 的输出。 - LoganMzz

2

我建议采用 @mark-watney 回答中的 jsonpath 方法,因为您不需要任何额外的工具。但是,如果您有多个容器,则需要添加过滤器。例如:

kubectl get pods pod-name -o jsonpath='{.status.containerStatuses[?(@.name=="container-name")].state.terminated.exitCode}'

0
kubectl get po pod_name -ojson | jq .status.containerStatuses[].state.terminated.exitCode

虽然这段代码可能可以回答问题,但最好还是包括一些上下文解释它的工作原理以及何时使用它。仅有代码的答案从长远来看并不实用。 - Mustafa

0

我想在一个临时的 Pod 中运行一个命令,以验证我的网络策略是否正确。容器内运行的命令的退出代码应该指示访问是允许还是拒绝的。例如:

    kubectl run --rm -it --image centos:7 --restart=Never xxx -- exit 1
    kubectl get pod xxx -ojson | jq .status.containerStatuses[].state.terminated.exitCode

将 'exit 1' 替换为实现我的检查的命令。

但是,当使用 --rm 运行容器时,由于 POD 在命令之后不再存在,因此无法检索退出状态。唯一的解决方法是不使用 --rm 选项,并在命令后清理临时 pod。

另一个更好的选择是从命令中回显输出字符串,然后检查输出。命令可以使用 'trap' 捕获任何退出并回显退出状态。

    trap 'echo EXITCODE $?; exit' EXIT

以上,EXIT捕获任何退出,并且'exit'使用原始退出代码退出。 然后使用以下命令获取退出代码。
  code="$( kubectl ... | awk '/EXITCODE/ { print $2 }')" 

0
您可以将 kubectl get 的输出导入 jq,它可以解析 JSON 并打印出退出代码,如果只有一个容器,您可以跳过 -c container_name
kubectl get pod pod_name -c container_name-n namespace -ojson | jq .status.containerStatuses[].state.terminated.exitCode

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