Rollout Restart Kubernetes Deployment from Java using YAKC
Introduction
In this post, I’ll show you how to perform the equivalent to kubectl rollout restart deployment/$deployment
(rolling restart) from Java using YAKC- Yet Another Kubernetes Client.
Rollout Restart
Starting at version 1.15, Kubernetes offers a new way to restart Deployments, DaemonSets, and StatefulSets using kubectl
.
You can simply invoke a kubectl rollout restart deployment/$deployment
and Kubernetes will restart your application with zero downtime.
Before v1.15 you could do something similar by adding an annotation to the Deployment spec template. If we dig into the source code for Kubectl, we’ll find out that what the provided command does is exactly that. Kubectl adds a new annotation to the Pod templates so that the underlying Pods get reconciled via new ReplicaSets without any downtime.
1case *appsv1.Deployment:
2 if obj.Spec.Paused {
3 return nil, errors.New("can't restart paused deployment (run rollout resume first)")
4 }
5 if obj.Spec.Template.ObjectMeta.Annotations == nil {
6 obj.Spec.Template.ObjectMeta.Annotations = make(map[string]string)
7 }
8 obj.Spec.Template.ObjectMeta.Annotations["kubectl.kubernetes.io/restartedAt"] = time.Now().Format(time.RFC3339)
9 return runtime.Encode(scheme.Codecs.LegacyCodec(appsv1.SchemeGroupVersion), obj)
Rollout Restart from Java
Now that we know that performing a rolling restart is as simple as patching a Deployment/DaemonSet/StatefulSet to add a new annotation to the PodTemplate, let’s see how we can achieve this with YAKC.
Since it’s a simple matter of patching the PodTemplate annotations, you can achieve this by using the following code:
1final Deployment deployment = new Deployment();
2deployment.setSpec(new DeploymentSpec());
3deployment.getSpec().setTemplate(PodTemplateSpec.builder()
4 .metadata(ObjectMeta.builder()
5 .putInAnnotations("yakc.marcnuri.com/restartedAt", Instant.now().toString())
6 .build())
7 .build());
8kubernetesClient.create(AppsV1Api.class)
9 .patchNamespacedDeployment("deployment-namespace", "your-namespace", deployment)
10 .get();
In the first lines, I create an empty Deployment
with an empty DeploymentSpec
. I could try to do this with the builders provided by YAKC. The problem is that since we are going to perform a PATCH some of the required fields will be missing and the builder validation would throw an Exception otherwise.
For the annotation part, I’m using the ObjectMeta#builder
(no required field exceptions this time). I’m simply adding an annotation for yakc.marcnuri.com/restartedAt
with the current timestamp (same as Kubectl).
Finally, I’m sending the Deployment PATCH using YAKC Kubernetes Client for the AppsV1API.
I showed you how to do this for Deployments, but you can do the exact same thing with DaemonSets:
1final DaemonSet daemonSet = new DaemonSet();
2daemonSet.setSpec(new DaemonSetSpec());
3daemonSet.getSpec().setTemplate(PodTemplateSpec.builder()
4 .metadata(ObjectMeta.builder()
5 .putInAnnotations("yakc.marcnuri.com/restartedAt", Instant.now().toString())
6 .build())
7 .build());
8kubernetesClient.create(AppsV1Api.class)
9 .patchNamespacedDaemonSet("daemonset-namespace", "your-namespace", daemonSet)
10 .get();
and StatefulSets:
1final StatefulSet statefulSet = new StatefulSet();
2statefulSet.setSpec(new StatefulSetSpec());
3statefulSet.getSpec().setTemplate(PodTemplateSpec.builder()
4 .metadata(ObjectMeta.builder()
5 .putInAnnotations("yakc.marcnuri.com/restartedAt", Instant.now().toString())
6 .build())
7 .build());
8kubernetesClient.create(AppsV1Api.class)
9 .patchNamespacedStatefulSet("statefulset-name", "your-namespace", statefulSet)
10 .get();
Following you can check the operation result in YAKC – Kubernetes Dashboard interface (you can read more about this project here):
Conclusion
In this post, I’ve shown you how to perform rollout restarts for Deployments, DaemonSets, and StatefulSets from Java using YAKC.
I’ve extracted the code for this post from my YAKC – Kubernetes Dashboard quickstart. You can learn more by visiting YAKC’s GitHub project site. You can also see related code here.