A logo showing the text blog.marcnuri.com
Español
Home»Java»Access the Kubernetes API from a Pod in Java

Recent Posts

  • Fabric8 Kubernetes Client 7.2 is now available!
  • Connecting to an MCP Server from JavaScript using AI SDK
  • Connecting to an MCP Server from JavaScript using LangChain.js
  • The Future of Developer Tools: Adapting to Machine-Based Developers
  • Connecting to a Model Context Protocol (MCP) Server from Java using LangChain4j

Categories

  • Artificial Intelligence
  • Front-end
  • Go
  • Industry and business
  • Java
  • JavaScript
  • Legacy
  • Operations
  • Personal
  • Pet projects
  • Tools

Archives

  • May 2025
  • April 2025
  • March 2025
  • February 2025
  • January 2025
  • December 2024
  • November 2024
  • August 2024
  • June 2024
  • May 2024
  • April 2024
  • March 2024
  • February 2024
  • January 2024
  • December 2023
  • November 2023
  • October 2023
  • September 2023
  • August 2023
  • July 2023
  • June 2023
  • May 2023
  • April 2023
  • March 2023
  • February 2023
  • January 2023
  • December 2022
  • November 2022
  • October 2022
  • September 2022
  • August 2022
  • July 2022
  • June 2022
  • May 2022
  • March 2022
  • February 2022
  • January 2022
  • December 2021
  • November 2021
  • October 2021
  • September 2021
  • August 2021
  • July 2021
  • January 2021
  • December 2020
  • November 2020
  • October 2020
  • September 2020
  • August 2020
  • July 2020
  • June 2020
  • May 2020
  • February 2020
  • January 2020
  • December 2019
  • October 2019
  • September 2019
  • July 2019
  • March 2019
  • November 2018
  • July 2018
  • June 2018
  • May 2018
  • April 2018
  • March 2018
  • February 2018
  • December 2017
  • July 2017
  • January 2017
  • December 2015
  • November 2015
  • December 2014
  • March 2014
  • February 2011
  • November 2008
  • June 2008
  • May 2008
  • April 2008
  • January 2008
  • November 2007
  • September 2007
  • August 2007
  • July 2007
  • June 2007
  • May 2007
  • April 2007
  • March 2007

Access the Kubernetes API from a Pod in Java

2020-06-06 in Java tagged Client / Cloud / Java / Eclipse JKube / Kubernetes / OpenShift / YAKC by Marc Nuri | Last updated: 2022-02-03
Versión en Español

Introduction

In this example, I will show you how to access the Kubernetes cluster’s REST API from inside a Pod using YAKC (Yet Another Kubernetes Client), Eclipse JKube and Spring Boot.

In the first part of the tutorial I’ll show how to create a very simple Spring Boot application with the required YAKC Kubernetes Client dependency (see the introductory post for YAKC).

Next you’ll see how to quickly deploy the application into a Kubernetes cluster. I will also show you how to perform requests to the Pod’s exposed REST endpoints to retrieve information from the cluster.

Example application

The first step will be to create an example Spring Boot Maven application. This is the pom.xml file that we’ll be using for this example. Besides the standard Spring Boot dependencies, we’ll need to include the required dependencies for YAKC Kubernetes Client:

1<!-- ... -->
2  <dependencies>
3<!-- ... -->
4    <dependency>
5      <groupId>com.marcnuri.yakc</groupId>
6      <artifactId>kubernetes-api</artifactId>
7      <version>${project.version}</version>
8    </dependency>
9    <dependency>
10      <groupId>com.marcnuri.yakc</groupId>
11      <artifactId>kubernetes-client</artifactId>
12      <version>${project.version}</version>
13    </dependency>
14  </dependencies>
15<!-- ... -->

We can now declare a shared Bean of KubernetesClient in the application’s main class (AccessClusterFromPodApplication):

1/* ... */
2  @Bean(destroyMethod = "close")
3  public KubernetesClient kubernetesClient() {
4    return new KubernetesClient();
5  }
6/* ... */

This Bean enables us to autowire the KubernetesClient singleton instance into any of the application’s components.

Cluster Service

We’ll define the different methods in the ClusterService interface and their implementations in the KubernetesClientClusterService implementation.

The most complex method in this class will be the implementation of getDeploymentLogs that will retrieve the aggregated Pod logs sorted by time for a specific deployment. Since this is the most complex method I’ll analyze its implementation, the rest of the method implementations should be self-explanatory.

