简介
在「Kubernetes 入门」实验中,你使用过 kubectl get、describe 和标签来确认应用是否正常运行。实际集群通常包含大量对象,因此下一项重要技能是提出范围更小的问题,只提取真正需要的证据。
在本实验中,你将部署一个小型商城工作负载,并从多个角度对其进行检查:命名空间、标签、结构化字段、控制器所有权和事件。最后,你将组合出一条简洁的命令,将 Deployment 与它管理的 Pod 关联起来。
你不需要记住所有输出格式。更重要的是练习将问题转换为范围明确的查询,例如:「有哪些对象存在?」「哪些 Pod 匹配这个 Service?」「谁拥有这个 Pod?」「最近发生了什么?」每个步骤都会为这套检查流程增加一个工具。
创建专用工作区
在本步骤中,你将创建一个命名空间,并将预先准备好的资源部署到其中。命名空间可以缩小后续查询的范围,避免混淆名称相同或相似的对象。
进入实验工作区,然后在修改集群状态前检查当前上下文。cd 会改变 Shell 的工作目录,因此后续使用 storefront.yaml 等相对路径时,都会指向预先准备好的工作区。
cd /home/labex/project/resource-inspection
kubectl config current-context
输出应为 labex-v135。创建命名空间,并应用预先准备好的多文档清单:
kubectl create namespace practice-observe
kubectl apply -f storefront.yaml
kubectl rollout status deployment/storefront -n practice-observe --timeout=60s
最后几行应类似下面这样。两个 Pod 启动期间,可能会显示其他中间滚动更新信息:
namespace/practice-observe created
deployment.apps/storefront created
service/storefront created
deployment "storefront" successfully rolled out
-n practice-observe 会将命令限制在该命名空间内。滚动更新命令会等待 Deployment 的两个副本都可用,而不是依赖任意设置的等待时间。
后续你会反复使用 -n practice-observe。否则,Kubernetes 命令会使用当前上下文中配置的命名空间——通常是 default。如果查询了错误的范围,即使对象运行正常,也可能看起来像是「不存在」。
发现资源及其作用域
在本步骤中,你将先使用 API 发现功能,再查询具体对象。kubectl api-resources 会列出当前 API 服务器支持的资源名称、简称,以及每种资源是否属于命名空间作用域。通过管道传给 head,可以只显示前 10 行,避免大量内容刷满终端。
kubectl api-resources | head
kubectl api-resources --namespaced=true | grep -E 'pods|deployments|services'
管道会将资源列表传递给 grep。-E 启用 | 或匹配功能,因此一条命令就可以匹配多个资源名称。注意,Pod、Deployment 和 Service 都属于命名空间作用域。
先使用完整名称列出应用对象,再使用常见简称重复查询:
kubectl get pods,deployments,services -n practice-observe
kubectl get po,deploy,svc -n practice-observe
这两条命令访问的是同一组 API 资源。简称可以减少输入,但在脚本和文档中,完整名称通常更清晰。
你应该看到一个 Deployment、两个自动生成的 Pod,以及一个 Service。用逗号分隔资源名称只是查询上的便利方式;这些对象仍然具有不同的职责和 API 结构。
输出中的资源类型前缀有助于理解合并后的结果。自动生成的后缀、地址和运行时间会有所不同:
NAME READY STATUS RESTARTS AGE
pod/storefront-... 1/1 Running 0 ...
pod/storefront-... 1/1 Running 0 ...
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/storefront 2/2 2 2 ...
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/storefront ClusterIP ... <none> 80/TCP ...
使用标签和选择器进行筛选
在本步骤中,你将使用标签作为可查询的元数据。--show-labels 会显示所有标签,而 -l 只选择标签符合指定表达式的对象。
kubectl get pods -n practice-observe --show-labels
kubectl get pods -n practice-observe -l app=storefront
kubectl get pods -n practice-observe -l 'app=storefront,tier=web'
选择器条件之间的逗号表示逻辑 与。因此,最后一条查询只会返回同时包含这两个标签的 Pod。
比较 Service 的选择器和筛选出的 Pod 标签:
kubectl get service storefront -n practice-observe -o jsonpath='Service selector: {.spec.selector.app}{"\n"}'
kubectl get pods -n practice-observe -l app=storefront -o custom-columns='NAME:.metadata.name,TIER:.metadata.labels.tier,IP:.status.podIP,READY:.status.containerStatuses[0].ready'
kubectl get endpointslices -n practice-observe -l kubernetes.io/service-name=storefront
JSONPath 会从 Service 中提取一个字段。-o custom-columns 会根据多个 Pod 字段生成紧凑的表格。与其在很长的 YAML 文档中手动查找,这种方式更加可靠。
最后一条命令会查询 EndpointSlice,其自动管理的 kubernetes.io/service-name 标签属于 storefront。EndpointSlice 记录了 Service 所选择的网络端点。只要 ENDPOINTS 列非空,就说明匹配的标签已经产生了可路由的后端。
Service 的选择器应输出 storefront,Pod 表格中的两行都应包含 tier=web。匹配的 app 标签就是连接点:Service 通过标签发现 Pod,而不是通过 Deployment 的所有权关系发现 Pod。
Service selector: storefront
NAME TIER IP READY
storefront-... web 10.244... true
storefront-... web 10.244... true
NAME ADDRESSTYPE PORTS ENDPOINTS AGE
storefront-... IPv4 80 10.244...,10.244... ...
追踪控制器所有权
在本步骤中,你将沿着 Deployment、ReplicaSet 和 Pod 之间的所有权关系进行追踪。控制器会附加 ownerReferences,让 Kubernetes 知道哪个上层对象负责管理每个从属对象。
kubectl get replicasets -n practice-observe -l app=storefront
kubectl get replicasets -n practice-observe -l app=storefront -o custom-columns='REPLICASET:.metadata.name,OWNER_KIND:.metadata.ownerReferences[0].kind,OWNER_NAME:.metadata.ownerReferences[0].name'
kubectl get pods -n practice-observe -l app=storefront -o custom-columns='POD:.metadata.name,OWNER_KIND:.metadata.ownerReferences[0].kind,OWNER_NAME:.metadata.ownerReferences[0].name'
ReplicaSet 的所有者应为 storefront Deployment。每个 Pod 的直接所有者都是自动生成的 ReplicaSet,而不是 Deployment:
Deployment/storefront -> ReplicaSet/storefront-... -> Pod/storefront-...
如果你需要同时查看这种关系、资源状态和最近事件,可以使用 kubectl describe:
kubectl describe deployment storefront -n practice-observe
不要每次都从头到尾阅读 describe 的全部输出。针对当前问题,应重点关注 Selector、副本数量、条件和事件。最好的检查命令,是用最少的干扰信息回答当前问题的命令。
将事件作为时间线阅读
在本步骤中,你将把事件作为按时间排序的证据进行检查。事件描述调度、镜像、容器和控制器的操作,但它们属于临时诊断信息,并不是永久的审计记录。
kubectl get events -n practice-observe --sort-by=.metadata.creationTimestamp
--sort-by 会根据字段路径对对象进行排序。先将时间线聚焦到 Deployment,再聚焦到一个指定的 Pod:
kubectl events -n practice-observe --for deployment/storefront
POD_NAME=$(kubectl get pods -n practice-observe -l app=storefront -o jsonpath='{.items[0].metadata.name}')
echo "$POD_NAME"
kubectl events -n practice-observe --for "pod/${POD_NAME}"
$(...) 是命令替换语法:Shell 会运行其中的命令,并将输出保存到 POD_NAME 中。现在,你已经拥有了一条可重复使用的检查路径:缩小命名空间范围、按标签筛选、提取字段、追踪所有者,最后查看相关的事件时间线。
控制器生成的 Pod 名称会在 Pod 被替换后发生变化,因此通过标签选择当前名称,比复制旧名称更加安全。这种模式会在后续故障排查实验中反复出现。
正常情况下,成功的生命周期通常会包含 Scheduled、Pulled、Created 和 Started。刚启动的本地集群在 Calico 准备就绪期间,也可能保留较早的 FailedCreatePodSandBox 警告。不要仅凭旧警告就断定应用仍然故障:应将其时间戳与后续正常事件进行比较,然后确认 Pod 当前的 READY 状态。时间戳和自动生成的 Pod 名称会在每次运行时变化,因此这里特意省略。
总结
你在没有扫描无关对象的情况下检查了一个 Kubernetes 应用。通过结合命名空间、标签、JSONPath、自定义列、所有者引用和事件,你将检查过程从宽泛的资源清单逐步收敛为精准的运行证据。下一项实验将把这套检查流程应用于故障 Pod 和容器。


