# 实验前置准备:制造多样化数据

先拉起几个不同状态和镜像的 Pod,为我们的查询提供素材。

kubectl run pod-nginx --image=nginx
kubectl run pod-httpd --image=httpd
kubectl run pod-fail --image=busybox -- false  # 故意让它 Error/CrashLoopBackOff

等几秒钟,确保它们状态稳定。


# 核心技术逻辑:如何找路径?

这是掌握 JSONPath 的唯一正确方法:先输出纯 JSON,看清结构再写路径。

执行:kubectl get pods -o json more 你会看到最外层是一个巨大的 JSON 对象,包含一个 items 数组。每个 Pod 都是 items 里的一个元素(Go 里的 Slice)。

  • $:代表整个 JSON 根节点(在 kubectl 中可以省略)。
  • .:代表获取子节点(Struct 的字段)。
  • []:代表操作数组。[*] 表示遍历整个切片。

# 实验过程

# 阶级一:基础提取(遍历数组)

目标: 获取当前命名空间下所有 Pod 的名称。

既然我们知道数据都在 items 数组里,而名字在 metadata.name 里,命令就是:

kubectl get pods -o jsonpath='{.items[*].metadata.name}'

预期输出: pod-fail pod-httpd pod-nginx (所有名字连在了一起,中间有空格)。


# 阶级二:高级格式化(CKA 必考的 range 循环)

刚才的输出都在同一行,很不优雅,而且无法同时输出多个字段。K8s 的 JSONPath 扩展了 Go Template 的 range 语法,这是考场上的一击必杀技。

目标: 按行输出每个 Pod 的名称和它的 IP 地址,中间用 Tab 键隔开。

命令解析:

  • {range .items[*]}:开启一个 Go 切片循环。在循环内部,当前上下文就变成了单个 Pod 对象。
  • {.metadata.name}:获取名字。
  • {"\t"}:插入一个 Tab 制表符。
  • {.status.podIP}:获取 IP。
  • {"\n"}:插入一个换行符。
  • {end}:结束循环。
kubectl get pods -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.status.podIP}{"\n"}{end}'

预期输出: pod-fail (可能为空,因为它挂了) pod-httpd 192.168.x.x pod-nginx 192.168.y.y


# 阶级三:条件过滤(Filter 表达式)

这是最高阶的用法。有时候题目要求只提取满足特定条件的资源。

语法规则: ?(@.字段 == "值")

  • ?() 是过滤器的固定语法。
  • @ 代表当前正在遍历的元素自身。

目标: 只提取状态处于 Running 的 Pod 名称。

我们要在遍历 items 数组时加上条件拦截:

kubectl get pods -o jsonpath='{.items[?(@.status.containerStatuses[0].ready==true)].metadata.name}'

预期输出: 只有 pod-httpd pod-nginx,那个处于 Error/CrashLoopBackOff 的 pod-fail 被完美过滤掉了。


# 阶级四:资源排序(Sort-by)

排序其实不属于 -o jsonpath 的范畴,但经常与数据提取结合使用。它的参数直接接受一个 JSONPath 表达式。

目标: 列出所有 Node 节点,并按它们的创建时间(metadata.creationTimestamp)进行排序。

kubectl get nodes --sort-by='.metadata.creationTimestamp'

(由于你的 Master 和 Node1/Node2 是按顺序加入的,你会清楚地看到时间的先后排序)


# 🛠️ 清理战场

kubectl delete pod pod-nginx pod-httpd pod-fail