Implementing and Working With Kubernetes Services

In this tutorial, our goal is to build on the previous concepts by implementing the Kubernetes services that expose the application to external users.
February 16, 2024

In the previous tutorial on Kubernetes, we’ve learned what it takes to deploy a pod that runs a simple Angular application. We’ve also learned how to access this pod via command line / Terminal and to understand the structure / layout of those services.

In this tutorial, our goal is to build on the previous concepts by implementing the Kubernetes services that expose the application to external users. Remember that we were able to see the contents of the pod via the “exec” command, but we couldn’t see anything displayed when we navigated to the IP address of the service in our browser.

Key References


  • A Local installation of Kubernetes. You may certainly use a cloud deployment, but you may run into additional challenges when it comes to accessing those pods, services, etc. Refer to the cloud provider documentation if you’re going that route.
  • An installation of a terminal software. On Linux and MacOS, you’ll find these out of the box; for Windows, you can use PowerShell or the Terminal feature in VSCode, which we will be using here.
  • A basic understanding of command line / Terminal instructions. We’ll cover what you need, but it’s important for you to understand how to navigate files, how to see what’s running in your cluster (for troubleshooting purposes), etc.
  • A basic understanding of YAML Files. We've written a tutorial on this topic in case you need to get up to speed - YAML File Format
  • A basic understanding of Kubernetes Services.

Kubernetes Services and Pods

In Kubernetes, pods are blocks that run applications. The architecture of Kubernetes is such that pods can be scaled up and down without impact on the overall performance of the cluster. In other words, the Kubernetes engine will manage the lifecycle of a pod and ensure that it is properly created and removed. With that in mind, we can appreciate the fact that it becomes challenging to direct traffic to and from specific pods - they’re simply going to get different IP addresses as they’re removed and created by the engine. There must be a better approach to this! Kubernetes Services are what makes that possible - they’re essentially a gatekeeper of pods and ensure that the traffic flow is directed to the right destination.

Kubernetes Services Implementation

Our main objective is to access the application that we’ve deployed in the previous tutorial from the web browser. To accomplish this task, we need to create a service that will expose the port of the application to a port of the minikube instance. Here’s the code we’re going to create in a new YAML file:

apiVersion: v1
kind: Service
  name: myappservice
    app: myfirstapp  
  - port: 80      
    name: http      
    nodePort: 30100  
  type: NodePort

Line 1 - apiVersion: v1

Kubernetes uses a specification of OpenAPI and currently has 3 major revisions. For our simple application, the older revision is going to be just fine; you can see what has been changed and which features are available in the latest versions on the official Kubernetes specification.

Line 2 - kind: Service

As we’ve discussed in the Pod deployment tutorial, you must specify the kind of deployment you’re looking to do in Kubernetes. Based on the kind keyword, the Kubernetes engine will know what element to create.

Line 3, 4 - metadata:, name: myappservice

Every object can be given a name in Kubernetes. The goal, as we’re going to see shortly is to create references to other objects based on their name. In this tutorial, the service will be referencing the pod by name which we will create at the Pod level.

Line 4, 5, 6 - spec:, selector:, app: myfirstapp

This is where the unique ID of the element comes into play. We need to point the service to the pod we’re looking to impact. By adding the “app: myfirstapp” value-key pair to the selector element, the Kubernetes engine will make the link between the service and the associated pod.

Line 7, 8, 9, 10 - ports:, - port: 80, name: http, nodePort: 30100

The service will open up a port on minikube and “link” it back to the pod we have specified. Notce that we’re also mentioning port 80 which is the port on which the pod is serving the angular application. If you’re confused about that, refer to the previous tutorial in which we deployed this pod.

Line 11 - type: NodePort

There are different types of services in Kubernetes. In this case, the simplest approach is to use NodePort. We’ve thus specified it in the type key-value pair.

Specifying the Kubernetes Pod Name

At this point, we’re ready to deploy the service YAML file. However, even if we were to deploy this implementation, we wouldn’t be able to reach the Pod.


Because we haven’t specified the name within the implementation of the Pod. Here’s the revised file of our previous Pod:

apiVersion: v1
kind: Pod
  name: myfirstapp  
    app: myfirstapp
  - name: myfirstapp    
    image: richardchesterwood/k8s-fleetman-webapp-angular:release0

Notice that we have not only the name but also the label key-value pair which is used as a reference. In Kubernetes, every element must have a name, but the labels aren’t required.

Kubernetes Services Deployment

In the previous tutorial, we deployed the Pod. The first step here is to re-deploy the pod to Kubernetes so that the label we’ve added is applied. In Kubernetes, when you re-issue the following command, the Pod will be updated instead of re-deployed again:

kubectl apply -f .\myfirstpod.yaml

Notice that you’ll receive a confirmation message that will confirm that the changes have been deployed. If you make no changes to the same file and re-issue the command above, you’ll receive a message stating that no changes have been made.

Figure 1 - Deploying Kubernetes Services | Deploying a Service YAML Configuration File onto Kubernetes
Figure 1 - Deploying Kubernetes Services | Deploying a Service YAML Configuration File onto Kubernetes

We deploy the service we’ve specified with the same command:

kubectl apply -f .\myfirstapp-serv.yaml

As we’ve seen before, Kubernetes will deploy this service in a few moments; issue the following command to see it listed in your cluster:

kubectl get all

Viewing the Pod Application Through the Kubernetes Service

At this point, we’ve deployed everything we need to view the application through the browser. However, we still need to understand where the application is being served. As previously configured, we have a NodePort specified at the address of 30100. What’s the IP address? Issue the following command to see the IP address of minikube:

minikube ip

You’ll notice that this IP is different from what we’ve previously seen under the items listed by running the “kubectl get all command.” Those IP addresses are internal to the cluster.

If you’re running on Linux without Docker Desktop, you can navigate to that IP address in your browser, add the port, and you should be able to see the application. I’m running Docker Desktop with minikube which requires me to issue an additional command:

minikube service myappservice

Once the command executes, minikube will open the appropriate port / IP address to service the application in a browser as shown below.

Figure 2 - Deploying Kubernetes Services | Viewing the Application through a Browser

Conclusion on Deploying Kubernetes Services

At this point, we’ve created a pod that is running a container with an application using Angular. We’ve also created a service that exposes the user traffic from a web browser into our web app inside the cluster. We can view the application running within our pod as “a regular user.”