Are healthchecks defined per container or per pod in Kubernetes? - kubernetes

In Google Cloud blog they say that if Readiness probe fails, then traffic will not be routed to a pod. And if Liveliness probe fails, a pod will be restarted.
Kubernetes docs they say that the kubelet uses Liveness probes to know if a container needs to be restarted. And Readiness probes are used to check if a container is ready to start accepting requests from clients.
My current understanding is that a pod is considered Ready and Alive when all of its containers are ready. This in turn implies that if 1 out of 3 containers in a pod fails, then the entire pod will be considered as failed (not Ready / not Alive). And if 1 out of 3 containers was restarted, then it means that the entire pod was restarted. Is this correct?

A Pod is ready only when all of its containers are ready.
When a Pod is ready, it should be added to the load balancing pools of all matching Services because it means that this Pod is able to serve requests.
As you can see in the Readiness Probe documentation:
The kubelet uses readiness probes to know when a container is ready to start accepting traffic.
Using readiness probe can ensure that traffic does not reach a container that is not ready for it.
Using liveness probe can ensure that container is restarted when it fail ( the kubelet will kill and restart only the specific container).
Additionally, to answer your last question, I will use an example:
And if 1 out of 3 containers was restarted, then it means that the entire pod was restarted. Is this correct?
Let's have a simple Pod manifest file with livenessProbe for one container that always fails:
---
# web-app.yml
apiVersion: v1
kind: Pod
metadata:
labels:
run: web-app
name: web-app
spec:
containers:
- image: nginx
name: web
- image: redis
name: failed-container
livenessProbe:
httpGet:
path: /healthz # I don't have this endpoint configured so it will always be failed.
port: 8080
After creating web-app Pod and waiting some time, we can check how the livenessProbe works:
$ kubectl describe pod web-app
Name: web-app
Namespace: default
Containers:
web:
...
State: Running
Started: Tue, 09 Mar 2021 09:56:59 +0000
Ready: True
Restart Count: 0
...
failed-container:
...
State: Waiting
Reason: CrashLoopBackOff
Last State: Terminated
Reason: Completed
Exit Code: 0
Ready: False
Restart Count: 7
...
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
...
Normal Killing 9m40s (x2 over 10m) kubelet Container failed-container failed liveness probe, will be restarted
...
As you can see, only the failed-container container was restarted (Restart Count: 7).
More information can be found in the Liveness, Readiness and Startup Probes documentation.

For Pods with multiple containers, we do have an option to restart only single containers conditions applied it have required access.
Command :
kubectl exec POD_NAME -c CONTAINER_NAME "Command used for restarting the container"
Such that required POD is not deleted and k8s doesn't need to recreate the POD.

Related

What happens when kubernetes readiness-probe return false? How long to wait?

What happens when Kubernetes readiness-probe returns false? Does Kubernetes restart that pod after timeout? How long Kubernetes waits for readiness?
Readiness probe doesn't restart the pod/container, readiness probe determines that the container is ready to serve traffic. If the container is probed and considered not "ready", the container will be removed from the endpoints and traffic wont be sent to it, until it is ready again.
[1] https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/#define-readiness-probes
[2] https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes
[3] kubectl explain pod.spec.containers.readinessProbe
KIND: Pod
VERSION: v1
RESOURCE: readinessProbe <Object>
DESCRIPTION:
Periodic probe of container service readiness. Container will be removed
from service endpoints if the probe fails. Cannot be updated. More info:
https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes
Probe describes a health check to be performed against a container to
determine whether it is alive or ready to receive traffic.
FIELDS:
exec <Object>
One and only one of the following should be specified. Exec specifies the
action to take.
failureThreshold <integer>
Minimum consecutive failures for the probe to be considered failed after
having succeeded. Defaults to 3. Minimum value is 1.
httpGet <Object>
HTTPGet specifies the http request to perform.
initialDelaySeconds <integer>
Number of seconds after the container has started before liveness probes
are initiated. More info:
https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes
periodSeconds <integer>
How often (in seconds) to perform the probe. Default to 10 seconds. Minimum
value is 1.
successThreshold <integer>
Minimum consecutive successes for the probe to be considered successful
after having failed. Defaults to 1. Must be 1 for liveness and startup.
Minimum value is 1.
tcpSocket <Object>
TCPSocket specifies an action involving a TCP port. TCP hooks not yet
supported
timeoutSeconds <integer>
Number of seconds after which the probe times out. Defaults to 1 second.
Minimum value is 1. More info:
https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes
Let's use the default readiness probe from the documentation:
cat pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
readinessProbe:
exec:
command:
- cat
- /tmp/healthy
initialDelaySeconds: 5
periodSeconds: 5
To perform a probe, the kubelet executes the command cat /tmp/healthy in the target container. If the command succeeds, it returns 0, then the container is ready and can "serve". if the command returns anything but 0, container is not healthy.
Since this file doesn't exist in the container from the start, when the pod starts, it is going to be very unhealthy.
date && k get pods nginx
Thu 2 Dec 2021 19:08:43 AST
NAME READY STATUS RESTARTS AGE
nginx 0/1 Running 0 66s
now, lets exec into it and create the file, so that the command succeeds.
k exec -it nginx -- bash
root#nginx:/# touch /tmp/healthy
root#nginx:/# exit
exit
checking again:
date && k get pods nginx
Thu 2 Dec 2021 19:09:26 AST
NAME READY STATUS RESTARTS AGE
nginx 1/1 Running 0 110s
removing again:
k exec -it nginx -- bash
root#nginx:/# rm /tmp/healthy
root#nginx:/# exit
exit
checking:
date && k get pods nginx
Thu 2 Dec 2021 19:09:53 AST
NAME READY STATUS RESTARTS AGE
nginx 0/1 Running 0 2m17s