1@Override
2  public String getDeploymentLogs(String deploymentName) {
3    try {
4      final Deployment deployment = kubernetesClient.create(AppsV1Api.class)
5        .readNamespacedDeployment(deploymentName, getNamespace()).get();
6      return kubernetesClient.create(CoreV1Api.class).listNamespacedPod(getNamespace(),
7        new ListNamespacedPod().labelSelector(
8          deployment.getSpec().getSelector().getMatchLabels().entrySet().stream()
9            .map(e -> String.format("%s=%s", e.getKey(), e.getValue())).collect(
10            Collectors.joining(","))
11        )).stream()
12        .flatMap(this::getPodLog)
13        .sorted()
14        .collect(Collectors.joining("\n"));
15    } catch(NotFoundException e) {
16      throw new ResponseStatusException(HttpStatus.NOT_FOUND, e.getMessage());
17    } catch (IOException e) {
18      throw new ServerErrorException(e.getMessage(), e);
19    }
20  }
21
22  private Stream<String> getPodLog(Pod pod) {
23    try {
24      return Stream.of(kubernetesClient.create(CoreV1Api.class)
25        .readNamespacedPodLog(pod.getMetadata().getName(), getNamespace(), new ReadNamespacedPodLog().timestamps(true))
26        .get().split("\n")
27      ).map(logLine -> {
28        final String[] splitLine = logLine.split("\\s", 2);
29        return String.format("%s [%s] - %s", splitLine[0], pod.getMetadata().getName(),
30          splitLine.length > 1 ? splitLine[1] : "");
31      });
32    } catch (IOException e) {
33      throw new ServerErrorException("Cannot retrieve log", e);
34    }
35  }

The method starts by creating the client for the Apps V1 API which is used to get the information for the provided Deployment name in the configured namespace.

The Deployment spec.selector.matchLabels field entries are used in a Core V1 API client to retrieve the Pods that match this selector. The resulting Pods are streamed and flat mapped to a stream of log entries for all of the matching Pods, this mapping is performed by the getPodLog method.

The getPodLog method uses the Core V1 API client to read the logs of a given Pod including timestamps. The resulting log is then split by line separators and transformed to include the Pod name after the timestamp.

After the mapping is completed the getDeploymentLogs sorts the log entries and merges them back into a single String which is returned.

Despite the complexity to merge logs from all Pods for a given deployment, YAKC’s declarative and streamable interfaces make it very easy and straightforward. The resulting implementation is very readable too and I can accomplish this task with very few lines of code.

Cluster Resource

The ClusterResource class implements the different REST endpoints that will be exposed by our application. This class is a standard Spring RestController with GetMapping annotated methods to retrieve the configured namespace, available Deployments and Pods in this namespace and the aggregated log entries for all Pods in a given Deployment. For the service method explained in the previous section, we can perform a GET request to http://cluster-ingress-url/deployments/deployment-name/logs to retrieve the aggregate log for the specified deployment:

1@GetMapping("deployments/{deployment}/logs")
2  public String getDeploymentLogs(@PathVariable("deployment") String deployment) {
3    return clusterService.getDeploymentLogs(deployment);
4  }

Deploying the application into the Cluster

We’ve seen the anatomy of our application and how it makes use of YAKC to interact with a Kubernetes cluster. Now let’s see how to deploy the application into the cluster.

The main requirement to allow access from a Pod to the cluster’s API is to provide access to the default Pod’s service account. You can achieve this by running the following command:

1kubectl create clusterrolebinding default-cluster-admin --clusterrole cluster-admin --serviceaccount=default:default

From this point on, the default service account (credentials provided in /var/run/secrets/kubernetes.io/serviceaccount/token) in your Pod will be able to access the cluster’s REST API.

Eclipse JKube

The example uses Eclipse JKube’s Kubernetes Maven Plugin to easily build and deploy the Java application into Kubernetes.

The plugin is configured in the pom.xml:

1<!-- ... -->
2<plugin>
3  <groupId>org.eclipse.jkube</groupId>
4  <artifactId>kubernetes-maven-plugin</artifactId>
5  <version>1.18.1</version>
6  <executions>
7    <execution>
8      <id>jkube</id>
9      <phase>package</phase>
10      <goals>
11        <goal>build</goal>
12        <goal>resource</goal>
13        <goal>apply</goal>
14      </goals>
15    </execution>
16  </executions>
17  <configuration>
18    <enricher>
19      <config>
20        <jkube-service>
21          <type>NodePort</type>
22        </jkube-service>
23      </config>
24    </enricher>
25  </configuration>
26</plugin>
27<!-- ... -->

The plugin is configured so that the docker image is built and deployed into the cluster when running the mvn package command.

You can also see a JKube enricher configuration to make the Kuberentes service of type NodePort.

If we are running Minikube we first need to get access to the Docker daemon in the cluster. This allows us to skip pushing the built image to a shared registry too.

  • eval $(minikube docker-env) on Linux
  • @FOR /f "tokens=*" %i IN ('minikube -p minikube docker-env') DO @%i on Windows

We can now proceed to deploy our application (mvn clean package):

Access Cluster From Pod JKube mvn package
Access Cluster From Pod JKube mvn package

The application should now be deployed, if running Minikube we can check out some of the endpoints with the following commands:

Access Cluster From Pod curl
Access Cluster From Pod curl

Conclusion

In this post, we’ve seen how we can very easily access a Kubernetes cluster REST API from within a Java application running in one of the cluster’s Pods using YAKC (Yet Another Kubernetes Client). We’ve also covered how to build the image for the application and deploy it on the cluster with very little configuration taking advantage of Eclipse JKube’s Kubernetes Maven Plugin.

You can check the full source code for this post in the quickstarts section of YAKC’s GitHub repository.

YAKC - Yet Another Kubernetes Client
YAKC - Yet Another Kubernetes Client
Twitter iconFacebook iconLinkedIn iconPinterest iconEmail icon

Post navigation
JBang: Unlocking Java's Scripting PotentialKubernetes Client for Java: Introducing YAKC
© 2007 - 2025 Marc Nuri