Kubernetes Client Java API in Java

Overview

The Kubernetes Java Client API provides a fluent interface for interacting with Kubernetes clusters. It allows you to create, read, update, and delete Kubernetes resources programmatically.

Dependencies

Maven Configuration

<properties>
<kubernetes-client.version>18.0.0</kubernetes-client.version>
</properties>
<dependencies>
<!-- Kubernetes Client -->
<dependency>
<groupId>io.kubernetes</groupId>
<artifactId>client-java</artifactId>
<version>${kubernetes-client.version}</version>
</dependency>
<!-- For Spring Boot integration -->
<dependency>
<groupId>io.kubernetes</groupId>
<artifactId>client-java-spring-integration</artifactId>
<version>${kubernetes-client.version}</version>
</dependency>
<!-- For metrics -->
<dependency>
<groupId>io.kubernetes</groupId>
<artifactId>client-java-metrics</artifactId>
<version>${kubernetes-client.version}</version>
</dependency>
</dependencies>

Core Client Setup

1. Kubernetes Client Configuration

import io.kubernetes.client.openapi.ApiClient;
import io.kubernetes.client.openapi.Configuration;
import io.kubernetes.client.openapi.apis.*;
import io.kubernetes.client.util.Config;
import io.kubernetes.client.util.KubeConfig;
import io.kubernetes.client.util.credentials.AccessTokenAuthentication;
import okhttp3.OkHttpClient;
import javax.net.ssl.*;
import java.io.*;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.concurrent.TimeUnit;
public class KubernetesClientFactory {
// Create client from default configuration (~/.kube/config)
public static ApiClient createDefaultClient() throws IOException {
return Config.defaultClient();
}
// Create client from specific kubeconfig file
public static ApiClient createClientFromConfig(String configPath) throws IOException {
return Config.fromConfig(configPath);
}
// Create client from in-cluster configuration (when running inside Kubernetes)
public static ApiClient createInClusterClient() throws IOException {
return Config.fromCluster();
}
// Create client with custom configuration
public static ApiClient createCustomClient(String masterUrl, String token, 
String caCertPath) throws IOException {
ApiClient client = new ApiClient();
client.setBasePath(masterUrl);
client.setVerifyingSsl(true);
client.setAuthentication(new AccessTokenAuthentication(token));
if (caCertPath != null) {
client.setSslCaCert(new File(caCertPath));
}
return client;
}
// Create client with custom HTTP settings
public static ApiClient createClientWithHttpConfig(ApiClient baseClient, 
int connectTimeout, 
int readTimeout,
int writeTimeout) {
OkHttpClient httpClient = baseClient.getHttpClient()
.newBuilder()
.connectTimeout(connectTimeout, TimeUnit.SECONDS)
.readTimeout(readTimeout, TimeUnit.SECONDS)
.writeTimeout(writeTimeout, TimeUnit.SECONDS)
.build();
baseClient.setHttpClient(httpClient);
return baseClient;
}
// Create client that ignores SSL verification (for testing only)
public static ApiClient createInsecureClient(String masterUrl, String token) {
try {
// Create trust manager that does not validate certificate chains
final TrustManager[] trustAllCerts = new TrustManager[] {
new X509TrustManager() {
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) 
throws CertificateException {}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) 
throws CertificateException {}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[]{};
}
}
};
// Install the all-trusting trust manager
SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
// Create an ssl socket factory with our all-trusting manager
SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
OkHttpClient insecureClient = new OkHttpClient.Builder()
.sslSocketFactory(sslSocketFactory, (X509TrustManager) trustAllCerts[0])
.hostnameVerifier((hostname, session) -> true)
.build();
ApiClient client = new ApiClient();
client.setBasePath(masterUrl);
client.setAccessToken(token);
client.setHttpClient(insecureClient);
client.setVerifyingSsl(false);
return client;
} catch (Exception e) {
throw new RuntimeException("Failed to create insecure client", e);
}
}
}

2. Core Kubernetes Service

import io.kubernetes.client.openapi.ApiClient;
import io.kubernetes.client.openapi.ApiException;
import io.kubernetes.client.openapi.Configuration;
import io.kubernetes.client.openapi.apis.*;
import io.kubernetes.client.openapi.models.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import java.util.*;
import java.util.stream.Collectors;
@Service
public class KubernetesService {
private static final Logger logger = LoggerFactory.getLogger(KubernetesService.class);
private final CoreV1Api coreV1Api;
private final AppsV1Api appsV1Api;
private final BatchV1Api batchV1Api;
private final NetworkingV1Api networkingV1Api;
private final CustomObjectsApi customObjectsApi;
public KubernetesService(ApiClient apiClient) {
Configuration.setDefaultApiClient(apiClient);
this.coreV1Api = new CoreV1Api();
this.appsV1Api = new AppsV1Api();
this.batchV1Api = new BatchV1Api();
this.networkingV1Api = new NetworkingV1Api();
this.customObjectsApi = new CustomObjectsApi();
}
// Health check
public boolean isClusterHealthy() {
try {
coreV1Api.getAPIResources();
return true;
} catch (ApiException e) {
logger.error("Cluster health check failed", e);
return false;
}
}
// Get cluster version
public String getClusterVersion() {
try {
V1APIVersions versions = coreV1Api.getAPIVersions();
return versions.getServerAddressByClientCIDRs().toString();
} catch (ApiException e) {
logger.error("Failed to get cluster version", e);
return "Unknown";
}
}
}

