Streamline your container workflow with Codefresh!

Intro to Kubernetes, setting up your first app and why it’s just like snowboarding

Docker Tutorial | February 23, 2017

So, as I was further educating myself on the different orchestration solutions available (Kubernetes, Mesos, Swarm) I realized it would be useful to share my experience and simplify (as much as it can be simplified) the path for whomever wants to kick the tires and learn. Here’s a good head start for working with Kubernetes AKA K8s.

Prerequisite , You should already by familiar with the concept of containers/docker, if you’re new to docker checkout our container academy for an intro to Docker.

So why snowboarding?

If you’ve tried snowboarding you probably remember the first few days on the slopes. Unlike skiing, where beginners can usually avoid falling too often, snowboarders are more likely to plant their faces directly into snow at least a few dozens times their first day.  But this quite changes fast if you keep snowboarding for at least one or two more days. Once you get a few face plants under your belt snowboarding becomes much easier, faster to learn and above all fun! My experience with Kubernetes was very similar. The first few days, I was puzzled I wasn’t quite sure I understood all the different components, how to use them, and even more why I need them. Then, as I started to play around I ended up not only understanding the moving parts but also realizing just why Kubernetes is so powerful.

My intention in this blog is to make the very first few days with Kubernetes as easy as possible. Once you get the basics you can easily start benefiting from a platform that allows you to deploy microservices smoothly, scale your application, and rollout changes on the fly….

What we will cover in this blog?

  • The 3 basic entities you must know to run a simple micro-services application on kubernetes.
  • Then, we will setup a local Kubernetes cluster that you can easily work with on your own Mac (most of these instructions will transfer to Linux or Windows).
  • Lastly, we will run a simple app called Demochat built with two microservices: a Node.js webserver and MongoDB.

By the end of this blog, you will know how to run and scale an application that is composed of two services on Kubernetes.

Entities you must know

Pods

A pod is the smallest deployable entity in Kubernetes and it is important to understand the main principles around pods

  • Containers always run inside a Pod.
  • A pod usually has 1 container but can have more.
  • Containers in the same pod are guaranteed to be located on the same machine and share resources

Why you might want to run more than one container in a pod

If you have containers that are tightly coupled and share a lot of I/O then you may want them on the same machine and allow them to share resources.

Deployment

Here is when the fun begin, while you can obviously run Pods manually, monitor them, stop them etc… you don’t really want to do that. Deployment is a key object in Kubernetes that simplifies these operations for you. The simple way to think of Deployment is as an entity that manages Pods, either a single Pod or a replica set (set of instances of the same Pod configuration).

It is also key to understand the relationship between Pods and Deployments. Say for example, your application has two microservices: a web server and an api server. You will need to define a Pod and Deployment for each microservice. In the Pod you will define which image to run and in the Deployment you will define how many instances of this Pod you will want to have at any given point (for scalability, load balancing, etc…).

The Deployment object will then

  • Create the pod (or multiple instance of it) for your microservice
  • Monitor these pods to make sure they are up and and healthy. If one fails, the Deployment object will create a new pod to take it’s place.

After the creation of the Deployment object. You can then

  • Further scale up or down your pods.
  • Rollout new changes to the pods (say you want to run a newer image of your microservice in your pods)
  • Rollback changes from pods

In the illustration below you can see two deployment objects. One for each microservice (a web server and an api server). Each deployment object is managing 3 instances of the same pods. The pod instances can span more than one node (for scalability and reliability).

 

 

Services

Services allow you to expose your microservices (that run in pods) both internally and externally between the other running pods.

The service object exposes a consistent IP and port for the microservice.  Any call to that IP will be rouited to one of the microservice’s running Pods.

The benefit of services is that while each and every pod is assigned an IP, Pods can be shut down (due to failure or rollout of new changes) and the pod’s ip will no longer be available. Meanwhile the service IP and port will not change and always accessible to the other pods in your cluster.

By default, the DNS service of Kubernetes exposes the service name to all pods so they can refer to it simply by its name. We will see this in action in the  Demochat application.

Setup Kubernetes locally

We will use minikube to work with kubernetes cluster locally.

Disclaimer: These guidelines have been tested on OS X. If you are following these on Windows it might be slightly different

Installation

There are the 3 component you need to have installed.

  • Download & Install the latest Docker Toolbox (this is not the same thing as just installing Docker)
  • Install Kubectl (command line tool for kubernetes) by running the following

  • Download & install VirtualBox for OS X. Direct link to the binaries here (minikube relies on some of the drivers)
  • Install Minikube

