ship rudder inspiration — kubernetes tutorial.

This is a part two of our Kubernetes guide, do check out our part1 if you haven’t seen it to make it easier to understand this writeup.

When concluding part 1 of our Kubernetes series, we created a yaml config file called ourapp-pod.yaml in the root folder of our codebase which I promised we would continue from.

Open up ourapp-pod.yaml file and type in the following:

apiVersion: v1

kind: Pod

metadata:

name: ourapp

labels:

component: web

spec:

containers:

- name: ourapp-container

image: covenant/dockerize-nodejs-image

ports:

- containerPort: 5000

Create a new file in that same root folder of your project, let’s call it ourapp-node.yaml and type in the following:

apiVersion: v1

kind: Service

metadata:

name: ourapp-node

spec:

type: NodePort

ports:

- port: 5050

targetPort: 5000

nodePort: 30001

selector:

component: web

Don’t worry, we would go into details of what exactly are those files and what their contents mean 😎.

Objects in Kubernetes

Kubernetes uses config files to describe objects declaratively, a Pod for example as we would soon see is a type of object in Kubernetes.

Objects are basically “items” we create in our Kubernetes environment to make our applications work in an expected way. These items are used to serve various purposes from setting up networks to monitoring and running containers.

API-Versions which are represented by the apiVersion: v1 attribute, which you saw earlier, in both config files are used by Kubernetes internally to scope the types of objects that we can create in a given config file.

A different API-Version would contain a completely different set of objects that we would be allowed to create.

The kind attribute in our config files represents the “type of object” we are creating.

apiVersion: v1

kind: Pod

#from ourapp-pod.yaml file

------------------------------------------------- apiVersion: v1

kind: Service

#from ourapp-node.yaml file

A config file that has a kind attribute of Pod is used to define the config settings and specification which Kubernetes will use to run a container.

A config file with kind: Service is used by Kubernetes to setup networking within a kubernetes cluster.

Don’t worry if it sounds a bit confusing, you will understand much better as we go on 😊😊.

Pods

A pod is the smallest unit of deployment in Kubernetes. It is what will serve as a “carrier” or “enclosure” of a container.

A pod is used to run a grouping of one or more containers that are very closely related and have a tightly coupled relationship.

A pod is used as an enclosure for one or more containers that must absolutely be executed with each other.

Here’s a diagram representing our current project that would help you understand the structure and relationship between a Node, Pod and Container:

Node -> Pod -> Container relationship. A pod is the smallest unit of deployment in Kubernetes.

Here’s another diagram depicting a Pod for a hypothetical project that contains a MongoDB container and a service in NodeJS that listens to whenever a new record is inserted helps recompute indexes:

multiple containers that are tightly related in a pod

Let’s go back to our first config file now ourapp.yaml that had these contents having kind: Pod .

apiVersion: v1

kind: Pod

metadata:

name: ourapp

labels:

component: web

spec:

containers:

- name: ourapp-container

image: covenant/dockerize-nodejs-image

ports:

- containerPort: 5000

It should be a bit clear now what this config file means. We are instructing Kubernetes to do the following:

apiVersion: v1 :- uses the v1 scope so that we can have access to object types like Pod which are under the v1 scope. kind: Pod :- describes the type of object we want Kubernetes to create in using this config file. In our case, we want Kubernetes to create a Pod for us. metadata :- this is used to describe our pods through naming and also having custom labels that better describe what our pod is about. A particular label which we used called component is also used to associate our Pod with our service as we would soon see. spec :- this is used to describe the contents of our object and their definitions. containers :- since we are creating a pod which is essentially a grouping of one or more containers that are tightly coupled together, we enumerate our containers under the containers attribute. containers | -name :- we use the name attribute to give an identity to the container we are creating in this pod. It is this name attribute that would help us in identifying individual containers in a pod which could be very useful in instances where we want to view the log of a particular container. containers | image :- we use the image attribute to point Kubernetes to our image which has been pushed to our Docker Hub repository. containers | ports :- we use this attribute to enumerate the various port structures associated with our individual containers. containers | ports | containerPort :- the containerPort attribute is used to specify the particular port which we want exposed to the outside world from our individual container. In this case we want “port 5000” exposed because it is the port which our nodejs app starts on.

Services

A service is a Kubernetes object that is used to setup networking in a Kubernetes cluster.

We have four major types of Services which are

Load Balancer. Ingress. NodePort. ClusterIp.

A NodePort type of service is used for exposing a Pod to the outside world and is only used mostly in development environments. This is what is being used in our current ourapp-node.yaml file to make the container in our pod accessible from our browser as we will soon see

We will discuss what the other 3 sub-types are in more detail later.

Let’s get into our ourapp-node.yaml file which is the config file describing a service and understand what it does.

apiVersion: v1

kind: Service

metadata:

name: ourapp-node

spec:

type: NodePort

ports:

- port: 5050

targetPort: 5000

nodePort: 30001

selector:

component: web

We’ve talked about apiVersion, kind and metadata attributes earlier on, we’ve also discussed what a spec type of NodePort means.

Let’s discuss on the remaining two which are selector and ports .

Selector

Selector as the name suggests is a key-value pair which is used to identify the Kubernetes objects to which the Service should be applied. You would remember that in our Pod config file i.e ourapp.yaml, we had a label property:

apiVersion: v1

kind: Pod

metadata:

name: ourapp-container

labels:

component: web

spec:

containers:

- name: ourapp

image: covenant/dockerize-nodejs-image

ports:

- containerPort: 5000

Our selector simply searches for every Kubernetes objects(in our case it was a Pod) that have a key value label metadata matching it’s description. Since “component: web” in our label matches our selector description of “component: web” , Kubernetes immediately knows to apply our NodePort service to our Pod.

Ports

The ports attribute defines the port mappings for our service.

- port: This defines the port number through which another pod in the same Kubernetes cluster could use to access our target pod. targetPort: This is the port number of the target container in our Pod that we want to open up traffic to. You would notice that the value here (5000) matches what we defined as our container port in ourapp.yaml file. nodePort: This is the port number that we are going to use in our browser i.e in the outside world to access our container when it is running.

Sticky Notes

Kubernetes works with a concept of “objects” which are used to serve various purposes from setting up networks to monitoring and running containers. A Pod is a type of Kubernetes Object. A pod is the smallest unit of deployment in Kubernetes and serves as enclosure for one or more containers that are tightly related to each other. We define a Pod in a kubernetes config file by using a kind attribute of “Pod” A Service is also a type of Kubernetes Object which is majorly used to setup networking. Kubernetes uses the concept of labels and selectors to apply services to other Kubernetes objects such as Pods. A NodePort service should only be used in development for the most part.

Conclusion

We’ve learnt alot in this section about Pods and NodePort services, we will still learn a whole lot about this brilliant tool as we continue.

Hire Me

Have any interesting project?, super awesome. Shoot me an email at covenantchukwudi@gmail.com