Deploying your first app to Kubernetes

Deploying your first app to Kubernetes

For introduction about Kubernetes first read: What is Kubernetes?

Lets admit that installing Kubernetes for the first time is not an easy task. Because it has multiple components, there are multiple paths (options) and the documentation varies between Windows/Linux/macOS.

Let’s start by saying that Kubernetes mainly runs on Linux, so production clusters will be hosted on Linux machines or VMs. While there are ways to install a one node cluster to your development PC that relies on a virtual machine if you are running Windows or macOS.

Luckily when we install Docker on Windows, it creates a virtual machine to run Linux containers (either using Hyper-V or Virtual Box). And also luckily that Docker now supports Kubernetes out of the box. So that’s the easiest way to run Kubernetes on Windows, using Docker..

Installing Kubernetes on Windows (using Docker)

Go to Docker: Settings > Kubernetes > Enable Kubernetes

That’s it! it just takes a few minutes to download many containers and start them, then it will say Kubernetes is running in the status circle below.

Alternative way (using Minikube)

The other way is Minikube but if you take a look at the instructions document, you would understand why it’s better to go for the Docker option!

Real Production Clusters

For real production clusters you go with one of these options:

Confirm your installation is working

Whatever was the installation method you went for, most probably you already got Kubectl (the client command line tool to connect to Kubernetes) installed on your machine. You can confirm that by running:

kubectl version

If everything is working fine, it should give you 2 versions, one is the client version, and the server version or error connecting to cluster.

If the command is not installed on your machine, you can download it from this link. It’s just an exe that you download and then you should add its location to your PATH environment variable. Here are the full instructions.

If you get client version, but can’t connect to server, then you need to take a look at the configuration file that tells kubectl where is the cluster and how to authenticate to it.

Look for the file: C:\Users\<username>\.kube\config

It should contain the connection to your cluster, if you installed using docker or minikube it should be already populated, otherwise you should get it from the cloud provider, from inside you cluster’s master node config at same location, or retry the whole installation.

First things to do in your cluster

  1. Dashboard

First thing to do is to run the Kubernetes Dashboard. The Dashboard allow you to see what’s happening in your cluster, whats running, check logs, get console access inside pods, delete things…etc.

Run the below command to install it. This downloads the dashboard container and runs it inside the cluster:

kubectl create -f https://raw.githubusercontent.com/kubernetes/dashboard/master/src/deploy/recommended/kubernetes-dashboard.yaml

Usually anything inside the cluster is not accessible from outside, so we run a proxy on our local machine to allow us access to inside:

kubectl proxy

Then you open this url into a browser: http://localhost:8001/api/v1/namespaces/kube-system/services/https:kubernetes-dashboard:/proxy/#!/overview

Kubernetes Dashboard UI

In the dashboard you will notice that there multiple namespaces, default is an empty namespace that you can use to install your apps. Another notable namespace is kube-system, this one has the Kubernetes system containers and services (including the dashboard that we just installed).

2. NGINX Ingress Controller (skip if on cloud)

I know this is getting more complicated, but you need one more thing to save you the trouble of not knowing what to look for later. You may not need this step if you are using a cloud based cluster since it may already be handled. But if you are creating your own cluster or want to try Ingress locally on your PC, then it’s better to use this basic step to setup Ingress controller to allow later tutorials to work.

When you deploy your app as a “Pod” it gets a random local IP each time, that is only accessible from inside your cluster. Then you create a “Service” to allow other Containers/Pods to access your service by name (not knowing it’s IP). This only works for services that needs to be internally accessible, like APIs that are going to be accessed from front-ends. But what about front-ends themselves that needs to be accessed by users from outside the cluster?

Thanks to for the diagram

Here comes the name Ingress (allowing external traffic to go inside the cluster, routing it to the correct service internally). So you can deploy as many apps as you want inside the cluster (but say only one process can gain access to the port 80 on the physical machine/cluster node). So you deploy an ingress Pod in this basic example, it’s an NGINX web server, that listen to the actual physical port 80 on the cluster nodes, and then configure it to route traffic the rest of apps. Sometimes routing work using different host names (for example foo.com goes to foo service, and bar.com goes to bar service). Or it can work using Urls (like http://cluster/foo/… goes to foo service and http://cluster/bar/… goes to bar service).

Updated: for more details on deploying NGINX Ingress, check the ingress article.

Deploy your first app

Now it’s finally time to deploy our first app. For simplicity, I’ll use the sample asp.net core website that doesn’t need a database. Create a file named mysample.yaml with the following content:

kind: Service
apiVersion: v1
metadata:
  name: mysample-service
spec:
  selector:
    app: mysample
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mysample-deployment
  labels:
    app: mysample
spec:
  replicas: 2
  selector:
    matchLabels:
      app: mysample
  template:
    metadata:
      labels:
        app: mysample
    spec:
      containers:
      - name: mysample
        image: microsoft/dotnet-samples:aspnetapp
        ports:
        - containerPort: 80

This file describes 2 Kubernetes objects:

  1. Service: with the name mysample-service that direct traffic to this service to any Pod with label mysample. It’s recommended that you define services before Pods.
  2. Deployment: with a name and label (it’s good to use a lot of labels for your objects to be able to select them later). And it defines that we need a replica set with 2 instances of this Pod template, and define that we need to match Pods with our label. Then define the template which has a spec saying the required container image (here is an image from Docker Hub), and we define that we expose port 80.

To deploy this you need to execute the following command:

kubectl apply -f mysample.yaml

Since we are not specifying a namespace (not in yaml nor in the kubectl command) the default namespace will be used. Here is what it looks like in the dashboard:

Sample deployment on the Dashboard

Note that the service is currently only available from inside the cluster network, which means we will not be able to browse it directly and will have to use the proxy to test it. Here is the url to open it using the proxy (assuming “kubectl proxy” command is running). Note the namespace and service name in the url:

http://localhost:8001/api/v1/namespaces/default/services/http:mysample-service:/proxy/#!/

You have deployed your first app to Kubernetes!

Read more

To understand more details about these objects, checkout these docs: