How to Create a Kubernetes Pod

Introduction

Right after setting up our Kubernetes cluster, our first thinking will be how to create a pod on it. Let’s see how to create a Kubernetes Pod in this guide. For illustrating purpose we are not going to create a separate namespace, Instead, we will use the default namespace. If you are unaware about what is namespace have a quick read.

In the default namespace of kubernetes cluster we don’t have a pod yet. Let’s start with listing and creating one.

root@k8mas1:~# kubectl get pods
No resources found in default namespace.
root@k8mas1:~#

The above output shows we don’t have a pod.

Creating a Kubernetes Pod in easy way

To create a pod in single command with options and arguments use

root@k8mas1:~# kubectl run nginx-pod --image=nginx
pod/nginx-pod created
root@k8mas1:~#

This will take few seconds to complete creating the pod by downloading its image from docker.io

Let’s list the created Pods

root@k8mas1:~# kubectl get pods
NAME        READY   STATUS              RESTARTS   AGE
nginx-pod   0/1     ContainerCreating   0          5s
root@k8mas1:~#

root@k8mas1:~# kubectl get pods
NAME        READY   STATUS    RESTARTS   AGE
nginx-pod   1/1     Running   0          10s
root@k8mas1:~#

To know the pod running on which node, use wide option with -o option.

root@k8mas1:~# kubectl get pods -o wide
NAME        READY   STATUS    RESTARTS   AGE     IP                NODE                          NOMINATED NODE   READINESS GATES
nginx-pod   1/1     Running   0          3m57s   192.168.145.223   k8nod1.linuxsysadmins.local   <none>           <none>
root@k8mas1:~#

To get more information about the created pod we can use describe option.

root@k8mas1:~# kubectl describe pods nginx-pod 
Name:         nginx-pod
Namespace:    default
Priority:     0
Node:         k8nod1.linuxsysadmins.local/192.168.0.27
Start Time:   Sun, 24 May 2020 00:02:22 +0000
Labels:       run=nginx-pod
Annotations:  cni.projectcalico.org/podIP: 192.168.145.223/32
Status:       Running
IP:           192.168.145.223
IPs:
  IP:  192.168.145.223
Containers:
  nginx-pod:
    Container ID:   docker://2e413b101b7f121e132cabadf6d543c880a206215d9d907f51be4aad0413aac5
    Image:          nginx
    Image ID:       docker-pullable://nginx@sha256:30dfa439718a17baafefadf16c5e7c9d0a1cde97b4fd84f63b69e13513be7097
    Port:           <none>
    Host Port:      <none>
    State:          Running
      Started:      Sun, 24 May 2020 00:02:28 +0000
    Ready:          True
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-f4srz (ro)
Conditions:
  Type              Status
  Initialized       True 
  Ready             True 
  ContainersReady   True 
  PodScheduled      True 
Volumes:
  default-token-f4srz:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-f4srz
    Optional:    false
QoS Class:       BestEffort
Node-Selectors:  <none>
Tolerations:     node.kubernetes.io/not-ready:NoExecute for 300s
                 node.kubernetes.io/unreachable:NoExecute for 300s
Events:
  Type    Reason     Age    From                                  Message
  ----    ------     ----   ----                                  -------
  Normal  Scheduled  2m45s  default-scheduler                     Successfully assigned default/nginx-pod to k8nod1.linuxsysadmins.local
  Normal  Pulling    2m44s  kubelet, k8nod1.linuxsysadmins.local  Pulling image "nginx"
  Normal  Pulled     2m39s  kubelet, k8nod1.linuxsysadmins.local  Successfully pulled image "nginx"
  Normal  Created    2m39s  kubelet, k8nod1.linuxsysadmins.local  Created container nginx-pod
  Normal  Started    2m39s  kubelet, k8nod1.linuxsysadmins.local  Started container nginx-pod
root@k8mas1:~#

Running a Dry Run

Before creating a pod if you need to know what will happen when we run the kubectl run command it’s possible by adding --dry-run option. This won’t create the pod instead it will show what will happens.

# kubectl run nginx-pod --image=nginx --dry-run=client

If you need to print the YAML format or JSON format in screen it’s too possible by including -o yaml or -o json.

Output in YAML format

root@k8mas1:~# kubectl run nginx-pod --image=nginx --dry-run=client -o yaml
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: nginx-pod
  name: nginx-pod
