diff --git a/README.md b/z1/README.md similarity index 100% rename from README.md rename to z1/README.md diff --git a/docker-compose.yaml b/z1/docker-compose.yaml similarity index 100% rename from docker-compose.yaml rename to z1/docker-compose.yaml diff --git a/prepare-app.sh b/z1/prepare-app.sh similarity index 100% rename from prepare-app.sh rename to z1/prepare-app.sh diff --git a/remove-app.sh b/z1/remove-app.sh similarity index 100% rename from remove-app.sh rename to z1/remove-app.sh diff --git a/start-app.sh b/z1/start-app.sh similarity index 100% rename from start-app.sh rename to z1/start-app.sh diff --git a/stop-app.sh b/z1/stop-app.sh similarity index 100% rename from stop-app.sh rename to z1/stop-app.sh diff --git a/z2/Dockerfile b/z2/Dockerfile new file mode 100644 index 0000000..2b6c75b --- /dev/null +++ b/z2/Dockerfile @@ -0,0 +1,13 @@ +# Stage 1: Build +FROM node:18-alpine as builder +WORKDIR /app +COPY package*.json ./ +RUN npm install +COPY . . +RUN npm run build + +# Stage 2: Run +FROM nginx:alpine +COPY --from=builder /app/dist /usr/share/nginx/html +COPY nginx.conf /etc/nginx/conf.d/default.conf +EXPOSE 80 diff --git a/z2/README.md b/z2/README.md new file mode 100644 index 0000000..31b8b00 --- /dev/null +++ b/z2/README.md @@ -0,0 +1,144 @@ +# Kubernetes Task Manager - Technical Documentation + +## Project Purpose + +This project demonstrates a production-like Kubernetes deployment featuring: +- Multi-container application +- Persistent storage +- Scalable frontend +- Proper resource management + +## Deployment Components + +### Core Objects + +| Object Type | Name | Purpose | +|-------------------|---------------------|------------------------------------------------------------------| +| `Namespace` | `web-app` | Isolates all application resources | +| `Deployment` | `web-app` | Manages 2 replicas of frontend pods | +| `StatefulSet` | `mysql` | Manages database pod with stable network identity + +| `Service` | `web-app-service` | Exposes frontend on NodePort 30080 | +| `PersistentVolume`| `mysql-pv` | Provides 5Gi storage for database | + +### Container Images + +| Component | Image | Port | Notes | +|-----------|-----------------------------|------|----------------------------------------| +| Frontend | `k8s-task-manager-frontend` | 80 | Custom-built Nginx image | +| Database | `mysql:5.7` | 3306 | With preconfigured credentials | +| Backend | `k8s-task-manager-api` | 8080 | Node.js/Express REST API | + +## Deployment Workflow + +```mermaid +graph TD + A[prepare-app.sh] --> B[Creates PV directories] + B --> C[Builds frontend image] + C --> D[start-app.sh] + D --> E[Creates Namespace] + E --> F[Deploys PV/PVC] + F --> G[Deploys MySQL StatefulSet] + G --> H[Deploys Frontend] + H --> I[Creates Service] + +# Key Configuration Details +## Resource Allocation + +Frontend: + +resources: + requests: + cpu: "100m" + memory: "128Mi" + limits: + cpu: "250m" + memory: "256Mi" + + +Database: + +resources: + requests: + cpu: "500m" + memory: "512Mi" + limits: + cpu: "1000m" + memory: "1Gi" + +Backend: + +```yaml +resources: + requests: + cpu: "200m" + memory: "256Mi" + limits: + cpu: "500m" + memory: "512Mi" + +Storage Configuration + +# persistentvolume.yaml +spec: + capacity: + storage: 5Gi + accessModes: + - ReadWriteOnce + hostPath: + path: "/mnt/data/mysql" + + +# Operational Procedures +## Accessing the Application + +Local Development: +minikube service web-app-service -n web-app + +Production Access: +http://:30080 + +Monitoring Commands: +# Check pod status +kubectl get pods -n web-app -w + +# View frontend logs +kubectl logs -n web_app deploy/web-app -f + +# Verify database health +kubectl exec -n web-app mysql-0 -- mysql -uroot -ppassword -e "SHOW DATABASES;" + +# Maintenance Tasks +Scaling Frontend: +kubectl scale -n web-app deployment/web-app --replicas=3 + +Database Backup: +kubectl exec -n web-app mysql-0 -- \ + mysqldump -u root -ppassword taskmanager > backup_$(date +%F).sql + +# Security Notes +Database Credentials: + +Default credentials are for demonstration only + +In production, use: +envFrom: +- secretRef: + name: mysql-credentials + +Network Exposure: +Current: NodePort (30080) +Recommended: Ingress with TLS termination + +# Troubleshooting Guide +Symptom Diagnostic Steps Resolution +Frontend not responding kubectl get svc -n web-app Verify NodePort configuration +Database pod crash loops kubectl describe pod mysql-0 -n web-app Check storage permissions +High CPU usage kubectl top pods -n web-app Adjust resource limits + +Cleanup Procedure +# Full uninstall +./stop-app.sh + +# Optional: Remove persistent data +sudo rm -rf /mnt/data/mysql diff --git a/z2/deployment.yaml b/z2/deployment.yaml new file mode 100644 index 0000000..61c99ee --- /dev/null +++ b/z2/deployment.yaml @@ -0,0 +1,45 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: web-app + namespace: web-app + labels: + app: k8s-task-manager + tier: frontend +spec: + replicas: 2 + selector: + matchLabels: + app: k8s-task-manager + tier: frontend + template: + metadata: + labels: + app: k8s-task-manager + tier: frontend + spec: + containers: + - name: web-app + image: k8s-task-manager-frontend:latest + imagePullPolicy: IfNotPresent + ports: + - containerPort: 80 + resources: + requests: + cpu: "100m" + memory: "128Mi" + limits: + cpu: "250m" + memory: "256Mi" + livenessProbe: + httpGet: + path: / + port: 80 + initialDelaySeconds: 5 + periodSeconds: 10 + readinessProbe: + httpGet: + path: / + port: 80 + initialDelaySeconds: 5 + periodSeconds: 10 diff --git a/z2/index.html b/z2/index.html new file mode 100644 index 0000000..87f9560 --- /dev/null +++ b/z2/index.html @@ -0,0 +1,375 @@ + + + + + + K8s Task Manager + + + + +
+
+