Pod Operations

3. Pod Management Service

@Service
public class PodService {
private static final Logger logger = LoggerFactory.getLogger(PodService.class);
private final CoreV1Api coreV1Api;
public PodService(CoreV1Api coreV1Api) {
this.coreV1Api = coreV1Api;
}
// List pods in namespace
public List<V1Pod> listPods(String namespace) throws ApiException {
V1PodList podList = coreV1Api.listNamespacedPod(
namespace, 
null,      // pretty
null,      // allowWatchBookmarks
null,      // continue
null,      // fieldSelector
null,      // labelSelector
null,      // limit
null,      // resourceVersion
null,      // resourceVersionMatch
null,      // timeoutSeconds
null       // watch
);
return podList.getItems();
}
// List pods with label selector
public List<V1Pod> listPodsWithLabels(String namespace, Map<String, String> labels) 
throws ApiException {
String labelSelector = labels.entrySet().stream()
.map(entry -> entry.getKey() + "=" + entry.getValue())
.collect(Collectors.joining(","));
V1PodList podList = coreV1Api.listNamespacedPod(
namespace,
null,      // pretty
null,      // allowWatchBookmarks
null,      // continue
null,      // fieldSelector
labelSelector, // labelSelector
null,      // limit
null,      // resourceVersion
null,      // resourceVersionMatch
null,      // timeoutSeconds
null       // watch
);
return podList.getItems();
}
// Get pod by name
public V1Pod getPod(String namespace, String podName) throws ApiException {
return coreV1Api.readNamespacedPod(podName, namespace, null);
}
// Create pod
public V1Pod createPod(String namespace, V1Pod pod) throws ApiException {
return coreV1Api.createNamespacedPod(namespace, pod, null, null, null, null);
}
// Create simple pod
public V1Pod createSimplePod(String namespace, String podName, String image, 
Map<String, String> labels) throws ApiException {
V1Pod pod = new V1Pod()
.metadata(new V1ObjectMeta()
.name(podName)
.namespace(namespace)
.labels(labels))
.spec(new V1PodSpec()
.containers(Arrays.asList(
new V1Container()
.name(podName + "-container")
.image(image)
.ports(Arrays.asList(
new V1ContainerPort().containerPort(8080)
))
)));
return createPod(namespace, pod);
}
// Delete pod
public void deletePod(String namespace, String podName) throws ApiException {
coreV1Api.deleteNamespacedPod(
podName, 
namespace, 
null,      // pretty
null,      // dryRun
null,      // gracePeriodSeconds
null,      // orphanDependents
null,      // propagationPolicy
null       // body
);
}
// Get pod logs
public String getPodLogs(String namespace, String podName, String containerName) 
throws ApiException {
return coreV1Api.readNamespacedPodLog(
podName, 
namespace, 
containerName, // container
null,          // follow
null,          // insecureSkipTLSVerifyBackend
null,          // limitBytes
null,          // pretty
null,          // previous
null,          // sinceSeconds
null,          // tailLines
null,          // timestamps
null           // version
);
}
// Execute command in pod
public String execCommandInPod(String namespace, String podName, String containerName, 
String[] command) throws ApiException, IOException {
// This is a simplified version - in practice, you'd use the Exec class
// from io.kubernetes.client.Exec
Process process = Runtime.getRuntime().exec(new String[] {
"kubectl", "exec", "-n", namespace, podName, "-c", containerName, "--"
});
// For full implementation, use io.kubernetes.client.Exec
return "Command execution would be implemented here";
}
// Get pod status
public PodStatus getPodStatus(String namespace, String podName) throws ApiException {
V1Pod pod = getPod(namespace, podName);
V1PodStatus status = pod.getStatus();
return new PodStatus(
podName,
namespace,
status.getPhase(),
status.getPodIP(),
status.getStartTime(),
getContainerStatuses(status)
);
}
private List<ContainerStatus> getContainerStatuses(V1PodStatus podStatus) {
List<ContainerStatus> statuses = new ArrayList<>();
if (podStatus.getContainerStatuses() != null) {
for (V1ContainerStatus containerStatus : podStatus.getContainerStatuses()) {
statuses.add(new ContainerStatus(
containerStatus.getName(),
containerStatus.getImage(),
containerStatus.getReady(),
containerStatus.getRestartCount(),
containerStatus.getState()
));
}
}
return statuses;
}
// Watch pods
public void watchPods(String namespace, PodWatcher watcher) {
try {
coreV1Api.listNamespacedPodCall(
namespace,
null,      // pretty
null,      // allowWatchBookmarks
null,      // continue
null,      // fieldSelector
null,      // labelSelector
null,      // limit
null,      // resourceVersion
null,      // resourceVersionMatch
null,      // timeoutSeconds
true,      // watch
new io.kubernetes.client.custom.Watch.ResponseCallback<V1Pod>() {
@Override
public void onResponse(io.kubernetes.client.custom.Watch.Response<V1Pod> response) {
watcher.onEvent(response.type, response.object);
}
@Override
public void onFailure(Throwable t, io.kubernetes.client.custom.Watch.Response<V1Pod> response) {
watcher.onError(t);
}
}
);
} catch (ApiException e) {
watcher.onError(e);
}
}
// Status classes
public static class PodStatus {
private final String name;
private final String namespace;
private final String phase;
private final String podIP;
private final OffsetDateTime startTime;
private final List<ContainerStatus> containerStatuses;
public PodStatus(String name, String namespace, String phase, String podIP, 
OffsetDateTime startTime, List<ContainerStatus> containerStatuses) {
this.name = name;
this.namespace = namespace;
this.phase = phase;
this.podIP = podIP;
this.startTime = startTime;
this.containerStatuses = containerStatuses;
}
// Getters
public String getName() { return name; }
public String getNamespace() { return namespace; }
public String getPhase() { return phase; }
public String getPodIP() { return podIP; }
public OffsetDateTime getStartTime() { return startTime; }
public List<ContainerStatus> getContainerStatuses() { return containerStatuses; }
}
public static class ContainerStatus {
private final String name;
private final String image;
private final Boolean ready;
private final Integer restartCount;
private final V1ContainerState state;
public ContainerStatus(String name, String image, Boolean ready, 
Integer restartCount, V1ContainerState state) {
this.name = name;
this.image = image;
this.ready = ready;
this.restartCount = restartCount;
this.state = state;
}
// Getters
public String getName() { return name; }
public String getImage() { return image; }
public Boolean getReady() { return ready; }
public Integer getRestartCount() { return restartCount; }
public V1ContainerState getState() { return state; }
}
public interface PodWatcher {
void onEvent(String eventType, V1Pod pod);
void onError(Throwable t);
}
}

