How to run Pods and Services locally on Kubernetes

In order to run something on k8s we need to create a runnable unit. This can be a pod or a service.

What is a Kubernetes Pod?

A Kubernetes Pod is the smallest deployable unit on Kubernetes. It is represented by one or more Docker containers, generally tightly coupled, which are meant to be part of the same deployable unit. As such, containers within a Pod, share the Pod IP address, they can communicate with each other via localhost and they share other privileges, e.g. network and volumes.

What is a Kubernetes Service

A Kubernetes Service is an abstraction that exposes a logical set of Pods. It is generally used as the entry point for clients of exposed containers within a Pod.

How to define a Pod?

We describe Pods via YML files. In this post I’ve created a pod-helloworld.yml file.

apiVersion: v1
kind: Pod
    app: helloworld
  - name: k8s-course
    image: alzamabar/k8s-course:v1
    - containerPort: 3000

The above script creates a Pod named that runs the Docker image: alzamabar/k8s-course:v1 on port 3000

Having a k8s running engine

There are various ways one can run k8s locally. As of the time of writing (July 2018) I’m using the Docker Edge native client for Mac (which will eventually make its way to the stable version). However other options are available, e.g. Minikube (

Once you’ve chosen the k8s engine you want to use, make sure it’s started.

Creating the Pod from its definition

In order to create the runnable unit on k8s, the following command can be used (assuming there is a pod-helloworld.yml file in the current directory):

kubectl create -f ./helloworld.yml


Accessing the pod through port-forwarding

There are various ways of exposing the Pod. One is through Pod port’s forwarding. The command is the following:

kubectl port-forward <pod-name> 8081:3000

Doing that on my laptop, the following appears on the command line:


K8s is now listening on localhost:8081 and will forward all traffic to port 3000 (which is the k8s pod native port, as defined in the above pod definition file).

Opening the address: http://localhost:8081on my browser yielded to the following output:


Exposing a service on Kubernetes running locally

If you’re running k8s locally (e.g. via the Docker native client), you can create a service by expose the pod port with type NodePort as follows:

kubectl expose pod --type=NodePort --name=nodehello-service

This command creates a k8s service by exposing the Pod we have already described as a NodePort type and assigning the service the name nodehello-service

Upon running this command I get the following output:


I can now inspect the service by running the following command:

kubectl get service


I can see that the k8s service is not up and running. If I want to access it, I need to access localhost on the service port, indicated under the PORT(S) column. I can see that the port is 30189 therefore to access this service from a browser I can visit the following address from a browser: http://localhost:30189


You can achieve the same by viewing the service description through the following command:

kubectl describe service nodehello-service

On my laptop I get the following output:


As you can see the ingress LoadBalancer is localhost and the NodePort is 30189.

Deleting the Kubernetes Pod and Service

To delete the Pod, it’s enough to run the following command (assuming there is a pod-helloworld.yml file in the current directory):

kubectl delete -f ./pod-helloworld.yml


At this point the Pod is deleted but the service is still there. If you want to delete the service as well, you can run the command:

kubectl delete service nodehello-service