you can find the latest installation guide for minikube here

Test your environment

Start minikube (might take a min or two) by running “minikube start”

Run “kubectl get nodes” to test that minikube setup successfully

To work directly with the Docker deamon on the minikube cluster run

Running demochat on our local minikube cluster

The Demochat application requires two services to run

  • MongoDB
  • Demochat webserver that is implemented in Node and can be found here

First let’s pull the docker image

and then

Now, once we have the images locally let’s run a pod to deploy the MongoDB service. While you can use the kubectl create command to create pods and deployment, in this example we will simply use the kubectl run command which will result in creating a pod and deployment to manage this pod.

This will create a pod for our MongoDB, based on mongo:latest using port 27017 and add it to a deployment named “mongo”.

Lets verify we have mongo running the way we want.

Now lets see the running pods.

Even though we have our service, it’s not yet exposed and available to other pods. For that we will use the kubectl expose command which will create a service.

We can view our running services

By default the service is listening on the port specified by our pod (in this case 27017). We could define it differently using the –port flag and then redirect to the pod’s port using –target-port but for now this is good and we will keep it simple 😉

The mongo service we just created is now discoverable for any future pod by either using the alias ‘mongo’ (this happens automatically with the DNS plugin for Kubernetes which is on by default) or by using the environment variable that will be set for any future pod.

In our example the demochat web server microservice will use the alias to connect to the mongo service.

You can see it referenced in our code for the demochat web server microservice

Now let’s run a pod and deployment for the demochat web-server microservice. Here we’ll specify port 5000.

We can use kubectl get deployment  and kubectl get pods  again to see that we both our pods running.

Great! now we have our application running. The last step is to expose our web server microservice and try it out. Run kubectl expose --type=NodePort . The new flag tells minikube to assign a port for each node we add and map it back.

Disclaimer: if you run this example on GKE (Google Container Engine) or on any cloud based Kubernetes and you want to expose it to the internet you will use --type=LoadBalancer . However, in our example we are running it locally on our minikube cluster so we use the  --type=NodePort 

Lets see all of our services our up and running

Take note of the port assigned to demochat. In my example it’s been assigned port 31793 but it will be different every time you run it. This port is maps to port 5000 on the pod (as we configured previously).

To access our application through the browser we need to figure out the minikube host IP and add the assigned port.  We will use the minikube ip command to retrieve the IP.

and now we can open a browser and put the IP and port  (in the example above it came up as 192.168.99.101:(the port set for your application).

 

Super! Our application is running!

Lets practice one more thing before shutting it down.

Scaling a microservice

Lets see how we can scale our web server microservice and run replicas. We will run two pods with our demochat web server microservice. To do that we will update the deployment and let it know it needs to keep two pods of this service running. If for some reason one of the pods will fails, the deployment object will automatically add a new one.

Now lets run kubectl get pods  again

We can see there are 2 pods of demochat running now. From now on, the demochat service we created will load balance the calls between these two pods.

Turning our application down

To shut down the application we can simply use the kubectl delete  command

Now we can see that there are no mongo or demochat services, deployments or pods running. When you start using this in production you’ll use a yaml file to save everything so you can put it up and pull it down. We’ll cover that in another blog post.

Thats it for today, I’ll be writing a few more guides soon. I hope you found it useful. Please feel free to leave comments or questions here and I will try to answer.

Here are some resources to learn more on these entities (keep in mind the Kubernetes documentation is constantly being updated/restructures/moved so these links might need to get updated every now and then)

Additional resources

Whats next?

In the next blog we will cover how to rollout and rollback changes to microservices, manage secrets and more…

Raziel Tabib

About Raziel Tabib

Co-Founder and CEO, Codefresh

Reader Interactions

Enjoy this article? Don't forget to share.

Comments

  1. Thanks for the post. I’m starting my studies with Kubernetes and this was my first Hello World. And everything went well! Thank you.

    • Sure thing! Happy you found it useful

  2. Excellent intro article – I’ve started to learn Kubernetes recently and this helped me.

    Thanks!

  3. A very good article for K8s 101. Thank you.

  4. Very well written and easy to understand. Only thing that wasn’t clear was about the port mapping. Which port stays same when the pod goes up and down? Is it port 5000?

    • Both ports actually stay the same. The exposed port (3000) stays the same and forwards to a new pod. The new pod comes up listening on port 5000.

Reply This Comment: Robson Bittencourt Cancel reply

Your email address will not be published. Required fields are marked *

Follow me on Twitter