..is the smallest deployable unit one can create and manage inside Kubernetes(K8s). A Pod can have one or more running containers, so it is a set of running containers.
What is a container?
A container image is a binary containing an application you created and all that needs for its running like system and application libraries, configuration files, etc. When you run a container image it becomes container. You can imagine a container image as a software-package but when you run it becomes container.
Why there is a difference? A container image can be changed. While a container is immutable, meaning that you can not change it once you create it. If there is a new version of a container image, the only way to apply those changes to the container is to destroy the old one and start new.
The container runtime is the software responsible for running containers. K8s supports any container runtime that implements Kubernetes CRI (Container Runtime Interface) like Docker, containerd, CRI-O.
What is a Pod?
As already mentioned a Pod is the smallest deployable unit in K8s. It is as well a set of containers. That set can have one or more containers bound by some logic.
What a Pod does?
You can think of a Pod as a single machine, a host. It is not that but you can imagine it like that. A Pod has:
- a unique IP address
- persistent storage volumes(optional, if required)
- configuration, which defines how container(s) should be run
From K8s point, a Pod is a process running in a cluster. That process has a unique IP address so other processes(Pods) can communicate with it. On the other hand containers in a Pod share the same IP address. This means if they want to communicate with outside they are using unique ports. So, no two containers are on the same port.
Inter container communication in the same Pod goes over localhost. If there is attached persistent storage volume that can be used as a means of communication as well.
Basic operations with a Pod
I’m running these examples on the local cluster based on the k3d. If you do not have access to other K8s clusters where you can execute these examples, go to my quick intro to k3d.
Basic Pod configuration
Let’s start by running:
> kubectl run nginx-ser --image nginx --restart=Never --dry-run=client -o yaml
With this kubectl command you say that you want the Pod named nginx-ser
made from nginx
image(in this case, default, it is Docker image). Other flags --dry-run
prevents its deployment, and -o
specify output to be YAML format. The result should be something like this:
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: nginx-ser
name: nginx-ser
spec:
containers:
- image: nginx
name: nginx-ser
resources: {}
dnsPolicy: ClusterFirst
restartPolicy: Always
status: {}
Lets dump this into file:
> kubectl run nginx-ser --image nginx --restart=Never --dry-run=client -o yaml > pod.yaml
Open this file pod.yaml
any editor you like and remove unneeded lines so it looks like:
apiVersion: v1
kind: Pod
metadata:
labels:
run: nginx-ser
name: nginx-ser
spec:
containers:
- image: nginx
name: nginx-ser
To create a Pod run:
> kubectl apply -f pod.yaml
If you look inside pod.yaml
file you’ll see a basic Pod configuration:
apiVersion
: tells which version of K8s API to usekind
: what K8s resource to operate withmetadata
: these arelabels
andannotations
. You use them to organize your Podsspec
: a Pod configuration specification wherecontainers
is defined
Under spec.containers
you put an array of container definitions. Each container definition should have at least name
. The image
property is not required
as it can be defaulted or managed by higher config management. In my case, I’m using Docker runtime so it is a docker image. This docker image is pulled from
Docker Hub.
Inspect a Pod
You can check the status of a Pod:
❯ kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx-ser 1/1 Running 0 14m
Here you see a Pod:
- name
- ready status: is pod healthy and if it is ready to receive status
- status
- number of restarts
- age
You can get more information if you add the option -o wide
:
❯ kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-ser 1/1 Running 0 6h4m 10.42.0.22 k3d-private-cluster-server-0 <none> <none>
In this example, you see internal IP, IP number inside a cluster, and a node
name where Pod is scheduled.
You get a YAML definition of a Pod if you do:
❯ kubectl get pods -o yaml
This could be quite verbose so redirect it some file and open it in an editor. Specifying output option -o
you can set the format of output,
where most interesting and used are wide
, yaml
and json
.
A good way to see a Pod is to describe it:
❯ kubectl describe pods nginx-ser
Name: nginx-ser
Namespace: default
Priority: 0
Node: k3d-private-cluster-server-0/172.19.0.2
Start Time: Sun, 21 Mar 2021 12:42:17 +0100
Labels: run=nginx-ser
Annotations: <none>
Status: Running
IP: 10.42.0.22
IPs:
IP: 10.42.0.22
Containers:
nginx-ser:
Container ID: containerd://34b8f75b1f3b3ad891791198409cf25412e6bbc18468a2706aa441ee9001a41c
Image: nginx
Image ID: docker.io/library/nginx@sha256:d2925188effb4ddca9f14f162d6fba9b5fab232028aa07ae5c1dab764dca8f9f
Port: <none>
Host Port: <none>
State: Running
Started: Sun, 21 Mar 2021 12:42:19 +0100
Ready: True
Restart Count: 0
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from default-token-j6lht (ro)
Conditions:
Type Status
Initialized True
Ready True
ContainersReady True
PodScheduled True
Volumes:
default-token-j6lht:
Type: Secret (a volume populated by a Secret)
SecretName: default-token-j6lht
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: <none>
You can check container logs:
kubectl logs nginx-ser
Modifying a Pod
To modify a Pod you need to modify its specification. Either you get a Pod as YAML file and modify it:
> kubectl get pod nginx-ser > nginx-ser.yaml
Then open file nginx-ser.yaml
and modify it. Then apply it again:
> kubectl apply -f nginx-ser.yaml
Or edit it directly inside K8s:
> kubectl edit pods nginx-ser
This will open Pod’s YAML configuration inside the vi editor. Once you save your modifications and exit the editor your changes will be applied.
Delete a Pod
Just do:
> kubectl delete pod nginx-ser
Hands-On
Let’s try to access to running nginx server on deployed Pod. At the moment this Pos is not visible outside. That means you can access it only inside a K8s cluster. One way is to run temporary with curl command:
❯ kubectl run curl --image curlimages/curl --restart=Never -it --rm -- curl http://<target ip>
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
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>
pod "curl" deleted
Above kubectl
command uses curlimages/curl
Docker image to create a Pod named curl
. It creates an interactive terminal with -it
so it writes output to your
terminal. Delete this Pod after execution with --rm
. Executes a command curl <target ip>
.
❓ Do you remember how to get the target pod internal IP?
Now try to run pod named httpd
with image httpd
. Check what is assigned IP and try to curl it. If are successful you should get:
<html><body><h1>It works!</h1></body></html>
Thank you for reading my blog!
If you have any questions let me know.
Sign up for my email newsletter or use this RSS feed to get notified of new blog posts.