一、简介

在本教程中,我们将探索使用 Kubernetes Java API 过滤资源的不同方法。

在之前介绍 Kubernetes Java API 的文章中,我们重点介绍了查询、操作和监控集群资源的可用方法。

这些示例假设我们要么正在寻找特定类型的资源,要么针对单一资源。 然而,在实践中,大多数应用程序需要一种基于某些标准来定位资源的方法。

Kubernetes 的 API 支持三种方法来限制这些搜索的范围:

  • 命名空间:范围仅限于给定的 Kubernetes命名空间
  • 字段选择器:范围仅限于具有匹配字段值的资源
  • 标签选择器:范围仅限于具有匹配标签的资源

此外,我们可以将这些方法组合到一个查询中 。这为我们提供了很大的灵活性来满足复杂的需求。

现在,让我们更详细地了解每种方法。

2. 使用命名空间

使用命名空间是限制查询范围的最基本方法。 顾名思义,命名空间查询仅返回指定命名空间内的项目。

在 Java API 中,命名空间查询方法遵循 listNamespacedXXX() 模式。 例如,要列出特定命名空间中的pod ,我们可以使用 listNamespacedPod()

ApiClient client  = Config.defaultClient();
CoreV1Api api = new CoreV1Api(client);
String ns = "ns1";
V1PodList items = api.listNamespacedPod(ns,null, null, null, null, null, null, null, null, 10, false);
items.getItems()
  .stream()
  .map((pod) -> pod.getMetadata().getName() )
  .forEach((name) -> System.out.println("name=" + name));

这里使用 ApliClientCoreV1Api 来进行对Kubernetes API服务器的实际访问。我们使用 ns1 作为命名空间来过滤资源。我们还使用与非命名空间方法中类似的其余参数。

正如预期的那样,命名空间查询也有 调用 变体,因此允许我们使用前面描述的相同技术创建 监视异步调用和分页的工作方式也与其非命名空间版本相同。

3. 使用字段选择器

命名空间 API 调用使用起来很简单,但有一些限制:

  • 这是要么全有要么全无的情况,这意味着我们不能选择多个(但不是全部)命名空间
  • 无法根据资源属性进行过滤
  • 对每个场景使用不同的方法会导致更复杂/冗长的客户端代码

字段选择器提供了一种根据其中一个 字段 的值来选择资源的方法 。 Kubernetes 术语中的 字段 只是与资源的 YAML 或 JSON 文档中给定值关联的 JSON 路径。例如,这是运行 Apache HTTP 服务器的 pod 的典型 Kubernetes YAML:

apiVersion: v1
kind: Pod
metadata:
  labels:
    app: httpd
  name: httpd-6976bbc66c-4lbdp
  namespace: ns1
spec:
  ... fields omitted
status:
  ... fields omitted
  phase: Running

status.phase 字段 包含现有 Pod 的状态。 相应的 字段选择器 表达式只是字段名称后跟运算符和值。现在,让我们编写一个查询,返回所有命名空间中所有正在运行的 pod:

String fs = "status.phase=Running";        
V1PodList items = api.listPodForAllNamespaces(null, null, fs, null, null, null, null, null, 10, false);
// ... process items

字段选择器表达式仅支持相等(“=”或“==”)和不等(“!=”)运算符。此外,我们可以在同一个调用中传递多个逗号分隔的表达式。 在这种情况下,最终效果是它们将被组合在一起以产生最终结果:

String fs = "metadata.namespace=ns1,status.phase=Running";        
V1PodList items = api.listPodForAllNamespaces(null, null, fs, null, null, null, null, null, 10, false);
// ... process items

请注意:字段值区分大小写! 在前面的查询中,使用“running”而不是“Running”(大写“R”)将产生空结果集。

字段选择器的一个重要限制是它们依赖于资源。所有资源类型仅支持 metadata.namemetadata.namespace 字段。

尽管如此,字段选择器在与动态字段一起使用时特别有用。上一个示例中的 status.phase 就是一个示例。将字段选择器与 Watch 结合使用, 我们可以轻松创建一个监控应用程序,该应用程序会在 pod 终止时收到通知。

4. 使用标签选择器

标签是包含任意键/值对的特殊字段,我们可以将其添加到任何 Kubernetes 资源作为其创建的一部分。标签选择器与字段选择器类似,因为它们本质上允许根据资源列表的值过滤资源列表,但提供了更大的灵活性:

  • 支持其他运算符: in/notin/exists/not contains
  • 与字段选择器相比,跨资源类型的使用保持一致

回到 Java API,我们通过使用所需条件构造字符串并将其作为参数传递给所需资源 API listXXX 调用来使用标签选择器。使用相等和/或不等式过滤特定标签值使用与字段选择器使用的相同语法。

让我们看看查找所有标签为“app”且值为“httpd”的 pod 的代码:

String ls = "app=httpd";        
V1PodList items = api.listPodForAllNamespaces(null, null, null, ls, null, null, null, null, 10, false);
// ... process items

in 运算符类似于 SQL 对应项,允许我们在查询中创建一些 OR 逻辑:

String ls = "app in ( httpd, test )";        
V1PodList items = api.listPodForAllNamespaces(null, null, null, ls, null, null, null, null, 10, false);

此外,我们可以使用 labelname 或 *!*labelname 语法检查字段是否存在:

String ls = "app";
V1PodList items = api.listPodForAllNamespaces(null, null, null, ls, null, null, null, null, 10, false);

最后,我们可以在单个 API 调用中链接多个表达式。生成的项目列表仅包含满足所有表达式的资源:

String ls = "app in ( httpd, test ),version=1,foo";
V1PodList items = api.listPodForAllNamespaces(null, null, null, ls, null, null, null, null, 10, false);

5. 结论

在本文中,我们介绍了使用 Java Kubernetes API 客户端过滤资源的不同方法。与往常一样,示例的完整源代码可以在 GitHub 上找到。