俗话说,工欲善其事,必先利其器。在使用 Kubernetes 时,首先需要初始化客户端。通常情况下,我们可以这样创建 Kubernetes
客户端:
try (final KubernetesClient client = new KubernetesClientBuilder().build()) {
// 使用客户端进行操作
}
这种方式会使用默认设置,从 ~/.kube/config
目录或 KUBECONFIG
环境变量定义的路径读取 kubeconfig
文件。但如果你想自定义客户端的创建,也可以通过传递一个 Config
对象给构建器来实现:
Config kubeConfig = new ConfigBuilder()
.withMasterUrl("https://192.168.42.20:8443/")
.build();
try (final KubernetesClient client = new KubernetesClientBuilder().withConfig(kubeConfig).build()) {
// 使用客户端进行操作
}
俗话说,熟能生巧。本节将介绍 Kubernetes 客户端库中所有支持资源的 DSL 使用示例。尽管大多数资源的使用方式大同小异,但我们仍然将其一一列出,方便大家查阅:
Pods
可以通过 client.pods()
访问。以下是一些常见的 Pod
资源使用示例:
yaml
文件加载 Pod
到 Pod
对象:Pod myPod = client.pods().load(new FileInputStream("some-pod.yml")).item();
Pod
对象:PodList podList = client.pods().inNamespace("FunTester").list();
Pod
对象:PodList podList = client.pods().inAnyNamespace().list();
Pod
对象:PodList podList = client.pods().inNamespace("FunTester").withLabel("foo", "bar").list();
Pod
:Pod myPod = client.pods().inNamespace("FunTester").withName("nginx-pod").get();
Pod
:Pod aPod = new PodBuilder().withNewMetadata().withName("demo-pod1").endMetadata()
.withNewSpec()
.addNewContainer()
.withName("nginx")
.withImage("nginx:1.7.9")
.addNewPort().withContainerPort(80).endPort()
.endContainer()
.endSpec()
.build();
Pod createdPod = client.pods().inNamespace("FunTester").resource(aPod).create();
Pod
应用到 Kubernetes 集群:client.pods().inNamespace("FunTester").resource(pod).serverSideApply();
Pod
对象:client.pods().inNamespace("FunTester").withName("nginx").edit(
p -> new PodBuilder(p).editOrNewMetadata().addToLabels("new","label").endMetadata().build()
);
Pod
对象的日志:String log = client.pods().inNamespace("FunTester").withName("test-pod").getLog();
Pod
的日志:LogWatch watch = client.pods().inNamespace(namespace).withName(podName).tailingLines(10).watchLog(System.out);
Pod
:client.pods().inNamespace("FunTester").withName("nginx").delete();
Pod
对象:client.resourceList(pod1, pod2).inNamespace("FunTester").delete();
Pod
准备就绪:Pod pod = client.pods().inNamespace("FunTester").withName("nginx").waitUntilReady(5, TimeUnit.MINUTES);
Pod
满足特定条件:Pod pod = client.pods().inNamespace("FunTester").withName("nginx").waitUntilCondition(pod -> pod.getStatus().getPhase().equals("Succeeded"), 1, TimeUnit.MINUTES);
Pod
:int containerPort = client.pods().inNamespace("FunTester").withName("testpod").get().getSpec().getContainers().get(0).getPorts().get(0).getContainerPort();
LocalPortForward portForward = client.pods().inNamespace("FunTester").withName("testpod").portForward(containerPort, 8080);
Pod
:final CountDownLatch deleteLatch = new CountDownLatch(1);
Watch podWatch = client.pods().withName("pod1").watch(new Watcher<>() {
@Override
public void eventReceived(Action action, Pod resource) {
switch (action) {
case DELETED:
deleteLatch.countDown();
}
}
@Override
public void onClose(WatcherException e) { }
});
deleteLatch.await(10, TimeUnit.MINUTES);
Pod
:client.pods().inNamespace(currentNamespace).withName(pod1.getMetadata().getName())
.file("/tmp/toBeUploaded").upload(tmpFile.toPath());
Pod
读取文件:try (InputStream is = client.pods().inNamespace(currentNamespace).withName(pod1.getMetadata().getName()).file("/msg").read()) {
String result = new BufferedReader(new InputStreamReader(is)).lines().collect(Collectors.joining("\n"));
}
Pod
添加临时容器:PodResource resource = client.pods().withName("pod1");
resource.ephemeralContainers()
.edit(p -> new PodBuilder(p)
.editSpec()
.addNewEphemeralContainer()
.withName("debugger")
.withImage("busybox")
.withCommand("sleep", "36000")
.endEphemeralContainer()
.endSpec()
.build());
resource.waitUntilCondition(p -> p.getStatus()
.getEphemeralContainerStatuses()
.stream()
.filter(s -> s.getName().equals("debugger"))
.anyMatch(s -> s.getState().getRunning() != null), 2, TimeUnit.MINUTES);
ByteArrayOutputStream out = new ByteArrayOutputStream();
try (ExecWatch watch = resource.inContainer("debugger")
.writingOutput(out)
.exec("sh", "-c", "echo 'FunTester hello world!'")) {
assertEquals(0, watch.exitCode().join());
assertEquals("hello world!\n", out.toString());
}
Pod
内部使用 Kubernetes 客户端:当尝试从 Pod
内部访问 Kubernetes API 时,身份验证的方式与在本地系统中有所不同。客户端通过从 /var/run/secrets/kubernetes.io/serviceaccount/
读取 ServiceAccount
并从环境变量 KUBERNETES_SERVICE_HOST
和 KUBERNETES_SERVICE_PORT
中读取 apiServer URL 来进行身份验证。使用 Fabric8 Kubernetes 客户端时,你无需担心这些细节,只需像这样使用即可:
// 从挂载的卷中读取 serviceaccount 并从环境变量中获取 apiServer URL。
KubernetesClient client = new KubernetesClientBuilder().build();
Service
可以通过 client.services()
访问。以下是一些常见的 Service
使用示例:
Service
:Service aService = client.services().load(new FileInputStream("service.yml")).item();
Service
:Service service = client.services().inNamespace("FunTester").withName("some-service").get();
Service
:Service createdSvc = client.services().inNamespace("FunTester").resource(svc).create();
Service
对象应用到 Kubernetes 集群:Service createdSvc = client.services().inNamespace("FunTester").resource(svc).serverSideApply();
Service
对象:ServiceList svcList = client.services().inNamespace("FunTester").list();
Service
对象:ServiceList svcList = client.services().inAnyNamespace().list();
Service
对象:ServiceList svcList = client.services().inNamespace("FunTester").withLabel("foo", "bar").list();
Service
:client.services().inNamespace("FunTester").withName("some-svc").delete();
Service
:client.services().inNamespace("FunTester").watch(new Watcher<>() {
@Override
public void eventReceived(Action action, Service resource) {
// 根据操作类型执行某些操作
}
@Override
public void onClose(WatcherException cause) {
}
});
Deployment
可以通过 client.apps().deployments()
访问。以下是一些常见的 Deployment
使用示例:
Deployment
:Deployment aDeployment = client.apps().deployments().load(new FileInputStream("test-deployments.yml")).item();
Deployment
:Deployment deploy = client.apps().deployments().inNamespace("FunTester").withName("deploy-1").get();
Deployment
:Deployment deployment1 = new DeploymentBuilder()
.withNewMetadata()
.withName("FunTesterdeployment1")
.addToLabels("test", "deployment")
.endMetadata()
.withNewSpec()
.withReplicas(1)
.withNewTemplate()
.withNewMetadata()
.addToLabels("app", "httpd")
.endMetadata()
.withNewSpec()
.addNewContainer()
.withName("busybox")
.withImage("busybox")
.withCommand("sleep","36000")
.endContainer()
.endSpec()
.endTemplate()
.withNewSelector()
.addToMatchLabels("app","httpd")
.endSelector()
.endSpec()
.build();
client.apps().deployments().inNamespace("FunTester").resource(deployment1).create();
Deployment
对象应用到 Kubernetes 集群:Deployment createdDeployment = client.apps().deployments().inNamespace("FunTester").resource(deployObj).serverSideApply();
Deployment
对象:DeploymentList aDeploymentList = client.apps().deployments().inNamespace("FunTester").list();
Deployment
对象:DeploymentList aDeploymentList = client.apps().deployments().inAnyNamespace().list();
Deployment
对象:DeploymentList aDeployList = client.apps().deployments().inNamespace("FunTester").withLabel("foo", "bar").list();
Deployment
:// 将 Deployment 扩展到 2 个副本
Deployment updatedDeploy = client.apps().deployments().inNamespace("FunTester")
.withName("deployment1").edit(
d -> new DeploymentBuilder(d).editSpec().withReplicas(2).endSpec().build()
);
Deployment
中的单个容器镜像:Deployment updatedDeployment = client.apps()
.deployments()
.inNamespace("FunTester")
.withName("ngix-controller")
.updateImage("docker.io/nginx:latest");
Deployment
中的多个容器镜像:Map<String, String> containerToImageMap = new HashMap<>();
containerToImageMap.put("nginx", "nginx:perl");
containerToImageMap.put("sidecar", "someImage:someVersion");
Deployment updatedDeployment = client.apps().deployments()
.inNamespace("FunTester")
.withName("nginx-deployment")
.updateImage(containerToImageMap);
Deployment
:Deployment deployment = client.apps().deployments()
.inNamespace("FunTester")
.withName("nginx-deployment")
.rolling()
.restart();
Deployment
的滚动更新:Deployment deployment = client.apps().deployments()
.inNamespace("FunTester")
.withName("nginx-deployment")
.rolling()
.pause();
Deployment
的滚动更新:Deployment deployment = client.apps().deployments()
.inNamespace("FunTester")
.withName("nginx-deployment")
.rolling()
.resume();
Deployment
:Deployment deployment = client.apps().deployments()
.inNamespace("FunTester")
.withName("nginx-deployment")
.rolling()
.undo();
Deployment
:client.apps().deployments().inNamespace("FunTester").withName("foo").delete();
Deployment
:client.apps().deployments().inNamespace("FunTester").watch(new Watcher<>() {
@Override
public void eventReceived(Action action, Deployment resource) {
// 根据操作类型执行某些操作
}
@Override
public void onClose(WatcherException cause) {
}
});
Deployment
:client.apps().deployments().inNamespace("FunTester").withName("nginx-deployment").scale(1);
Deployment
日志:client.apps().deployments().inNamespace("FunTester").withName("nginx").watchLog(System.out);
ReplicaSet
可以通过 client.apps().replicaSets()
访问。以下是一些常见的 ReplicaSet
使用示例:
ReplicaSet
:ReplicaSet replicaSet = client.apps().replicaSets().inNamespace("FunTester")
.load(new FileInputStream("test-replicaset.yml")).item();
ReplicaSet
:ReplicaSet rs = client.apps().replicaSets().inNamespace("FunTester").withName("rs1").get();
ReplicaSet
:ReplicaSet replicaset1 = new ReplicaSetBuilder()
.withNewMetadata()
.withName("replicaset1")
.addToLabels("app", "guestbook")
.addToLabels("tier", "frontend")
.endMetadata()
.withNewSpec()
.withReplicas(1)
.withNewSelector()
.withMatchLabels(Collections.singletonMap("tier", "frontend"))
.endSelector()
.withNewTemplate()
.withNewMetadata()
.addToLabels("app", "guestbook")
.addToLabels("tier", "frontend")
.endMetadata()
.withNewSpec()
.addNewContainer()
.withName("busybox")
.withImage("busybox")
.withCommand("sleep","36000")
.withNewResources()
.withRequests(requests)
.endResources()
.withEnv(envVarList)
.endContainer()
.endSpec()
.endTemplate()
.endSpec()
.build();
client.apps().replicaSets().inNamespace("FunTester").resources(replicaset1).create();
ReplicaSet
对象应用到 Kubernetes 集群:ReplicaSet rs = client.apps().replicaSets().inNamespace("FunTester").resource(replicaSet).serverSideApply();
ReplicaSet
对象:ReplicaSetList rsList = client.apps().replicaSets().inNamespace("FunTester").list();
ReplicaSet
对象:ReplicaSetList rsList = client.apps().replicaSets().inAnyNamespace().list();
ReplicaSet
对象:ReplicaSetList rsList = client.apps().replicaSets().inNamespace("FunTester").withLabel("foo", "bar").list();
ReplicaSet
:client.apps().replicaSets().inNamespace("FunTester").withName("rs1").delete();
ReplicaSet
:client.apps().replicaSets().inNamespace("FunTester").watch(new Watcher<>() {
@Override
public void eventReceived(Action action, ReplicaSet resource) {
// 根据操作类型执行某些操作
}
@Override
public void onClose(WatcherException e) {
}
});
ReplicaSet
:// 扩展到 3 个副本
client.apps().replicaSets().inNamespace("FunTester").withName("nginx-rs").scale(3);
ReplicaSet
中的镜像:ReplicaSet replicaSet = client.apps().replicaSets()
.inNamespace("FunTester")
.withName("soaktestrs")
.updateImage("nickchase/soaktest");
ReplicaSet
中的多个镜像:Map<String, String> containerToImageMap = new HashMap<>();
containerToImageMap.put("c1", "image1");
containerToImageMap.put("c2", "image2");
ReplicaSet replicaSet = client.apps().replicaSets()
.inNamespace("FunTester")
.withName("soaktestrs")
.updateImage(containerToImageMap);
好的,下面是一个使用 Kubernetes Java 客户端的虚拟场景脚本示例。假设我们需要实现以下需求:
fun-tester
)。以下是实现上述需求的完整脚本:
import io.fabric8.kubernetes.api.model.*;
import io.fabric8.kubernetes.client.*;
import io.fabric8.kubernetes.client.dsl.LogWatch;
import io.fabric8.kubernetes.client.dsl.PodResource;
import java.util.concurrent.TimeUnit;
public class KubernetesFunTesterDemo {
public static void main(String[] args) {
// 初始化 Kubernetes 客户端
try (KubernetesClient client = new KubernetesClientBuilder().build()) {
String namespace = "fun-tester";
// 1. 创建命名空间
Namespace ns = new NamespaceBuilder()
.withNewMetadata()
.withName(namespace)
.endMetadata()
.build();
client.namespaces().resource(ns).create();
System.out.println("命名空间 " + namespace + " 创建成功!");
// 2. 在命名空间中部署一个 Nginx Pod
Pod nginxPod = new PodBuilder()
.withNewMetadata()
.withName("nginx-pod")
.addToLabels("app", "nginx")
.endMetadata()
.withNewSpec()
.addNewContainer()
.withName("nginx-container")
.withImage("nginx:1.21.0")
.addNewPort().withContainerPort(80).endPort()
.endContainer()
.endSpec()
.build();
client.pods().inNamespace(namespace).resource(nginxPod).create();
System.out.println("Nginx Pod 创建成功!");
// 3. 为 Pod 创建一个 Service
Service nginxService = new ServiceBuilder()
.withNewMetadata()
.withName("nginx-service")
.endMetadata()
.withNewSpec()
.addNewPort()
.withPort(80)
.withTargetPort(new IntOrString(80))
.endPort()
.withSelector(nginxPod.getMetadata().getLabels())
.withType("LoadBalancer")
.endSpec()
.build();
client.services().inNamespace(namespace).resource(nginxService).create();
System.out.println("Nginx Service 创建成功!");
// 4. 监听 Pod 的状态,直到 Pod 准备就绪
PodResource<Pod> podResource = client.pods().inNamespace(namespace).withName("nginx-pod");
Pod readyPod = podResource.waitUntilReady(5, TimeUnit.MINUTES);
System.out.println("Nginx Pod 已准备就绪,状态为: " + readyPod.getStatus().getPhase());
// 5. 获取 Pod 的日志并打印到控制台
String podLog = podResource.getLog();
System.out.println("Nginx Pod 日志如下:");
System.out.println(podLog);
// 6. 删除命名空间及其所有资源
client.namespaces().withName(namespace).delete();
System.out.println("命名空间 " + namespace + " 及其所有资源已删除!");
} catch (KubernetesClientException e) {
System.err.println("Kubernetes 操作失败: " + e.getMessage());
e.printStackTrace();
}
}
}
KubernetesClientBuilder
创建 Kubernetes 客户端。NamespaceBuilder
创建一个名为 fun-tester
的命名空间。PodBuilder
创建一个 Nginx Pod,并指定容器镜像为 nginx:1.21.0
。ServiceBuilder
创建一个 Service,将流量转发到 Nginx Pod 的 80 端口。waitUntilReady
方法等待 Pod 准备就绪。getLog
方法获取 Pod 的日志并打印到控制台。运行脚本后,控制台会输出以下内容:
命名空间 fun-tester 创建成功!
Nginx Pod 创建成功!
Nginx Service 创建成功!
Nginx Pod 已准备就绪,状态为: Running
Nginx Pod 日志如下:
(Nginx 的启动日志)
命名空间 fun-tester 及其所有资源已删除!
kubectl
可以正常使用。NodePort
。5 分钟
)可以根据实际环境调整。FunTester 原创精华
【免费合集】从 Java 开始性能测试
故障测试与 Web 前端
服务端功能测试
性能测试专题
Java、Groovy、Go
白盒、工具、爬虫、UI 自动化
理论、感悟、视频