-
What are containers? Isolated environments that contain everything an application needs to run. They are portable, efficient, and easy to use. Eg: Docker lets you create, deploy, and run containers.
-
Container Orchestration: Managing the lifecycle of containers, especially in large, dynamic environments. It involves deploying, scaling, and managing containers.
-
Why do we need container orchestration?
-
Starting up a single container requires a lot of manual work. Imagine managing a cluster of VMs containing multiple containers.
-
If we want to manage these clusters for us, like simply provide the scripts/instructions to someone else, and it will take care of the rest.
-
If we want to move our containers from one host to another, we need to make sure that the containers are running and the data is not lost.
-
Along with the above points, what if we can monitor the health of our containers, and if they are unhealthy, we can restart them automatically. This is also where container orchestration comes in.
-
-
In Kubernetes, if we want to start a container we don't start a container directly. We start a Pod.
Note: A single Pod can contain one or more containers.
-
A Node is simply a EC2 machine (VM) where we can run our containers. In Kubernetes, we divide the Nodes into two categories:
- Master Nodes (Control Pane)
- Worker Nodes
-
Master Nodes are responsible for managing the Pods. Its the master node's responsibility to:
- deploy bunch of containers as per the requirement.
- manage them.
-
Worker Nodes are the ones who actually run the containers.
-
Kubernetes Cluster is the collection of Master Nodes and Worker Nodes.
Master Node Internals
-
API Server: its the main entry point for all requests. developer sends the request (eg: 'pls initiate and run that docker image') to this server inside master nodes.
-
etcd: similar to redis. but unlike redis, its a distributed key-value store that stores the cluster state (eg: if there we want to run them on different pods, then storing 'pod1': backend1, 'pod2': backend2). means key-value pairs can be shared across multiple machines.
-
Scheduler: it looks at the cluster state and decides where to run the container. eg: if there are 2 worker nodes, then it will decide to run the container on worker node 1 or 2.
-
Controller Manager: runs an infinite loop to make sure that the cluster state is as per the requirement (checks it by running other controllers). eg: if the container is down, then it will restart it.
Worker Node Internals
-
container runtime: its the place where the container actually runs. eg: docker.
-
kubelet: it is the agent that runs on each worker node. it is responsible for making sure that the containers are running in a pod.
-
kube-proxy: it is responsible for making sure that the network is properly set up. eg: if we have 2 pods, then it will make sure that they can communicate with each other.
-
-
In summary, hierarchy is like this 👇
We can create a Kubernetes cluster in two ways:
Locally:
- Minikube
- Kind (Recommended)
Cloud:
- GKE (Google Kubernetes Engine)
- Install Kind using instructions here.
-
Create a single node cluster:
kind create cluster --name 100x-k8s
-
Check the Docker containers running:
docker ps
Notice, there is a single container running (control plane). In our case, the master node is acting as the worker node.
-
To delete the cluster:
kind delete cluster --name 100x-k8s
-
To setup a multi-node cluster, create a
clusters.ymlfile (or check the/k8s/clusters.yml).
-
Go to the path where the
clusters.ymlfile is located and run:kind create cluster --config clusters.yml --name 100x-k8s
-
Check the no. of nodes running (1 Master and 2 Worker Nodes).

You will hit the
masternode port since it is the only node that is exposed to the outside world.
-
To check the cluster info (although, will give forbidden error):
kubectl cluster-info --context kind-100x-k8s
-
To find the credentials, run:
cat ~/.kube/configThis is the file that contains the credentials to access the cluster.
-
To access the cluster, we need to install
kubectl:brew install kubectl
-
Check if the
kubectlis installed:kubectl version
-
-
Now, we can access the cluster using
kubectl:kubectl get nodes
-
To check the HTTP requests made by
kubectl:kubectl get nodes -v=10
-
-
If you check the output of the below command, you will notice that there are no pods running:
kubectl get pods
-
Till now, we have created a cluster of 3 nodes.
-
Let's create a single container from an image inside a pod.
-
Find a good image to run. In our case, we will go with
nginx. Checknginxusing docker first:docker run -p 3005:80 nginx
-
Now, let's create a pod using
kubectl. Pressctrl + cto stop the running container and run the below command to startnginxinside a pod:kubectl run nginx --image=nginx --port=80
-
Check the pods
kubectl get pods
-
Check the logs
kubectl logs nginx
-
Describe the pod
kubectl describe pod nginx
Notice, the node where the pod is running. It will be running on one of the worker nodes.
-
-
To delete the pod:
kubectl delete pod nginx
Notice: we can't yet access the pod yet, we will be able to do that once we understand the concept of services.
- Instead of running the
kubectl runcommand over and over again, we can create a manifest file.
-
Create a
pod-manifest.ymlfile (or check the/k8s/pod-manifest.yml).
-
Write the below configuration in the
pod-manifest.ymlfile:apiVersion: v1 kind: Pod metadata: name: nginx spec: containers: - name: nginx image: nginx ports: - containerPort: 80
Explaining above Configuration
-
apiVersion: The version of the Kubernetes API we want to use -
kind: The type of object we want to create. In this case, a Pod. -
metadata: Data about the Pod. In this case, the name of the Pod. -
spec: The specification of the Pod. This is where we define the containers that should run in the Pod.-
containers: A list of containers that should run in the Pod.-
name: The name of the container. -
image: The image to use for the container. -
ports: A list of ports that should be exposed by the container.containerPort: The port that should be exposed by the container.
-
-
-
-
Create the pod using the manifest file:
kubectl apply -f pod-manifest.yml
-
Check the pods
kubectl get pods
-
-
To delete the pod:
kubectl delete pod nginx
So, now our cluster is up and running. And its current state looks like this 👇



