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 podsYou 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: ClusterFirstIn 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 createdUsually, 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=clientThe --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.yamlThis 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 namespaceYou 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 15mEach 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, orCrashLoopBackOffRESTARTS: 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 node1You 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_NAMETo 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-nginxWhile 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 logsEditing 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.yamlAfter 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 --forceGetting 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.