1. Overview

Kubernetes provides two widely known mechanisms, namely, livenessProbe and readinessProbe, to keep track of the health and availability of containers inside a pod.

In this tutorial, we’ll learn about the livenessProbe and readinessProbe mechanisms by configuring them for different scenarios.

2. Basics

Kubernetes continuously monitors the health of containers inside the pods using the livenessProbe and the readinessProbe.

The livenessProbe serves as a diagnostic check to confirm if the container is alive. On the other hand, readinessProbe ensures that the container is healthy to serve incoming traffic.

When the livenessProbe fails, Kubernetes considers the pod unhealthy, and then, attempts to restart it as a recovery measure. On the other hand, if the readinessProbe fails, Kubernetes isolates the pod, preventing it from receiving more incoming traffic. Further, if a subsequent probe succeeds, Kubernetes identifies the pod as healthy and resumes incoming traffic flow.

Now that we’ve got a basic understanding of these mechanisms, we’ll learn more about them in the subsequent sections by exploring different configuration scenarios.

3. HTTP Get Probe

We can configure both livenessProbe and readinessProbe for a pod using an HTTP Get Probe. With this approach, Kubernetes performs a periodic HTTP GET request at a specific endpoint and port of the container to check its health:

livenessProbe:
  httpGet:
    path: <endpoint>
    port: <port_number>
readinessProbe:
  httpGet:
    path: <endpoint>
    port: <port_number

Furthermore, if Kubernetes receives a response with a 2xx HTTP status code for the probe request, it considers the pod healthy. However, if it gets any other status code in the response, such as 3xx, 4xx, or 5xx, it treats the pod as unhealthy.

Let’s understand this by configuring these probes for a pod running nginx server in Kubernetes:

$ cat nginx-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
    - name: nginx-container
      image: nginx
      ports:
        - containerPort: 80
      readinessProbe:
        httpGet:
          path: /
          port: 80
        initialDelaySeconds: 5
        periodSeconds: 10
      livenessProbe:
        httpGet:
          path: /
          port: 80
        initialDelaySeconds: 10
        periodSeconds: 15

We must note that it’s mandatory to specify the path and port properties. However, the initialDelaySeconds and periodSeconds parameters are optional, and they can take default values of 0 and 10 seconds, respectively.

While initialDelaySeconds helps us add any delay to the first probe after the container starts, periodSeconds decides the subsequent periodicity.

Now, let’s use the configuration from the nginx-pod.yaml file to create the nginx pod:

$ kubectl apply -f nginx-pod.yaml
pod/nginx-pod created

Finally, let’s list the pods and verify that the nginx pod is up and in a Running state:

$ kubectl get pods
NAME        READY   STATUS    RESTARTS   AGE
nginx       1/1     Running   0          3m43s

We can observe that the RESTARTS count is zero. Further, this field keeps track of the number of attempts made to restart and recover the pod if the livenessProbe fails.

4. Command Probe

In this section, we’ll learn how to use Shell commands to configure the liveness and readiness probes:

readinessProbe:
  exec:
    command:
      - "shell-cmd"
livenessProbe:
  exec:
    command: 
      - "shell-cmd"

With a command probe, Kubernetes can execute a shell command to infer the health and availability of the container. If the exit status of the command is zero, then it treats the container as healthy. Otherwise, for non-zero exit status, it considers the pod unhealthy and performs recovery actions such as restarts.

Let’s apply our understanding by configuring the probes for a pod that has an Ubuntu image running inside a container:

$ cat ubuntu-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: test-ubuntu
  labels:
    app: ubuntu
spec:
  containers:
  - image: ubuntu
    command:
      - "sleep"
      - "604800"
    imagePullPolicy: IfNotPresent
    name: test-ubuntu
    livenessProbe:
      exec:
        command: 
          - "ps"
          - "-C"
          - "sleep"
      initialDelaySeconds: 5
      periodSeconds: 10
      successThreshold: 1
      failureThreshold: 2
    readinessProbe:
      exec:
        command:
          - "ls"
          - "/bin"
          - "/boot"
          - "/usr"
      initialDelaySeconds: 10
      periodSeconds: 15
      successThreshold: 1
      failureThreshold: 2

We must note that we’ve used the ps command in livenessProbe to check if the sleep command responsible for keeping the container alive is still running. Additionally, we used the ls command in readinessProbe to ensure critical directories are present.

Further, in case of a failure, we want at least two attempts before Kubernetes can mark the pod as unhealthy, so we’ve set failureThreshold value as 2. On the other hand, a single successful attempt is sufficient to declare the pod healthy, so we’ve set the successThreshold parameter as 1.

Now, let’s go ahead and create the pod using the configuration from the ubuntu-pod.yaml file:

$ kubectl apply -f ubuntu-pod.yaml 
pod/test-ubuntu created

Finally, let’s verify the status of the test-ubuntu pod along with the RESTARTS property:

$ kubectl get pod test-ubuntu
NAME          READY   STATUS    RESTARTS   AGE
test-ubuntu   1/1     Running   0          24s

Great! It looks like we’ve got this right, as the status field shows as Running, and there are no restarts.

5. TCP Socket Probe

For a container running a TCP-based network service, we can also choose to set up a TCP socket probe for both liveness and readiness checks:

livenessProbe:
  tcpSocket:
    port: <port_number>
readinessProbe:
  tcpSocket:
    port: <port_number>

With this approach, Kubernetes periodically establishes a TCP connection to the specified port. If the connection is successful, then it infers that the pod is healthy. Otherwise, it treats the pod as unhealthy and performs recovery actions such as restarting it.

Now, let’s put this into action by configuring livenessProbe and readinessProbe for a pod that’s running a Redis server inside a container:

$ cat redis-server-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: redis-server
spec:
  containers:
  - name: redis
    image: redis:latest
    ports:
    - containerPort: 6379
    livenessProbe:
      tcpSocket:
        port: 6379
      initialDelaySeconds: 15
      periodSeconds: 20
      timeoutSeconds: 5
    readinessProbe
      exec:
        command: 
          - "redis-cli"
          - "ping"
      initialDelaySeconds: 15
      periodSeconds: 20
      timeoutSeconds: 5

We must note that the Redis server accepts connection at the 6379 port, so we used the same port while configuring livenessProbe with tcpSocket. In addition, we’re using the redis-cli command to ping the Redis server as a readiness check. Furthermore, we specify the timeoutSeconds property to define the maximum duration the probe can wait to establish the connection before considering it a failure. 

Now, let’s use the configuration from the redis-server-pod.yaml file to create the redis-server pod:

$ kubectl apply -f redis-server-pod.yaml
pod/redis-server-pod created

Again, we can verify that the redis-server pod is running with 0 RESTARTS:

$ kubectl get pods
NAME           READY   STATUS    RESTARTS   AGE
redis-server   1/1     Running   0          2m56s

Fantastic! We’ve learned one more configuration for setting up the probes for the pods running in Kubernetes.

It’s important to understand that livenessProbe and readinessProbe are supposed to be lightweight, so that there’s no severe impact on the container when executed periodically. Almost always, we should keep the minimal and critical check necessary to infer the pod’s health at the container level.

6. Conclusion

In this article, we learned about livenessProbe and readinessProbe in Kubernetes. Additionally, we explored different scenarios for configuring the HTTP Get, TCP Socket, and Command probes.

Comments are open for 30 days after publishing a post. For any issues past this date, use the Contact form on the site.