DEV Community

Cover image for K8s Hands-on: Creating Pod on Kubernetes Cluster, Minikube, Imperative & Declarative Way
Ömer Berat Sezer
Ömer Berat Sezer

Posted on

K8s Hands-on: Creating Pod on Kubernetes Cluster, Minikube, Imperative & Declarative Way

In the previous post, we've mentioned about the Kubernetes tutorial. Please have a look below link, if you haven't seen before:

In this post, we'll see how to create pod in 2 ways.

How to install Minikube?

  • Minikube is a lightweight tool that runs a single-node Kubernetes cluster locally for development and testing.

  • It includes essential Kubernetes components like the API server, scheduler, controller manager, and etcd, along with optional add-ons like the dashboard and ingress. Minikube supports multiple platforms and integrates with kubectl for seamless interaction with the cluster.

  • All you need is Docker (or similarly compatible) container or a Virtual Machine environment, and Kubernetes is a single command away: minikube start

  • To install: https://minikube.sigs.k8s.io/docs/start/

K8s Creating Pod - Imperative Way

This scenario shows:

  • how to create basic K8s pod using imperative commands,
  • how to get detailed information about a pod for troubleshooting,
  • how to run commands inside a pod,
  • how to delete pod.

Steps

  • Run minikube (in this scenario, K8s runs on WSL2-Ubuntu, possible to run Linux or Win on where docker is installed)
  • Minikube is not cluster, it is only learning environment, it is designed for running K8s commands.
user@k8s:~$ minikube start
😄  minikube v1.35.0 on Ubuntu 20.04
✨  Automatically selected the docker driver. Other choices: none, ssh
📌  Using Docker driver with root privileges
👍  Starting "minikube" primary control-plane node in "minikube" cluster
🚜  Pulling base image v0.0.46 ...
💾  Downloading Kubernetes v1.32.0 preload ...
    > preloaded-images-k8s-v18-v1...:  333.57 MiB / 333.57 MiB  100.00% 31.49 M
🔥  Creating docker container (CPUs=2, Memory=3100MB) ...
🐳  Preparing Kubernetes v1.32.0 on Docker 27.4.1 ...
    ▪ Generating certificates and keys ...
    ▪ Booting up control plane ...
    ▪ Configuring RBAC rules ...
🔗  Configuring bridge CNI (Container Networking Interface) ...
🔎  Verifying Kubernetes components...
    ▪ Using image gcr.io/k8s-minikube/storage-provisioner:v5
🌟  Enabled addons: storage-provisioner, default-storageclass
Enter fullscreen mode Exit fullscreen mode
  • Run pod in imperative way with kubectl run podName --image=imageName and get pod info in default namespace with kubectl get pods -o wide
user@k8s:~$ kubectl run firstpod --image=nginx --restart=Never
pod/firstpod created

user@k8s:~$ kubectl get pods -o wide
NAME       READY   STATUS    RESTARTS   AGE   IP           NODE       NOMINATED NODE   READINESS GATES
firstpod   1/1     Running   0          13s   10.244.0.4   minikube   <none>           <none>
Enter fullscreen mode Exit fullscreen mode
  • To get pods in all namespaces with -A
user@k8s:~$ kubectl get pods -o wide -A
NAMESPACE     NAME                               READY   STATUS    RESTARTS        AGE     IP             NODE       NOMINATED NODE   READINESS GATES
default       firstpod                           1/1     Running   0               2m56s   10.244.0.4     minikube   <none>           <none>
kube-system   coredns-668d6bf9bc-2bt7j           1/1     Running   2 (4m36s ago)   5m8s    10.244.0.3     minikube   <none>           <none>
kube-system   etcd-minikube                      1/1     Running   1 (4m36s ago)   5m12s   192.168.49.2   minikube   <none>           <none>
kube-system   kube-apiserver-minikube            1/1     Running   1 (4m36s ago)   5m12s   192.168.49.2   minikube   <none>           <none>
kube-system   kube-controller-manager-minikube   1/1     Running   1 (4m36s ago)   5m12s   192.168.49.2   minikube   <none>           <none>
kube-system   kube-proxy-52562                   1/1     Running   1 (4m36s ago)   5m8s    192.168.49.2   minikube   <none>           <none>
kube-system   kube-scheduler-minikube            1/1     Running   1 (4m36s ago)   5m12s   192.168.49.2   minikube   <none>           <none>
kube-system   storage-provisioner                1/1     Running   2 (3m48s ago)   5m10s   192.168.49.2   minikube   <none>           <none>
Enter fullscreen mode Exit fullscreen mode
  • Describe pod to get more information about pods especially when troubleshooting:
user@k8s:~$ kubectl describe pod firstpod
Name:         firstpod
Namespace:    default
Priority:     0
Node:         minikube/192.168.49.2
Start Time:   Mon, 19 Jan 2025 14:14:23 +0100
Labels:       run=firstpod
Annotations:  <none>
Status:       Running
IP:           10.244.0.4
IPs:
  IP:  10.244.0.4
