A Beginner’s Journey: Deploying Pods to a local Kubernetes Cluster Made Simple

Sharmila S
8 min readJul 9, 2022

This article guides you through creating and deploying a pod along with a service to a Kubernetes cluster in your local system.

System Pre-requisites

  • Docker
  • Minikube

Pods

  • Pods are the smallest deployable units in Kubernetes.
  • A pod has a container running in it. (In some cases, a pod might contain more than one container).
  • Apps can be scaled by spinning up more pods (not by running more containers in a single pod).
  • Each pod is assigned a private IP address.
  • A node can have multiple pods.

Applications should be containerised to deploy to a pod.

In this article, we will deploy the docker image of a simple hello world application. This app is built using node.js.

If you are not familiar with docker, this article will guide you in the process of creating a docker image of a node application.

The docker image used in this article is published to dockerhub. So, you can easily use it to follow along with the tutorial. If you already have a docker image ready to be deployed, you can also go ahead with that.

Dockerhub— where users can create their own private/public repositories to contain their images and also can access any open-source image.

Configuring the Pod

Kubernetes includes a container runtime (eg. docker). The container runtime will spin up a container from the image that we provide.

If minikube is not installed in your system, visit this site to download it.

  • Start minikube in your system using the command below in your terminal.
minikube start
minikube start
  • The next step is to create a YAML file to hold the configurations for our pod. Let’s name it pod.yaml and add the following.
pod.yaml

We have some pre-defined fields for configuring our pod. We can have a glance at these specifications by typing kubectl explain pod in the terminal.

This informs us that, for the pod configuration, the version is v1 and the kind is Pod . It also displays a brief explanation of the required fields for configuring pods. To learn more, visit here.

Now, let’s look into each line of our YAML file.

apiVersion: v1
kind: Pod

The above two statements in the file describe the version and the kind of configuration. (As we just learnt that for a pod, the apiVersion should be ‘v1’ and the kind should be ‘Pod’)

metadata:
- name: pod-demo
labels:
app: hello-world

The ‘metadata’ field is used to provide the ‘name’ and ‘labels’ for the pod.

Here, the name of our pod is pod-demo and it has a label app: hello-world. Labels are useful in filtering out certain pods from all the pods in a namespace.

spec:
containers:
- name: hello-world
image: sharmilas22/hello-world-app:latest
ports:
- containerPort: 4000

Under the spec option, we can mention the specifications of the containers that will run inside the pod. Here, we specify that a container with the name hello-world should be spun up using the image sharmilas22/hello-world-app:latest (this image will be pulled from dockerhub to your system)

image in dockerhub

Along with these data, we also mention the port where our app would be running (4000).

  • Once we made the YAML file ready, our next step would be to apply them using,
kubectl apply -f pod.yaml

-f option is used to specify the file path (here, ‘pod.yaml’).

apply pod.yaml

Our pod is now created. We can view all the pods in our system using,

kubectl get pods 
Pod running

The status of our pod is ‘Running’, which means our pod is up and running.
If you see ‘ContainerCreating’ as the status, it means that the pod is now getting created and will be up when it’s done.

Learn more about the pod status, here.

The -o wide option is used with the above command to view more information about the running pods.

-o wide option

We can see that the IP assigned to the pod is ‘172.17.0.2’ and minikube is the node where the pod is running.

The IP address of the pod can be used to access them from the kubernetes network.

Let’s try to access our pod from the minikube network. Type the following command, to enter into the minikube in command mode.

minikube ssh

Once we enter into the minikube in command mode, we request to the pod IP (the IP assigned to our pod is 172.17.0.2, we can view it using kubectl get pods -o wide as we saw earlier) with the app port (4000).

curl http://<IP-of-your-pod>:4000

We could able to access and get a response from the app! Congratulations! We deployed our pod to the Kubernetes cluster successfully!!

But our job is not over yet.

Our pod is deployed and running, but not exposed to our local system, i.e. we cannot be able to access it from outside the minikube (from our local system).

We need a kubernetes ‘service’ to allow us to connect to our pods from outside the kubernetes network.

Let’s create a Service for our pod

  • Create a new file called ‘service.yaml’ and add the following,

Similar to a pod, we can use kubectl explain service to have a quick look at the fields needed for our configuration. Our service config file should have the apiVersion as ‘v1’ and kind as ‘Service’.

Learn more about service here.

service

We are also specifying a name for our service (here, ‘service-demo’) using the metadata field.

metadata:
name: service-demo

In spec , we define three fields: type, selector and ports.

spec:
type: NodePort
selector:
app: hello-world
ports:
- protocol: TCP
port: 80
targetPort: 4000
nodePort: 30001

type — This field is used to specify the type of the service. The service type would define how the service is exposed. There are 4 valid options: ClusterIP, NodePort, ExternalName and LoadBalancer.

ClusterIP —(default) Exposes the service within the cluster where it’s present.

NodePort — Exposes the service on the nodeIP and nodePort. Can be accessible outside the cluster.

LoadBalancer — Exposes the service to an external load balancer (eg., aws Elastic Load Balancer).

ExternalName — Aliases the service to the specified externalName.

Learn more here.

Here, our service will be of type NodePort.

selector — This field is used to map the pods to the service using labels. Here, we have the selector as app: hello-world , so this service will open traffic to any pod that is running with this particular label. (Remember that we provided this exact label to our pod while configuring it)

ports — We define a port with the TCP protocol and port 80.

  • The targetPort is the port where our container is running (here, our container port is 4000).
  • The nodePort is the port where we want our service to be exposed. The port number to be specified should be in the range of 30000 to 32767 (Here, we gave 30001 as our node port). Using the nodePort and the nodeIP, we can access our service from outside the cluster.

Let’s apply the service.yaml to create our service,

kubectl apply -f service.yaml

Our service is deployed now.

To view all the objects(pods, services etc) in the kubernetes network, we can use kubectl get all command.

kubectl get all
kubectl get all

Now, we can see that our service ‘service-demo’ is running.

The URL of the service is used to access our pod from outside the kubernetes cluster. Let us get the URL for our service using,

minikube service <service-name> --url

Let’s try to access the URL from our system.

Congratulations! We have successfully deployed our pod and connected it to a service to access it!

Let’s try to understand the URL.

http://192.168.64.2:30001

In this URL ‘192.168.64.2’ is the node IP and ‘30001’ is the node port.

We know that the node port is 30001 since we provided it in the service configuration.

But what does the IP address mean?

Since we are running kubernetes on our local system, the minikube is the only node running in our kubernetes cluster. (We can view all the nodes by kubectl get nodes )

Our pod is running in the minikube node. Hence, the node IP for our service is the IP address of the minikube which could be viewed by,

minikube ip
nodeIP

We can also look into the details of our pod to know that it is running in the minikube node. The command ‘kubectl describe pod pod-demo’ gives us all the necessary information about our pod ‘pod-demo’.

From the above picture, we can understand that our pod is running in the node ‘minikube’ which has the IP 192.168.64.2. And this is the reason for our service to have this IP address.

Some useful Kubectl commands

  • To view all the pods/services,
kubectl get podskubectl get services 
  • To delete pods/services,
kubectl delete pod <pod-name>
or
kubectl delete pod/<pod-name>
kubectl delete svc <service-name>
or
kubectl delete svc/<service-name>
  • To view information about a particular pod or a service,
kubectl describe pod <pod-name>
or
kubectl describe pod/<pod-name>
kubectl describe svc <service-name>
or
kubectl describe svc/<service-name>

--

--

Sharmila S

Software Engineer | Writes about Full Stack Web Development | 1 X AWS | CKA http://sharmilas.bio.link/