second assingment

This commit is contained in:
vinayak rao 2022-05-07 16:44:18 +05:30
parent 915fff0034
commit ca61f86bb6
13 changed files with 12132 additions and 69 deletions

133
Readme.md
View File

@ -3,9 +3,9 @@
This is a product management application for admin. Here you can upload, edit, delete products. Probably a front-end
will show these products to the user if future.
*Edit functionality is not implemented at this moment*
_Edit functionality is not implemented at this moment_
![homepage](images/product-manager-homepage.png?raw=true "System Architecture")
![homepage](images/product-manager-homepage.png?raw=true 'System Architecture')
# Requirements
@ -13,105 +13,116 @@ The basic system requirements are as follows
- Any OS, preferably Linux
- Docker
- Docker compose
- Kubernetes
# Architecture
![System design diagram](images/product-manager.jpg?raw=true "System Architecture")
![System design diagram](images/product-manager.jpg?raw=true 'System Architecture')
### Technology used
- Django (Backend Rest API)
- React (Frontend)
- Postgres - as persistent database
- kubernetes
- Docker
# Docker environment
# Kubernetes environment
For shipping and deploying the application docker-compose is used. All the configurations are in the docker-compose.yml
file.
For shipping and deploying the application kubernetes is used. All the configurations are in the k8s folder.
Key points of the docker-compose.yml is given below.
Key points of the the kubernetes objects is given below.
## services
### Namespace
- **backend:** runs the Django web API.
- **db** runs the postgres database required for the backend API
- **web** this is the service for front-end application
- **Namespace**: We used namespace to group our project resources together and isolate theme.
### Deployment
Deployment is used for managing the application pods.
- **production-manager-backend:** runs the Django web API.
- **production-manager-frontend** run front-end application
### Services
The kubernetes services are used to expose our application as a network service.
- **backend-service:** service used to communicate with the backend APO.
- **mysql-service** runs the mysql database service required for the backend API
- **front-service** this is the entrypoint for the front-end application
### Statefulset:
PostgreSQL database is deployed as a statefulset kuebernetes object. StatefulSet is used to manage stateful applications with persistent storage. Storage stays associated with replacement pods. Volumes persist when pods are deleted.. You can find more information about statefulset [here](https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/)
### ConfigMap:
A ConfigMap is used to store nginx configuration file. The front pod will consume the ConfigMaps as the default configuration files for nginx web server. This ConfigMap contains the rules for mapping the `/api` request to the backend service.
### PersistentVolumeClaim:
PVC is binding between a Pod and PV. Pod request the Volume through the PVC.PVC is the request to provision persistent storage with a specific type and configuration.PVCs describe the storage capacity and characteristics a pod requires, and the cluster attempts to match the request and provision the desired persistent volume.
### PersistentVolume:
We used a persitent volume in order to save the database data in a persistent volume which is independent of the lifecycle of the Pods. It means that data represented by a PV continue to exist as the cluster changes and as Pods are deleted and recreated.
## Virtual networks
One virtual network is used
- main
We used the internal kubernets network , and we used services to expose the backend, frontend and postgreSQL databases as a network services.
## Volumes
For persisting the data of the db container docker volume bind is used.
For persisting the data of the db container, we used a persistent volume using the kubernetes host localfile as we do not have any NFS for this purpose. This persistent volume is mapped to the local `/mnt/pg` folder.
- pg-data
## A description of the container configuration performed.
## list of the containers
Two configuration was made to adapt the application to new architecture.
### product-manager-backend
- Connection between database and the backend :
The credentials for PostgreSQL in the statefulset.yml file are also passed as environement variables in the deployment.yml file for the products manager backend deployment.
This container runs under the service name backend. The dockerfile user for this container is located
at `product-manager-backend/Dockerfile`. This container is based on python:3.9 image.
- Connection between the frontend and the backend: Nginx based image is used to serve the frontend files. A ConfigMap is used to store nginx configuration file to forward all the `/api` request to the products manager backend service.
### product-manager-frontend
### Prepare the app
The frontend container for the application. The dockerfile is located
at `product-manager-frontend/.docker/dev/Dockerfile`. Base image used to build this container is `Node:14`.
### db container
The container is built using the official `postgres:latest` image pulled from dockerhub.
## Preparation
To prepare the environment for the first time run the following command
```shell
bash prepare-app.sh
```
## Running
Run the app background
```shell
bash start-app.sh
```
see the logs of backend
As We used minikube the local docker registry is not reachable for it, we should proxy the docker daemon to the minikube registry before building our application images, for this we have to run the following command.
```
docker-compose logs -f backend
eval $(minikube docker-env)
```
see the logs of forntend
Now I can build the images and they will be accessible for minikube. To prepare the application you have to run the command :
```
docker-compose logs -f web
sh prepare-app.sh
```
see the logs of database
The script will build the frontend and the backend images.
### Run the app
To run the app you have to run:
```
docker-compose logs -f db
sh start-app.sh
```
## Stopping
the script which will create a namespace and all the required kubernetes object of the application.
```shell
bash stop-app.sh
```
### To stop the app
## Removing containers
```shell
bash remove-app.sh
```
The `stop-app.sh` script will remove the namespace and its resources also it will remove the persistent volume we created in the run script.
# Viewing the app
After running the app. visit [http://localhost:3000](http://localhost:3000) to view the app
After deploying the app. We need to expose the application service outside the kubernetes we used the `kubectl port-forwading` to forward the front end service localy .
```
POD_NAME=$(kubectl get pods --namespace vinayakrao -l "app=product-manager-frontend" -o jsonpath="{.items[0].metadata.name}")
kubectl port-forward $POD_NAME 3000:80 --namespace vinayakrao
```
Then visit [http://localhost:3000](http://localhost:3000) to view the app

4
k8s/00-namespace.yaml Normal file
View File

@ -0,0 +1,4 @@
apiVersion: v1
kind: Namespace
metadata:
name: vinayakrao

View File

@ -0,0 +1,38 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: product-manager-backend-deployment
labels:
app: product-manager-backend
spec:
replicas: 1
selector:
matchLabels:
app: product-manager-backend
template:
metadata:
labels:
app: product-manager-backend
spec:
initContainers:
- name: init-cont
image: busybox:1.31
command: ['sh', '-c',
'echo -e "Checking for the availability of PostgreSQL Server deployment"; while ! nc -z postgres-db-service 5432; do sleep 1; printf "-"; done; echo -e " >> PostgreSQL DB Server has started";']
containers:
- name: product-manager-backend
image: product-manager-backend:latest
imagePullPolicy: IfNotPresent
command: ['bash']
args: ['scripts/backend_entrypoint.sh']
ports:
- containerPort: 8000
env:
- name: POSTGRES_DB
value: postgres
- name: POSTGRES_USER
value: postgres
- name: POSTGRES_PASSWORD
value: postgres
- name: DATABASE_HOST
value: postgres-db-service

View File

@ -0,0 +1,54 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: product-manager-frontend-deployment
labels:
app: product-manager-frontend
spec:
replicas: 1
selector:
matchLabels:
app: product-manager-frontend
template:
metadata:
labels:
app: product-manager-frontend
spec:
containers:
- name: product-manager-frontend
image: product-manager-frontend:latest
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
volumeMounts:
- mountPath: /etc/nginx/conf.d/ # mount nginx-conf volumn to /etc/nginx
readOnly: true
name: nginx-conf
volumes:
- name: nginx-conf
configMap:
name: nginx-conf # place ConfigMap `nginx-conf` on /etc/nginx
items:
- key: default.conf
path: default.conf
---
apiVersion: v1
kind: ConfigMap
metadata:
name: nginx-conf
namespace: vinayakrao
data:
default.conf: |
server {
listen 80;
root /usr/share/nginx/html;
index index.html;
location / {
try_files $uri /index.html;
}
location /api/ {
# The following statement will proxy traffic to the upstream named Backend
proxy_pass http://backend-service:8000;
}
}

12
k8s/service-backend.yml Normal file
View File

@ -0,0 +1,12 @@
# Backend service
apiVersion: v1
kind: Service
metadata:
name: backend-service
spec:
selector:
app: product-manager-backend
ports:
- protocol: TCP
port: 8000
targetPort: 8000

11
k8s/service-frontend.yml Normal file
View File

@ -0,0 +1,11 @@
apiVersion: v1
kind: Service
metadata:
name: frontend-service
spec:
selector:
app: product-manager-frontend
ports:
- protocol: TCP
port: 80
targetPort: 80

View File

@ -0,0 +1,14 @@
# PostgreSQL StatefulSet Service
apiVersion: v1
kind: Service
metadata:
name: postgres-db-service
spec:
selector:
app: postgresql-db
type: ClusterIP
clusterIP: None
ports:
- port: 5432
targetPort: postgresql
protocol: TCP

58
k8s/statefulset.yaml Normal file
View File

@ -0,0 +1,58 @@
# PostgreSQL StatefulSet
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: postgresql-db
spec:
serviceName: postgresql-db-service
selector:
matchLabels:
app: postgresql-db
template:
metadata:
labels:
app: postgresql-db
spec:
containers:
- name: postgresql-db
image: postgres:latest
imagePullPolicy: 'IfNotPresent'
volumeMounts:
- name: pv-claim
mountPath: /var/lib/postgresql/data
env:
- name: POSTGRES_DB
value: postgres
- name: POSTGRES_USER
value: postgres
- name: POSTGRES_PASSWORD
value: postgres
ports:
- name: postgresql
containerPort: 5432
protocol: TCP
volumeClaimTemplates:
- metadata:
name: pv-claim
namespace: vinayakrao
spec:
storageClassName: ''
accessModes: ['ReadWriteOnce']
resources:
requests:
storage: 1Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv-volume
labels:
type: local
spec:
storageClassName: ''
capacity:
storage: 2Gi
accessModes: ['ReadWriteOnce']
hostPath:
path: '/mnt/pg'

View File

@ -1,5 +1,6 @@
#!/bin/bash
echo "Preparing the app.."
docker-compose build
echo "Preparation complete."
docker build ./product-manager-backend -t product-manager-backend
docker build ./product-manager-frontend -t product-manager-frontend
echo "Preparation complete."

View File

@ -0,0 +1,27 @@
# Use official node image as the base image
FROM node:latest as build
# Set the working directory
WORKDIR /usr/local/app
COPY package.json yarn.lock /usr/local/app/
ENV NODE_OPTIONS=--openssl-legacy-provider
# Install all the dependencies
RUN yarn install --pure-lockfile --loglevel verbose
# Add the source code to app
COPY ./ /usr/local/app/
ENV REACT_APP_BASE_URL='/api/'
# Generate the build of the application
RUN npm run build
# Stage 2: Serve app with nginx server
# Use official nginx image as the base image
FROM nginx:latest
# Copy the build output to replace the default nginx contents.
COPY --from=build /usr/local/app/build /usr/share/nginx/html
# Expose port 80
EXPOSE 80

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,5 @@
#!/bin/bash
echo "running the app"
docker-compose up -d
echo "Connecting to the database....Please wait."
sleep 10
echo "The app is available at http://localhost:3000"
echo "Deploying the app"
kubectl apply -f ./k8s --namespace vinayakrao
echo "The app is deployed"

View File

@ -1,5 +1,8 @@
#!/bin/bash
echo "stopping the app.."
docker-compose stop
echo 'Deleting namespace'
kubectl delete namespaces vinayakrao
echo 'Deleting persistent volume'
kubectl delete pv pv-volume
echo "App stopped"