Rolling updates

Make sure you are in the correct namespace

kubectl config set-context --current --namespace=myspace

If you just came from the Resources and Limits section then you should already have the pods and deployments active that you need. If not, you will need run the following commands to deploy the needed elements into myspace

Deploy the Spring Boot app if needed:

kubectl apply -f apps/kubefiles/myboot-deployment-resources-limits.yml
kubectl apply -f apps/kubefiles/myboot-service.yml

Terminal 1: watch the Pods.

watch -n 1 -- kubectl get pods

Terminal 2: curl loop the service.

  • Minikube

  • Hosted

IP=$(minikube ip -p devnation)
PORT=$(kubectl get service/myboot -o jsonpath="{.spec.ports[*].nodePort}")

If using a hosted Kubernetes cluster like OpenShift then use curl and the EXTERNAL-IP address with port 8080 or get it using kubectl:

IP=$(kubectl get service myboot -o jsonpath="{.status.loadBalancer.ingress[0].ip}")
PORT=$(kubectl get service myboot -o jsonpath="{.spec.ports[*].port}")
If you are in AWS, you need to get the hostname instead of ip.
IP=$(kubectl get service myboot -o jsonpath="{.status.loadBalancer.ingress[0].hostname}")

Curl the Service:

curl $IP:$PORT

And run loop script:

while true
do curl $IP:$PORT
sleep 0.8
done

Terminal 3 : Run commands.

Describe (or kubectl edit) the Deployment:

kubectl describe deployment myboot
.
.
.
Replicas:               1 desired | 1 updated | 1 total | 1 available | 0 unavailable
StrategyType:           RollingUpdate
MinReadySeconds:        0
RollingUpdateStrategy:  25% max unavailable, 25% max surge
.
.
.

StrategyType options include RollingUpdate and Recreate:

Change the replicas:

If you’re running this tutorial from within VSCode or would like to use VSCode to edit the resource targeted, make sure you set the following environment variable before issuing the kubectl edit:

export KUBE_EDITOR="code -w"
kubectl edit deployment myboot

Look for "replicas":

spec:
  progressDeadlineSeconds: 600
  replicas: 1
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      app: myboot

And update to "2":

spec:
  progressDeadlineSeconds: 600
  replicas: 2
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      app: myboot

Save and close your editor and a new pod will come to life:

kubectl get pods
NAME                     READY   STATUS    RESTARTS   AGE
myboot-d78fb6d58-2fqml   1/1     Running   0          25s
myboot-d78fb6d58-ljkjp   1/1     Running   0          3m

Change the image associated with the deployment:

kubectl edit deployment myboot

Find the image attribute:

    spec:
      containers:
      - image: quay.io/rhdevelopers/myboot:v1
        imagePullPolicy: IfNotPresent
        name: myboot

and change the image myboot:v2:

    spec:
      containers:
      - image: quay.io/rhdevelopers/myboot:v2
        imagePullPolicy: IfNotPresent
        name: myboot
kubectl get pods
NAME                      READY   STATUS              RESTARTS   AGE
myboot-7fbc4b97df-4ntmk   1/1     Running             0          9s
myboot-7fbc4b97df-qtkzj   0/1     ContainerCreating   0          0s
myboot-d78fb6d58-2fqml    1/1     Running             0          3m29s
myboot-d78fb6d58-ljkjp    1/1     Terminating         0          8m

And the output from terminal 2:

Aloha from Spring Boot! 211 on myboot-d78fb6d58-2fqml
Aloha from Spring Boot! 212 on myboot-d78fb6d58-2fqml
Bonjour from Spring Boot! 0 on myboot-7fbc4b97df-4ntmk
Bonjour from Spring Boot! 1 on myboot-7fbc4b97df-4ntmk

Check the status of the deployment:

kubectl rollout status deployment myboot
deployment "myboot" successfully rolled out

Notice that there is a new RS:

kubectl get rs
NAME                DESIRED   CURRENT   READY   AGE
myboot-7fbc4b97df   2         2         2       116s
myboot-d78fb6d58    0         0         0       10m

Describe the Deployment:

kubectl describe deployment myboot

And check out the Events section:

...
Events:
  Type    Reason             Age    From                   Message
  ----    ------             ----   ----                   -------
  Normal  ScalingReplicaSet  16m    deployment-controller  Scaled up replica set myboot-d78fb6d58 to 1
  Normal  ScalingReplicaSet  6m15s  deployment-controller  Scaled up replica set myboot-d78fb6d58 to 2
  Normal  ScalingReplicaSet  2m55s  deployment-controller  Scaled up replica set myboot-7fbc4b97df to 1
  Normal  ScalingReplicaSet  2m46s  deployment-controller  Scaled down replica set myboot-d78fb6d58 to 1
  Normal  ScalingReplicaSet  2m46s  deployment-controller  Scaled up replica set myboot-7fbc4b97df to 2
  Normal  ScalingReplicaSet  2m37s  deployment-controller  Scaled down replica set myboot-d78fb6d58 to 0

You can list the revisions associated to your deployment by running the following command:

kubectl rollout history deployment/myboot

You can rollback to v1 using the following command:

kubectl rollout undo deployment/myboot --to-revision=1

And it rolls back to Aloha:

Bonjour from Spring Boot! 501 on myboot-7fbc4b97df-qtkzj
Bonjour from Spring Boot! 502 on myboot-7fbc4b97df-qtkzj
Aloha from Spring Boot! 0 on myboot-d78fb6d58-vnlch

On minikube, you may receive errors from curl during the rollover activity.

Aloha from Spring Boot! 119 on myboot-d78fb6d58-2zp4h
curl: (7) Failed to connect to 192.168.99.100 port 31528: Connection refused

The reason is the the missing Live and Ready Probes

Try using the Quarkus image instead of the Spring Boot one

kubectl set image deployment/myboot myboot=quay.io/rhdevelopers/quarkus-demo:v1

And there should be no errors, Quarkus simply boots up crazy fast

Aloha from Spring Boot! 62 on myboot-d78fb6d58-smb7h
Aloha from Spring Boot! 63 on myboot-d78fb6d58-smb7h
Supersonic Subatomic Java with Quarkus myboot-5cf696848b-tlt6l:1
Supersonic Subatomic Java with Quarkus myboot-5cf696848b-tlt6l:2