Kubernetes Task Manager

+

Manage your cluster tasks efficiently

+
+
+ +
+
+
+

Cluster Overview

+
+
+
3
+
Nodes
+
+
+
12
+
Pods
+
+
+
5
+
Services
+
+
+
+ +
+

Recent Tasks

+
    +
  • + Deploy new frontend version +
    + + +
    +
  • +
  • + Scale database pods +
    + + +
    +
  • +
  • + Update ingress configuration +
    + + +
    +
  • +
+
+ + +
+
+ +
+

Resource Usage

+
+ + + + CPU + Memory + +
+
+
+
+ + + + + + + + diff --git a/z2/namespace.yaml b/z2/namespace.yaml new file mode 100644 index 0000000..5251413 --- /dev/null +++ b/z2/namespace.yaml @@ -0,0 +1,6 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: web-app + labels: + app: k8s-task-manager diff --git a/z2/nginx.conf b/z2/nginx.conf new file mode 100644 index 0000000..fa79728 --- /dev/null +++ b/z2/nginx.conf @@ -0,0 +1,18 @@ +server { + listen 80; + server_name localhost; + + location / { + root /usr/share/nginx/html; + index index.html; + try_files $uri $uri/ /index.html; + } + + gzip on; + gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript; + + location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ { + expires 1y; + add_header Cache-Control "public, no-transform"; + } +} diff --git a/z2/package.json b/z2/package.json new file mode 100644 index 0000000..eec106d --- /dev/null +++ b/z2/package.json @@ -0,0 +1,12 @@ +{ + "name": "k8s-task-manager-frontend", + "version": "1.0.0", + "description": "Frontend for Kubernetes Task Manager", + "scripts": { + "build": "mkdir -p dist && cp index.html dist/", + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "ISC" +} diff --git a/z2/persistentvolume.yaml b/z2/persistentvolume.yaml new file mode 100644 index 0000000..1aefe34 --- /dev/null +++ b/z2/persistentvolume.yaml @@ -0,0 +1,16 @@ +apiVersion: v1 +kind: PersistentVolume +metadata: + name: mysql-pv + namespace: web-app + labels: + type: local + app: k8s-task-manager +spec: + storageClassName: manual + capacity: + storage: 5Gi + accessModes: + - ReadWriteOnce + hostPath: + path: "/mnt/data/mysql" diff --git a/z2/prepare-app.sh b/z2/prepare-app.sh new file mode 100755 index 0000000..6ec2d02 --- /dev/null +++ b/z2/prepare-app.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +sudo mkdir -p /mnt/data/mysql +sudo chmod 777 -R /mnt/data + +docker build -t k8s-task-manager-frontend:latest -f Dockerfile . + +if command -v minikube &> /dev/null; then + minikube image load k8s-task-manager-frontend:latest +fi + +echo "Kubernetes application preparation complete!" diff --git a/z2/service.yaml b/z2/service.yaml new file mode 100644 index 0000000..258960b --- /dev/null +++ b/z2/service.yaml @@ -0,0 +1,18 @@ +apiVersion: v1 +kind: Service +metadata: + name: web-app-service + namespace: web-app + labels: + app: k8s-task-manager + tier: frontend +spec: + type: NodePort + selector: + app: k8s-task-manager + tier: frontend + ports: + - protocol: TCP + port: 80 + targetPort: 80 + nodePort: 30080 diff --git a/z2/start-app.sh b/z2/start-app.sh new file mode 100755 index 0000000..9404fa3 --- /dev/null +++ b/z2/start-app.sh @@ -0,0 +1,15 @@ +#!/bin/bash + +kubectl apply -f namespace.yaml + +kubectl apply -f persistentvolume.yaml + +kubectl apply -f statefulset.yaml + +kubectl wait --for=condition=ready pod -l app=mysql --timeout=120s -n web-app + +./prepare-app.sh +kubectl apply -f deployment.yaml +kubectl apply -f service.yaml + +echo "Application deployed to Kubernetes!" diff --git a/z2/statefulset.yaml b/z2/statefulset.yaml new file mode 100644 index 0000000..43671f8 --- /dev/null +++ b/z2/statefulset.yaml @@ -0,0 +1,50 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: mysql + namespace: web-app + labels: + app: k8s-task-manager + tier: database +spec: + serviceName: mysql + replicas: 1 + selector: + matchLabels: + app: k8s-task-manager + tier: database + template: + metadata: + labels: + app: k8s-task-manager + tier: database + spec: + containers: + - name: mysql + image: mysql:5.7 + env: + - name: MYSQL_ROOT_PASSWORD + value: "password" + - name: MYSQL_DATABASE + value: "taskmanager" + ports: + - containerPort: 3306 + name: mysql + volumeMounts: + - name: mysql-persistent-storage + mountPath: /var/lib/mysql + resources: + requests: + cpu: "500m" + memory: "512Mi" + limits: + cpu: "1000m" + memory: "1Gi" + volumeClaimTemplates: + - metadata: + name: mysql-persistent-storage + spec: + accessModes: [ "ReadWriteOnce" ] + resources: + requests: + storage: 2Gi diff --git a/z2/stop-app.sh b/z2/stop-app.sh new file mode 100755 index 0000000..1416721 --- /dev/null +++ b/z2/stop-app.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +kubectl delete -f service.yaml +kubectl delete -f deployment.yaml + +kubectl delete -f statefulset.yaml +kubectl delete -f persistentvolume.yaml + +kubectl delete -f namespace.yaml + +echo "Application removed from Kubernetes!"