Ready to get your hands dirty and start using Kubernetes? If you recall, in the last article we talked about what K8s is and how it works internally. Let’s see Kubernetes in action in this one!

In the Kubernetes world everything is an object. To put simply, an object is something you create in Kubernetes to give it a configuration of sorts so that it knows how to run and serve your application. Once you create K8s objects describing your application, the controllers work to ensure that the object's current state matches the described desired state.

There are many Kubernetes objects, some of which you already would have come across if you tried the Okteto Quick Start Guide. We’ll talk about three very important objects in this article: Pods, Deployments, and Namespaces. Trying out the things mentioned in this tutorial series yourself is highly recommended if you really want to be comfortable using K8s. In case you're looking to get that hands-on experience with these concepts without having to do the setup work - don't worry we've got you covered for free with Okteto Cloud!

Pods

Pods are the smallest and most fundamental of objects in Kubernetes. Instead of running containers directly on nodes, Kubernetes runs them inside pods. So think of a pod basically as a wrapper for your containers. A pod usually runs a single container but it can have multiple containers too. What's important to remember is that all the containers of a pod will run on the same node, sharing the same network and resources. Another important thing to remember about Pods is that they are immutable. While you can change the image being used to run the container in the Pod, you can not update fields like the Pod name or the namespace it’s in.

You would usually containerize your application's front-end and back-end parts and have these containers run in separate pods. This is what we saw in the Quick Start Guide. If you open a terminal and run

kubectl get pods

you would see these pods. Additionally, you’ll see another pod running a MongoDB container which is used as the database for our application.

Each pod has a unique IP address assigned to it. While you can’t ping this IP address from outside the cluster, it can be pinged from within.

Let’s do something exciting shall we? Let’s launch a pod and use that to ping our existing frontend pod. To create an object in Kubernetes, a Pod in this case, there are two ways: declarative and imperative. The declarative way involves writing a YAML file describing the object, whereas the imperative way involves using kubectl. kubectl is a command-line tool that allows you to talk to your Kubernetes cluster. Let’s use the imperative way here and run:

kubectl run temp-pod --image=busybox -it -- /bin/sh

This command does a couple of things for us. kubectl run creates a Pod named “temp-pod” and runs a container inside it using the “busybox” image. The -it is used to give us access to a shell inside this Pod and we also specify that we want to run /bin/sh as the first command in this shell. You should also be able to see this pod on your Okteto dashboard. Now let us get the IP address of the frontend pod so we can ping it. To do that, in another terminal, run:

kubectl get pods -o wide

The kubectl get command can be used to get all kubernetes objects of a particular type. Here we use it to get all pods. The -o wide flag tells it to provide us with even more details like the IP addresses of the Pods. Once you copy the IP address of the pod, go back to the shell inside the “temp-pod” and run

wget -O- <IP Address>

You should see an output like:

Connecting to 10.8.6.136 (10.8.6.136:80)
writing to stdout
<!DOCTYPE html>
<html>
  <head>
    <title>Movies</title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"/>
  <link rel="icon" href="favicon.png"><script defer src="app.770412f1098441c2c698.js"></script></head>
  <body>
    <div id="root"></div>
  </body>
</html>
-                    100% |************************************************************************************************************|   353  0:00:00 ETA
written to stdout

How cool, right? To destroy this pod you can simply select it in your Dashboard and click on “Destroy”. If you want to go the kubectl route then you can run kubectl delete pod temp-pod in your terminal. The kubectl delete command works for all Kubernetes objects and takes in the object type and object name as arguments.

destroy a pod using the button in the okteto dashboard

Deployments

So you might be wondering why Kubernetes doesn’t run containers directly instead of running Pods. This is because Pods are meant to be ephemeral and having containers in Pods enables easy replication - which is one of the most important features of K8s.

A single pod is just meant to run a single instance of your application. You would never create individual pods to serve your application. Why? Because that would mean if the traffic suddenly increases, your Pod will run out of resources and you will face downtime. Instead you create a bunch of identical pods. If one of these pods goes down or the traffic increases and you need more pods, Kubernetes will itself bring up more pods. This management of multiple similar pods is done by the deployment controller when you create a Deployment object.

I think you can now see now why it’s recommended to create a Deployment instead of Pods. The Deployment object will further create and manage the Pods for you. If you look closely at your dashboard you’ll see that api and frontend are actually Deployments. This is why when you did kubectl get pods the pods were not called api and frontend and instead had some random string added to the end. This helps tell that the pods were created by the deployment and not us directly.

Let’s not take my word for it and verify that Pods are indeed actually managed by their Deployments :)

Go to your terminal and see the name of the pod created by the api deployment. After that delete the pod by running

kubectl delete pod <api pod name>

Now run kubectl get pods again and you’ll see that another pod is coming up in its place with a different name. This is because Okteto told Kubernetes to create a deployment which ensures that one api pod runs at all times. You can also see this in the YAML used to create the deployment from your dashboard:

see the number of replicas in the okteto dashboard

Namespaces

If you took a closer look at your Okteto dashboard, you’d see that there is something called “Namespace” in the top right corner. If you click that, you’ll also see the option to create a new namespace.

create a new namespace directly okteto dashboard

Namespaces in Kubernetes are a way to partition your cluster into multiple virtual clusters. You always deploy K8s objects (like Pods, Deployments, etc) in a particular namespace. Deploying different objects in different namespaces allows you to isolate different projects on the same cluster.

Let’s see this in action. Click on “New Namespace” in the dropdown shown above and enter a name - I’m going to go with “golang-rinkiyakedad”. Now switch to this namespace from the same menu and deploy using the same steps you followed in the Quick Start Guide, except that use https://github.com/okteto/go-getting-started as the repository URL this time.

Once the deployment process is complete, head over to the URL shown under “Endpoints” in the dashboard and you should see a webpage showing “Hello world!”.

see the application's endpoints directly okteto dashboard

This means you can now work on two completely different projects and both are running on the same cluster. Pretty cool, right? When using Kubernetes directly, we specify the namespace under the metadata section of an object’s YAML. You can see this by selecting the “hello-world” deployment and seeing its YAML:

see the application's yaml directly okteto dashboard

You can read more about how to manage your namespaces in Okteto by heading over to the Documentation.

So this was it for this article, we started by taking a look at the most fundamental Kubernetes object - Pods. From there we discussed how serving your application using a single pod is not ideal and how you should be leveraging the Deployment object for this instead. Finally, we took a look at Namespaces and saw how they allow you to divide up your Kubernetes cluster and enable deploying multiple different applications. I hope you now have a much better idea about these three very important Kubernetes objects!

In the next article, we’ll see how storage works in K8s clusters and take a look at some other important Kubernetes objects. Until then, feel free to experiment with the apps we deployed on Kubernetes in this article :)