Deployment Operations

4. Deployment Management Service

@Service
public class DeploymentService {
private static final Logger logger = LoggerFactory.getLogger(DeploymentService.class);
private final AppsV1Api appsV1Api;
public DeploymentService(AppsV1Api appsV1Api) {
this.appsV1Api = appsV1Api;
}
// List deployments in namespace
public List<V1Deployment> listDeployments(String namespace) throws ApiException {
V1DeploymentList deploymentList = appsV1Api.listNamespacedDeployment(
namespace,
null,      // pretty
null,      // allowWatchBookmarks
null,      // continue
null,      // fieldSelector
null,      // labelSelector
null,      // limit
null,      // resourceVersion
null,      // resourceVersionMatch
null,      // timeoutSeconds
null       // watch
);
return deploymentList.getItems();
}
// Get deployment by name
public V1Deployment getDeployment(String namespace, String deploymentName) 
throws ApiException {
return appsV1Api.readNamespacedDeployment(deploymentName, namespace, null);
}
// Create deployment
public V1Deployment createDeployment(String namespace, V1Deployment deployment) 
throws ApiException {
return appsV1Api.createNamespacedDeployment(namespace, deployment, null, null, null, null);
}
// Create simple deployment
public V1Deployment createSimpleDeployment(String namespace, String deploymentName, 
String image, int replicas, 
Map<String, String> labels) throws ApiException {
Map<String, String> selectorLabels = new HashMap<>(labels);
selectorLabels.put("app", deploymentName);
V1Deployment deployment = new V1Deployment()
.metadata(new V1ObjectMeta()
.name(deploymentName)
.namespace(namespace)
.labels(labels))
.spec(new V1DeploymentSpec()
.replicas(replicas)
.selector(new V1LabelSelector()
.matchLabels(selectorLabels))
.template(new V1PodTemplateSpec()
.metadata(new V1ObjectMeta()
.labels(selectorLabels))
.spec(new V1PodSpec()
.containers(Arrays.asList(
new V1Container()
.name(deploymentName + "-container")
.image(image)
.ports(Arrays.asList(
new V1ContainerPort().containerPort(8080)
))
.resources(new V1ResourceRequirements()
.requests(Map.of(
"cpu", new Quantity("100m"),
"memory", new Quantity("128Mi")
))
.limits(Map.of(
"cpu", new Quantity("500m"),
"memory", new Quantity("512Mi")
))
)
))
)
)
);
return createDeployment(namespace, deployment);
}
// Update deployment
public V1Deployment updateDeployment(String namespace, String deploymentName, 
V1Deployment deployment) throws ApiException {
return appsV1Api.replaceNamespacedDeployment(
deploymentName, 
namespace, 
deployment, 
null,      // pretty
null,      // dryRun
null,      // fieldManager
null       // fieldValidation
);
}
// Scale deployment
public V1Deployment scaleDeployment(String namespace, String deploymentName, int replicas) 
throws ApiException {
V1Deployment deployment = getDeployment(namespace, deploymentName);
deployment.getSpec().setReplicas(replicas);
return updateDeployment(namespace, deploymentName, deployment);
}
// Update deployment image
public V1Deployment updateDeploymentImage(String namespace, String deploymentName, 
String containerName, String newImage) 
throws ApiException {
V1Deployment deployment = getDeployment(namespace, deploymentName);
deployment.getSpec().getTemplate().getSpec().getContainers().stream()
.filter(container -> containerName.equals(container.getName()))
.findFirst()
.ifPresent(container -> container.setImage(newImage));
return updateDeployment(namespace, deploymentName, deployment);
}
// Delete deployment
public void deleteDeployment(String namespace, String deploymentName) throws ApiException {
appsV1Api.deleteNamespacedDeployment(
deploymentName,
namespace,
null,      // pretty
null,      // dryRun
null,      // gracePeriodSeconds
null,      // orphanDependents
null,      // propagationPolicy
null       // body
);
}
// Get deployment status
public DeploymentStatus getDeploymentStatus(String namespace, String deploymentName) 
throws ApiException {
V1Deployment deployment = getDeployment(namespace, deploymentName);
V1DeploymentStatus status = deployment.getStatus();
return new DeploymentStatus(
deploymentName,
namespace,
status.getReplicas(),
status.getUpdatedReplicas(),
status.getReadyReplicas(),
status.getAvailableReplicas(),
status.getUnavailableReplicas(),
status.getConditions()
);
}
// Rollback deployment (using patch)
public V1Deployment rollbackDeployment(String namespace, String deploymentName, 
String revision) throws ApiException {
// Create rollback spec
V1DeploymentRollback rollback = new V1DeploymentRollback()
.name(deploymentName)
.rollbackTo(new V1RollbackConfig().revision(Long.parseLong(revision)));
// This would use the patch API in practice
// For simplicity, we're showing the concept
logger.info("Rolling back deployment {} to revision {}", deploymentName, revision);
return getDeployment(namespace, deploymentName);
}
// Wait for deployment to be ready
public boolean waitForDeploymentReady(String namespace, String deploymentName, 
long timeoutSeconds) throws ApiException, InterruptedException {
long startTime = System.currentTimeMillis();
long timeoutMillis = timeoutSeconds * 1000;
while (System.currentTimeMillis() - startTime < timeoutMillis) {
DeploymentStatus status = getDeploymentStatus(namespace, deploymentName);
if (status.isReady()) {
logger.info("Deployment {} is ready", deploymentName);
return true;
}
logger.debug("Waiting for deployment {} to be ready...", deploymentName);
Thread.sleep(5000); // Wait 5 seconds between checks
}
logger.warn("Timeout waiting for deployment {} to be ready", deploymentName);
return false;
}
public static class DeploymentStatus {
private final String name;
private final String namespace;
private final Integer replicas;
private final Integer updatedReplicas;
private final Integer readyReplicas;
private final Integer availableReplicas;
private final Integer unavailableReplicas;
private final List<V1DeploymentCondition> conditions;
public DeploymentStatus(String name, String namespace, Integer replicas, 
Integer updatedReplicas, Integer readyReplicas,
Integer availableReplicas, Integer unavailableReplicas,
List<V1DeploymentCondition> conditions) {
this.name = name;
this.namespace = namespace;
this.replicas = replicas;
this.updatedReplicas = updatedReplicas;
this.readyReplicas = readyReplicas;
this.availableReplicas = availableReplicas;
this.unavailableReplicas = unavailableReplicas;
this.conditions = conditions;
}
public boolean isReady() {
return readyReplicas != null && 
replicas != null && 
readyReplicas.equals(replicas);
}
// Getters
public String getName() { return name; }
public String getNamespace() { return namespace; }
public Integer getReplicas() { return replicas; }
public Integer getUpdatedReplicas() { return updatedReplicas; }
public Integer getReadyReplicas() { return readyReplicas; }
public Integer getAvailableReplicas() { return availableReplicas; }
public Integer getUnavailableReplicas() { return unavailableReplicas; }
public List<V1DeploymentCondition> getConditions() { return conditions; }
}
}

