• Home
  • LLMs
  • Python
  • Docker
  • Kubernetes
  • Java
  • Maven
  • All
  • About
Kubernetes | Pods (pods|po)
  1. Notes
  2. Pods (pods|po)
  3. Manifest YAML file
  4. Manage Pods
  5. List detailled inforation about a Pod
  6. Define Pods resources (CPU, RAM)
  7. Define Init Containers
  8. Define Sidecar Containers
  9. Health Checks
  10. Labels
  11. Delete Pods

  1. Notes
    See these pages for more details about Pods:
    https://kubernetes.io/docs/concepts/workloads/pods/
    https://kubernetes.io/docs/tasks/manage-kubernetes-objects/imperative-command/
    https://kubernetes.io/docs/concepts/security/controlling-access/
    https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/
    https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#dns-subdomain-names
    https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/
  2. Pods (pods|po)
    Pods are the atomic units of deployment in Kubernetes.
    A Pod is a special container that defines one or more containers that can run inside of it.
    Containers, running inside a Pod, share the Pod's resources: IP address, ports, hostname, volumes, ...
    They can communicate with each other using localhost interface.

    To share resources, containers leverage Linux features: Control groups (cgroups) and kernel namespaces.
    Control groups (cgroups) allow containers to use only their assigned resources: cpu, ram, and iops.
    Kernel namespaces (Network, UTS, IPC, ...) allow containers to have their own unique and limited view of the system resources (filesystem, network interfaces, disk, ...):

    It's recommended to have only one container inside a Pod.
    But there might be use cases where it will be acceptable to have more than one container running inside a Pod. For example, it's possible to co-locate multiple containers that provide services that are tightly coupled and/or they need to share the Pod's resources.
    It's also possible to have one main container inside the Pod and add one or more sidcar containers that provide additional features to the main container (for example: logging, monitoring, ...).

    To create/deploy a Pod, you need first to create a manifest file (YAML). The manifest file describe the Pod and its components (name, image, port, ...). You can use "kubectl" (or any rest client tool) to post the manifest file to the API server If applicable, the API server verifies that the request is authenticated, validates it's authorized, and runs the admission controllers on it. The API server verifies the manifest file and, if no issues, it writes a record for that manifest in the cluster store (etcd). The scheduler will then read the record and deploy it to a healthy worker node with enough available resources.

    The same behaviour, described above, applies if you use the imperative command ("kubectl create") to create the Pod.

    You can also use imperative commands (kubectl command-line tool) to create and manage Pods.

    Here's the list of events that leads to the creation of a Pod:
    • You define a Pod in a manifest file (YAML)

    • You post the manifest file to the API server.

    • The API server validates the manifest and persist it in the cluster store (etcd) as record of intent (desired state)

    • The scheduler reads the record, converts it into a PodSpec, and schedules the PodSpec to a healthy worker node with enough available resources.

    • The kubelet (a Kubernetes agent) accepts the PodSpec and start the creation of the Pod.

    • The Pod enters the Pending state while the container runtime, on the worker node, downloads the images and starts the containers.

    • The Pod remains in the Pending state until all of its containers are created.

    • The Pod enters the running state, if its containers are created successfully.

    • The Pod enters the succeeded state, if it successfully finishes its tasks.

    • The Pod enters the failed state, if one or more container failed.

    • The Pod won't be rescheduled if it fails to start.
  3. Manifest YAML file
    The hello-busybox-pod.yaml file provides a declarative configuration of a Pod:
    $ vi hello-busybox-pod.yaml
    apiVersion: v1
    kind: Pod
    metadata:
      name: hello-busybox # will be used as the hostname of the conatiners
    spec:
      containers:
        - name: hello-busybox
          image: busybox:latest
          command: ['sh', '-c', 'echo "hello, busybox!"; sleep 300;']
    The Pod's name must be a valid DNS subdomain name:
    • Maximum 253 characters.
    • The name must contain only lowercase alphanumeric characters ([a-z0-9]), minus character ('-') and period character ('.').
    • The name must start and end with an alphanumeric character.

    To deploy the hello-busybox-pod.yaml file:
    $ kubectl apply -f hello-busybox-pod.yaml
    pod/hello-busybox created
    The "hello-busybox-pod.yaml" file defines the following fields:
    • The apiVersion field defines the Kubernetes API group and the Kubernetes API version.
      Its value is written as following: <api-group>/<api-version>
      Example: storage.k8s.io/v1
      The Pods are defined in the core API group, which is the default if the api-group is not set.
      So in the case of Pods, only the api version needs to be provided.

    • The kind field defines the type of the Kubernetes object to be created (Pod).

    • The metadata field defines the Pod metadata (name, labels, namespace, ...).

    • The spec field defines the containers information (name, image, command, ports, ...).

    Note: The command field can also be written as following:
    command: ['sh']
    args: ['-c', 'echo "hello, busybox!"; sleep 300;']
    command:
    - sh
    - -c
    - echo "hello, busybox!"; sleep 300;
    command:
    - sh
    - -c
    - |
      echo "hello, busybox!";
      sleep 300;
    Note: Managing Pods using the Manifest Yam file (declarative) is the recommended way, but in some cases you might want to use the imperative command "kubectl create" to create a Pod.

    The following command creates and run a Pod using the busybox image and opens an interactive shell:
    $ kubectl run -i -t hello-busybox --image=busybox:latest -- sh
    -i, --stdin: Keep stdin open on the container(s) in the pod, even if nothing is attached.
    -t, --tty: Allocated a TTY for each container in the pod.

    You can use the "--dry-run" flag to print the YAML file:
    $ kubectl apply -f hello-busybox-pod.yaml --dry-run=client -o yaml
    apiVersion: v1
    kind: Pod
    metadata:
      annotations:
        kubectl.kubernetes.io/last-applied-configuration: |
          {"apiVersion":"v1","kind":"Pod","metadata":{"annotations":{},"labels":{},"name":"hello-busybox"},"spec":{"containers":[{"command":["sh","-c","echo \"hello, busybox!\"; sleep 300;"],"image":"busybox:latest","name":"hello-busybox"}]}}
      name: hello-busybox
      namespace: test
    spec:
      containers:
      - command:
        - sh
        - -c
        - echo "hello, busybox!"; sleep 300;
        image: busybox:latest
        name: hello-busybox
    You can use the "view-last-applied" flag to print the YAML file as it was applied the last time:
    $ kubectl apply -f hello-busybox-pod.yaml view-last-applied
    You can edit and update the definition of a kubernetes object:
    $ kubectl edit pod hello-busybox
  4. Manage Pods
    • To list all Pods (kubectl get pods):
      $ kubectl get pods
      NAME            READY   STATUS    RESTARTS   AGE
      hello-busybox   1/1     Running   0          18s

    • To list detailed information about all Pods (-o wide):
      $ kubectl get pods -o wide
      NAME            READY   STATUS    RESTARTS   AGE   IP         NODE             NOMINATED NODE   READINESS GATES
      hello-busybox   1/1     Running   0          80s   10.1.0.9   docker-desktop   <none>           <none>

    • To see the info of a specific Pod (kubectl get pod <POD-NAME>):
      $ kubectl get pod hello-busybox
      NAME            READY   STATUS    RESTARTS   AGE
      hello-busybox   1/1     Running   0          18s

    • To see detailed information about a specific Pod (-o wide):
      $ kubectl get pods hello-busybox -o wide
      NAME            READY   STATUS    RESTARTS   AGE   IP         NODE             NOMINATED NODE   READINESS GATES
      hello-busybox   1/1     Running   0          80s   10.1.0.9   docker-desktop   <none>           <none>

    • To monitor the status of the Pods (--watch):
      $ kubectl get pods --watch
      NAME            READY   STATUS              RESTARTS   AGE
      hello-busybox   0/1     ContainerCreating   0          2s
      hello-busybox   1/1     Running             0          17s
      A Pod is available when the field STATUS shows Running and the field READY shows the conainers ready (1/1). If a Pod has many containers, then the READY field should show the number of all its containers

    • To run a commands in a Pod (kubectl exec):
      $ kubectl exec hello-busybox -- env
      HOSTNAME=hello-busybox
      ...
      -- (double dash) separate the kubectl arguments from the command (and its arguments) you want to run in the Pod.

      If more than one container are running in the Pod, then the command will be executed against the first container in the Pod. To execute the command against a specific container, you need to use the --container (-c) flag and give it the name of the container:
      $ kubectl exec hello-busybox -c hello-busybox -- env
      The --container (-c) flag applies also to init containers.

    • To login into a Pod:
      $ kubectl exec -it hello-busybox -- sh
      / # ps
      PID   USER     TIME  COMMAND
          1 root      0:00 sleep 300
          7 root      0:00 sh
         13 root      0:00 ps
      / #
      -- (double dash) separate the kubectl arguments from the command (and its arguments) you want to run in the Pod.

      The options -it opens an interactive session with the Pod's remote shell by connecting the local shell's data streams to the Pod's data streams (stdin (standard input), stdout (standard out), and stderr (standard error)).
      -i, --stdin: Keep stdin open on the container(s) in the pod, even if nothing is attached.
      -t, --tty: Allocated a TTY for each container in the pod.

      If more than one container are running in the Pod, then the command will be executed against the first container in the Pod. To login to a specific container, you need to use the --container (-c) flag and give it the name of the container:
      $ kubectl exec -it hello-busybox -c hello-busybox -- sh
      The --container (-c) flag applies also to init containers.

    • To print the logs of a Pod (kubectl logs):
      $ kubectl logs hello-busybox
      hello, busybox!
      If more than one container are running in the Pod, then the command will be executed against the first container in the Pod (see the command: kubectl describe pod hello-busybox). To print the logs of a specific container, you need to use the --container (-c) flag and give it the name of the container:
      $ kubectl logs hello-busybox -c hello-busybox
      The --container (-c) flag applies also to init containers.

      You can use the --follow (-f) flag to continusly stream the logs in your terminal.

      You can use the --previous (-p) flag to show the logs of a previous instance of the Pod.

    • To copy files from the local VM to a Pod (kubectl cp):
      $ kubectl cp ./file1.txt hello-busybox:/tmp/file1.txt
      To copy files from the Pod to the local VM:
      $ kubectl cp hello-busybox:tmp/file1.txt ./file1-from-busybox-tar.txt
      Note that the path to the file in the Pod doesn't have the leading character '/'. This was needed to avoid this warning "tar: removing leading '/' from member names".

    • To forward a port from the local VM to a Pod (kubectl port-forward):
      kubectl apply -f - <<EOF
      apiVersion: v1
      kind: Pod
      metadata:
        name: hello-nginx
      spec:
        containers:
          - name: hello-nginx
            image: nginx:latest
            ports:
            - containerPort: 80
      EOF
      $ kubectl port-forward hello-nginx 8080:80
      Forwarding from 127.0.0.1:8080 -> 80
      Forwarding from [::1]:8080 -> 80
      $ curl http://localhost:8080
      <html>
      <head>
      <title>Welcome to nginx!</title>
      ...
      You can also use a Service to forward a port, but note that it will be bound to only one Pod of the Service:
      $ kubectl port-forward svc/kubernetes-dashboard-kong-proxy 8443:443 -n kubernetes-dashboard
  5. List detailed information about a Pod
    • To print the manifest file of a specific Pod as stored in the cluster store (etcd):
      $ kubectl get pod hello-busybox -o yaml
      apiVersion: v1
      kind: Pod
      metadata:
        annotations:
          kubectl.kubernetes.io/last-applied-configuration: |
            {"apiVersion":"v1","kind":"Pod","metadata":{"annotations":{},"labels":{},"name":"hello-busybox","namespace":"default"},"spec":{"containers":[{"args":["-c","echo \"hello, busybox!\"; sleep 300;"],"command":["sh"],"image":"busybox:latest","name":"hello-busybox"}]}}
        managedFields:
        - apiVersion: v1
      ...
          manager: kubelet
          operation: Update
        name: hello-busybox
        namespace: default
      spec:
        containers:
        - args:
          - -c
          - echo "hello, busybox!"; sleep 300;
          command:
          - sh
          image: busybox:latest
          imagePullPolicy: Always
          name: hello-busybox
          resources: {}
          terminationMessagePath: /dev/termination-log
          terminationMessagePolicy: File
          volumeMounts:
          - mountPath: /var/run/secrets/kubernetes.io/serviceaccount
            name: default-token-qvt58
            readOnly: true
        dnsPolicy: ClusterFirst
        enableServiceLinks: true
        nodeName: docker-desktop
        preemptionPolicy: PreemptLowerPriority
        priority: 0
        restartPolicy: Always
        schedulerName: default-scheduler
        securityContext: {}
        serviceAccount: default
        serviceAccountName: default
        terminationGracePeriodSeconds: 30
        tolerations:
      ...
        volumes:
        - name: default-token-qvt58
          secret:
            defaultMode: 420
            secretName: default-token-qvt58
      status:
        hostIP: 192.168.65.4
        phase: Running
        podIP: 10.1.0.15
        podIPs:
        - ip: 10.1.0.15
        qosClass: BestEffort
      Note: The printed yaml object contains more settings than what it was defined in the original manifest file.
      Some of the settings are the default values that Kubernets gives to the missing field in the manifest file.
      Some of the settings are runtime information set by Kubernets (node IP address, Pod IP address, container info, status, ...).

      The status field provides detailed information about the different transitional states of the Pod.

    • To describe a Pod (kubectl describe pod):

      The command provides detailed information about the Pod (node IP address, Pod IP address, container info, ...) and its current state.
      It also provide the list of the events (Scheduled, Pulled, Created, Started, ...) occurred while creating and running the Pod.

      $ kubectl describe pod hello-busybox
      Name:         hello-busybox
      Namespace:    default
      Priority:     0
      Node:         docker-desktop/192.168.65.4
      Labels:       product=mtitek
                    stage=dev
      Annotations:  <none>
      Status:       Running
      IP:           10.1.0.15
      IPs:
        IP:  10.1.0.15
      Containers:
        hello-busybox:
          Container ID:  docker://dacd7d6f411764b02b26884ef48c5ceec1d60faace4a8fbbc670638e2a6cb806
          Image:         busybox:latest
          Image ID:      docker-pullable://busybox@sha256:b5fc1d7b2e4ea86a06b0cf88de915a2c43a99a00b6b3c0af731e5f4c07ae8eff
          Port:          <none>
          Host Port:     <none>
          Command:
            sh
          Args:
            -c
            echo "hello, busybox!"; sleep 300;
          State:          Running
          Ready:          True
          Restart Count:  0
          Environment:    <none>
          Mounts:
            /var/run/secrets/kubernetes.io/serviceaccount from default-token-qvt58 (ro)
      Conditions:
        Type              Status
        Initialized       True
        Ready             True
        ContainersReady   True
        PodScheduled      True
      Volumes:
        default-token-qvt58:
          Type:        Secret (a volume populated by a Secret)
          SecretName:  default-token-qvt58
          Optional:    false
      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  3m13s  default-scheduler  Successfully assigned default/hello-busybox to docker-desktop
        Normal  Pulling    3m12s  kubelet            Pulling image "busybox:latest"
        Normal  Pulled     3m12s  kubelet            Successfully pulled image "busybox:latest" in 448.2757ms
        Normal  Created    3m12s  kubelet            Created container hello-busybox
        Normal  Started    3m12s  kubelet            Started container hello-busybox
  6. Define Pods resources (CPU, RAM)
    You can define the resources ("memory", "cpu") required for the containers running inside the Pod.
    You can use the field "requests" to define the minimum resources required for a container.
    You can use the field "limits" to define the maximum resources to be allocated to a container.

    The resources required by a Pod is the sum of the resources requested by all the containers of that Pod.
    Kubernetes will check if a node has available resources required by the Pod before deploying it in that node.

    The field "memory" allows you to define the memory that you would like to be allocated to the container.
    You can provide a value for the memory on kilobyte (k), Megabyte (M), Gigabyte (G).
    You can also provide a value for the memory on kibibyte (ki), Mebibytes (Mi), Gibibyte (Gi).
    Note that kilobyte is a multiplier of 1000 bytes while kibibyte is 2 to the power of 10 bytes (1024 bytes).
    Note that Megabyte is represented by the uppercase character "M".
    The lowercase character "m" represents the Milli unit (1000m = 1M).
    The OOM killer will be triggered if the application tries to allocate more than the limit defined for the container (Exit Code 137).

    The field "cpu" allows you to define the CPU core that you would like to be allocated to the container.
    You can provide a value for the the CPU cores on millicores (m).
    You can also provide a numerical value for the the CPU cores (0.5 for half a core (1024/2 = 512m), 2 for two cores (1024*2 = 2048m)).
    If the CPU usage exceeds the limits, then the processes inside the container will be throttled (slowed).

    If a Pod doesn't define a limit for the memory then in theory it can use more memory if available in the node but in such case Kubernetes won't be able to claim back the extra memory used by the Pod to give it to the new Pods. If no memory left on the node, then Kubernetes will check all the Pods that are using more memory than what they requested and terminate them. Any restarted Pod will need to be scheduled on a node that has the requested memory.

    If a Pod doesn't define a limit for the CPU cores then in theory it can use more cores if available in the node but if new Pods need to be installed on that node then Kubernetes will claim back the cpu used by the Pod and tries to divide the cores on all the pods with respect to the value of the "requests" field of each Pod.

    apiVersion: v1
    kind: Pod
    metadata:
      name: hello-busybox-resources
    spec:
      containers:
        - name: hello-busybox-resources
          image: busybox:latest
          command: ['sh', '-c', 'echo "hello, busybox!"; sleep 300;']
          resources:
            requests:
              memory: 100Mi
              cpu: 100m
            limits:
              memory: 200Mi
              cpu: 200m
    You can define a "ResourceQuota" to set the maximum resources (requests and limits) for all the objects to be created within a namespace.
    $ vi namespace-resource-quota.yaml
    apiVersion: v1
    kind: ResourceQuota
    metadata:
      name: namespace-resource-quota
    spec:
      hard:
        requests.memory: 1Gi
        requests.cpu: 1
        limits.memory: 2Gi
        limits.cpu: 2
    If you try to create an object that doesn't define a requests or limits, you will get an error:
    Error from server (Forbidden): error when creating "hello-busybox-pod.yaml": pods "hello-busybox" is forbidden:
    failed quota: namespace-resource-quota: must specify
    limits.cpu for: hello-busybox;
    limits.memory for: hello-busybox;
    requests.cpu for: hello-busybox;
    requests.memory for: hello-busybox
    To check the resources usage:
    $ kubectl get resourcequota/namespace-resource-quota
    NAME                       AGE   REQUEST                                            LIMIT
    namespace-resource-quota   13m   requests.cpu: 100m/1, requests.memory: 100Mi/1Gi   limits.cpu: 200m/2, limits.memory: 200Mi/2Gi
    You can also define a "LimitRange" to set the maximum resources (requests and limits) for all the objects of a specific type.
    $ vi resources-limit-range.yaml
    apiVersion: v1
    kind: LimitRange
    metadata:
      name: resources-limit-range
    spec:
      limits:
      - default: # default value for containers that doesn't specifyc a request or limits
          cpu: 1024m
        defaultRequest:
          cpu: 512m
        min: # minimum value for request and limits
          cpu: 512m
        max: # maximum value for request and limits
          cpu: "2"
        type: Container
    You will get an error, if you try to create an object that define values for requests or limits that exceeds the values in the ResourceQuota or LimitRange.
    Error from server (Forbidden): error when creating "hello-busybox-resources-pod.yaml": pods "hello-busybox-resources" is forbidden:
    minimum cpu usage per Container is 512m, but request is 100m
  7. Define Init Containers
    You can define init containers to perform special tasks before the main container get created.
    All init containers need to execute and complete succefully before the main container get created.

    $ vi hello-init-container-busybox-pod.yaml
    apiVersion: v1
    kind: Pod
    metadata:
      name: hello-init-container-busybox
    spec:
      initContainers:
      - name: init-container-show-hello
        image: busybox:latest
        command: ['sh', '-c', 'echo "hello, init container!"; sleep 5;']
      containers:
        - name: hello-init-container-busybox
          image: busybox:latest
          command: ['sh', '-c', 'echo "hello, busybox!"; sleep 300;']
    $ kubectl get pods hello-init-container-busybox
    NAME                           READY   STATUS    RESTARTS        AGE
    hello-init-container-busybox   1/1     Running   3 (2m48s ago)   18m
    Note that the column READY is showing "1/1" which means that the Pod has only 1 container and it's running.

    $ kubectl logs hello-init-container-busybox -c init-container-show-hello
    hello, init container!
  8. Define Sidecar Containers
    You can define sidcar containers to run before the main container get created.
    All sidcar containers need to run succefully before the main container get created.

    $ vi hello-sidcar-container-busybox-pod.yaml
    apiVersion: v1
    kind: Pod
    metadata:
      name: hello-sidcar-container-busybox
    spec:
      initContainers:
      - name: sidcar-container-show-hello
        image: busybox:latest
        command: ['sh', '-c', 'echo "hello, sidcar container!"; sleep infinity;']
        restartPolicy: Always
      containers:
        - name: hello-sidcar-container-busybox
          image: busybox:latest
          command: ['sh', '-c', 'echo "hello, busybox!"; sleep 300;']
    $ kubectl get pods hello-sidcar-container-busybox
    NAME                             READY   STATUS    RESTARTS   AGE
    hello-sidcar-container-busybox   2/2     Running   0          75s
    Note that the column READY is showing "2/2" which means that two containers are running.

    $ kubectl logs hello-sidcar-container-busybox -c sidcar-container-show-hello
    hello, sidcar container!
  9. Health Checks
    Kubernetes allow you to define probes to check the health of the Pod.
    You can define the liveness, readiness, and the startup probes.

    The startup probes ensure that the Pod complete all its tasks before Kubernetes starts monitoring its liveness and readiness.
    The liveness probes ensure that the Pod was started properly.
    The readiness probes ensure that the Pod is ready to process requests.

    If the startup probes fail then the Pod is restarted.
    The same for the liveness probes, if they fail then the Pod is restarted.
    If the readiness probes fail then the Pod is flagged as not willing to serve requests but it won't be restarted.

    Note that by default, the Pods are configured to always restart after a termination.
    This behaviour is managed by the restartPolicy field which support three settings: Always (default), OnFailure (non-zero exit status), Never.

    The probes have there settings:
    • initialDelaySeconds (default: 0): tells Kubernetes to wait the configured number of seconds before executing the first probe.

    • timeoutSeconds (default: 1): tells Kubernetes to timeout the probe if its execution last more than the configured number of seconds.

    • periodSeconds (default: 10): tells Kubernetes to execute the probe every x seconds.

    • failureThreshold (default: 3): tells Kubernetes to fail the probes check after x consecutive failures.

    • successThreshold (default: 1): tells Kubernetes to succeed the probes check after x consecutive successes (must be 1 for liveness and startup probes).

    • terminationGracePeriodSeconds (default: 30): tells Kubernetes to wait the defined number of seconds to let the Pod to terminate gracefully before forcing its termination (cannot be defined for the readiness probes).

    There are four means to check the health of the Pod using a probe:
    • exec: Execute a command inside the Pod. The probe is considered successful if the command exit with a status code of zero.
      exec:
        command: ['sh', '-c', 'test -f /tmp/file1;']

    • tcpSocket: Execute a tcp check against the Pod using the provided IP address and port. The probe is considered successful if the connection succeeds (port open).
      tcpSocket:
        port: 5432

    • httpGet: Execute an HTTP GET request against the Pod using the provided IP address, port, and path. The probe is considered successful if the response has a satus code >=200 and <400.
      httpGet:
        path: /healthz
        port: 80

    • grpc: Execute an RPC (remote procedure call) against the Pod. The probe is considered successful if the response is SERVING.
      grpc:
        port: 1024

    Let's define a Pod that declares the the liveness, readiness, and the startup probes:
    $ vi hello-probes-busybox-pod.yaml
    apiVersion: v1
    kind: Pod
    metadata:
      name: hello-probes-busybox
    spec:
      restartPolicy: Always
      containers:
        - name: hello-probes-busybox
          image: busybox:latest
          command: ['sh', '-c', 'touch /tmp/liveness-probe; touch /tmp/readiness-probe; touch /tmp/startup-probe; sleep infinity;']
          startupProbe:
            exec:
              command:
              - cat
              - /tmp/liveness-probe
            initialDelaySeconds: 5
            timeoutSeconds: 5
            periodSeconds: 10
            failureThreshold: 5
            successThreshold: 1
            terminationGracePeriodSeconds: 5
          livenessProbe:
            exec:
              command:
              - cat
              - /tmp/readiness-probe
            initialDelaySeconds: 5
            timeoutSeconds: 5
            periodSeconds: 10
            failureThreshold: 5
            successThreshold: 1
            terminationGracePeriodSeconds: 5
          readinessProbe:
            exec:
              command:
              - cat
              - /tmp/startup-probe
            initialDelaySeconds: 5
            timeoutSeconds: 5
            periodSeconds: 10
            failureThreshold: 5
            successThreshold: 5
    Let's create the Pod:
    $ kubectl apply -f hello-probes-busybox-pod.yaml
    pod/hello-probes-busybox created
    Let's check the Pod:
    $ kubectl get pods -w
    NAME                   READY   STATUS    RESTARTS   AGE
    hello-probes-busybox   0/1     Running   0          3s
    hello-probes-busybox   0/1     Running   0          10s
    hello-probes-busybox   1/1     Running   0          41s
  10. Labels
    Labels are key/value pairs (strings) that can be added to Kubernetes objects to group them so it can be easy to query and identify them (i.e. selector query).

    Labels can be written using the following format: key-prefix/key-name: value

    The key-prefix is optional and must be a valid DNS subdomain name.

    The key-name is mandatory and must respect the following constraints:
    • Maximum 63 characters.
    • The name can contain alphanumeric characters ([a-zA-Z0-9]), minus character ('-'), underscore character ('_'), and period character ('.').
    • The name must start and end with an alphanumeric character.

    The label value is any string that respect the same constraints as the key-name.

    Let's define a simple Pod with a Label:
    $ vi hello-labels-busybox-pod.yaml
    apiVersion: v1
    kind: Pod
    metadata:
      name: hello-labels-busybox # will be used as the hostname of the conatiners
      labels:
        label1-key/label1-name: label1-value
    spec:
      containers:
        - name: hello-labels-busybox
          image: busybox:latest
          command: ['sh', '-c', 'echo "hello, busybox!"; sleep infinity;']
    Let's deploy the hello-labels-busybox-pod.yaml file:
    $ kubectl apply -f hello-labels-busybox-pod.yaml
    pod/hello-labels-busybox created
    To add, update, or delete a label, you can update and apply the manifest file of the Pod. You can also use the imperative command kubectl label to add, update, or delete labels.

    To add a new label to the pod:
    $ kubectl label pods hello-labels-busybox "label2-key/label2-name=label2-value"
    pod/hello-labels-busybox labeled
    To show the labels attached to the Pod:
    $ kubectl get pods hello-labels-busybox --show-labels
    NAME                   READY   STATUS    RESTARTS   AGE    LABELS
    hello-labels-busybox   1/1     Running   0          109s   label1-key/label1-name=label1-value,label2-key/label2-name=label2-value
    You can use the option "--label-columns" ("-L") to present the label names as columns in the output of the command.
    The option accepts a comma separated list of labels names. You can also specify the options multiple times (-L label1 -L label2).
    Note that the labels names are case-sensitive.
    $ kubectl get pods hello-labels-busybox -L label1-key/label1-name -L LABEL-UNKNOWN
    NAME                   READY   STATUS    RESTARTS   AGE   LABEL1-NAME    LABEL-UNKNOWN
    hello-labels-busybox   1/1     Running   0          2m    label1-value
    To update a label of a pod:
    $ kubectl label pods hello-labels-busybox "label1-key/label1-name=label1-value-new" --overwrite
    pod/hello-labels-busybox labeled
    You need to use the option "--overwrite", otherwise you will get an error:
    error: 'label1-key/label1-name' already has a value (label1-value), and --overwrite is false

    To delete a label of a pod:
    $ kubectl label pods hello-labels-busybox "label2-key/label2-name-"
    pod/hello-labels-busybox labeled
    To show the labels changes:
    $ kubectl get pods hello-labels-busybox --show-labels
    NAME                   READY   STATUS    RESTARTS   AGE    LABELS
    hello-labels-busybox   1/1     Running   0          3m     label1-key/label1-name=label1-value-new
    You can use the option "--selector" ("-l") to filter Pods based on their label names.
    Note that the labels names/values are case-sensitive.
    The option supports the following operators:
    • key1=value1: Select all objects that have a label key "key1" and its value is equal to "value1".
    • key1!=value1: Select all objects that doesn't have a label key "key1" that its value is equal to "value1".
    • key1 in (value1, value2): Select all objects that have a label key "key1" and its value is equal to "value1" or "value2".
    • key1 notin (value1, value2): Select all objects that doesn't have a label key "key1" that its value is equal to "value1" or "value2".
    • key1: Select all objects that have a label key "key1".
    • !key1: Select all objects that doesn't have a label key "key1".

    Example using the "=" operator:
    $ kubectl get pods -l "label1-key/label1-name=label1-value-new" --show-labels
    NAME                   READY   STATUS    RESTARTS   AGE    LABELS
    hello-labels-busybox   1/1     Running   0          3m     label1-key/label1-name=label1-value-new
    Example using the "!" operator.
    Make sure to wrap the selector within single notes otherwise you will get an error (-bash: !label2: event not found).
    $ kubectl get pods -l '!label2-key/label2-name' --show-labels
    NAME                   READY   STATUS    RESTARTS   AGE    LABELS
    hello-labels-busybox   1/1     Running   0          3m     label1-key/label1-name=label1-value-new
  11. Delete Pods
    To delete a Pod: using manifest file (kubectl delete):
    $ kubectl delete -f hello-busybox-pod.yaml
    pod "hello-busybox" deleted
    To delete a Pod using its name:
    $ kubectl delete pod hello-busybox
    pod "hello-busybox" deleted
    By default, the Pod takes 30 seconds to gracefully shut down before it get completely terminated. Meanwhile the pod will show the state "Terminating".
    To delete a Pod immediately:
    $ kubectl delete pod hello-busybox --grace-period=0
    pod "hello-busybox" deleted
© 2025  mtitek