Kubernetes — Orchestration Guide [A Lovely Symphony 2]

Covenant Chukwudi
MyCloudSeries
Published in
6 min readMar 28, 2019
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:

  1. apiVersion: v1 :- uses the v1 scope so that we can have access to object types like Pod which are under the v1 scope.
  2. 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.
  3. 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.
  4. spec :- this is used to describe the contents of our object and their definitions.
  5. 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.
  6. 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.
  7. containers | image :- we use the image attribute to point Kubernetes to our image which has been pushed to our Docker Hub repository.
  8. containers | ports :- we use this attribute to enumerate the various port structures associated with our individual containers.
  9. 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

  1. Load Balancer.
  2. Ingress.
  3. NodePort.
  4. 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.

  1. - port: This defines the port number through which another pod in the same Kubernetes cluster could use to access our target pod.
  2. 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.
  3. 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

  1. Kubernetes works with a concept of “objects” which are used to serve various purposes from setting up networks to monitoring and running containers.
  2. A Pod is a type of Kubernetes Object.
  3. 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.
  4. We define a Pod in a kubernetes config file by using a kind attribute of “Pod”
  5. A Service is also a type of Kubernetes Object which is majorly used to setup networking.
  6. Kubernetes uses the concept of labels and selectors to apply services to other Kubernetes objects such as Pods.
  7. 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

--

--

Covenant Chukwudi
MyCloudSeries

I build products that would have positive effect on lives