spec:
  containers:
  - image: nginx
    name: nginx-pod
    resources: {}
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}
root@k8mas1:~#

Printing the output in JSON format.

root@k8mas1:~# kubectl run nginx-pod --image=nginx --dry-run=client -o json
{
    "kind": "Pod",
    "apiVersion": "v1",
    "metadata": {
        "name": "nginx-pod",
        "creationTimestamp": null,
        "labels": {
            "run": "nginx-pod"
        }
    },
    "spec": {
        "containers": [
            {
                "name": "nginx-pod",
                "image": "nginx",
                "resources": {}
            }
        ],
        "restartPolicy": "Always",
        "dnsPolicy": "ClusterFirst"
    },
    "status": {}
}
root@k8mas1:~#

Without typing any YAML coding it’s possible to redirect the output to a file by running.

# kubectl run nginx-pod --image=nginx --dry-run=client -o yaml > nginx-pod.yaml

This will create the YAML file as show below.

root@k8mas1:~# cat nginx-pod.yaml 
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: nginx-pod
  name: nginx-pod
spec:
  containers:
  - image: nginx
    name: nginx-pod
    resources: {}
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}
root@k8mas1:~#

This is the easiest way to create a Kubernetes Pod. However, if you need to add more options to the pod it’s better to go with creating in a hard way.

Creating a Kubernetes Pod in a Hard way

To create a pod in a hard way first we need to create with a YAML file. To prepare the YAML file we can use vim or some other IDE. Personally, I use Sublime, Atom and Visual Studio Code. Atom one is very lightweight and handy to me.

Alternatively, as shown above we can create by redirecting the output to a file and then modify as per our need.

I have created a YAML file quickly by using atom.

apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod
  labels:
    name: web-app
spec:
  containers:
  - name: web-app-container
    image: nginx
    resources:
      limits:
        memory: "128Mi"
        cpu: "500m"
    ports:
      - containerPort: 80

Let’s copy paste and create a yaml file in server. To keep the same Syntax while copy paste run cat > my_first_pod.yaml.

To create the Pod from YAML file run the command kubectl.

root@k8mas1:~# kubectl create -f my_first_pod.yaml
pod/nginx-pod created
root@k8mas1:~#

To list the pod use the same command as we discussed above.

root@k8mas1:~# kubectl get pods
NAME        READY   STATUS    RESTARTS   AGE
nginx-pod   1/1     Running   0          55s
root@k8mas1:~#

However, we have another way to list the created pod as well. If you need to know which pods are created using a specific YAML file use the command as follow.

root@k8mas1:~# kubectl get -f my_first_pod.yaml 
NAME        READY   STATUS    RESTARTS   AGE
nginx-pod   1/1     Running   0          63s
root@k8mas1:~#

For a brief information about the created pod describe with -f option by pointing the YAML file.

root@k8mas1:~# kubectl describe -f my_first_pod.yaml 
Name:         nginx-pod
Namespace:    default
Priority:     0
Node:         k8nod1.linuxsysadmins.local/192.168.0.27
Start Time:   Sun, 24 May 2020 00:15:16 +0000
Labels:       name=web-app
Annotations:  cni.projectcalico.org/podIP: 192.168.145.222/32
Status:       Running
IP:           192.168.145.222
IPs:
  IP:  192.168.145.222
Containers:
  web-app-container:
    Container ID:   docker://9a1d8adde97ad1d0c0db957f8f913c00f8d3d8278246c96ba04964409d3f7655
    Image:          nginx
    Image ID:       docker-pullable://nginx@sha256:30dfa439718a17baafefadf16c5e7c9d0a1cde97b4fd84f63b69e13513be7097
    Port:           80/TCP
    Host Port:      0/TCP
    State:          Running
      Started:      Sun, 24 May 2020 00:15:22 +0000
    Ready:          True
    Restart Count:  0
    Limits:
      cpu:     500m
      memory:  128Mi
    Requests:
      cpu:        500m
      memory:     128Mi
    Environment:  <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-f4srz (ro)
Conditions:
  Type              Status
  Initialized       True 
  Ready             True 
  ContainersReady   True 
  PodScheduled      True 
Volumes:
  default-token-f4srz:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-f4srz
    Optional:    false
