1. 简介
本教程将展示如何在 Java 应用中使用 Kubernetes 官方提供的客户端库来调用 Kubernetes API。
2. 为什么需要调用 Kubernetes API?
如今,Kubernetes 已成为管理容器化应用的事实标准。它提供了一套功能强大的 API,允许我们部署、扩缩容和监控应用及其相关资源,比如存储、密钥和环境变量。可以这么说,这套 API 是分布式系统中的“系统调用”。
大多数情况下,我们的应用其实并不需要感知自己运行在 Kubernetes 上。这是一件好事,因为这意味着我们可以本地开发,然后通过几条命令和 YAML 配置轻松地部署到多个云平台,改动很少。
但有些场景下,我们确实需要与 Kubernetes API 交互才能实现特定功能:
✅ 启动一个外部程序执行任务,并在之后获取其完成状态
✅ 根据用户请求动态创建或修改服务
✅ 跨多个 Kubernetes 集群(甚至跨云平台)构建自定义监控仪表盘
虽然这些场景不常见,但借助 Kubernetes API,实现起来其实非常简单直接。
而且,由于 Kubernetes API 是开放规范,我们可以放心地认为代码能在任何合规的实现上无修改运行。
3. 本地开发环境准备
在开始编写应用前,我们首先需要一个可用的 Kubernetes 集群。虽然可以选择使用公有云平台,但在本地搭建轻量级集群通常更便于控制配置细节。
以下是一些适合本地开发的轻量级发行版:
具体安装步骤这里不再赘述,无论选择哪种方式,请确保在开始开发前能正常运行 kubectl 命令。
4. Maven 依赖配置
首先,我们在项目的 pom.xml 中添加 Kubernetes Java 客户端依赖:
<dependency>
<groupId>io.kubernetes</groupId>
<artifactId>client-java</artifactId>
<version>11.0.0</version>
</dependency>
最新版本的 client-java 可从 Maven Central 获取。
5. Hello, Kubernetes
接下来我们写一个简单的示例程序,列出当前集群中的节点,并打印一些基本信息。
尽管这个例子很简单,但它完整展示了连接集群并调用 API 所需的基本步骤。无论你在实际项目中调用哪个接口,这些步骤都是通用的。
5.1. 初始化 ApiClient
ApiClient 类是整个客户端库中最核心的类之一,它封装了与 Kubernetes API Server 通信的所有逻辑。推荐使用 Config 类中的静态方法来初始化这个对象。最简单的方式是使用 defaultClient()
方法:
ApiClient client = Config.defaultClient();
使用该方法可以确保我们的代码既能在本地开发环境中运行,也能部署到集群内部。它会自动按照以下顺序查找配置文件:
✅ 由 KUBECONFIG 环境变量指定的配置文件
✅ $HOME/.kube/config 文件
✅ Pod 内部的服务账户令牌:*/var/run/secrets/kubernetes.io/serviceaccount*
✅ 直接访问本地地址:http://localhost:8080
⚠️ 第三项特别重要,它使得我们的应用可以在集群内部以 Pod 形式运行时,依然能正常访问 API。
另外,如果配置文件中定义了多个上下文(context),此方法会自动使用当前设置为默认的那个(通过 kubectl config set-context 设置)。
5.2. 创建 API Stub
有了 ApiClient 实例后,我们可以用它来创建各种 Kubernetes API 的调用桩(stub)。在这个例子中,我们将使用 CoreV1Api 类来获取节点列表:
CoreV1Api api = new CoreV1Api(client);
这里我们传入了之前创建的 ApiClient 实例。
⚠️ 虽然也提供了无参构造函数,但我们应避免使用它。因为其内部会依赖一个全局默认的 ApiClient 实例,必须提前调用 Configuration.setDefaultApiClient()
设置好,否则会导致运行时异常或维护困难。
更好的做法是使用依赖注入框架统一管理这些对象的生命周期,并按需注入到业务代码中。
5.3. 调用 Kubernetes API
最后一步就是真正发起 API 请求,获取节点信息。CoreV1Api 提供了 listNode
方法,正好满足需求:
V1NodeList nodeList = api.listNode(null, null, null, null, null, null, null, null, 10, false);
nodeList.getItems()
.stream()
.forEach((node) -> System.out.println(node));
在这个例子中,我们对大部分参数传了 null
,因为它们是可选的。最后两个参数适用于所有 listXXX
类型的方法,分别表示请求超时时间和是否开启 Watch 模式。
下面是 listNode
的完整签名:
public V1NodeList listNode(
String pretty,
Boolean allowWatchBookmarks,
String _continue,
String fieldSelector,
String labelSelector,
Integer limit,
String resourceVersion,
String resourceVersionMatch,
Integer timeoutSeconds,
Boolean watch) {
// ... method implementation
}
本次入门仅介绍基础使用,暂时忽略分页、过滤和 Watch 相关参数。返回值是一个 POJO 对象,对应 API 返回的数据结构。对于节点列表,返回的是 V1Node
对象列表,每个对象都包含大量节点信息。下面是典型的输出示例:
class V1Node {
metadata: class V1ObjectMeta {
labels: {
beta.kubernetes.io/arch=amd64,
beta.kubernetes.io/instance-type=k3s,
// ... 其他标签省略
}
name: rancher-template
resourceVersion: 29218
selfLink: null
uid: ac21e09b-e3be-49c3-9e3a-a9567b5c2836
}
// ... 多个字段省略
status: class V1NodeStatus {
addresses: [class V1NodeAddress {
address: 192.168.71.134
type: InternalIP
}, class V1NodeAddress {
address: rancher-template
type: Hostname
}]
allocatable: {
cpu=Quantity{number=1, format=DECIMAL_SI},
ephemeral-storage=Quantity{number=18945365592, format=DECIMAL_SI},
hugepages-1Gi=Quantity{number=0, format=DECIMAL_SI},
hugepages-2Mi=Quantity{number=0, format=DECIMAL_SI},
memory=Quantity{number=8340054016, format=BINARY_SI},
pods=Quantity{number=110, format=DECIMAL_SI}
}
capacity: {
cpu=Quantity{number=1, format=DECIMAL_SI},
ephemeral-storage=Quantity{number=19942490112, format=BINARY_SI},
hugepages-1Gi=Quantity{number=0, format=DECIMAL_SI},
hugepages-2Mi=Quantity{number=0, format=DECIMAL_SI},
memory=Quantity{number=8340054016, format=BINARY_SI},
pods=Quantity{number=110, format=DECIMAL_SI}}
conditions: [
// ... 节点状态省略
]
nodeInfo: class V1NodeSystemInfo {
architecture: amd64
kernelVersion: 4.15.0-135-generic
kubeProxyVersion: v1.20.2+k3s1
kubeletVersion: v1.20.2+k3s1
operatingSystem: linux
osImage: Ubuntu 18.04.5 LTS
// ... 更多字段省略
}
}
}
可以看到,返回的信息非常丰富。作为对比,下面是等效的 kubectl
命令输出:
root@rancher-template:~# kubectl get nodes
NAME STATUS ROLES AGE VERSION
rancher-template Ready control-plane,master 24h v1.20.2+k3s1
6. 总结
本文带你快速入门了 Kubernetes Java 客户端的基本使用。后续我们会进一步深入探讨:
✅ 不同 API 调用方式的区别
✅ 如何使用 Watch 实时监听集群事件
✅ 如何利用分页高效获取大量数据
一如既往,本文的完整示例代码可以在 GitHub 找到。