Service Operations

5. Service Management Service

@Service
public class ServiceService {
private static final Logger logger = LoggerFactory.getLogger(ServiceService.class);
private final CoreV1Api coreV1Api;
public ServiceService(CoreV1Api coreV1Api) {
this.coreV1Api = coreV1Api;
}
// List services in namespace
public List<V1Service> listServices(String namespace) throws ApiException {
V1ServiceList serviceList = coreV1Api.listNamespacedService(
namespace,
null,      // pretty
null,      // allowWatchBookmarks
null,      // continue
null,      // fieldSelector
null,      // labelSelector
null,      // limit
null,      // resourceVersion
null,      // resourceVersionMatch
null,      // timeoutSeconds
null       // watch
);
return serviceList.getItems();
}
// Get service by name
public V1Service getService(String namespace, String serviceName) throws ApiException {
return coreV1Api.readNamespacedService(serviceName, namespace, null);
}
// Create service
public V1Service createService(String namespace, V1Service service) throws ApiException {
return coreV1Api.createNamespacedService(namespace, service, null, null, null, null);
}
// Create simple service
public V1Service createSimpleService(String namespace, String serviceName, 
String selectorApp, int port, int targetPort) 
throws ApiException {
V1Service service = new V1Service()
.metadata(new V1ObjectMeta()
.name(serviceName)
.namespace(namespace))
.spec(new V1ServiceSpec()
.selector(Map.of("app", selectorApp))
.ports(Arrays.asList(
new V1ServicePort()
.port(port)
.targetPort(new IntOrString(targetPort))
))
.type("ClusterIP"));
return createService(namespace, service);
}
// Create load balancer service
public V1Service createLoadBalancerService(String namespace, String serviceName,
String selectorApp, int port, int targetPort)
throws ApiException {
V1Service service = new V1Service()
.metadata(new V1ObjectMeta()
.name(serviceName)
.namespace(namespace)
.annotations(Map.of(
"service.beta.kubernetes.io/aws-load-balancer-type", "nlb"
)))
.spec(new V1ServiceSpec()
.selector(Map.of("app", selectorApp))
.ports(Arrays.asList(
new V1ServicePort()
.port(port)
.targetPort(new IntOrString(targetPort))
))
.type("LoadBalancer"));
return createService(namespace, service);
}
// Delete service
public void deleteService(String namespace, String serviceName) throws ApiException {
coreV1Api.deleteNamespacedService(
serviceName,
namespace,
null,      // pretty
null,      // dryRun
null,      // gracePeriodSeconds
null,      // orphanDependents
null,      // propagationPolicy
null       // body
);
}
// Get service endpoints
public V1Endpoints getServiceEndpoints(String namespace, String serviceName) 
throws ApiException {
return coreV1Api.readNamespacedEndpoints(serviceName, namespace, null);
}
}

