查看 Pod 和节点

学习如何使用 kubectl get、kubectl describe、kubectl logs 和 kubectl exec 排除 Kubernetes 应用故障。

目标

  • 了解 Kubernetes Pod。
  • 了解 Kubernetes 节点。
  • 对已部署的应用故障排除。

Kubernetes Pod

在模块 2 中创建 Deployment 时, Kubernetes 创建了一个 Pod 来托管你的应用实例。Pod 是 Kubernetes 抽象出来的, 表示一组一个或多个应用容器(如 Docker),以及这些容器的一些共享资源。这些资源包括:

  • 共享存储,当作卷
  • 网络,作为唯一的集群 IP 地址
  • 有关每个容器如何运行的信息,例如容器镜像版本或要使用的特定端口

Pod 为特定于应用的“逻辑主机”建模,并且可以包含相对紧耦合的不同应用容器。 例如,Pod 可能既包含带有 Node.js 应用的容器,也包含另一个不同的容器, 用于提供 Node.js 网络服务器要发布的数据。Pod 中的容器共享 IP 地址和端口, 始终位于同一位置并且共同调度,并在同一节点上的共享上下文中运行。

Pod 是 Kubernetes 平台上的原子单元。当我们在 Kubernetes 上创建 Deployment 时, 该 Deployment 会在其中创建包含容器的 Pod(而不是直接创建容器)。 每个 Pod 都与调度它的节点绑定,并保持在那里直到终止(根据重启策略)或删除。 如果节点发生故障,则会在集群中的其他可用节点上调度相同的 Pod。

总结:

  • Pod
  • 节点
  • Kubectl 主要命令

Pod 是一个或多个应用容器(例如 Docker)的组合,包括共享存储(卷)、IP 地址和有关如何运行它们的信息。

Pod 概览

查看 Pod 和节点 - 图1

节点

Pod 总是运行在节点上。节点是 Kubernetes 中参与计算的机器,可以是虚拟机或物理计算机,具体取决于集群。 每个节点由控制面管理。节点可以有多个 Pod,Kubernetes 控制面会自动处理在集群中的节点上调度 Pod。 控制面的自动调度考量了每个节点上的可用资源。

每个 Kubernetes 节点至少运行:

  • Kubelet,负责 Kubernetes 控制面和节点之间通信的进程;它管理机器上运行的 Pod 和容器。
  • 容器运行时(如 Docker)负责从镜像仓库中提取容器镜像、解压缩容器以及运行应用。

如果容器紧耦合并且需要共享磁盘等资源,则只应将其编排在一个 Pod 中。

节点概览

查看 Pod 和节点 - 图2

使用 kubectl 进行故障排除

在模块 2 中, 你使用了 kubectl 命令行界面。你将继续在第 3 个模块中使用 kubectl 来获取有关已部署应用及其环境的信息。 最常见的操作可以使用以下 kubectl 子命令完成:

  • kubectl get - 列出资源
  • kubectl describe - 显示有关资源的详细信息
  • kubectl logs - 打印 Pod 中容器的日志
  • kubectl exec - 在 Pod 中的容器上执行命令

你可以使用这些命令查看应用的部署时间、当前状态、运行位置以及配置。

现在我们了解了有关集群组件和命令行的更多信息,让我们来探索一下我们的应用。

节点是 Kubernetes 中负责计算的机器,可能是虚拟机或物理计算机,具体取决于集群。 多个 Pod 可以在一个节点上运行。

检查应用配置

让我们验证之前场景中部署的应用是否在运行。我们将使用 kubectl get 命令查看现存的 Pod:

kubectl get pods

如果没有 Pod 在运行,请等几秒,让 Pod 再次列出。一旦看到一个 Pod 在运行,就可以继续操作。

接下来,要查看 Pod 内有哪些容器以及使用了哪些镜像来构建这些容器,我们运行 kubectl describe pods 命令:

kubectl describe pods

我们在这里看到了 Pod 的容器相关详情:IP 地址、使用的端口以及 Pod 生命期有关的事件列表。

describe 子命令的输出宽泛,涵盖了一些我们还未讲到的概念,但不用担心, 这节课结束时你就会熟悉这些概念了。

注:describe子命令可用于获取有关大多数 Kubernetes 原语的详细信息, 包括节点、Pod 和 Deployment。describe 的输出设计为人类可读的信息,而不是脚本化的信息。

在终端中显示应用

回想一下,Pod 运行在隔离的、私有的网络中,因此我们需要代理访问它们,这样才能进行调试和交互。 为了做到这一点,我们将使用 kubectl proxy 命令在第二个终端中运行一个代理。 打开一个新的终端窗口,在这个新的终端中运行以下命令:

**kubectl proxy**

现在我们再次获取 Pod 命令并直接通过代理查询该 Pod。 要获取 Pod 命令并将其存到 POD_NAME 环境变量中,运行以下命令:

**export POD_NAME="$(kubectl get pods -o go-template --template '{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}')"**
**echo Name of the Pod: $POD_NAME**

要查看应用的输出,运行 curl 请求:

**curl http://localhost:8001/api/v1/namespaces/default/pods/$POD_NAME:8080/proxy/**

URL 是到 Pod API 的路由。

查看容器日志

应用通常发送到标准输出的所有内容都成为 Pod 内容器的日志。 我们可以使用 kubectl logs 命令检索这些日志:

**kubectl logs "$POD_NAME"**

注:我们不需要指定容器名称,因为在 Pod 内只有一个容器。

在容器上执行命令

一旦 Pod 启动并运行,我们就可以直接在容器上执行命令。 为此,我们使用 exec 子命令,并将 Pod 的名称作为参数。让我们列出环境变量:

**kubectl exec "$POD_NAME" -- env**

另外值得一提的是,由于 Pod 中只有一个容器,所以容器本身的名称可以被省略。

接下来,让我们在 Pod 的容器中启动一个 bash 会话:

**kubectl exec -ti $POD_NAME -- bash**

现在我们在运行 Node.js 应用的容器上有一个打开的控制台。该应用的源代码位于 server.js 文件中:

**cat server.js**

你可以通过运行 curl 命令查看应用是否启动:

**curl http://localhost:8080**

注:在这里我们使用了 localhost,因为我们在 NodeJS Pod 内执行了此命令。 如果你无法连接到 localhost:8080,请确保你已经运行了 kubectl exec 命令,并且从 Pod 内启动了该命令。

要关闭你的容器连接,键入 **exit**

如果你准备好了,请继续学习使用服务来暴露你的应用