Lesson 2.1: Pods (Basic Pod operations, multi-container pods)


Imperative

[root@master ~]# kubectl run nginx-pod --image=nginx:latest 
pod/nginx-pod created
 
[root@master ~]# kubectl get pods 
NAME        READY   STATUS    RESTARTS   AGE
nginx-pod   1/1     Running   0          16s
 

Declarative

[root@master ~]# cat pod.yml 
apiVersion: v1 
kind: Pod
metadata:
  name: nginx-pod
  labels:
    env: demo 
    type: frontend
spec: 
  containers:
  - name: nginx-container
    image: nginx
    ports:
    - containerPort: 80 
 
[root@master ~]# kubectl create -f pod.yml 

Generating a Manifest File

The below command is a very useful way to generate a Kubernetes Pod manifest file using kubectl.

[root@master ~]# kubectl run nginx --image=nginx --dry-run=client -o yaml > pod-new.yml 
 
# Modify the file according to the requirement
[root@master ~]# cat pod-new.yml 
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: nginx
  name: nginx
spec:
  containers:
  - image: nginx
    name: nginx
    resources: {}
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}
  • kubectl run nginx:

    • This is the command to create a Pod named nginx.
  • --image=nginx:

    • Specifies the Docker image to use for the Pod. In this case, it's the official nginx image.
  • --dry-run=client:

    • The --dry-run=client flag tells kubectl to simulate the creation of the Pod without actually creating it in the cluster.
    • This is useful for generating a manifest file or testing a command without making any changes to the cluster.
  • -o yaml:

    • The -o yaml flag outputs the generated Pod configuration in YAML format.
    • Instead of applying the configuration directly, it prints the YAML manifest to the terminal.
  • > pod-new.yml:

    • This redirects the output of the command (the YAML manifest) to a file named pod-new.yml.
[root@master ~]# kubectl describe pod nginx-pod 
[root@master ~]# kubectl get pods nginx-pod --show-labels 
NAME        READY   STATUS    RESTARTS   AGE     LABELS
nginx-pod   1/1     Running   0          2m10s   env=demo,type=frontend
[root@master ~]# kubectl get pods -o wide 
NAME        READY   STATUS    RESTARTS   AGE     IP           NODE                         NOMINATED NODE   READINESS GATES
nginx-pod   1/1     Running   0          2m37s   10.244.0.7   cka-cluster1-control-plane   <none>           <none>

Multi-Container Pods

A multi-container Pod in Kubernetes is a single Pod that contains multiple containers running together in a shared environment. These containers share the same network namespace, storage, and lifecycle, but they can perform different tasks or roles within the Pod.

Key Characteristics of Multi-Container Pods

  • Shared Resources:

    • Network: Containers in the same Pod share the same IP address and port space. They can communicate with each other using localhost.
    • Storage: Containers can share volumes (e.g., emptyDir, ConfigMap, Secret) to exchange data.
    • Lifecycle: All containers in the Pod start and stop together. If one container fails, the entire Pod is affected.
  • Sidecar Pattern: Multi-container Pods are often used to implement the sidecar pattern, where a secondary container (the "sidecar") assists the primary container by providing additional functionality (e.g., logging, monitoring, or proxying).

  • Init Containers: Multi-container Pods can also include init containers, which run before the main containers to perform setup tasks (e.g., waiting for dependencies, initializing data).

  • Use Cases:

    • Logging and monitoring (e.g., a logging sidecar container).
    • Proxying network traffic (e.g., an Istio sidecar proxy).
    • Data processing (e.g., a container that processes data generated by another container).
    • Dependency management (e.g., an init container that waits for a database to be ready).

This example demonstrates how to use init containers to manage dependencies and ensure that your application starts only when all required resources are available.

[root@master ~]# cat multi-pod.yml 
apiVersion: v1
kind: Pod
metadata:
  name: myapp
  labels:
    name: myapp-pod
spec:
  containers:
  - name: myapp-container
    image: busybox:1.28
    command: ['sh','-c','echo the app is running && sleep 30']
    env:
    - name: FIRSTNAME
      value: "sanjeeb"
  initContainers:
  - name: init-myservice
    image: busybox:1.28
    command: ['sh','-c']
    args: ['until nslookup myservice.default.svc.cluster.local ; do echo waiting for service to be up ; sleep 2 ; done ']

Pod Definition

  • apiVersion: v1: Specifies the Kubernetes API version.
  • kind: Pod: Defines the resource type as a Pod.
  • metadata:
    • name: myapp: The Pod is named myapp.
    • labels: Adds a label name: myapp-pod to the Pod for identification.

