1

背景:

在日常运维工作中,我们需要管理和操作大量的配置文件,这在使用 Kubernetes 集群管理应用时尤为常见。Kubernetes 提供了一个名为 ConfigMap 的资源对象,它用于存储应用的配置信息。有时,我们需要查找哪些 ConfigMap 包含特定的配置值,例如一个特定的 IP 地址或者字符串。在这篇技术博客中,我将演示如何使用 kubectljq 工具来高效地搜索含有特定值的 ConfigMaps。
前面已经完成了:kubectl获取ConfigMap导出YAML时如何忽略某些字段kubectl获取命名空间下所有configmap集合的方法在Kubernetes中优雅地导出和清理Ingress资源。现在继续去扩展一下jq的用户

使用 kubectl 和 jq 搜索 ConfigMaps

kubectl 是 Kubernetes 的命令行工具,使用者可以通过它与 Kubernetes 集群进行交互。jq 是一个轻量级且灵活的命令行 JSON 处理器。结合这两个工具可以让我们更加方便地处理 JSON 格式的输出。

下面是我的一个应用场景:我有命令空间下confgimap中引用了10.0.4.65,我想要知道我在那个命名空间,那一个cm中使用了该变量内容,应该如何操作呢?

kubectl get cm --all-namespaces -o json | jq -r '.items[] | select(.data and (.data[] | contains("10.0.4.65"))) | "\(.metadata.namespace) \(.metadata.name)"'

image.png
这个命令做了什么:

  1. kubectl get cm --all-namespaces -o json:获取集群中所有命名空间的 ConfigMaps,并以 JSON 格式输出。
  2. jq -r:使用 jq 进行原样(raw)格式化处理,并传入后续查询。
  3. .items[]:遍历 JSON 中的 items 数组。
  4. select(.data and (.data[] | contains("10.0.4.65"))):选择具有 data 字段的 items,并且该字段中包含特定字符串 "10.0.4.65"。
  5. "\(.metadata.namespace) \(.metadata.name)":输出每个匹配项的命名空间和名称。

发散思维:其他用法和场景

过滤特定命名空间的 ConfigMap

有时候我们只需关注特定命名空间的配置信息:

kubectl get cm -n mynamespace -o json | jq -r '.items[] | select(.data and (.data[] | contains("10.0.4.65"))) | .metadata.name'

在这个命令中,-n mynamespace 参数确保只有 mynamespace 命名空间中的 ConfigMaps 被获取。

查找使用特定镜像的 Deployment

可能我们还想知道正在哪些 Deployment 中使用了特定的镜像:

kubectl get deploy --all-namespaces -o json | jq -r '.items[] | select(.spec.template.spec.containers[].image | contains("myimage:mytag")) | "\(.metadata.namespace) \(.metadata.name)"'

这个查询会返回所有使用名为 "myimage:mytag" 镜像的 Deployment 的命名空间和名称。

检查资源限制

我们还可以检查哪些 Pod 被设置了特定的资源限制,例如内存使用限制:

kubectl get po --all-namespaces -o json | jq -r '
  .items[] |
  select(
    .spec.containers[]?.resources?.limits?.memory // "" | contains("500Mi")
  ) | "\(.metadata.namespace) \(.metadata.name)"'

image.png

此处我们搜索那些内存限制设为 "500Mi" 的 Pod。
jq 是一个功能强大的轻量级命令行 JSON 处理器,它在 Kubernetes 环境管理中充当了一个不可或缺的角色。通过结合 kubectl 的输出和 jq 的处理能力,运维工程师可以快速发现和处理集群中的数据。本节将进一步探讨 jq 的其他高级用法,帮助技术人员优化日常工作流程。

使用 jq 过滤和映射数据

映射数据属性

jq 可以将 JSON 对象中的数据映射到一个新的结构中去。例如,我们可能想要提取所有 ConfigMaps 的名称和创建时间:

kubectl get cm --all-namespaces -o json | jq -r '.items[] | {name: .metadata.name, creationTime: .metadata.creationTimestamp}'

这个命令会创建一个新的 JSON 对象,每个对象包含 namecreationTime 两个字段。
image.png

使用 jq 函数

jq 有一组内建的函数可以用来处理数据。若要对时间戳进行格式化,我们可以使用 fromdate 函数:

kubectl get cm --all-namespaces -o json | jq -r '.items[] | {name: .metadata.name, creationTime: (.metadata.creationTimestamp | fromdate)}'

这里,我们将 ISO 8601 格式的时间戳转换成 Unix 时间戳格式。
image.png

过滤特定的字段

jq 允许您选择性地查看所需的特定字段。例如,若要在输出中只包含特定名称的 ConfigMaps:

kubectl get cm --all-namespaces -o json | jq -r '.items[] | select(.metadata.name | test("deploy.*")) | .metadata.name'

image.png

统计数量

如果您想统计匹配特定条件的 ConfigMaps 的数量,可以使用 jq

kubectl get cm --all-namespaces -o json | jq '[.items[] | select(.data and (.data[] | contains("10.0.4.65")))] | length'

此命令返回一个数组,包含所有满足条件的 ConfigMaps,并使用 length 获取其数量。
image.png

对 JSON 数组和对象进行高级操作

排序和唯一化

jq 可以对数组进行排序,同时删除重复元素:

kubectl get pods --all-namespaces -o json | jq '[.items[] | {name: .metadata.name, namespace: .metadata.namespace, timestamp: .metadata.creationTimestamp}] | unique_by(.name, .namespace) | sort_by(.timestamp)'

如此一来,我们得到了一个按创建时间排序,并且包含唯一 Pod 名称的列表。

分组和分类

集群中的资源可以按照一定的属性进行分组。比如,我们想按照命名空间对 Pods 进行分组:

kubectl get pods --all-namespaces -o json | jq '[.items | group_by(.metadata.namespace)[] | {namespace: (.[0].metadata.namespace), pods: map(.metadata.name)}]'

该命令返回每个命名空间的 Pod 名称列表。
image.png

进行复杂查询的 jq 脚本

对于更复杂的查询,我们可以编写一小段 jq 脚本。例如,我们想要获取所有 ConfigMaps 并对其进行某些复杂的转换:

kubectl get cm --all-namespaces -o json | jq 'include "my_jq_lib"; .items[] | my_complex_transformation'

这里,my_jq_lib 是包含我们自定义的 jq 函数的脚本,而 my_complex_transformation 是我们定义的具体转换函数。
注:这里是chatgpt帮生成的没有使用过这种脚本的方式

结论

使用 kubectljq 可以大幅简化 Kubernetes 的配置管理和搜索工作。在本文中,我们探讨了如何搜索包含特定配置值的 ConfigMaps,并且讨论了一些其他实用场景。这些工具的强大组合为运维人员提供了灵活性和效率,使其能够更好地管理和操作 Kubernetes 集群的资源。随着需求的不断变化,我们也应该不断探索这些工具的新用法,以适应不断变化的技术挑战。


对你无可奈何
40 声望12 粉丝