After concluding the Kubernetes class on @KodeKloud, I've successfully deployed the Voting App on Kubernetes using Deployments. This class project allowed me to apply what I learned, integrating multiple tech stacks like Python, Redis, .NET, PostgreSQL, and Node.js. Deploying it on Kubernetes emphasized the importance of container orchestration in real-world scenarios.
Here's a detailed breakdown of its components and how they interconnect:
- voting-app (Python):
- Functionality: Allows users to cast their votes between two options.
- Interaction: It communicates directly with the Redis database, storing the voting data for processing.
- redis (Redis):
- Functionality: An in-memory data structure store that serves as a temporary data store and message broker for our system.
- Interaction: It holds the voting data temporarily, which the worker service then picks up for further processing.
- worker (.NET):
- Functionality: This is our background processing unit. It's responsible for collecting, analyzing, and then saving the processed data.
- Interaction: The worker retrieves the voting data from Redis, processes the votes, and subsequently saves the results into the PostgreSQL database.
- db (PostgreSQL):
- Functionality: Serves as the persistent storage system for our application, ensuring long-term data safety and integrity.
- Interaction: The result-app directly queries this database to retrieve and display the final voting results to the users.
- result-app (Node.js):
- Functionality: It's our frontend component, designed to present users with the results of their votes in a clear, intuitive format.
- Interaction: It communicates with the PostgreSQL database to fetch the voting results and present them to the users. Each of these components is containerized and managed by Kubernetes, ensuring scalability, high availability, and seamless interaction.
- Initiated the project by creating a directory named "voting app".
- Within this directory, I generated individual pod definition files for each component of the application.
- Inside the "voting app" directory, I crafted a deployment configuration file named voting-app-deploy.yaml and a voting-app-service.yaml.
- The contents of this file are as follows:
voting-app-deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: voting-app-deploy
labels:
name: voting-app-deploy
app: demo-voting-app
spec:
replicas: 1
selector:
matchLabels:
name: voting-app-pod
app: demo-voting-app
template:
metadata:
name: voting-app-pod
labels:
name: voting-app-pod
app: demo-voting-app
spec:
containers:
- name: voting-app
image: kodekloud/examplevotingapp_vote:v1
ports:
- containerPort: 80
voting-app-service.yaml
apiVersion: v1
kind: Service
metadata:
name: voting-service
labels:
name: voting-service
app: demo-voting-app
spec:
type: LoadBalancer
ports:
- port: 80
targetPort: 80
selector:
name: voting-app-pod
app: demo-voting-app
Next is to create a redis deployment and its service. Create a definition file with the below:
redis-deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: redis-deploy
labels:
name: redis-deploy
app: demo-voting-app
spec:
replicas: 1
selector:
matchLabels:
name: redis-pod
app: demo-voting-app
template:
metadata:
name: redis-pod
labels:
name: redis-pod
app: demo-voting-app
spec:
containers:
- name: redis
image: redis
ports:
- containerPort: 6379
redis-service.yaml
apiVersion: v1
kind: Service
metadata:
name: redis
labels:
name: redis-service
app: demo-voting-app
spec:
ports:
- port: 6379
targetPort: 6379
selector:
name: redis-pod
app: demo-voting-app
- For the database layer of our application, I set up a PostgreSQL deployment.
- The deployment configuration was established in a file named postgres-deployment.yaml and service in a postgres-service.yaml configuration file
postgres-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: postgres-deploy
labels:
name: postgres-deploy
app: demo-voting-app
spec:
replicas: 1
selector:
matchLabels:
name: postgres-pod
app: demo-voting-app
template:
metadata:
name: postgres-pod
labels:
name: postgres-pod
app: demo-voting-app
spec:
containers:
- name: postgres
image: postgres
ports:
- containerPort: 5432
env:
- name: POSTGRES_USER
value: "postgres"
- name: POSTGRES_PASSWORD
value: "postgres"
- name: POSTGRES_HOST_AUTH_METHOD
value: trust
postgres-service.yaml
apiVersion: v1
kind: Service
metadata:
name: db
labels:
name: postgres-service
app: demo-voting-app
spec:
ports:
- port: 5432
targetPort: 5432
selector:
name: postgres-pod
app: demo-voting-app
- To process and handle backend operations, a Worker App deployment was created.
- This was defined in the worker-app-deployment.yaml file, structured as:
apiVersion: apps/v1
kind: Deployment
metadata:
name: worker-app-deploy
labels:
name: worker-app-deploy
app: demo-voting-app
spec:
replicas: 1
selector:
matchLabels:
name: worker-app-pod
app: demo-voting-app
template:
metadata:
name: worker-app-pod
labels:
name: worker-app-pod
app: demo-voting-app
spec:
containers:
- name: worker-app
image: kodekloud/examplevotingapp_worker:v1
- Lastly, I drafted a deployment configuration for the Result Application, which displays voting outcomes to users.
- This configuration was saved in the result-app-deploy.yaml file and result-app-service.yaml.
result-app-deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: result-app-deploy
labels:
name: result-app-deploy
app: demo-voting-app
spec:
replicas: 1
selector:
matchLabels:
name: result-app-pod
app: demo-voting-app
template:
metadata:
name: result-app-pod
labels:
name: result-app-pod
app: demo-voting-app
spec:
containers:
- name: result-app
image: kodekloud/examplevotingapp_result:v1
ports:
- containerPort: 80
result-app-service.yaml
apiVersion: v1
kind: Service
metadata:
name: result-service
labels:
name: result-service
app: demo-voting-app
spec:
type: LoadBalancer
ports:
- port: 80
targetPort: 80
selector:
name: result-app-pod
app: demo-voting-app
With all deployment definition files ready, it's time to switch to the terminal. Here, I'll initiate the deployment processes and configure their respective services for seamless interactions.
Begin by ensuring the cluster is free from any non-default pods and services.
kubectl get pods
From my observations, there are no extra pods and services active other than those that come default with Kubernetes.
Initiate the deployment for the voting app using:
kubectl create -f voting-app-deployment.yaml
Once the deployment is completed, proceed with creating the associated service:
kubectl create -f voting-app-service.yaml
It's crucial to verify that our deployments are functioning as intended. Check their status with:
Kubectl get deployment
The output should indicate that the voting app is up and operational.
Now, let's establish the Redis deployment using:
kubectl create -f redis-deploy.yaml
Once deployed, it's time to create the corresponding service for Redis:
kubectl create -f redis-service.yaml
Deploy PostgreSQL using the following command:
kubectl create -f postgres-deploy.yaml
Once the deployment has completed, initiate the associated service:
kubectl create -f postgres-service.yaml
Ensure all deployments are active and healthy:
Kubectl get deployments
Also, validate the services associated with the deployments:
kubectl get service
Next, deploy the result application:
kubectl create -f result-app-deploy.yaml
And the service:
kubectl create -f result-app-service.yaml
Deploy the worker application:
kubectl create -f worker-app-deploy.yaml
confirm all services are setup
To be certain, do a final check of both the deployments and services to confirm everything is in order:
Kubectl get deployments
kubectl get service
To access the voting frontend service locally, use the following command:
kubectl port-forward service/voting-service 8080:80
For accessing the result backend service locally, utilize:
kubectl port-forward service/result-service 8081:80
If there's a need to accommodate more traffic, consider scaling up the voting app deployment. For instance, to run three replicas, execute:
kubectl scale deployment voting-app-deploy --replicas=3
To validate that the scaling took effect, check the number of pods:
This should confirm that there are three instances of the voting app.
With this setup, every time the voting page is refreshed, it is highly likely that a different pod will serve the request, showcasing the load distribution across the replicas.