Access the Kuberntes API from a Pod in Java


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:

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

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.

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:

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:

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:

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

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

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

Leave a comment

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