Here in this article we will demonstrate the usage Pods which are the most basic deployable units in Kubernetes Cluster. We will also look at and understand about the containers that are encapsulated within a pod and the types of containers that can be launched based on the use case.
Fedora 36 server
Kubernetes Cluster v1.22.5
What are Pods
Pods are the very basic deployable units that we can create in kubernetes cluster. Pods encapsulate and run one or more containers. There is a host process associated with each container that is running within a Pod. Pod is just a logical unit like a wrapper around those containers. These containers share the storage and network resouces. Pod is similar to set of containers with shared namespaces and shared filesystem volumes.
App Containers – Pods with single container
Step1: Run and Describe a nginx pod
As a first step let’s create an instance of nginx image as shown below.
[admin@kubemaster kubernetes]$ kubectl run nginx-inst1 --image=nginx pod/nginx-inst1 created
Now that our nginx instance is created let us try to get some details about the instance using the below command.
[admin@kubemaster kubernetes]$ kubectl describe pod nginx-inst1 Name: nginx-inst1 Namespace: default Priority: 0 Service Account: default Node: kubenode/192.168.122.49 Start Time: Sat, 08 Oct 2022 19:35:51 +0530 Labels: run=nginx-inst1 Annotations: <none> Status: Running IP: 10.0.1.5 IPs: IP: 10.0.1.5 Containers: nginx-inst1: Container ID: cri-o://a821354dcdb232c943c2c266ee26f6485cc9ba6c8ef16407859c440cc49b37ce Image: nginx Image ID: docker.io/library/nginx@sha256:2f770d2fe27bc85f68fd7fe6a63900ef7076bc703022fe81b980377fe3d27b70 Port: <none> Host Port: <none> State: Running Started: Sat, 08 Oct 2022 19:36:25 +0530 Ready: True Restart Count: 0 Environment: <none> Mounts: /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-8pxl6 (ro) Conditions: Type Status Initialized True Ready True ContainersReady True PodScheduled True Volumes: kube-api-access-8pxl6: Type: Projected (a volume that contains injected data from multiple sources) TokenExpirationSeconds: 3607 ConfigMapName: kube-root-ca.crt ConfigMapOptional: <nil> DownwardAPI: true QoS Class: BestEffort Node-Selectors: <none> Tolerations: node.kubernetes.io/not-ready:NoExecute op=Exists for 300s node.kubernetes.io/unreachable:NoExecute op=Exists for 300s Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Scheduled 77s default-scheduler Successfully assigned default/nginx-inst1 to kubenode Normal Pulling 76s kubelet Pulling image "nginx" Normal Pulled 43s kubelet Successfully pulled image "nginx" in 33.527070421s Normal Created 43s kubelet Created container nginx-inst1 Normal Started 43s kubelet Started container nginx-inst1
The above output provides us with most of the details about the pod. But if you want to get detailed information in either yaml or json format we can use the below commands.
[admin@kubemaster kubernetes]$ kubectl get pod nginx-inst1 -o yaml [admin@kubemaster kubernetes]$ kubectl get pod nginx-inst1 -o json
Step2: Execute into Pod Containers
From the above nginx pod that we just created we can see that its a single container pod as there is only one continer named nginx within the pod.
As per the below command we are trying to get a interactive bash shell from the running nginx container.
[admin@kubemaster kubernetes]$ kubectl exec -it nginx-inst1 -- bash root@nginx-inst1:/#
Let us try to check some details about the Pod
The hostname of the nginx container is same as the name of the pod.
root@nginx-inst1:/# hostname nginx-inst1
The IP address can be captured from the /etc/hosts file as shown below. This IP address will be allocated based on the POD CIDR range that we provide during the kubernetes cluster initialization.
root@nginx-inst1:/# cat /etc/hosts # Kubernetes-managed hosts file. 127.0.0.1 localhost ::1 localhost ip6-localhost ip6-loopback fe00::0 ip6-localnet fe00::0 ip6-mcastprefix fe00::1 ip6-allnodes fe00::2 ip6-allrouters 10.0.1.5 nginx-inst1
By default the Pod uses a default serviceaccount. serviceaccounts are system id that are used by pods to communicate with the API server.
Here is the secret token for our default serviceaccount that the nginx pod is using.
root@nginx-inst1:/# cat /var/run/secrets/kubernetes.io/serviceaccount/token eyJhbGciOiJSUzI1NiIsImtpZCI6IjFOckw3anZrY1FLM1BOWGdpV2dvVzF0dzNPWjZmSS1WUmlYUnFoWkhHSTAifQ.eyJhdWQiOlsiaHR0cHM6Ly9rdWJlcm5ldGVzLmRlZmF1bHQuc3ZjLmNsdXN0ZXIubG9jYWwiXSwiZXhwIjoxNjk2NzczOTUxLCJpYXQiOjE2NjUyMzc5NTEsImlzcyI6Imh0dHBzOi8va3ViZXJuZXRlcy5kZWZhdWx0LnN2Yy5jbHVzdGVyLmxvY2FsIiwia3ViZXJuZXRlcy5pbyI6eyJuYW1lc3BhY2UiOiJkZWZhdWx0IiwicG9kIjp7Im5hbWUiOiJuZ2lueC1pbnN0MSIsInVpZCI6ImFiOTEyMjgxLTMxYmItNGU2MS1hMGFjLTcwOTQyMTBmZTRhZSJ9LCJzZXJ2aWNlYWNjb3VudCI6eyJuYW1lIjoiZGVmYXVsdCIsInVpZCI6IjU4MmQzNzIwLTY1ZDAtNGIwOC04ZjE2LWIyMTJhODg4MDY0ZiJ9LCJ3YXJuYWZ0ZXIiOjE2NjUyNDE1NTh9LCJuYmYiOjE2NjUyMzc5NTEsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDpkZWZhdWx0OmRlZmF1bHQifQ.X9cLOh2Vu44rYzdeERYlj5SEQG0KLfS0g03r4tZ7RezWDJOtZboUmrnIQ9jbjjQqLouVXL5Imt-5oVSp1wxBCdfPQKiOoCZmHUsqVnhsHicRnliyKzhsm8kTea1fGo2McP0VNQFDgmcHd7-Bm-l5HwSsVrbyqXHYIsDn1Fi94y0f5h5OMLQ4-v55geoCrKQgg0K9kZdlnJPu1pAlbj-osa4OBMWLiECHbVtv_ueYpPdlScEmx4QggA9V3e_KEfqOwaFSoAX3ER7WJW1oJO2lFmfq2U-TLPTQXNdEr93vELsqG669gdGihmjqq5G0eYy9zB_TnU-UPY6LcLDxCJRH5A
Step3: Replicate Pod
Here we will try to create another instance of the nginx pod to scale the nginx instance horizontally.
[admin@kubemaster kubernetes]$ kubectl run nginx-inst2 --image=nginx pod/nginx-inst2 created
Now let’s try to get the details of the IP address that is allocated and the node on which these two pods are scheduled as shown below.
[admin@kubemaster kubernetes]$ kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES nginx-inst1 1/1 Running 0 4m10s 10.0.1.5 kubenode <none> <none> nginx-inst2 1/1 Running 0 18s 10.0.1.172 kubenode <none> <none>
As you can see the pods are allocated with an IP address from the subnet “10.0.1.x”.
Pods natively provide two kinds of shared resources for their constituent containers: networking and storage.
Step4: Termination of Pod
By default when a pod deletion request is submitted to API server, kubelet tries to grace-fully shutdown the container process with pid 1 in the pod with a default grace period of 30 sec after which kubelet triggers the forcible shutdown with SIGKILL signal.
[admin@kubemaster kubernetes]$ kubectl delete pod nginx-inst1 # This termination of pod tries a grace full shutdown of the container process
If we want to forcibally terminate the pod we can pass grace period with 0 sec and –force flags as shown below.
[admin@kubemaster kubernetes]$ kubectl delete pod nginx-inst2 --force --grace-period=0 Warning: Immediate deletion does not wait for confirmation that the running resource has been terminated. The resource may continue to run on the cluster indefinitely. pod "nginx-inst2" force deleted
Init Containers – Pods with multiple containers
A Pod can have multiple containers running apps within it but Init Containers are a specialized type of containers that are executed before any App Containers are started. The Init Containers need to be executed successfully to their completion state in the order they are defined.
Init containers do not support lifecycle, livenessProbe, readinessProbe, or startupProbe because they must run to completion before the Pod can be ready. Init containers can run with a different view of the filesystem than app containers in the same Pod. Consequently, they can be given access to Secrets that app containers cannot access. Init containers can securely run utilities or custom code that would otherwise make an app container image less secure. By keeping unnecessary tools separate you can limit the attack surface of your app container image.
Step1: Create a Pod with Init Container
Here is a very basic init container demo in which we have one init container which will loop through a count of 100. Once this loops completes the init container should get into completion state and the app container should be initiated and get into running state.
[admin@kubemaster workloads]$ cat initcontainerapp.yml apiVersion: v1 kind: Pod metadata: name: initcontainer-demo labels: app.kubernetes.io/name: initcontainer-demo spec: containers: - name: myapp image: busybox:1.28 command: ['sh', '-c', 'echo The app is running! && sleep 3600'] initContainers: - name: init-myservice image: busybox:1.28 command: ['sh', '-c', "for i in `seq 1 100`; do echo $i; sleep 1; done"]
Let’s apply this yaml definition file as shown below.
[admin@kubemaster workloads]$ kubectl apply -f initcontainerapp.yml pod/initcontainer-demo created
Now if we check the pod status it is still not in running state as the init container is still running in the pod.
[admin@kubemaster workloads]$ kubectl get pods NAME READY STATUS RESTARTS AGE initcontainer-demo 0/1 Init:0/1 0 30s
We can check the logs of the init-myservice container as shown below. Once this init-myservice container count reaches to 100, the init-myservices container execution completes.
[admin@kubemaster workloads]$ kubectl logs initcontainer-demo -c init-myservice 1 2 3 4 ... 100
As shown below the pod is now in running state means the app container is initiated and in running state now.
[admin@kubemaster workloads]$ kubectl get pods NAME READY STATUS RESTARTS AGE initcontainer-demo 1/1 Running 0 104s
We can check the status of each container using the kubectl describe command as shown below.
[admin@kubemaster workloads]$ kubectl describe pod initcontainer-demo Name: initcontainer-demo Namespace: default Priority: 0 Service Account: default Node: kubenode/192.168.122.49 Start Time: Sat, 08 Oct 2022 20:34:26 +0530 Labels: app.kubernetes.io/name=initcontainer-demo Annotations: <none> Status: Running IP: 10.0.1.123 IPs: IP: 10.0.1.123 Init Containers: init-myservice: Container ID: cri-o://089101d6704582c964447b7ea62d587214ceaa5ed2518b3bf551d68ff00f7e00 Image: busybox:1.28 Image ID: docker.io/library/busybox@sha256:141c253bc4c3fd0a201d32dc1f493bcf3fff003b6df416dea4f41046e0f37d47 Port: <none> Host Port: <none> Command: sh -c for i in `seq 1 100`; do echo $i; sleep 1; done State: Terminated Reason: Completed Exit Code: 0 Started: Sat, 08 Oct 2022 20:34:27 +0530 Finished: Sat, 08 Oct 2022 20:36:07 +0530 Ready: True Restart Count: 0 Environment: <none> Mounts: /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-vbsx4 (ro) Containers: myapp: Container ID: cri-o://8097eebf3c608dab378e5dd3cb6f68117b3993e9d1fdb853e49c48c94d3f0a24 Image: busybox:1.28 Image ID: docker.io/library/busybox@sha256:141c253bc4c3fd0a201d32dc1f493bcf3fff003b6df416dea4f41046e0f37d47 Port: <none> Host Port: <none> Command: sh -c echo The app is running! && sleep 3600 State: Running Started: Sat, 08 Oct 2022 20:36:08 +0530 Ready: True Restart Count: 0 Environment: <none> Mounts: /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-vbsx4 (ro) Conditions: Type Status Initialized True Ready True ContainersReady True PodScheduled True Volumes: kube-api-access-vbsx4: Type: Projected (a volume that contains injected data from multiple sources) TokenExpirationSeconds: 3607 ConfigMapName: kube-root-ca.crt ConfigMapOptional: <nil> DownwardAPI: true QoS Class: BestEffort Node-Selectors: <none> Tolerations: node.kubernetes.io/not-ready:NoExecute op=Exists for 300s node.kubernetes.io/unreachable:NoExecute op=Exists for 300s Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Scheduled 4m2s default-scheduler Successfully assigned default/initcontainer-demo to kubenode Normal Pulled 4m2s kubelet Container image "busybox:1.28" already present on machine Normal Created 4m2s kubelet Created container init-myservice Normal Started 4m2s kubelet Started container init-myservice Normal Pulled 2m21s kubelet Container image "busybox:1.28" already present on machine Normal Created 2m21s kubelet Created container myapp Normal Started 2m21s kubelet Started container myapp
Ephemeral Containers – Pods with Debugging Containers
Pods are the basic deployable units which can only be disposed and replaced with a new Pod. We cannot add a new container to an already existing Pod. In order to debug a faulty container in a Pod we need to deploy a ephemeral container with some utility tools which can help us to debug a faulty container in a pod.
Ephemeral containers are created using a special ephemeral containers handler in the API rather than by adding them directly to pod.spec, so it’s not possible to add an ephemeral container using kubectl edit.
Ephemeral containers are useful for interactive troubleshooting when kubectl exec is insufficient because a container has crashed or a container image doesn’t include debugging utilities.
Distroless images are a kind of minimal container images which are built with a reduced attack surface and exposure to bugs and vulnerabilities.
Let’s try to create a pod with a distroless image which does not contain the required utilities to debug the container.
[admin@kubemaster workloads]$ kubectl run ephemeral-demo --image=registry.k8s.io/pause:3.1 --restart=Never
[admin@kubemaster workloads]$ kubectl get pods NAME READY STATUS RESTARTS AGE ephemeral-demo 1/1 Running 0 14s
Now if we try to get shell into the ephemeral-demo pod we will get an error as the shell utilities are not available in this distroless image.
[admin@kubemaster workloads]$ kubectl exec -it ephemeral-demo -- sh ERRO exec failed: unable to start container process: exec: "sh": executable file not found in $PATH command terminated with exit code 255
Now in order get a view of the ephemeral pod container we will use kubectl debug to instantiate a debugging container and attach it to the pod ephemeral-demo as shown below.
[admin@kubemaster workloads]$ kubectl debug -it ephemeral-demo --image=busybox:1.28 --target=ephemeral-demo Targeting container "ephemeral-demo". If you don't see processes from this container it may be because the container runtime doesn't support this feature. Defaulting debug container name to debugger-cqtwt. If you don't see a command prompt, try pressing enter. / #
This command adds a new busybox container and attaches to it. The –target parameter targets the process namespace of another container. Please note that there are other methods to carry out debugging of the pod containers as mentioned in the Documentation – https://kubernetes.io/docs/tasks/debug/debug-application/debug-running-pod/#ephemeral-container.
Hope you enjoyed reading this article. Thank you..