ConfigMap and Secret Operations

6. Configuration Management Service

@Service
public class ConfigManagementService {
private static final Logger logger = LoggerFactory.getLogger(ConfigManagementService.class);
private final CoreV1Api coreV1Api;
public ConfigManagementService(CoreV1Api coreV1Api) {
this.coreV1Api = coreV1Api;
}
// ConfigMap operations
public V1ConfigMap createConfigMap(String namespace, String name, 
Map<String, String> data) throws ApiException {
V1ConfigMap configMap = new V1ConfigMap()
.metadata(new V1ObjectMeta()
.name(name)
.namespace(namespace))
.data(data);
return coreV1Api.createNamespacedConfigMap(namespace, configMap, null, null, null, null);
}
public V1ConfigMap getConfigMap(String namespace, String name) throws ApiException {
return coreV1Api.readNamespacedConfigMap(name, namespace, null);
}
public V1ConfigMap updateConfigMap(String namespace, String name, 
Map<String, String> data) throws ApiException {
V1ConfigMap configMap = getConfigMap(namespace, name);
configMap.setData(data);
return coreV1Api.replaceNamespacedConfigMap(
name, namespace, configMap, null, null, null, null);
}
public void deleteConfigMap(String namespace, String name) throws ApiException {
coreV1Api.deleteNamespacedConfigMap(name, namespace, null, null, null, null, null, null);
}
// Secret operations
public V1Secret createSecret(String namespace, String name, 
Map<String, byte[]> data) throws ApiException {
V1Secret secret = new V1Secret()
.metadata(new V1ObjectMeta()
.name(name)
.namespace(namespace))
.data(data);
return coreV1Api.createNamespacedSecret(namespace, secret, null, null, null, null);
}
public V1Secret createDockerRegistrySecret(String namespace, String name,
String registryUrl, String username,
String password) throws ApiException {
String auth = Base64.getEncoder().encodeToString(
(username + ":" + password).getBytes());
Map<String, String> data = Map.of(
".dockerconfigjson", Base64.getEncoder().encodeToString(
String.format(
"{\"auths\":{\"%s\":{\"username\":\"%s\",\"password\":\"%s\",\"auth\":\"%s\"}}}",
registryUrl, username, password, auth
).getBytes()
)
);
V1Secret secret = new V1Secret()
.metadata(new V1ObjectMeta()
.name(name)
.namespace(namespace))
.type("kubernetes.io/dockerconfigjson")
.data(data);
return coreV1Api.createNamespacedSecret(namespace, secret, null, null, null, null);
}
public V1Secret getSecret(String namespace, String name) throws ApiException {
return coreV1Api.readNamespacedSecret(name, namespace, null);
}
public void deleteSecret(String namespace, String name) throws ApiException {
coreV1Api.deleteNamespacedSecret(name, namespace, null, null, null, null, null, null);
}
}