Containers:
  firstpod:
    Container ID:   docker://62e52deac315d337a3f73f7f78dd3a847abff2cc9aecb8291755bea02fa0d547
    Image:          nginx
    Image ID:       docker-pullable://nginx@sha256:0a399eb16751829e1af26fea27b20c3ec28d7ab1fb72182879dcae1cca21206a
    Port:           <none>
    Host Port:      <none>
    State:          Running
      Started:      Mon, 19 Jan 2025 14:14:35 +0100
    Ready:          True
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-gl9h8 (ro)
Conditions:
  Type                        Status
  PodReadyToStartContainers   True
  Initialized                 True
  Ready                       True
  ContainersReady             True
  PodScheduled                True
Volumes:
  kube-api-access-gl9h8:
    Type:                    Projected (a volume that contains injected data from multiple sources)
    TokenExpirationSeconds:  3607
    ConfigMapName:           kube-root-ca.crt
    ConfigMapOptional:       <nil>
    DownwardAPI:             true
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:
  Type    Reason     Age   From               Message
  ----    ------     ----  ----               -------
  Normal  Scheduled  42s   default-scheduler  Successfully assigned default/firstpod to minikube
  Normal  Pulling    42s   kubelet            Pulling image "nginx"
  Normal  Pulled     30s   kubelet            Successfully pulled image "nginx" in 11.17s (11.17s including waiting). Image size: 191717838 bytes.
  Normal  Created    30s   kubelet            Created container: firstpod
  Normal  Started    30s   kubelet            Started container firstpod
Enter fullscreen mode Exit fullscreen mode
  • To reach logs in the pod (when encountered troubleshooting):
user@k8s:~$ kubectl logs firstpod
/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
/docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
/docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf
10-listen-on-ipv6-by-default.sh: info: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf
/docker-entrypoint.sh: Sourcing /docker-entrypoint.d/15-local-resolvers.envsh
/docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
/docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
/docker-entrypoint.sh: Configuration complete; ready for start up
2025/01/20 13:14:35 [notice] 1#1: using the "epoll" event method
2025/01/20 13:14:35 [notice] 1#1: nginx/1.27.3
2025/01/20 13:14:35 [notice] 1#1: built by gcc 12.2.0 (Debian 12.2.0-14)
2025/01/20 13:14:35 [notice] 1#1: OS: Linux 5.10.60.1-microsoft-standard-WSL2
2025/01/20 13:14:35 [notice] 1#1: getrlimit(RLIMIT_NOFILE): 1048576:1048576
2025/01/20 13:14:35 [notice] 1#1: start worker processes
2025/01/20 13:14:35 [notice] 1#1: start worker process 29
2025/01/20 13:14:35 [notice] 1#1: start worker process 30
2025/01/20 13:14:35 [notice] 1#1: start worker process 31
2025/01/20 13:14:35 [notice] 1#1: start worker process 32
2025/01/20 13:14:35 [notice] 1#1: start worker process 33
2025/01/20 13:14:35 [notice] 1#1: start worker process 34
2025/01/20 13:14:35 [notice] 1#1: start worker process 35
2025/01/20 13:14:35 [notice] 1#1: start worker process 36

Enter fullscreen mode Exit fullscreen mode
  • Entering into the pod with bash:
user@k8s:~$ kubectl exec -it firstpod -- bash
root@firstpod:/# hostname
firstpod

root@firstpod:/# ls
bin  boot  dev  docker-entrypoint.d  docker-entrypoint.sh  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var

root@firstpod:/# env
KUBERNETES_SERVICE_PORT_HTTPS=443
KUBERNETES_SERVICE_PORT=443
HOSTNAME=firstpod
PWD=/
PKG_RELEASE=1~bookworm
HOME=/root
KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443
DYNPKG_RELEASE=1~bookworm
NJS_VERSION=0.8.7
TERM=xterm
SHLVL=1
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.27.3
NJS_RELEASE=1~bookworm
_=/usr/bin/env

root@firstpod:/# exit
exit

user@k8s:~$ kubectl get pods -o wide
NAME       READY   STATUS    RESTARTS   AGE     IP           NODE       NOMINATED NODE   READINESS GATES
firstpod   1/1     Running   0          9m18s   10.244.0.4   minikube   <none>           <none>
Enter fullscreen mode Exit fullscreen mode
  • Delete pod:
user@k8s:~$ kubectl delete pod firstpod
pod "firstpod" deleted

user@k8s:~$ kubectl get pods -o wide
No resources found in default namespace.
Enter fullscreen mode Exit fullscreen mode
  • Imperative way could be difficult to store and manage process. Every time we have to enter commands. To prevent this, we can use YAML file to define pods and pods' feature. This way is called Declerative Way.

K8s Creating Pod - Declarative Way (With Yaml File)

This scenario shows:

  • how to create basic K8s pod using yaml file,
  • how to get more information about pod (to solve troubleshooting),