QoS Class:       Guaranteed
Node-Selectors:  <none>
Tolerations:     node.kubernetes.io/not-ready:NoExecute for 300s
                 node.kubernetes.io/unreachable:NoExecute for 300s
Events:
  Type    Reason     Age    From                                  Message
  ----    ------     ----   ----                                  -------
  Normal  Scheduled  4m     default-scheduler                     Successfully assigned default/nginx-pod to k8nod1.linuxsysadmins.local
  Normal  Pulling    3m59s  kubelet, k8nod1.linuxsysadmins.local  Pulling image "nginx"
  Normal  Pulled     3m54s  kubelet, k8nod1.linuxsysadmins.local  Successfully pulled image "nginx"
  Normal  Created    3m54s  kubelet, k8nod1.linuxsysadmins.local  Created container web-app-container
  Normal  Started    3m54s  kubelet, k8nod1.linuxsysadmins.local  Started container web-app-container
root@k8mas1:~#

Exposing the Created Kubernetes Pod

Once after creating the pod, we need to reach the web server for that we need to expose the pod by creating a service.

root@k8mas1:~# kubectl create service clusterip nginx-service --tcp 80:80
service/nginx-service created
root@k8mas1:~#

List the created Service.

root@k8mas1:~# kubectl get service
NAME            TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)   AGE
kubernetes      ClusterIP   10.96.0.1        <none>        443/TCP   30d
nginx-service   ClusterIP   10.101.209.142   <none>        80/TCP    3s
root@k8mas1:~#

To access the Pod list the pod with more information by using -o wide option.

root@k8mas1:~# kubectl get pods -o wide
NAME        READY   STATUS    RESTARTS   AGE     IP                NODE                          NOMINATED NODE   READINESS GATES
nginx-pod   1/1     Running   0          9m18s   192.168.145.231   k8nod1.linuxsysadmins.local   <none>           <none>
root@k8mas1:~# 

And do a curl to verify the reachability.

root@k8mas1:~# curl http://192.168.145.231
<!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>
root@k8mas1:~# 

Shell access to Pod

To access the shell of any pod use

root@k8mas1:~# kubectl exec nginx-pod -it /bin/bash
root@nginx-pod:/# 
root@nginx-pod:/# hostname 
nginx-pod
root@nginx-pod:/#

These are the environment variables set inside this Pod.

root@nginx-pod:/# env
KUBERNETES_SERVICE_PORT_HTTPS=443
KUBERNETES_SERVICE_PORT=443
HOSTNAME=nginx-pod
PWD=/
NGINX_SVC_PORT_80_TCP=tcp://10.107.251.87:80
NGINX_SVC_PORT=tcp://10.107.251.87:80
PKG_RELEASE=1~buster
HOME=/root
KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443
NGINX_SVC_SERVICE_PORT=80
NGINX_SVC_PORT_80_TCP_ADDR=10.107.251.87
NGINX_SVC_SERVICE_PORT_80_80=80
NJS_VERSION=0.3.9
TERM=xterm
NGINX_SVC_PORT_80_TCP_PORT=80
SHLVL=1
NGINX_SVC_PORT_80_TCP_PROTO=tcp
KUBERNETES_PORT_443_TCP_PROTO=tcp
KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1
KUBERNETES_SERVICE_HOST=10.96.0.1
KUBERNETES_PORT=tcp://10.96.0.1:443
KUBERNETES_PORT_443_TCP_PORT=443
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
NGINX_VERSION=1.17.10
NGINX_SVC_SERVICE_HOST=10.107.251.87
_=/usr/bin/env
root@nginx-pod:/#

Finally, let see how to do a clean up.

Deleting a Kubernetes Pod

To delete the pod we can remove it by running.

root@k8mas1:~# kubectl delete pods nginx-pod 
pod "nginx-pod" deleted
root@k8mas1:~#

root@k8mas1:~# kubectl get pods
No resources found in default namespace.
root@k8mas1:~#

Once the pod removed we can’t revert back.

To remove a service or svc.

root@k8mas1:~# kubectl delete service nginx-service
service "nginx-service" deleted
root@k8mas1:~#

That’s it we have successfully completed with creating our first Kubernetes Pod.

Conclusion

Creating a Kubernetes Pod in several ways are discussed above. To get more updates on Kubernetes guides follow us by subscribing to our newsletter.