Namespace Operations

7. Namespace Management Service

@Service
public class NamespaceService {
private static final Logger logger = LoggerFactory.getLogger(NamespaceService.class);
private final CoreV1Api coreV1Api;
public NamespaceService(CoreV1Api coreV1Api) {
this.coreV1Api = coreV1Api;
}
// List all namespaces
public List<V1Namespace> listNamespaces() throws ApiException {
V1NamespaceList namespaceList = coreV1Api.listNamespace(
null,      // pretty
null,      // allowWatchBookmarks
null,      // continue
null,      // fieldSelector
null,      // labelSelector
null,      // limit
null,      // resourceVersion
null,      // resourceVersionMatch
null,      // timeoutSeconds
null       // watch
);
return namespaceList.getItems();
}
// Get namespace
public V1Namespace getNamespace(String namespace) throws ApiException {
return coreV1Api.readNamespace(namespace, null);
}
// Create namespace
public V1Namespace createNamespace(String namespace) throws ApiException {
V1Namespace ns = new V1Namespace()
.metadata(new V1ObjectMeta().name(namespace));
return coreV1Api.createNamespace(ns, null, null, null, null);
}
// Create namespace with labels
public V1Namespace createNamespace(String namespace, Map<String, String> labels) 
throws ApiException {
V1Namespace ns = new V1Namespace()
.metadata(new V1ObjectMeta()
.name(namespace)
.labels(labels));
return coreV1Api.createNamespace(ns, null, null, null, null);
}
// Delete namespace
public void deleteNamespace(String namespace) throws ApiException {
coreV1Api.deleteNamespace(
namespace,
null,      // pretty
null,      // dryRun
null,      // gracePeriodSeconds
null,      // orphanDependents
null,      // propagationPolicy
null       // body
);
}
// Check if namespace exists
public boolean namespaceExists(String namespace) {
try {
getNamespace(namespace);
return true;
} catch (ApiException e) {
if (e.getCode() == 404) {
return false;
}
throw new RuntimeException("Failed to check namespace existence", e);
}
}
}

Event Monitoring and Watch

8. Event Monitoring Service