Container Definition

  • containers: Defines the main container(s) in the Pod.
    • name: myapp-container: The container is named myapp-container.
    • image: busybox:1.28: Uses the busybox:1.28 image, a lightweight Linux utility container.
    • command: Specifies the command to run in the container:
      • ['sh','-c','echo the app is running && sleep 30'] This command prints the app is running and then sleeps for 30 seconds.
    • env: Defines environment variables for the container:
      • FIRSTNAME: "sanjeeb": Sets the environment variable FIRSTNAME to sanjeeb.

Init Container

  • initContainers: Defines one or more init containers that run before the main container(s).
    • name: init-myservice: The init container is named init-myservice.
    • image: busybox:1.28: Uses the same busybox:1.28 image.
    • command and args: Specifies the command and arguments to run in the init container:
      • This script repeatedly checks if the DNS name myservice.default.svc.cluster.local resolves (i.e., if the service myservice is available).
      • If the service is not available, it prints waiting for service to be up and sleeps for 2 seconds before retrying.
      • Once the service is available, the init container exits successfully, allowing the main container to start.
[root@master ~]# kubectl apply -f multi-pod.yml 
pod/myapp created
 
[root@master ~]# kubectl get pod 
NAME    READY   STATUS     RESTARTS   AGE
myapp   0/1     Init:0/1   0          7s
 
[root@master ~]# kubectl describe pod myapp 
...
Status:           Pending
Init Containers:
  init-myservice:
    Command:
          sh
          -c
        Args:
          until nslookup myservice.default.svc.cluster.local ; do echo waiting for service to be up ; sleep 2 ; done 
    State:          Running
Containers:
  myapp-container:
    Command:
      sh
      -c
      echo the app is running && sleep 30
    State:          Waiting
      Reason:       PodInitializing
...
  • Pod Status:
    • The output shows that the Pod myapp is in the Init:0/1 state, which means the init container (init-myservice) is running, but the main container (myapp-container) has not started yet.
      • Init:0/1: This indicates that 0 out of 1 init containers have completed successfully.
      • The Pod is in the Pending state because the init container is still running.
  • Init Container State:
    • The init container (init-myservice) is in the Running state.
    • It is executing the command: until nslookup myservice.default.svc.cluster.local ; do echo waiting for service to be up ; sleep 2 ; done
  • Main Container State:
    • The main container (myapp-container) is in the Waiting state with the reason PodInitializing.
    • This means the main container cannot start until the init container completes successfully.

Error Logs

[root@master ~]# kubectl logs pod/myapp
Defaulted container "myapp-container" out of: myapp-container, init-myservice (init)
Error from server (BadRequest): container "myapp-container" in pod "myapp" is waiting to start: PodInitializing
 
[root@master ~]# kubectl logs pod/myapp -c init-myservice
nslookup: can't resolve 'myservice.default.svc.cluster.local'
Server:    10.96.0.10
Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local
waiting for service to be up

The logs confirm that the init container (init-myservice) is stuck because it cannot resolve the DNS name myservice.default.svc.cluster.local. This means the service myservice does not exist in the default namespace.

  • The init container was repeatedly trying to resolve the DNS name but failed because the service didn’t exist.
  • The DNS server (10.96.0.10, which is CoreDNS) was reachable, but the service myservice was missing.
  • The Pod was stuck in the Init:0/1 state because the init container hadn’t completed successfully.
  • The main container (myapp-container) was in the Waiting state with the reason PodInitializing.

Creating the service

To fix the issue, create the myservice service using the following YAML:

[root@master ~]# cat multi-pod-service.yml 
apiVersion: v1
kind: Service
metadata:
  name: myservice
  namespace: default
spec:
  selector:
    app: myservice
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80
 
[root@master ~]# kubectl apply -f multi-pod-service.yml 
service/myservice created
[root@master ~]# kubectl get svc 
NAME         TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.96.0.1      <none>        443/TCP   24h
myservice    ClusterIP   10.96.83.233   <none>        80/TCP    3s
  • name: myservice: The service is named myservice.
  • namespace: default: The service is created in the default namespace.
  • selector: app: myservice: The service will route traffic to Pods with the label app: myservice.
  • port: 80: The service exposes port 80.
  • targetPort: 80: The service forwards traffic to port 80 on the Pods. The service myservice was successfully created with the ClusterIP 10.96.83.233.

Success Logs

Once the service was created, the init container was able to resolve the DNS name myservice.default.svc.cluster.local and exited successfully.

