Using Namespaces and Selectors With the Kubernetes Java API – 在Kubernetes Java API中使用命名空间和选择器

最后修改: 2021年 5月 12日

中文/混合/英文(键盘快捷键:t)

1. Introduction

1.绪论

In this tutorial, we’ll explore different ways to filter resources using the Kubernetes Java API.

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

In our previous articles covering the Kubernetes Java API, we’ve focused on the available methods to query, manipulate, and monitor cluster resources.

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

Those examples assumed that we were either looking for resources of a specific kind or targeting a single resource. In practice, however, most applications need a way to locate resources based on some criteria.

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

Kubernetes’ API supports three ways to limit the scope of those searches:

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

  • Namespaces: scope limited to a given Kubernetes namespace
  • Field Selectors: scope limited to resources having matching field values
  • Label Selectors: scope limited to resources having matching labels

Moreover, we can combine those methods in a single query. This gives us a lot of flexibility to address even complex requirements.

此外,我们可以在一个单一的查询中结合这些方法。这给了我们很大的灵活性,甚至可以解决复杂的要求。

Now, let’s see each method in more detail.

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

2. Using Namespaces

2.使用命名空间

Using namespaces is the most basic way to limit the scope of a query. As the name implies, a namespaced query only returns items within the specified namespace.

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

In the Java API, namespaced query methods follow the pattern listNamespacedXXX(). For instance, to list pods in a specific namespace, we’d use listNamespacedPod():

在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));

Here, ApliClient and CoreV1Api  are used to perform actual access to the Kubernetes API server. We use ns1 as the namespace to filter resources. We also use the remaining arguments similar to the ones in the non-namespaced method.

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

As expected, namespaced queries also have call variants, thus allowing us to create Watches using the same techniques described before. Asynchronous calls and paging also work in the same way as their non-namespaced versions.

正如预期的那样,命名的查询也有调用变体,从而使我们能够使用相同的技术之前描述的来创建Watch异步调用和分页的工作方式也与它们的非命名版本相同。

3. Using Field Selectors

3.使用字段选择器

Namespaced API calls are simple to use but have some limitations:

命名的API调用使用起来很简单,但有一些限制。

  • It’s all-or-nothing, meaning we can’t select more than one (but not all) namespaces
  • No way to filter based on resource properties
  • Using a different method for each scenario leads to more complex/verbose client code

Field selectors provide a way to select resources based on the value of one of its fields. A field in Kubernetes parlance is just the JSON path associated with a given value in a resource’s YAML or JSON document. For instance, this is a typical Kubernetes YAML for a pod running an Apache HTTP server:

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

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

The field status.phase contains the status of an existing Pod. The corresponding field selector expression is simply the field name followed by an operator and value. Now, let’s code a query that returns all running pods in all namespaces:

字段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

A field selector expression supports only the equality (‘=’ or ‘==’) and inequality (‘!=’) operators. Also, we can pass multiple comma-separated expressions in the same call. In this case, the net effect is that they’ll be ANDed together to produce the final result:

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

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

Be aware: field values are case-sensitive! In the previous query, using “running” instead of “Running” (capital “R”) would yield an empty result set.

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

An important limitation of field selectors is that they are resource-dependent. Only metadata.name and metadata.namespace fields are supported across all resource kinds.

字段选择器的一个重要限制是,它们是依赖于资源的。只有metadata.namemetadata.namespace字段在所有的资源种类中被支持。

Nevertheless, field selectors are especially useful when used with dynamic fields. An example is the status.phase in the previous example. Using a field selector together with a Watch, we can easily create a monitoring application that gets notified when pods terminate.

尽管如此,字段选择器在与动态字段一起使用时特别有用。前面的例子中的status.phase就是一个例子。使用字段选择器和Watch,我们可以轻松地创建一个监控应用程序,当pod终止时得到通知。

4. Using Label Selectors

4.使用标签选择器

Labels are special fields that contain arbitrary key/value pairs that we can add to any Kubernetes resource as part of its creation. Label selectors are similar to field selector, as they essentially allow filtering a resource list based on its values, but offers more flexibility:

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

  • Support for additional operators: in/notin/exists/not exists
  • Consistent usage across resource types when compared to field selectors

Going back to the Java API, we use label selectors by constructing a string with the desired criteria and passing it in as an argument to the desired resource API listXXX call. Filtering for a specific label value using equality and/or inequality uses the same syntax used by field selectors.

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

Let’s see the code that looks for all pods that have a label “app” with the value “httpd”:

让我们看看寻找所有标签为 “app”、值为 “httpd “的pod的代码。

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

The in operator resembles its SQL counterpart and allows us to create some OR logic in queries:

in操作符类似于它的SQL对应物,允许我们在查询中创建一些OR逻辑。

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

Also, we can check for the presence or absence of a field using the labelname or !labelname syntax:

另外,我们可以使用labelname!labelname语法来检查一个字段是否存在。

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

Finally, we can chain multiple expressions in a single API call. The resulting items list contains only resources that satisfy all expressions:

最后,我们可以在一次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. Conclusion

5.总结

In this article, we’ve covered different ways to filter resources using the Java Kubernetes API client. As usual, the full source code of the examples can be found over on GitHub.

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