@Service
public class EventMonitoringService {
private static final Logger logger = LoggerFactory.getLogger(EventMonitoringService.class);
private final CoreV1Api coreV1Api;
private final AppsV1Api appsV1Api;
public EventMonitoringService(CoreV1Api coreV1Api, AppsV1Api appsV1Api) {
this.coreV1Api = coreV1Api;
this.appsV1Api = appsV1Api;
}
// Watch namespace events
public void watchNamespaceEvents(String namespace, EventWatcher watcher) {
try {
coreV1Api.listNamespacedEventCall(
namespace,
null,      // pretty
null,      // allowWatchBookmarks
null,      // continue
null,      // fieldSelector
null,      // labelSelector
null,      // limit
null,      // resourceVersion
null,      // resourceVersionMatch
null,      // timeoutSeconds
true,      // watch
new io.kubernetes.client.custom.Watch.ResponseCallback<V1Event>() {
@Override
public void onResponse(io.kubernetes.client.custom.Watch.Response<V1Event> response) {
watcher.onEvent(response.type, response.object);
}
@Override
public void onFailure(Throwable t, io.kubernetes.client.custom.Watch.Response<V1Event> response) {
watcher.onError(t);
}
}
);
} catch (ApiException e) {
watcher.onError(e);
}
}
// Get recent events for a namespace
public List<V1Event> getRecentEvents(String namespace, int limit) throws ApiException {
V1EventList eventList = coreV1Api.listNamespacedEvent(
namespace,
null,      // pretty
null,      // allowWatchBookmarks
null,      // continue
null,      // fieldSelector
null,      // labelSelector
limit,     // limit
null,      // resourceVersion
null,      // resourceVersionMatch
null,      // timeoutSeconds
null       // watch
);
return eventList.getItems();
}
// Watch pod events with filtering
public void watchPodEvents(String namespace, String podName, EventWatcher watcher) {
String fieldSelector = "involvedObject.name=" + podName + ",involvedObject.kind=Pod";
try {
coreV1Api.listNamespacedEventCall(
namespace,
null,      // pretty
null,      // allowWatchBookmarks
null,      // continue
fieldSelector, // fieldSelector
null,      // labelSelector
null,      // limit
null,      // resourceVersion
null,      // resourceVersionMatch
null,      // timeoutSeconds
true,      // watch
new io.kubernetes.client.custom.Watch.ResponseCallback<V1Event>() {
@Override
public void onResponse(io.kubernetes.client.custom.Watch.Response<V1Event> response) {
watcher.onEvent(response.type, response.object);
}
@Override
public void onFailure(Throwable t, io.kubernetes.client.custom.Watch.Response<V1Event> response) {
watcher.onError(t);
}
}
);
} catch (ApiException e) {
watcher.onError(e);
}
}
public interface EventWatcher {
void onEvent(String eventType, V1Event event);
void onError(Throwable t);
}
}

Spring Boot Integration

9. Spring Boot Configuration

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import io.kubernetes.client.openapi.ApiClient;
@Configuration
public class KubernetesConfig {
@Bean
public ApiClient kubernetesApiClient() throws Exception {
// Use in-cluster config when running in Kubernetes
// Use default config (~/.kube/config) when running locally
try {
return KubernetesClientFactory.createInClusterClient();
} catch (Exception e) {
return KubernetesClientFactory.createDefaultClient();
}
}
@Bean
public CoreV1Api coreV1Api(ApiClient apiClient) {
return new CoreV1Api(apiClient);
}
@Bean
public AppsV1Api appsV1Api(ApiClient apiClient) {
return new AppsV1Api(apiClient);
}
@Bean
public BatchV1Api batchV1Api(ApiClient apiClient) {
return new BatchV1Api(apiClient);
}
@Bean
public NetworkingV1Api networkingV1Api(ApiClient apiClient) {
return new NetworkingV1Api(apiClient);
}
@Bean
public CustomObjectsApi customObjectsApi(ApiClient apiClient) {
return new CustomObjectsApi(apiClient);
}
}

10. REST Controller for Kubernetes Operations

import org.springframework.web.bind.annotation.*;
import org.springframework.http.ResponseEntity;
import java.util.*;
@RestController
@RequestMapping("/api/kubernetes")
public class KubernetesController {
private final PodService podService;
private final DeploymentService deploymentService;
private final ServiceService serviceService;
private final ConfigManagementService configService;
private final NamespaceService namespaceService;
private final KubernetesService kubernetesService;
public KubernetesController(PodService podService, DeploymentService deploymentService,
ServiceService serviceService, ConfigManagementService configService,
NamespaceService namespaceService, KubernetesService kubernetesService) {
this.podService = podService;
this.deploymentService = deploymentService;
this.serviceService = serviceService;
this.configService = configService;
this.namespaceService = namespaceService;
this.kubernetesService = kubernetesService;
}
@GetMapping("/health")
public ResponseEntity<Map<String, Object>> health() {
boolean healthy = kubernetesService.isClusterHealthy();
String version = kubernetesService.getClusterVersion();
return ResponseEntity.ok(Map.of(
"healthy", healthy,
"version", version,
"timestamp", new Date()
));
}
@GetMapping("/namespaces")
public ResponseEntity<List<V1Namespace>> listNamespaces() {
try {
List<V1Namespace> namespaces = namespaceService.listNamespaces();
return ResponseEntity.ok(namespaces);
} catch (Exception e) {
return ResponseEntity.status(500).build();
}
}
@GetMapping("/namespaces/{namespace}/pods")
public ResponseEntity<List<V1Pod>> listPods(@PathVariable String namespace) {
try {
List<V1Pod> pods = podService.listPods(namespace);
return ResponseEntity.ok(pods);
} catch (Exception e) {
return ResponseEntity.status(500).build();
}
}
@GetMapping("/namespaces/{namespace}/deployments")
public ResponseEntity<List<V1Deployment>> listDeployments(@PathVariable String namespace) {
try {
List<V1Deployment> deployments = deploymentService.listDeployments(namespace);
return ResponseEntity.ok(deployments);
} catch (Exception e) {
return ResponseEntity.status(500).build();
}
}
@PostMapping("/namespaces/{namespace}/deployments")
public ResponseEntity<V1Deployment> createDeployment(
@PathVariable String namespace,
@RequestBody DeploymentRequest request) {
try {
V1Deployment deployment = deploymentService.createSimpleDeployment(
namespace,
request.getName(),
request.getImage(),
request.getReplicas(),
request.getLabels()
);
return ResponseEntity.ok(deployment);
} catch (Exception e) {
return ResponseEntity.status(500).build();
}
}
@PutMapping("/namespaces/{namespace}/deployments/{deploymentName}/scale")
public ResponseEntity<V1Deployment> scaleDeployment(
@PathVariable String namespace,
@PathVariable String deploymentName,
@RequestParam int replicas) {
try {
V1Deployment deployment = deploymentService.scaleDeployment(
namespace, deploymentName, replicas);
return ResponseEntity.ok(deployment);
} catch (Exception e) {
return ResponseEntity.status(500).build();
}
}
@GetMapping("/namespaces/{namespace}/pods/{podName}/logs")
public ResponseEntity<String> getPodLogs(
@PathVariable String namespace,
@PathVariable String podName,
@RequestParam(defaultValue = "app") String container) {
try {
String logs = podService.getPodLogs(namespace, podName, container);
return ResponseEntity.ok(logs);
} catch (Exception e) {
return ResponseEntity.status(500).build();
}
}
public static class DeploymentRequest {
private String name;
private String image;
private int replicas;
private Map<String, String> labels;
// Getters and setters
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getImage() { return image; }
public void setImage(String image) { this.image = image; }
public int getReplicas() { return replicas; }
public void setReplicas(int replicas) { this.replicas = replicas; }
public Map<String, String> getLabels() { return labels; }
public void setLabels(Map<String, String> labels) { this.labels = labels; }
}
}