When does a Pod get destroyed?

Pod lifecycle is managed by Kubelet in data plane.
As per the definition: If the liveness probe fails, the kubelet kills the container
Pod is just a container with dedicated network namespace & IPC namespace with a sandbox container.
Say, if the Pod is single app container Pod, then upon liveness failure:
Does kubelet kill the Pod?
or
Does kubelet kill the container (only) within the Pod?
The kubelet uses liveness probes to know when to restart a container (NOT the entire Pod). If the liveness probe fails, the kubelet kills the container, and then the container may be restarted, however it depends on its restart policy.
I've created a simple example to demonstrate how it works.
First, I've created an app-1 Pod with two containers (web and db).
The web container has a liveness probe configured, which always fails because the /healthz path is not configured.
$ cat app-1.yml
apiVersion: v1
kind: Pod
metadata:
labels:
run: app-1
name: app-1
spec:
containers:
- image: nginx
name: web
livenessProbe:
httpGet:
path: /healthz
port: 8080
httpHeaders:
- name: Custom-Header
value: Awesome
- image: postgres
name: db
env:
- name: POSTGRES_PASSWORD
value: example
After applying the above manifest and waiting some time, we can describe the app-1 Pod to check that only the web container has been restarted and the db container is running without interruption:
NOTE: I only provided important information from the kubectl describe pod app-1 command, not the entire output.
$ kubectl apply -f app-1.yml
pod/app-1 created
$ kubectl describe pod app-1
Name: app-1
...
Containers:
web:
...
Restart Count: 4 <--- Note that the "web" container was restarted 4 times
Liveness: http-get http://:8080/healthz delay=0s timeout=1s period=10s #success=1 #failure=3
...
db:
...
Restart Count: 0 <--- Note that the "db" container works fine
...
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
...
Normal Killing 78s (x2 over 108s) kubelet Container web failed liveness probe, will be restarted
...
We can connect to the db container to see if it is running:
NOTE: We can use the db container even when restarting the web container.
$ kubectl exec -it app-1 -c db -- bash
root#app-1:/#
In contrast, after connecting to the web container, we can observe that the liveness probe restarts this container:
$ kubectl exec -it app-1 -c web -- bash
root#app-1:/# command terminated with exit code 137
A pod is indeed the smallest element in Kubernetes, but that does not mean it is in fact "empty" without a container.
In order to spawn a pod and therefore the container elements needed to attach further containers a very small container is created using the pause image.
This is used to allocate an IP that is then used for the pod.
Afterward the init-containers or runtime container declared for the pod are started.
If the lifeness probe fails, the container is restarted. The pod survives this. This is even important: You might want to get the logs of the crashed/restarted container afterwards. This would not be possible, if the pod was destroyed and recreated.

How to resolve ERROR: epmd error for host nxdomain (non-existing domain)?

