website/content/zh/docs/tasks/debug-application-cluster/debug-running-pod.md

10 KiB
Raw Blame History

title content_type
调试运行中的 Pod task

本页解释如何在节点上调试运行中(或崩溃)的 Pod。

{{% heading "prerequisites" %}}

  • 你的 {{< glossary_tooltip text="Pod" term_id="pod" >}} 应该已经被调度并正在运行中, 如果你的 Pod 还没有运行,请参阅应用问题排查

  • 对于一些高级调试步骤,你应该知道 Pod 具体运行在哪个节点上,在该节点上有权限去运行一些命令。 你不需要任何访问权限就可以使用 kubectl 去运行一些标准调试步骤。

检查 Pod 的日志

首先,查看受到影响的容器的日志:

kubectl logs ${POD_NAME} ${CONTAINER_NAME}

如果你的容器之前崩溃过,你可以通过下面命令访问之前容器的崩溃日志:

kubectl logs --previous ${POD_NAME} ${CONTAINER_NAME}

使用容器 exec 进行调试

如果 {{< glossary_tooltip text="容器镜像" term_id="image" >}} 包含调试程序, 比如从 Linux 和 Windows 操作系统基础镜像构建的镜像,你可以使用 kubectl exec 命令 在特定的容器中运行一些命令:

kubectl exec ${POD_NAME} -c ${CONTAINER_NAME} -- ${CMD} ${ARG1} ${ARG2} ... ${ARGN}

{{< note >}} -c ${CONTAINER_NAME} 是可选择的。如果Pod中仅包含一个容器就可以忽略它。 {{< /note >}}

例如,要查看正在运行的 Cassandra pod中的日志可以运行

kubectl exec cassandra -- cat /var/log/cassandra/system.log

你可以在 kubectl exec 命令后面加上 -i-t 来运行一个连接到你的终端的 Shell比如

kubectl exec -it cassandra -- sh

若要了解更多内容,可查看获取正在运行容器的 Shell

使用临时调试容器来进行调试

{{< feature-state state="alpha" for_k8s_version="v1.18" >}}

当由于容器崩溃或容器镜像不包含调试程序(例如无发行版镜像等) 而导致 kubectl exec 无法运行时,{{< glossary_tooltip text="临时容器" term_id="ephemeral-container" >}}对于排除交互式故障很有用。

使用临时容器来调试的例子

{{< note >}} 本示例需要你的集群已经开启 EphemeralContainers 特性门控 kubectl 版本为 v1.18 或者更高。 {{< /note >}}

你可以使用 kubectl alpha debug 命令来给正在运行中的 Pod 增加一个临时容器。 首先,像示例一样创建一个 pod

kubectl run ephemeral-demo --image=k8s.gcr.io/pause:3.1 --restart=Never

{{< note >}} 本节示例中使用 pause 容器镜像,因为它不包含任何用户级调试程序,但是这个方法适用于所有容器镜像。 {{< /note >}}

如果你尝试使用 kubectl exec 来创建一个 shell你将会看到一个错误因为这个容器镜像中没有 shell。

kubectl exec -it ephemeral-demo -- sh
OCI runtime exec failed: exec failed: container_linux.go:346: starting container process caused "exec: \"sh\": executable file not found in $PATH": unknown

你可以改为使用 kubectl alpha debug 添加调试容器。 如果你指定 -i 或者 --interactive 参数,kubectl 将自动挂接到临时容器的控制台。

kubectl alpha debug -it ephemeral-demo --image=busybox --target=ephemeral-demo
Defaulting debug container name to debugger-8xzrl.
If you don't see a command prompt, try pressing enter.
/ #

此命令添加一个新的 busybox 容器并将其挂接到该容器。--target 参数指定另一个容器的进程命名空间。 这是必需的,因为 kubectl run 不能在它创建的pod中启用 共享进程命名空间

{{< note >}} {{< glossary_tooltip text="容器运行时" term_id="container-runtime" >}}必须支持--target参数。 如果不支持,则临时容器可能不会启动,或者可能使用隔离的进程命名空间启动。 {{< /note >}}

你可以使用 kubectl describe 查看新创建的临时容器的状态:

kubectl describe pod ephemeral-demo
...
Ephemeral Containers:
  debugger-8xzrl:
    Container ID:   docker://b888f9adfd15bd5739fefaa39e1df4dd3c617b9902082b1cfdc29c4028ffb2eb
    Image:          busybox
    Image ID:       docker-pullable://busybox@sha256:1828edd60c5efd34b2bf5dd3282ec0cc04d47b2ff9caa0b6d4f07a21d1c08084
    Port:           <none>
    Host Port:      <none>
    State:          Running
      Started:      Wed, 12 Feb 2020 14:25:42 +0100
    Ready:          False
    Restart Count:  0
    Environment:    <none>
    Mounts:         <none>
...

使用 kubectl delete 来移除已经结束掉的 Pod

kubectl delete pod ephemeral-demo

在节点上通过 shell 来调试

如果这些方法都不起作用,你可以找到运行 Pod 的主机并通过 SSH 进入该主机, 但是如果使用 Kubernetes API 中的工具,则通常不需要这样做。 因此,如果你发现自己需要使用 ssh 进入主机请在GitHub 上提交功能请求, 以描述你的用例以及这些工具不足的原因。