Usage Examples

@Service
public class KubernetesExampleService {
private final PodService podService;
private final DeploymentService deploymentService;
private final ServiceService serviceService;
private final ConfigManagementService configService;
public KubernetesExampleService(PodService podService, DeploymentService deploymentService,
ServiceService serviceService, ConfigManagementService configService) {
this.podService = podService;
this.deploymentService = deploymentService;
this.serviceService = serviceService;
this.configService = configService;
}
public void deployApplication(String namespace, String appName, String image) {
try {
// Create deployment
Map<String, String> labels = Map.of("app", appName, "version", "1.0");
V1Deployment deployment = deploymentService.createSimpleDeployment(
namespace, appName, image, 3, labels);
logger.info("Created deployment: {}", deployment.getMetadata().getName());
// Create service
V1Service service = serviceService.createSimpleService(
namespace, appName + "-service", appName, 80, 8080);
logger.info("Created service: {}", service.getMetadata().getName());
// Create config map
Map<String, String> configData = Map.of(
"application.properties", "server.port=8080\nlogging.level.com.example=DEBUG"
);
V1ConfigMap configMap = configService.createConfigMap(
namespace, appName + "-config", configData);
logger.info("Created config map: {}", configMap.getMetadata().getName());
// Wait for deployment to be ready
boolean ready = deploymentService.waitForDeploymentReady(namespace, appName, 300);
if (ready) {
logger.info("Application {} deployed successfully", appName);
} else {
logger.warn("Application {} deployment timeout", appName);
}
} catch (Exception e) {
logger.error("Failed to deploy application {}", appName, e);
}
}
public void monitorApplication(String namespace, String appName) {
// Set up pod watcher
podService.watchPods(namespace, new PodService.PodWatcher() {
@Override
public void onEvent(String eventType, V1Pod pod) {
if (appName.equals(pod.getMetadata().getLabels().get("app"))) {
logger.info("Pod event: {} - {} - {}", 
eventType, pod.getMetadata().getName(), pod.getStatus().getPhase());
}
}
@Override
public void onError(Throwable t) {
logger.error("Pod watch error", t);
}
});
}
}

This comprehensive Kubernetes Java Client implementation provides:

  1. Client Configuration: Multiple ways to configure Kubernetes client
  2. Pod Management: Create, read, update, delete pods with status monitoring
  3. Deployment Management: Full deployment lifecycle management
  4. Service Management: Service creation and management
  5. ConfigMap and Secrets: Configuration management
  6. Namespace Operations: Namespace lifecycle management
  7. Event Monitoring: Real-time event watching
  8. Spring Boot Integration: Easy Spring Boot configuration
  9. REST API: Expose Kubernetes operations via REST endpoints

The implementation handles error cases, provides fluent APIs, and supports both in-cluster and external Kubernetes configurations.

Leave a Reply

Your email address will not be published. Required fields are marked *


Macro Nepal Helper