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:
- Client Configuration: Multiple ways to configure Kubernetes client
- Pod Management: Create, read, update, delete pods with status monitoring
- Deployment Management: Full deployment lifecycle management
- Service Management: Service creation and management
- ConfigMap and Secrets: Configuration management
- Namespace Operations: Namespace lifecycle management
- Event Monitoring: Real-time event watching
- Spring Boot Integration: Easy Spring Boot configuration
- 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.