Rolling Updates en Kubernetes desde Java con Fabric8 Kubernetes Client 7
Introducción
En el mundo de las aplicaciones cloud-native, es esencial mantener tus servicios actualizados y funcionando sin problemas. Los usuarios exigen disponibilidad 24/7, y el tiempo de inactividad puede provocar pérdidas de ingresos y clientes insatisfechos. Al mismo tiempo, los desarrolladores se enfrentan a una presión creciente para ofrecer nuevas funcionalidades y correcciones de errores rápidamente.
Kubernetes proporciona una poderosa característica llamada Rolling Updates que te permite actualizar tus aplicaciones sin tiempo de inactividad. Al reemplazar gradualmente la versión antigua de tu aplicación por la nueva, Kubernetes garantiza que tus servicios sigan disponibles durante todo el proceso de actualización.
En este artículo, te mostraré cómo realizar un Rolling Update en Kubernetes desde Java utilizando el Fabric8 Kubernetes Client versión 7.
¿Cómo funcionan los Rolling Updates?
En Kubernetes, los Deployments son la forma más común de desplegar aplicaciones. Un Deployment especifica el estado deseado de tu aplicación, incluyendo el número de réplicas, imágenes de contenedor y otras configuraciones. Kubernetes, siendo un sistema declarativo, trabaja para garantizar que el estado real coincida con el estado deseado.
Cuando creas o actualizas un Deployment, Kubernetes crea un nuevo ReplicaSet para gestionar la versión actualizada de tu aplicación. El ReplicaSet garantiza que el número deseado de réplicas (Pods) estén en ejecución y estén saludables.
Durante un Rolling Update, Kubernetes creará un nuevo ReplicaSet con la versión actualizada de tu aplicación y escalará gradualmente el nuevo ReplicaSet mientras reduce el antiguo. Kubernetes esperará a que los nuevos Pods estén saludables antes de eliminar los antiguos, garantizando una interrupción mínima.
Si algo sale mal durante la actualización, Kubernetes te permite volver a una versión anterior. En este caso, el proceso se invierte: el antiguo ReplicaSet se escala mientras el nuevo se reduce.
Cómo realizar un Rolling Update desde Java
Veamos ahora cómo realizar actualizaciones de Kubernetes de forma programática utilizando el Fabric8 Kubernetes Client versión 7.
Para la demostración, utilizaremos Nginx como nuestra aplicación de ejemplo. Comencemos por desplegarla en el clúster.
Desplegando la aplicación Nginx
Primero, creamos un Deployment
para la aplicación nginx
.
Podemos utilizar fácilmente el Fabric8 Kubernetes Client y su DSL para crear y aplicar el Deployment
al clúster.
El siguiente fragmento muestra cómo:
import io.fabric8.kubernetes.api.model.PodSpecBuilder;
import io.fabric8.kubernetes.api.model.apps.DeploymentBuilder;
import io.fabric8.kubernetes.api.model.apps.DeploymentSpecBuilder;
import io.fabric8.kubernetes.client.KubernetesClientBuilder;
public class DeployNginx {
public static void main(String[] args) {
try (var client = new KubernetesClientBuilder().build()) {
var nginx = new DeploymentBuilder()
.withNewMetadata().withName("nginx").endMetadata()
.withSpec(new DeploymentSpecBuilder()
.withReplicas(1)
.withNewSelector().addToMatchLabels("app", "nginx").endSelector()
.withNewTemplate()
.withNewMetadata().addToLabels("app", "nginx").endMetadata()
.withSpec(new PodSpecBuilder()
.addNewContainer()
.withName("nginx")
.withImage("nginx:1.26")
.addNewPort().withContainerPort(80).endPort()
.endContainer()
.build())
.endTemplate()
.build())
.build();
client.apps().deployments().inNamespace("default").resource(nginx).serverSideApply();
}
}
}
Este código crea un nuevo Deployment
para la aplicación nginx con una única réplica.
El Deployment
utiliza la imagen de nginx nginx:1.26
y expone el puerto 80
.
Luego, utiliza el método serverSideApply()
para aplicar el nuevo Deployment
al clúster.
Actualizando la versión de la aplicación Nginx
Ahora que hemos desplegado la aplicación nginx, actualicémosla a una nueva versión.
Podemos actualizar fácilmente el Deployment
utilizando nuevamente el Fabric8 Kubernetes Client y su DSL.
import io.fabric8.kubernetes.api.model.apps.DeploymentBuilder;
import io.fabric8.kubernetes.client.KubernetesClientBuilder;
public class UpdateNginx {
public static void main(String[] args) {
try (var client = new KubernetesClientBuilder().build()) {
client.apps().deployments().inNamespace("default").withName("nginx")
.edit(nginx -> new DeploymentBuilder(nginx)
.editSpec().editTemplate().editSpec().editContainer(0)
.withImage("nginx:1.27")
.endContainer().endSpec().endTemplate().endSpec()
.build());
}
}
}
En este ejemplo, actualizamos la aplicación nginx a la versión 1.27
cambiando la imagen del contenedor en el Deployment
.
Para ello, utilizamos el método edit()
para modificar el Deployment
y aplicar los cambios al clúster.
Observa cómo el despliegue existente se pasa al constructor de DeploymentBuilder
para modificarlo en su lugar y preservar el resto de la configuración.
Revertir la aplicación nginx
Si algo sale mal durante el proceso de actualización, podemos revertir fácilmente la aplicación nginx a la versión anterior.
El siguiente fragmento muestra cómo revertir la aplicación nginx a la versión 1.26
:
import io.fabric8.kubernetes.client.KubernetesClientBuilder;
public class RollbackNginx {
public static void main(String[] args) {
try (var client = new KubernetesClientBuilder().build()) {
client.apps().deployments().inNamespace("default").withName("nginx")
.rolling().undo();
}
}
}
En este ejemplo, utilizamos el método rolling().undo()
para revertir la aplicación nginx a la versión anterior.
Kubernetes escalará automáticamente el antiguo ReplicaSet mientras reduce el nuevo ReplicaSet.
Pausar y reanudar el Rolling Update
Kubernetes proporciona los medios para pausar los despliegues para evitar cambios adicionales en el ReplicaSet del Deployment. Esto puede ser útil si deseas aplicar múltiples correcciones entre una pausa y una reanudación sin desencadenar despliegues intermedios.
El siguiente fragmento muestra cómo pausar las actualizaciones de forma programática para la aplicación nginx:
import io.fabric8.kubernetes.client.KubernetesClientBuilder;
public class PauseNginx {
public static void main(String[] args) {
try (var client = new KubernetesClientBuilder().build()) {
client.apps().deployments().inNamespace("default").withName("nginx")
.rolling().pause();
}
}
}
En este ejemplo, utilizamos el método rolling().pause()
para pausar las actualizaciones de forma programática para la aplicación nginx.
Cualquier cambio que apliquemos al Deployment no desencadenará un despliegue hasta que reanudemos las actualizaciones en curso.
El siguiente fragmento muestra cómo reanudar las actualizaciones para la aplicación nginx:
import io.fabric8.kubernetes.client.KubernetesClientBuilder;
public class ResumeNginx {
public static void main(String[] args) {
try (var client = new KubernetesClientBuilder().build()) {
client.apps().deployments().inNamespace("default").withName("nginx")
.rolling().resume();
}
}
}
En este ejemplo, utilizamos el método rolling().resume()
para reanudar las actualizaciones para la aplicación nginx.
Conclusión
Kubernetes proporciona una poderosa característica llamada Rolling Updates que te permite actualizar tus aplicaciones sin tiempo de inactividad. Aprovechando el Fabric8 Kubernetes Client, puedes realizar fácilmente Rolling Updates desde Java, asegurando que tus servicios sigan disponibles durante el proceso de actualización.
En este artículo, hemos visto cómo desplegar una aplicación, actualizar su versión, revertir a una versión anterior, pausar y reanudar el proceso de Rolling Update. El Fabric8 Kubernetes Client proporciona una API simple e intuitiva para interactuar con los recursos de Kubernetes, facilitando la gestión de tus aplicaciones desde Java.