I am trying to setup RabbitMQ Operator and RabbitMQ Cluster on K8S cluster on bare metal using this link
K8S Cluster has got 1 master and 1 worker node
RabbitMQ Cluster pod log
[root#re-ctrl01 containers]# kubectl logs definition-server-0 -n rabbitmq-system
BOOT FAILED (Tailored output)
===========
ERROR: epmd error for host definition-server-0.definition-nodes.rabbitmq-system: nxdomain (non-existing domain)
11:51:13.733 [error] Supervisor rabbit_prelaunch_sup had child prelaunch started with rabbit_prelaunch:run_prelaunch_first_phase() at undefined exit with reason {epmd_error,"definition-server-0.definition-nodes.rabbitmq-system",nxdomain} in context start_error. Crash dump is being written to: erl_crash.dump...
[root#re-ctrl01 containers]# kubectl describe pod definition-server-0 -n rabbitmq-system
Name: definition-server-0
Namespace: rabbitmq-system
Priority: 0
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 44s default-scheduler Successfully assigned rabbitmq-system/definition-server-0 to re-ctrl01.local
Normal Pulled 43s kubelet Container image "rabbitmq:3.8.16-management" already present on machine
Normal Created 43s kubelet Created container setup-container
Normal Started 43s kubelet Started container setup-container
Normal Pulled 42s kubelet Container image "rabbitmq:3.8.16-management" already present on machine
Normal Created 42s kubelet Created container rabbitmq
Normal Started 42s kubelet Started container rabbitmq
Warning Unhealthy 4s (x3 over 24s) kubelet Readiness probe failed: dial tcp 10.244.0.xxx:5672: connect: connection refused
I added the following entries to /etc/hosts file of worker node because I am NOT sure whether the entry has to be added to master or worker
[root#re-worker01 ~]# cat /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
127.0.0.1 re-worker01.local re-worker01 definition-server-0.definition-nodes.rabbitmq-system
I am stuck with this issue for almost 2 days. I googled and found similar issues but none resolved my issue
I see multiple issues in pod logs and describe output and I am unable to find out the root cause
Where can I find erl_crash.dump file on K8S ?
Is this really a hostname related issue ?
10.244.0.xxx:5672: connect: connection refused - Is this issue is because of 'epmd' or something else ?
I managed to resolve the issue after spending lot of time
I added the host definition-server-0.definition-nodes.rabbitmq-system to /etc/hosts file of RabbitMQ Cluster pod using hostAliases
YAML to add hostAliases is given below
apiVersion: rabbitmq.com/v1beta1
kind: RabbitmqCluster
metadata:
name: definition
namespace: rabbitmq-system
spec:
replicas: 1
override:
statefulSet:
spec:
template:
spec:
containers: []
hostAliases:
- ip: "127.0.0.1"
hostnames:
- "definition-server-0"
- "definition-server-0.definition-nodes.rabbitmq-system"

Why kubernetes reports "readiness probe failed" along with "liveness probe failed"

I have a working Kubernetes deployment of my application.
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
...
template:
...
spec:
containers:
- name: my-app
image: my-image
...
readinessProbe:
httpGet:
port: 3000
path: /
livenessProbe:
httpGet:
port: 3000
path: /
When I apply my deployment I can see it runs correctly and the application responds to my requests.
$ kubectl describe pod -l app=my-app
...
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 4m7s default-scheduler Successfully assigned XXX
Normal Pulled 4m5s kubelet, pool-standard-4gb-2cpu-b9vc Container image "my-app" already present on machine
Normal Created 4m5s kubelet, pool-standard-4gb-2cpu-b9vc Created container my-app
Normal Started 4m5s kubelet, pool-standard-4gb-2cpu-b9vc Started container my-app
The application has a defect and crashes under certain circumstances. I "invoke" such a condition and then I see the following in pod events:
$ kubectl describe pod -l app=my-app
...
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 6m45s default-scheduler Successfully assigned XXX
Normal Pulled 6m43s kubelet, pool-standard-4gb-2cpu-b9vc Container image "my-app" already present on machine
Normal Created 6m43s kubelet, pool-standard-4gb-2cpu-b9vc Created container my-app
Normal Started 6m43s kubelet, pool-standard-4gb-2cpu-b9vc Started container my-app
Warning Unhealthy 9s kubelet, pool-standard-4gb-2cpu-b9vc Readiness probe failed: Get http://10.244.2.14:3000/: net/http: request canceled (Client.Timeout exceeded while awaiting headers)
Warning Unhealthy 4s (x3 over 14s) kubelet, pool-standard-4gb-2cpu-b9vc Liveness probe failed: Get http://10.244.2.14:3000/: net/http: request canceled (Client.Timeout exceeded while awaiting headers)
Normal Killing 4s kubelet, pool-standard-4gb-2cpu-b9vc Container crawler failed liveness probe, will be restarted
It is expected the liveness probe fails and the container is restarted. But why do I see Readiness probe failed event?
As #suren wrote in the comment, readiness probe is still executed after container is started. Thus if both liveness and readiness probes are defined (and also fx they are the same), both readiness and liveness probe can fail.
Here is a similar question with a clear in-depth answer.
The readiness probe is used to determine if the container is ready to serve requests. Your container can be running but not passing the probe. If it doesn't pass the check no service will redirect to this container.
By default the period of the readiness probe is 10 seconds.
You can read more here : https://docs.openshift.com/container-platform/3.9/dev_guide/application_health.html
You configured the same check for readiness and liveness probe - therefore if the liveness check fails, it can be assumed that the readiness fails as well.
please provide an implementation function/method at backend, you can make /health named uri, and can write a liveness logic here and readiness can be your choice too.
/health uri, shall be associated with a function implementation which will can return 200 status code if everything goes fine, else it can be made to get failed

Kubernetes , liveness probe is failing but pod in Running state

I'm trying to do a blue green deployment with kubernetes , I have followed it , https://www.ianlewis.org/en/bluegreen-deployments-kubernetes , that is ok.
I have added a liveness probe to execute a healthcheck ,
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: flask-1.3
spec:
replicas: 2
template:
metadata:
labels:
name: app
version: "1.3"
spec:
containers:
- name: appflask
image: 192.168.99.100:5000/fapp:1.2
livenessProbe:
httpGet:
path: /index2
port: 5000
failureThreshold: 1
periodSeconds: 1
initialDelaySeconds: 1
ports:
- name: http
containerPort: 5000
the path "index2" doesnt exist , I want to test a failed deployment. the problem is when I execute:
kubectl get pods -o wide
for some seconds one of the pods is in state "RUNNING"
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
flask-1.3-6c644b8648-878qz 0/1 CrashLoopBackOff 6 6m19s 10.244.1.250 node <none> <none>
flask-1.3-6c644b8648-t6qhv 0/1 CrashLoopBackOff 7 6m19s 10.244.2.230 nod2e <none> <none>
after some seconds one pod is RUNNING when live is failing always:
NAME READY STATUS RESTARTS AGE
IP NODE NOMINATED NODE READINESS GATES
flask-1.3-6c644b8648-878qz 1/1 Running 7 6m20s 10.244.1.250 node <none> <none>
flask-1.3-6c644b8648-t6qhv 0/1 CrashLoopBackOff 7 6m20s 10.244.2.230 nod2e <none> <none>
And after RUNNING it back to CrashLoopBackOff, the question is , why for some seconds it keeps RUNNING if the livenesprobe go to fail always?
thanks in advance
You should be looking at Readiness probe instead, or both of them.
Readiness and liveness probes can be used in parallel for the same container. Using both can ensure that traffic does not reach a container that is not ready for it, and that containers are restarted when they fail.
Liveness probe checks if your application is in a healthy state in your already running pod.
Readiness probe will actually check if your pod is ready to receive traffic. Thus, if there is no /index2 endpoint, it will never appear as Running
What's happening to you is this:
When you first start the pod (or the container), it will start and will get into the "running" state. Now, if there are no processes running in the container, or if there is a non-continuous process (say sleep 100), when this process finishes, kubernetes is going to consider this pod completed.
Now, since you have a deployment, that is going to keep a certain amount of replicas running, it re-creates the pod. But again, there are no processes running, so again, it get into completed. This is an infinite loop.
If you want to keep the pod up and running, even though you have no processes inside running, you can pass the parameter tty: true, in your yaml file.
apiVersion: v1
kind: Pod
metadata:
name: debian
labels:
app: debian
spec:
containers:
- name: debian
image: debian
tty: true # this line will keep the terminal open
If you run the pod above without tty: true, same this is going to happen.