Kubernetes Client for Java: Introducing YAKC
Introduction
As some of you may know, I’m a proud member of the team maintaining Fabric8 Kubernetes Client (for a while now). Fabric8 is one of the most popular Java clients for Kubernetes and OpenShift. Fabric8 Kubernetes Client is great because it allows to perform most of the kubectl
supported operations from Java with a very neat and fluent API. However, accessing low-level REST API operations or specific API versions is hard because some of these decisions are taken for you (for now). This is the main reason that drove me to implement Yet Another Kubernetes Client (YAKC) as a side project during these Easter holidays.
Fabric8’s Kubernetes client aim is to provide a complete substitute of kubectl
for Java and it’s mostly a port for Java of the official client-go. On the other hand, YAKC is a declarative Java REST client for the Kubernetes API. YAKC provides access to the documented OpenAPI and model definitions with some helpers to detect the security configuration and extensions for non-documented features. It also provides a reactive interface to access resources and support for Streams.
YAKC – Yet Another Kubernetes Client
Now let’s see how you can make use of YAKC to perform some basic operations. You can also check the quickstarts folder in the repository for a list of increasing example projects.
Setup
The client is separated into several modules that provide support for future extensibility. In order to be able to access the complete features of the project you will need to depend on kubernetes-client and kubernetes-api modules.
Maven
1<dependencies>
2 <dependency>
3 <groupId>com.marcnuri.yakc</groupId>
4 <artifactId>kubernetes-api</artifactId>
5 <version>0.0.25</version>
6 </dependency>
7 <dependency>
8 <groupId>com.marcnuri.yakc</groupId>
9 <artifactId>kubernetes-client</artifactId>
10 <version>0.0.25</version>
11 </dependency>
12</dependencies>
Gradle
1dependencies {
2 compile 'com.marcnuri.yakc:kubernetes-api:0.0.25'
3 compile 'com.marcnuri.yakc:kubernetes-client:0.0.25'
4}
Once your project is setup, getting an instance of the client with autodetected settings is relatively easy:
1try (KubernetesClient kc = new KubernetesClient()) {
2 /* ... */
3}
You can also provide a manual configuration for the client if you don’t want to use autodetect features:
1final Configuration configuration = Configuration.builder()
2 .server("server-host")
3 .insecureSkipTlsVerify(true)
4 .username("user")
5 .password("password")
6 /* ... */
7 .build();
8try (KubernetesClient kc = new KubernetesClient(configuration )) {
9 /* ... */
10}
Resource object handling
Although the project doesn’t provide a completely fluent interface, writing a model object is relatively simple and effort-less as there are builders available for all Model types.
The following YAML resource definition:
1kind: Pod
2apiVersion: v1
3metadata:
4 name: yakc-test
5 labels:
6 app: yakc-kubernetes-client
7 annotations:
8 yakc: rulez!
9spec:
10 containers:
11 - name: yakc-pod
12 image: busybox
can be easily implemented as:
1Pod.builder()
2 .metadata(ObjectMeta.builder()
3 .name("yakc-test")
4 .putInLabels("app", "yakc-kubernetes-client")
5 .putInAnnotations("yakc", "rulez!")
6 .build())
7 .spec(PodSpec.builder()
8 .addToContainers(Container.builder()
9 .name("yakc-pod")
10 .image("busybox")
11 .build())
12 .build())
13 .build();
Basic examples
We can now see some examples describing how to perform some simple operations:
Create a Pod
The following code creates a pod in the “default” namespace with a label, an annotation and a single container with containous/whoami
image.
1kubernetesClient.create(CoreV1Api.class).createNamespacedPod("default", Pod.builder()
2 .metadata(ObjectMeta.builder()
3 .name("yakc-pod-example")
4 .putInLabels("app", "yakc-pod-example")
5 .putInAnnotations("com.marcnuri.yakc", "pod-example")
6 .build())
7 .spec(PodSpec.builder()
8 .addToContainers(Container.builder()
9 .image("containous/whoami")
10 .name("java-test-pod")
11 .build())
12 .build())
13 .build()).get();
List Pods in all namespaces
The following code will list Pods in all namespaces using the Java 8 Streams interface and print their names to the standard output.
1kubernetesClient.create(CoreV1Api.class).listPodForAllNamespaces().stream()
2 .map(Pod::getMetadata)
3 .map(ObjectMeta::getName)
4 .forEach(System.out::println);
Watch Pod resources in all namespaces
This example highlights how we can use the ReactiveX Observable class to watch some resources applying client-side filtering and stopping the subscription once the first MODIFIED event type is received.
1kubernetesClient.create(CoreV1Api.class).listPodForAllNamespaces().watch()
2 .filter(we -> we.getObject().getMetadata().getCreationTimestamp().isAfter(OffsetDateTime.now()))
3 .takeUntil(we -> we.getType() == Type.MODIFIED)
4 .map(WatchEvent::getObject).map(Pod::getMetadata).map(ObjectMeta::getName)
5 .subscribe(System.out::println);
Conclusion
In this post I’ve shown you how to perform a basic setup of a Java project to make use of YAKC (Yet Another Kubernetes Client). I also included some code snippets describing how to perform basic operations in our cluster.
More posts are coming documenting and describing what you can already see in the Quick start projects section of the GitHub repository.