Kubernetes Basics: Your First App Deployment
Day 33/90 with Shubham Londhe
Looking to deploy your applications with ease and efficiency? In this blog post, we’ll walk you through the step-by-step process of deploying applications on Kubernetes, the popular container orchestration platform.
What is Kubernetes?
Kubernetes is like a super-hero for managing containers. But what are containers? Think of them as small, portal packages that hold all the things your application needs to run the code smoothly.
Now, Imagine you have a bunch of containers that need to run together to make your application work. eg(Front-end, Back-end, database, etc). Kubernetes comes to the rescue!
It helps you manage and control these containers, making sure they run in the right place, at the right time, and on the right machines as well.
Kubernetes acts like a brain that cor-ordinates and distributes these containers across multiple computers called Nodes.
With Kubernetes, you can easily deploy, update and roll back your application without any downtime. It also handles load balancing, so that traffic is evenly distributed among your containers, keeping your application responsive and reliable.
Kubernetes is a popular container orchestration tool.
Let’s deploy our First application using kubernetes.
Note: Please follow the steps for deployment
Step 1: Pre-requisites:
Installation of Kubernetes on master and worker nodes:
Step 2: Clone a repository
git clone https://github.com/tejashreeSalvi/django-todo-cicd.git
Let's look into the docker file in this repository:
FROM python:3
WORKDIR /data
RUN pip install django==3.2
COPY . .
RUN python manage.py migrate
EXPOSE 8000
CMD ["python","manage.py","runserver","0.0.0.0:8000"]
It’s a Django application running on port number 8000
and the entry point to the application is manage.py
What are Containers?
Containers are a runtime environment where your application code, with dependencies, is packaged and executed.
Containers are created from images.
Step 3: Build an Image from Dockerfile
docker build . -t trajendra/django-todo:latest
- Go to the repository
cd django-todo
and run the above command to create an image.
- Run the
docker images
command to get the list of images.
The image is successfully created.
Step 4: Push the docker image to a Registry
- Login to the docker hub
docker login
After running the command it will prompt for username and password. Enter the details and you are successfully logged in.
- Push the image to registry
docker push trajendra/django-todo:latest
- Verify whether we have successfully been able to push the docker image to the registry.
WoW ! You have successfully created the image and pushed to registry. We will be creating containers from this image.
There are primary two ways to create and manage resources:
- Command-Line Interface
- YAML Manifests
Command-Line Interface:
The Kubernetes CLI referred to as kubectl
is a tool that allows you to interact with the Kubernetes Cluster. It provides a set of commands to create, modify, and manage Kubernetes resources
For example:
kubectl create
to create a resource,kubectl edit
orkubectl patch
to modify the resource andkubectl delete
to delete any resources,kubectl get pods
to get all the pods in the default namespace. There are many more commands.
YAML Manifests:
YAML manifests are configuration files written in YAML. These files define the desired state of Pods, Deployments, ConfigMaps, Secret, and many more.
We will be using YAML Manifests to deploy our application.
What is Pods?
The code of our application runs inside containers, which are encapsulated within Pods in Kubernetes.
- A Pod can contain one or more containers, and all the containers share the same resources such as CPU, memory, and storage
- Pods have their own unique IP address within the cluster, enabling other Pods or services to communicate with them.
- Pods in Kubernetes are considered ephemeral, meaning they can be created, scaled, or terminated dynamically based on the desired state of the system.
1 Pod = 1 container is recommendand as best practices.
Task 1: Create your First Pod.
We will be creating a single pod using the YAML Manifests.
pod.yml
apiVersion: v1
kind: Pod
metadata:
name: django-app
spec:
containers:
- name: django-app
image: trajendra/django-todo:latest
ports:
- containerPort: 8000
In pod.yml
file,
apiVersion: v1
specifies the Kubernetes API version being used.kind: Pod
indicates that you are creating a Pod object.metadata
contains metadata about the Pod, including its name.spec
defines the desired state of the Pod.containers
is an array of container objects running inside the Pod. In this case, there is only one container.name: crud-backend-app
sets the name of the container to "crud-backend-app".image: trajendra/crudbackend:latest
specifies the Docker image to be used for the container. In this case, it uses the image "trajendra/django-todo" with the "latest" tag.ports
defines the network ports that the container exposes. In this example, it exposes port 8000.
kubectl apply -f pod.yml
Run this command, Kubernetes will read our YAML file, and update any resources in our cluster accordingly. To see the newly created pod in action, you can run kubectl get pods
. You should see the pod running.
Worker nodes are the machines in the Kubernetes cluster where Pods are scheduled and containers are run
- Connect to Worker Node to verify if the container is successfully created.
docker ps
- Let’s go inside the container and execute the curl command
docker exec -it 3551dae bash
Hey ! We have successfully been able to create containers via pod using YAML Manifests
Namespaces
Namespaces are logical groups created inside a Cluster. They allow multiple teams or applications to co-exist in the same cluster.
Each namespace has its own set of resources, including Pods, Services, Deployments, ConfigMaps, and more.
- By default, Kubernetes provides a
default
namespace where resources are created if no specific namespace is specified - You can define RBAC (Role-Based Access Control) policies to grant different levels of access to resources based on namespaces.
Step 5: Create a Namespace
kubectl create namespace my-django-app
We will be creating my-django-app
namespace for our application to include all the pods, services, deployment, and containers in this namespace.
Task 2: Create a Pod inside the Namespace
pod.yml
apiVersion: v1
kind: Pod
metadata:
name: django-app
namespace: my-django-app
spec:
containers:
- name: django-app
image: trajendra/django-todo:latest
ports:
- containerPort: 8000
- To create the pod run the following command:
kubectl apply -f pod.yml
- To verify the pods created inside the namespace
kubectl get pods -n=my-django-app
Deleting a Pod
kubectl delete -f pod.yml
Here, the pod will be deleted from the namespace my-django-app
.
As we have added a namespace added in the metadata.
We just learned to create a pod inside the namespace.
Deployment
Our app runs inside kubernetes cluster. Application consists of multiple pods, each representing a component of the application. Instead of manually creating and managing individual pods for your application, you can use a deployment.
- It ensures that the desired number of replicas of each component is always available and handles any necessary updates or scaling.
- Kubernetes monitors the health of the Pods managed by a Deployment. If a Pod fails or becomes unresponsive, Kubernetes automatically replaces it to maintain the desired number of replicas.
Step 6: Create a Deployment
deployment.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-django-app-deployment
labels:
app: django-app
namespace: my-django-app
spec:
replicas: 3
selector:
matchLabels:
app: django-app
template:
metadata:
labels:
app: django-app
spec:
containers:
- name: django-app-container
image: trajendra/django-todo:latest
ports:
- containerPort: 8000
In Manifest, we have declared
kind
: Defines the type of resource, which is a Deployment in this case.
selector
: Specifies the labels used to select which Pods are part of this Deployment.
matchLabels
: Defines the labels that Pods must have to be considered part of the Deployment. In this case, Pods with the labelapp: django-app
will be included.replicas
: Defines the desired number of replicas (Pods) to maintain, set to 3 in this example.template
: Defines the Pod template used to create the Pods managed by the Deployment.
spec
: Specifies the specifications for the Pods created from the template.
kubectl apply -f deployment.yml # run the deployment
kubectl get pods -n=my-django-app # get the list of pods in namespace
You can then use the kubectl apply
command to create or update the Deployment in your Kubernetes cluster.
To get the pods created inside a namespace kubectl get pods -n=my-django-app
.
Scale
It is used to scale number of replicas(Pods) in the Deployments
Task 3: Create 10 replicas using Kubernetes CLI commands
kubectl scale deployment my-django-app-deployment --replicas=10 -n=my-django-app
--replicas=10
: Sets the desired number of replicas (Pods) to 10. This means that Kubernetes will adjust the number of Pods in the Deployment to match this value.
It has created 10 pods in Cluster
Service
You have a deployment with multiple pods running a web application. Each pod has its own IP address, which can change dynamically. If you expose these pods directly to clients, the clients would need to keep track of each pod’s IP address and handle potential changes. This approach becomes impractical as the number of pods scales up or down. To solve this problem, you can create a service.
It provides a way to expose your application running in Pods to other services or external users within the cluster.
Step 7: Expose your application to external users
service.yml
apiVersion: v1
kind: Service
metadata:
name: my-django-app-service
namespace: my-django-app
spec:
type: NodePort
selector:
app: django-app
ports:
# By default and for convenience, the `targetPort` is set to the same value as the `port` field.
- port: 80
targetPort: 8000
# Optional field
# By default and for convenience, the Kubernetes control plane will allocate a port from a range (default: 30000-32767)
nodePort: 30009
NodePort: Exposes the Service on a port across each cluster node’s IP. Allows external access to the Service. We are using NodePort (30007–32767) range of IP allowed.
port
: Specifies the port number on the Service itself. In this case, it is set to80
.targetPort
: Specifies the port number on the Pods that the Service should forward traffic to. In this example, it is set to8000
nodePort: 30009
: it is set to30009
, meaning that traffic arriving atnodeIP:30009
will be directed to the Service.
kubectl apply -f service.yml
Edit the inbound rule in the security group of the EC2 instance and click on save rules.
Access the Application
To access the application: http://<public_ip_of_instance>:30009
Well, Done! we have successfully deployed a todo application on Kubernetes Cluster.
To Delete the Deployment
kubectl delete -f deployment.yml
This is #Day33 of #90daysofdevops with Shubham Londhe
Do add some claps, if you liked the article 👏
Follow for more such content ❤
LinkedIn: https://www.linkedin.com/in/tejashree-salvi-003aa2195/