All the containers that make up your application will live in Pods. A Pod is a set of containers and shared resources that are always started and stopped together.

Pods can have multiple containers in them, but a best practice is to have only 1 container per Pod. Put multiple containers in a Pod only if what they do is tightly coupled and it wouldn't make sense to scale them up and down independently.

All containers in a Pod share the same network and can make requests to each other at localhost.

Defining Pods

The first step in creating a Pod is writing a YAML manifest file for it. See below for a very simple example of a Pod's manifest:

apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod
spec:
  containers:
  - name: nginx
    image: nginx:1.17-alpine
    ports:
    - containerPort: 80

The image this example uses is for an nginx web server. Create a file named "nginx-pod.yml" with these contents, then run kubectl apply -f nginx-pod.yml. This will update the cluster. The Pod will start soon thereafter.

$ kubectl apply -f nginx-pod.yml
pod/nginx-pod created

Managing Pods

Check your Pod with kubectl get pods.

$ kubectl get pods
NAME        READY   STATUS    RESTARTS   AGE
nginx-pod   1/1     Running   0          8m27s

This Pod will probably reach the "Running" status quickly.

You can bring down the Pod with kubectl delete pod nginx-pod or kubectl delete -f nginx-pod.yml.

$ kubectl delete pod nginx-pod
pod "nginx-pod" deleted

If you use kubectl apply and then quickly afterward use kubectl get pods you can catch the Pod before it has reached the "Running" status.

$ kubectl apply -f nginx-pod.yml && kubectl get pods
pod/nginx-pod created
NAME        READY   STATUS              RESTARTS   AGE
nginx-pod   0/1     ContainerCreating   0          0s

kubectl logs

You'll likely at some point want to read the logs of applications you deploy. It's a best practice when writing containerized apps to print logs to stdout and stderr. Kubernetes will gather these logs and display them if you use the kubectl logs command.

The nginx server from the previous example won't have any logs. Try adding a new Pod using the following manifest. It contains a process that prints a message every 10 seconds.

apiVersion: v1
kind: Pod
metadata:
  name: repeat-pod
spec:
  containers:
  - name: repeat
    image: bmcase/repeat-print
$ kubectl apply -f repeat-pod.yml
pod/repeat-pod created
$ kubectl get pods
NAME         READY   STATUS    RESTARTS   AGE
nginx-pod    1/1     Running   0          37m
repeat-pod   1/1     Running   0          6s

Once it's up and running, check its log messages with kubectl logs <pod-name>:

$ kubectl logs repeat-pod
It is now Wed May 29 18:45:18 UTC 2024
It is now Wed May 29 18:45:28 UTC 2024
It is now Wed May 29 18:45:38 UTC 2024

Many kubectl commands will have alternate ways to use them, and the arguments needed for these will be displayed with the --help argument. For kubectl logs, check out some of them with kubectl logs --help.

kubectl describe

kubectl get will tell you what you want to know about an object most of the time. But sometimes there is some info you can get better with kubectl describe.

For example: You might deploy a Pod, and then upon using kubectl get pods, you'll see the STATUS column for that Pod contains "ErrImagePull", or some other error message. You can then use kubectl describe pod <pod-name> and at the bottom of the response will be a list of events that can help you diagnose what went wrong.