second assingment
This commit is contained in:
parent
915fff0034
commit
ca61f86bb6
133
Readme.md
133
Readme.md
@ -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
4
k8s/00-namespace.yaml
Normal file
@ -0,0 +1,4 @@
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: vinayakrao
|
38
k8s/deployment-backend.yml
Normal file
38
k8s/deployment-backend.yml
Normal 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
|
54
k8s/deployment-frontend.yml
Normal file
54
k8s/deployment-frontend.yml
Normal 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
12
k8s/service-backend.yml
Normal 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
11
k8s/service-frontend.yml
Normal 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
|
14
k8s/statefulset-service.yaml
Normal file
14
k8s/statefulset-service.yaml
Normal 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
58
k8s/statefulset.yaml
Normal 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'
|
@ -1,5 +1,6 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo "Preparing the app.."
|
||||
docker-compose build
|
||||
docker build ./product-manager-backend -t product-manager-backend
|
||||
docker build ./product-manager-frontend -t product-manager-frontend
|
||||
echo "Preparation complete."
|
27
product-manager-frontend/Dockerfile
Normal file
27
product-manager-frontend/Dockerfile
Normal 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
|
11832
product-manager-frontend/yarn.lock
Normal file
11832
product-manager-frontend/yarn.lock
Normal file
File diff suppressed because it is too large
Load Diff
@ -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"
|
@ -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"
|
Loading…
Reference in New Issue
Block a user