Kubernetes Client for Java: Presentando YAKC
Introducción
Desde hace algún tiempo, soy uno de los miembros del equipo que se encarga del mantenimiento de Fabric8 Kubernetes Client, uno de los clientes Java más populares para Kubernetes y OpenShift. Fabric8 Kubernetes Client es una de las mejores opciones disponibles ya que nos permite hacer la mayoría de operaciones soportadas por kubectl
desde Java con una API muy elegante y fluida. No obstante, acceder a las operaciones de bajo nivel de la API REST o a una versión específica de la API es complicado, ya que el cliente de Fabric8 no lo permite (de momento). Este es el principal motivo que me ha llevado a implementar Yet Another Kubernetes Client (YAKC), un proyecto paralelo durante las vacaciones de Pascua.
El objetivo de Fabric8 Kubernetes Client es proporcionar un sustituto de kubectl
para Java siendo básicamente una adaptación de client-go. Por otro lado, YAKC es un cliente Java REST declarativo para la API de Kubernetes. YAKC proporciona acceso a las operaciones y modelo definidos en el esquema OpenAPI de Kubernetes además de herramientas para detectar la configuración de seguridad y extensiones para acceder a operaciones no documentadas en dicho esquema. También proporciona interfaces reactivas para acceder a los recursos y soporte para Streams.
YAKC – Yet Another Kubernetes Client
Veamos ahora cómo podemos emplear YAKC para realizar alguna de las operaciones básicas. También puedes examinar la carpeta quickstarts en el repositorio para acceder a una lista creciente de proyectos de ejemplo.
Setup
El cliente se compone de varios módulos que permitirán hacerlo extensible en el futuro. Para poder acceder a todas las características del proyecto hay que agregar dependencias a los módulos kubernetes-client y kubernetes-api.
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}
Una vez el proyecto se ha configurado, obtener una instancia del cliente con la configuración autodetectada es bastante sencillo:
1try (KubernetesClient kc = new KubernetesClient()) {
2 /* ... */
3}
También se puede proporcionar una configuración manual si no queremos que YAKC detecte la configuración automáticamente:
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}
Gestión de objetos correspondientes a Recursos
Aunque el proyecto no proporciona una interfaz fluida, construir un objeto es bastante sencillo y rápido ya que hay builders disponibles para todos las clases de Modelos.
La siguiente definición de un recurso en formato YAML:
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
podría ser reescrita de este modo:
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();
Ejemplos básicos
A continuación se muestran algunos ejemplos de como realizar alguna de las operaciones básicas:
Crear un Pod
El siguiente código crea un Pod en el namespace “default” con un label, una anotación y un único contenedor con la imagen containous/whoami
.
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();
Listar Pods en todos los namespaces
El siguiente código listará los Pods en todos los namespaces empleando la interfaz Streams (Java 8) para imprimir sus nombres por el standard output (consola).
1kubernetesClient.create(CoreV1Api.class).listPodForAllNamespaces().stream()
2 .map(Pod::getMetadata)
3 .map(ObjectMeta::getName)
4 .forEach(System.out::println);
Observar los recursos Pod en todos los namespaces
Este ejemplo demuestra como podemos emplear la clase Observable de ReactiveX para observar algunos recursos y aplicar filtrado del lado del cliente para completar la suscripción una vez el primer evento de tipo MODIFIED se recibe.
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);
Conclusión
En esta publicación hemos visto como realizar una configuración básica de un proyecto Java para poder utilizar YAKC (Yet Another Kubernetes Client) y algunos ejemplos sencillos de cómo realizar algunas operaciones básicas en nuestro clúster.
En breve se publicarán más artículos describiendo lo que ya se puede ver en la sección de proyectos Quick start del repositorio en GitHub.