Steps

  • Check whether your minikube runs or not. If not, please have a look above.

  • Create Yaml file (pod1.yaml) in your directory and copy the below definition into the file:

  • File: https://github.com/omerbsezer/Fast-Kubernetes/blob/main/labs/pod/pod1.yaml

  • YAML File Explanation:

    • kind: Pod => type of K8s object: Pod
    • name: firstpod => the name of pod
    • app: frontend => label pod with "app:frontend"
    • image: nginx:latest => image name:image version, nginx downloads from DockerHub
    • containerPort: 80 => open ports in the container
    • env: => environment variables
apiVersion: v1      
kind: Pod                        
metadata:
  name: firstpod                  
  labels:
    app: frontend                 
spec:
  containers: 
  - name: nginx                   
    image: nginx:latest           
    ports:
    - containerPort: 80          
    env:                         
      - name: USER
        value: "username"
Enter fullscreen mode Exit fullscreen mode
  • Apply/run the file to create pod in declerative way: kubectl apply -f pod1.yaml
user@k8s:~$ kubectl apply -f pod1.yaml
pod/firstpod created
user@k8s:~$ kubectl get pods -o wide
NAME       READY   STATUS    RESTARTS   AGE   IP           NODE       NOMINATED NODE   READINESS GATES
firstpod   1/1     Running   0          49s   10.244.0.3   minikube   <none>           <none>
Enter fullscreen mode Exit fullscreen mode
  • Describe firstpod:
user@k8s:~$ kubectl describe pod firstpod
Name:         firstpod
Namespace:    default
Priority:     0
Node:         minikube/192.168.49.2
Start Time:   Mon, 19 Jan 2025 17:09:56 +0100
Labels:       app=frontend
Annotations:  <none>
Status:       Running
IP:           10.244.0.3
IPs:
  IP:  10.244.0.3
Containers:
  nginx:
    Container ID:   docker://c49f47ffc746238981f4eeb9b287a14b58520f121e28484f7d3f6edc3fbe4218
    Image:          nginx:latest
    Image ID:       docker-pullable://nginx@sha256:0a399eb16751829e1af26fea27b20c3ec28d7ab1fb72182879dcae1cca21206a
    Port:           80/TCP
    Host Port:      0/TCP
    State:          Running
      Started:      Mon, 19 Jan 2025 17:10:08 +0100
    Ready:          True
    Restart Count:  0
    Environment:
      USER:  username
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-mc6h7 (ro)
Conditions:
  Type                        Status
  PodReadyToStartContainers   True
  Initialized                 True
  Ready                       True
  ContainersReady             True
  PodScheduled                True
Volumes:
  kube-api-access-mc6h7:
    Type:                    Projected (a volume that contains injected data from multiple sources)
    TokenExpirationSeconds:  3607
    ConfigMapName:           kube-root-ca.crt
    ConfigMapOptional:       <nil>
    DownwardAPI:             true
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:
  Type    Reason     Age   From               Message
  ----    ------     ----  ----               -------
  Normal  Scheduled  83s   default-scheduler  Successfully assigned default/firstpod to minikube
  Normal  Pulling    82s   kubelet            Pulling image "nginx:latest"
  Normal  Pulled     71s   kubelet            Successfully pulled image "nginx:latest" in 11.022s (11.022s including waiting). Image size: 191717838 bytes.
  Normal  Created    71s   kubelet            Created container: nginx
  Normal  Started    71s   kubelet            Started container nginx
Enter fullscreen mode Exit fullscreen mode
  • Delete pod using file: kubectl delete -f pod1.yaml:
user@k8s:~$ kubectl delete -f pod1.yaml
pod "firstpod" deleted

user@k8s:~$ kubectl get pods -o wide
No resources found in default namespace.
Enter fullscreen mode Exit fullscreen mode
  • You can also view the node:
kubectl get node -o wide
NAME       STATUS   ROLES           AGE     VERSION   INTERNAL-IP    EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION                      CONTAINER-RUNTIME
minikube   Ready    control-plane   5m36s   v1.32.0   192.168.49.2   <none>        Ubuntu 22.04.5 LTS   5.10.60.1-microsoft-standard-WSL2   docker://27.4.1
Enter fullscreen mode Exit fullscreen mode
  • If you want to delete minikube:
minikube delete
🔥  Deleting "minikube" in docker ...
🔥  Deleting container "minikube" ...
🔥  Removing /home/omer/.minikube/machines/minikube ...
💀  Removed all traces of the "minikube" cluster.
Enter fullscreen mode Exit fullscreen mode

Conclusion

In this post, we focused on creating K8s pod with imperative and declarative way. We’ll make other K8s hands-on samples for different K8s components.

If you found the tutorial interesting, I’d love to hear your thoughts in the blog post comments. Feel free to share your reactions or leave a comment. I truly value your input and engagement 😉

For other posts 👉 https://dev.to/omerberatsezer 🧐

Follow for Tips, Tutorials, Hands-On Labs for AWS, Kubernetes, Docker, Linux, DevOps, Ansible, Machine Learning, Generative AI.

https://github.com/omerbsezer/
https://www.linkedin.com/in/omerberatsezer/

Top comments (0)