[root@master ~]# kubectl logs pod/myapp 
Defaulted container "myapp-container" out of: myapp-container, init-myservice (init)
the app is running
 
# The DNS lookup succeeded, and the init container completed its task.
[root@master ~]# kubectl logs pod/myapp -c init-myservice
...
Name:      myservice.default.svc.cluster.local
Address 1: 10.96.83.233 myservice.default.svc.cluster.local
[root@master ~]# kubectl get pods 
NAME    READY   STATUS    RESTARTS      AGE
myapp   1/1     Running   4 (57s ago)   72m
 
[root@master ~]# kubectl exec -it myapp -- printenv
...
HOSTNAME=myapp
FIRSTNAME=sanjeeb
  • The DNS lookup succeeded, and the init container completed its task.
  • After the init container completed, the main container (myapp-container) started and executed its command:
    • The main container printed the app is running and then slept for 30 seconds (as defined in the Pod YAML).
  • The Pod transitioned to the Running state
  • The environment variable FIRSTNAME=sanjeeb was successfully passed to the container (as defined in the Pod YAML).

Note: You cannot add or remove the init containers once it is created

Example

[root@master nginx-multi-container]# cat pod.yml 
apiVersion: v1
kind: Pod
metadata:
  name: multi-container-pod 
  labels:
    app: myservice
spec: 
  initContainers:
  - name: init-myservice
    image: busybox:latest
    command: ['sh','-c','until nslookup myservice.default.svc.cluster.local; do echo waiting for myservice; sleep 2; done']
  containers:
  - name: nginx-container
    image: nginx:latest
    command: ["sh", "-c", "mkdir -p /var/log/nginx && nginx -g 'daemon off;'"]
    ports:
    - containerPort: 80 
  - name: logging-sidecar
    image: busybox:latest
    command: ["sh", "-c", "while [ ! -f /var/log/nginx/access.log ]; do sleep 1; done; tail -f /var/log/nginx/access.log"]
 
[root@master nginx-multi-container]# kubectl apply -f pod.yml 
pod/multi-container-pod created
 
[root@master nginx-multi-container]# kubectl get pods 
NAME                  READY   STATUS     RESTARTS   AGE
multi-container-pod   0/2     Init:0/1   0          6s
[root@master nginx-multi-container]# kubectl logs pod/multi-container-pod
Defaulted container "nginx-container" out of: nginx-container, logging-sidecar, init-myservice (init)
Error from server (BadRequest): container "nginx-container" in pod "multi-container-pod" is waiting to start: PodInitializing
 
[root@master nginx-multi-container]# kubectl logs pod/multi-container-pod -c nginx-container
Error from server (BadRequest): container "nginx-container" in pod "multi-container-pod" is waiting to start: PodInitializing
 
[root@master nginx-multi-container]# kubectl logs pod/multi-container-pod -c logging-sidecar
Error from server (BadRequest): container "logging-sidecar" in pod "multi-container-pod" is waiting to start: PodInitializing
 
[root@master nginx-multi-container]# kubectl logs pod/multi-container-pod -c init-myservice
** server can't find myservice.default.svc.cluster.local: NXDOMAIN
[root@master nginx-multi-container]# cat myservice.yml 
apiVersion: v1
kind: Service
metadata:
  name: myservice
spec:
  type: NodePort
  selector:
    app: myservice
  ports:
  - port: 80
    targetPort: 80
    nodePort: 30001
 
[root@master nginx-multi-container]# kubectl apply -f myservice.yml 
service/myservice created
 
[root@master nginx-multi-container]# kubectl get svc 
NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.96.0.1       <none>        443/TCP   25h
myservice    ClusterIP   10.96.195.178   <none>        80/TCP    3s
[root@master nginx-multi-container]# kubectl logs pod/multi-container-pod -c logging-sidecar
Name:	myservice.default.svc.cluster.local
 
[root@master nginx-multi-container]# kubectl logs pod/multi-container-pod -c logging-sidecar
# No logs
 
[root@master nginx-multi-container]# kubectl get pods
NAME                  READY   STATUS    RESTARTS   AGE
multi-container-pod   2/2     Running   0          117s
 
[root@master nginx-multi-container]# kubectl exec -it multi-container-pod -- sh 
Defaulted container "nginx-container" out of: nginx-container, logging-sidecar, init-myservice (init)
# cd /var/log/nginx
# ls
access.log  error.log
 
[root@master nginx-multi-container]# curl localhost:30001
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
 
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
 
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
All systems normal

© 2025 2023 Sanjeeb KC. All rights reserved.