Computer scienceSystem administration and DevOpsKubernetesRunning applications on Kubernetes

Working with a pod

10 minutes read

We’ve already seen what a Pod is and the part it plays in a Kubernetes cluster. In this topic, we’ll look at how to create, run, list, and delete Pods. We’ll also see how to view logs from application containers in a Pod and open a shell in a running container in a Pod for troubleshooting.

Creating a Pod

In practice, you wouldn’t create Pods directly. You’d use a workload resource such as Deployment or Job resources, which we cover later. To create a pod, you can use the kubectl run command:

$ kubectl run dev-nginx --image=nginx:latest --port=8080 

This is known as imperative management and is useful for quick tests. To verify that the Pod is available and running, use the following command:

$ kubectl get pods

You can also create Pods declaratively by defining the desired state in a YAML file. This manifest, along with other Kubernetes objects, should be treated like source code. This makes it easy to track changes over time. The Pod manifest includes various key fields and attributes: a metadata field containing the name and labels for the Pod, and a spec field containing volumes and container specifications:

apiVersion: v1
kind: Pod
metadata:
  name: nginx-server
spec:
  containers:
    - image: nginx:latest
      name: nginx
      ports:
        - containerPort: 8080
          name: http
          protocol: TCP
  restartPolicy: Always
  dnsPolicy: ClusterFirst

In the example shown above, the Pod runs the latest version of the NGINX image. You can specify any number of containers, but ideally you should run only one container per Pod. Once you have this manifest created, you can apply it with the kubectl apply command:

$ kubectl apply -f nginx-server.yaml # use the name for the file you created

Usually, it’ll be helpful to test the impact of potential changes before applying them. In that case, you can use the --dry-run flag to simulate the execution of the command without actually performing any changes in the cluster:

$ kubectl apply -f nginx-server.yaml --dry-run=client

The --dry-run flag also helps you generate Pod definitions on the fly so you don’t have to remember every field. For example, we generate the YAML manifest we used earlier with the following command:

$ kubectl run nginx-server --image=nginx:latest --dry-run=client --output yaml > nginx-server.yaml

This creates a YAML file, which we can then apply to the cluster with kubectl apply.

Pod information

We’ve already used the kubectl get pods command to view all Pods in the default namespace in our Kubernetes cluster. You can also use the shorthand kubectl get po command. If you have another namespace, you need to specify it with the --namespace or -n flag. You can also use the -A flag to view all Pods in all namespaces:

$ kubectl get po -A # view Pods in all namespaces
$ kubectl get po -n hyperspace # view Pods in the hyperspace namespace

You receive a table with details about the Pods, including their name, status, and age.


NAME      READY   STATUS    RESTARTS   AGE
pod1      1/1     Running   0          5m
pod2      1/1     Running   0          10m
pod3      1/1     Running   0          15m

Each row represents a Pod, and the columns provide the following information:

  • NAME: name of the pod

  • READY: number of containers in the pod that are ready versus the total number of containers in the pod

  • STATUS: current status of the pod. The possible values are Running, Pending, or CrashLoopBackOff

  • RESTARTS: number of times the containers in the Pod have been restarted

  • AGE: the amount of time that has passed since the Pod was created

You can request additional details with the -o wide flag such as the IP address assigned to the Pod and the node it is placed in:

$ kubectl get pods -o wide

NAME      READY   STATUS    RESTARTS   AGE     IP            NODE
pod1      1/1     Running   0          5m      10.244.1.10   node1
pod2      1/1     Running   0          10m     10.244.2.15   node2
pod3      1/1     Running   0          15m     10.244.1.25   node1

You can also get output in YAML or JSON format with -o yaml or -o json respectfully. This is useful especially when you want to use the output in a subsequent step in a script:

$ POD_NAME=$(kubectl get pods -o jsonpath='{.items[0].metadata.name}')
$ echo $POD_NAME

To get more information about a specific Pod, use kubectl describe command:

$ kubectl describe pod <pod-name> --namespace <namespace-name>

This command displays detailed information about the specified Pod. Here are some bits of information you can find: name, namespace, node, status, IP address, containers, conditions, volumes, and events. For example, the Events field can be very useful in determining why a Pod is not running:

...

Events:
  Type    Reason     Age   From               Message
  ----    ------     ----  ----               -------
  Normal  Scheduled  47m   default-scheduler  Successfully assigned default/dev-nginx to hyper-control-plane
  Normal  Pulling    47m   kubelet            Pulling image "nginx:latest"
  Normal  Pulled     46m   kubelet            Successfully pulled image "nginx:latest" in 26.062s (26.062s including waiting). Image size: 62960006 bytes.
  Normal  Created    46m   kubelet            Created container: dev-nginx
  Normal  Started    46m   kubelet            Started container dev-nginx

While the kubectl describe command provides a treasure trove of information, you may want to get logs from a container in a Pod. For that, these commands are useful:

$ kubectl logs <pod_name>
$ kubectl logs <pod_name> --container <container_name> # get logs from a specific container
$ kubectl logs <pod_name> --container <container_name> --follow # to continuously stream events
$ kubectl logs <pod_name> --container <container_name> --tail=10 # to view the last 10 lines of logs

Editing and deleting a Pod

For Pods created via workload resources, such as Deployment, Kubernetes automatically deletes Pods as needed. For example, a Job controller will ensure that the Pods it creates are deleted when the Job finishes executing. Additionally, in such cases, you cannot edit or delete the Pod manifest directly because the controller will recreate the Pod to meet the desired state. In such cases, you edit the controller manifest, which we see in future topics.

If you created the Pod directly, as we have done in this topic, you can edit some aspects and also delete Pods with the kubectl edit command. This opens a text editor where you can change editable aspects of the Pod, such as the image version:

$ kubectl edit pod <pod_name>

Once you close the editor, the changes, if valid, are applied. To delete a Pod, you can use the following command:

$ kubectl delete pod <pod-name> --namespace <namespace-name>

If you created the Pod declaratively, you can pass the Pod’s YAML manifest to delete it:

$ kubectl delete -f nginx-server.yaml

After running the delete command, Kubernetes initiates the deletion of the specified Pod. It may take a few moments for the container to fully terminate and remove the Pod from the cluster. To delete the Pod forcefully and immediately, you may use the following command:

$ kubectl delete pod <pod-name> --grace-period=0 --force

Getting a shell to a running container in a Pod

We saw how you can collect logs from a running container. In some cases, however, you might need an interactive shell session. This is very useful for debugging.

You can use the following command to get a shell to a running container in a Pod:

$ kubectl exec -it [pod-name] --container [container-name] -- /bin/bash

-it sets --stdin and --tty to true giving you an interactive shell where you can type additional commands. In our example above, the command to run in the container is /bin/bash, which means we can then run Bash commands in the container’s environment.

The double dash -- separates kubectl commands from the command you want to run in the container. You can omit the --container flag if the Pod contains only one container. Once the shell is open, we can interact with the container as if we were accessing it directly.

Conclusion

We have explored the basics of working with Pods in Kubernetes. We saw how to create Pods, inspect their status, view their logs, and edit/delete them when needed. We also looked at how to open a shell in a running container for troubleshooting. With these commands and concepts, you now have a solid foundation for working with Pods effectively.

9 learners liked this piece of theory. 1 didn't like it. What about you?
Report a typo