-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 45e112d
Showing
14 changed files
with
1,333 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
node_modules | ||
kube |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
node_modules | ||
*/public/uploads | ||
|
||
*.tar | ||
data/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
FROM node:18.0-slim | ||
COPY . . | ||
RUN npm install | ||
CMD [ "node", "index.js" ] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
|
||
SA II Project: Building and Scaling expressjs-mongodb-app on Kubernetes | ||
Project Overview | ||
Welcome to the documentation of the System Administration II course at TSBE. This project focuses on the installation and scaling of the expressjs-mongodb-app on a Kubernetes cluster. | ||
|
||
Project Goals | ||
The primary objectives of this project are to set up and configure a Kubernetes cluster with the following key features: | ||
|
||
Scalability: Utilizing Kubernetes orchestration for seamless scaling. | ||
Persistent Storage: Implementing containers with persistent storage, specifically for a MongoDB Database. | ||
Container Networking: Establishing effective container networking with port forwarding to enable external access. | ||
Security: Configuring a secure environment to minimize potential security risks. | ||
Used Ports: | ||
3000: expressjs-app | ||
27017: MongoDB | ||
|
||
Platform & Limitations | ||
The following virtual platform is hosted by the school to execute the project: | ||
|
||
vmKL1 | ||
The vmKL1 is the management machine used to set up, administer, and access the Kubernetes cluster. | ||
|
||
VM Specs: | ||
|
||
OS: Kali GNU/Linux | ||
Kernel: Linux 6.5.0-kali3-amd64 | ||
CPU: 2 vCPUs | ||
RAM: 16 GB | ||
Storage: /dev/sda 35 GB | ||
Network: Access to vmLM1 & Internet | ||
IP: 192.168.110.70 | ||
Installed Software: | ||
|
||
vscode | ||
vmLM1 | ||
|
||
The vmLM1 is the Kubernetes host itself. It will act as Control Plane (Master Node) & Data Plane (Worker Node). | ||
VM Specs: | ||
OS: Ubuntu 22.04.3 LTS | ||
Kernel: Linux | ||
CPU: 4 vCPUs | ||
RAM: 12 GB | ||
Storage: /dev/sda 16 GB | ||
Network: Access to vmKL1 & Internet | ||
IP: 192.168.110.60 | ||
Installed Software: | ||
minikube version: v1.32.0 | ||
The container network is set up in a way that only necessary communication is allowed. UFW is active and configured. Open ports to the Kubernetes Node (vmLM1): | ||
|
||
22/TCP -> SSH | ||
443/TCP -> Kubernetes API | ||
30703/TCP -> express-mongodb-app | ||
8001/TCP -> Kubernetes Dashboard | ||
31185/TCP -> Argocd (optional) | ||
As far as the container network goes, only pods that need external access are configured with NodePort. All other pods are configured with Cluster IP for Kubernetes internal-only communication. | ||
|
||
Manual Setup Guide | ||
vmKL1: | ||
# Update the System | ||
sudo apt update -y | ||
sudo apt upgrade -y | ||
|
||
vmLM1: | ||
# Port forward , Enable & open necessary ports on the server firewall | ||
sudo ufw allow 22/tcp | ||
sudo ufw allow 443/tcp | ||
sudo ufw allow 80 | ||
sudo ufw allow 8001 # for minikube dashboard | ||
sudo ufw allow 30703 # for express-mongodb-app | ||
sudo ufw allow 31185 # for argocd (optional) | ||
sudo ufw enable | ||
|
||
# Enable SSH access by uncommenting the following line in /etc/ssh/sshd_config | ||
Port 22 | ||
|
||
# Restart sshd | ||
sudo systemctl restart sshd | ||
|
||
# Update the System | ||
sudo apt update -y | ||
sudo apt upgrade -y | ||
|
||
# Install Docker | ||
sudo apt install docker.io | ||
docker --version # Check Docker version | ||
|
||
# Download Minikube | ||
curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64 | ||
sudo install minikube-linux-amd64 /usr/local/bin/minikube | ||
minikube version # Check Minikube version | ||
|
||
# Install Kubectl | ||
sudo snap install kubectl --classic | ||
kubectl version # Check Kubectl version | ||
|
||
# Start Minikube with Docker driver | ||
minikube start --driver=docker | ||
sudo usermod -aG docker $USER && newgrp docker | ||
minikube node add —worker | ||
kubectl label node <node_name> node-role.kubernetes.io/worker=worker | ||
kubectl get nodes | ||
|
||
# Update local apt cache | ||
sudo apt update | ||
|
||
# Create a namespace for the app | ||
kubectl create namespace nodejs-mongodb-app | ||
|
||
# Create a project folder for deployment | ||
mkdir ~/kube |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
const path = require('path') | ||
const express = require('express') | ||
const MongoClient = require('mongodb').MongoClient | ||
const multer = require('multer') | ||
const { marked } = require('marked') | ||
|
||
const app = express() | ||
const port = process.env.PORT || 3000 | ||
const mongoURL = process.env.MONGO_URL || 'mongodb://localhost:27017/dev' | ||
|
||
async function initMongo() { | ||
console.log('Initialising MongoDB...') | ||
let success = false | ||
while (!success) { | ||
try { | ||
client = await MongoClient.connect(mongoURL, { | ||
useNewUrlParser: true, | ||
useUnifiedTopology: true, | ||
}) | ||
success = true | ||
} catch { | ||
console.log('Error connecting to MongoDB, retrying in 1 second') | ||
await new Promise(resolve => setTimeout(resolve, 1000)) | ||
} | ||
} | ||
console.log('MongoDB initialised') | ||
return client.db(client.s.options.dbName).collection('notes') | ||
} | ||
|
||
async function start() { | ||
const db = await initMongo() | ||
|
||
app.set('view engine', 'pug') | ||
app.set('views', path.join(__dirname, 'views')) | ||
app.use(express.static(path.join(__dirname, 'public'))) | ||
|
||
app.get('/', async (req, res) => { | ||
res.render('index', { notes: await retrieveNotes(db) }) | ||
}) | ||
|
||
app.post( | ||
'/note', | ||
multer({ dest: path.join(__dirname, 'public/uploads/') }).single('image'), | ||
async (req, res) => { | ||
if (!req.body.upload && req.body.description) { | ||
await saveNote(db, { description: req.body.description }) | ||
res.redirect('/') | ||
} else if (req.body.upload && req.file) { | ||
const link = `/uploads/${encodeURIComponent(req.file.filename)}` | ||
res.render('index', { | ||
content: `${req.body.description} ![](${link})`, | ||
notes: await retrieveNotes(db), | ||
}) | ||
} | ||
}, | ||
) | ||
|
||
app.listen(port, () => { | ||
console.log(`App listening on http://localhost:${port}`) | ||
}) | ||
} | ||
|
||
async function saveNote(db, note) { | ||
await db.insertOne(note) | ||
} | ||
|
||
async function retrieveNotes(db) { | ||
const notes = await db.find().toArray() | ||
const sortedNotes = notes.reverse() | ||
return sortedNotes.map(it => ({ ...it, description: marked(it.description) })) | ||
} | ||
|
||
start() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
apiVersion: v1 | ||
kind: ConfigMap | ||
metadata: | ||
name: mongo-config | ||
data: | ||
MONGO_URL: "mongodb://mongo:27017/dev" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
apiVersion: autoscaling/v1 | ||
kind: HorizontalPodAutoscaler | ||
metadata: | ||
name: mongo-hpa | ||
spec: | ||
scaleTargetRef: | ||
apiVersion: apps/v1 | ||
kind: Deployment | ||
name: mongo | ||
minReplicas: 1 | ||
maxReplicas: 5 | ||
targetCPUUtilizationPercentage: 50 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
apiVersion: v1 | ||
kind: PersistentVolumeClaim | ||
metadata: | ||
name: mongo-pvc | ||
spec: | ||
accessModes: | ||
- ReadWriteOnce | ||
resources: | ||
requests: | ||
storage: 256Mi | ||
|
||
--- | ||
apiVersion: v1 | ||
kind: Service | ||
metadata: | ||
name: mongo | ||
spec: | ||
selector: | ||
app: mongo | ||
ports: | ||
- port: 27017 | ||
targetPort: 27017 | ||
|
||
--- | ||
apiVersion: apps/v1 | ||
kind: StatefulSet | ||
metadata: | ||
name: mongo | ||
spec: | ||
serviceName: "mongo" | ||
replicas: 1 | ||
selector: | ||
matchLabels: | ||
app: mongo | ||
template: | ||
metadata: | ||
labels: | ||
app: mongo | ||
spec: | ||
containers: | ||
- name: mongo | ||
image: mongo:6.0.2-focal | ||
ports: | ||
- containerPort: 27017 | ||
volumeMounts: | ||
- name: storage | ||
mountPath: /data/db | ||
resources: | ||
requests: | ||
memory: "512Mi" | ||
cpu: "250m" | ||
limits: | ||
memory: "1Gi" | ||
cpu: "500m" | ||
|
||
volumeClaimTemplates: | ||
- metadata: | ||
name: storage | ||
spec: | ||
accessModes: | ||
- ReadWriteOnce | ||
resources: | ||
requests: | ||
storage: 256Mi |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
apiVersion: autoscaling/v1 | ||
kind: HorizontalPodAutoscaler | ||
metadata: | ||
name: server-hpa | ||
spec: | ||
scaleTargetRef: | ||
apiVersion: apps/v1 | ||
kind: Deployment | ||
name: server | ||
minReplicas: 1 | ||
maxReplicas: 10 | ||
targetCPUUtilizationPercentage: 50 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
apiVersion: apps/v1 | ||
kind: Deployment | ||
metadata: | ||
name: server | ||
spec: | ||
replicas: 1 | ||
selector: | ||
matchLabels: | ||
app: server | ||
template: | ||
metadata: | ||
labels: | ||
app: server | ||
spec: | ||
containers: | ||
- name: server | ||
image: yavuzozbay/nodeserver:2.0.0 | ||
ports: | ||
- containerPort: 3000 | ||
env: | ||
- name: MONGO_URL | ||
valueFrom: | ||
configMapKeyRef: | ||
name: mongo-config | ||
key: MONGO_URL | ||
imagePullPolicy: Always | ||
resources: | ||
requests: | ||
memory: "128Mi" | ||
cpu: "100m" | ||
limits: | ||
memory: "264Mi" | ||
cpu: "250m" | ||
|
||
--- | ||
apiVersion: v1 | ||
kind: Service | ||
metadata: | ||
name: server-service | ||
spec: | ||
selector: | ||
app: server | ||
ports: | ||
- protocol: TCP | ||
port: 80 | ||
targetPort: 3000 | ||
type: NodePort |
Oops, something went wrong.