Assignment 2 Done
This commit is contained in:
parent
c07ce6fcb6
commit
d8e97aaaf7
123
Z2/z2/README.md
Normal file
123
Z2/z2/README.md
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
# Notes App — Kubernetes Deployment
|
||||||
|
|
||||||
|
A simple web application where you can write, view, and delete notes. Built with Flask (Python) and PostgreSQL.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## What the app does
|
||||||
|
|
||||||
|
- Add a note using the text box on the main page
|
||||||
|
- View all saved notes
|
||||||
|
- Delete any note with a button click
|
||||||
|
- Notes are stored in a PostgreSQL database and survive pod restarts
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Containers used
|
||||||
|
|
||||||
|
| Container | Image | Description |
|
||||||
|
|-----------|-------|-------------|
|
||||||
|
| `notes-web` | `notes-web:latest` (built locally) | Flask web app — serves the UI and handles requests |
|
||||||
|
| `postgres` | `postgres:15-alpine` | PostgreSQL database — stores notes |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Kubernetes objects
|
||||||
|
|
||||||
|
| Object | Name | Description |
|
||||||
|
|--------|------|-------------|
|
||||||
|
| Namespace | `notes-app` | Isolates all app objects from other workloads |
|
||||||
|
| Deployment | `notes-web` | Runs 2 replicas of the Flask web app |
|
||||||
|
| StatefulSet | `postgres` | Runs 1 PostgreSQL pod with stable identity |
|
||||||
|
| PersistentVolume | `postgres-pv` | 1Gi volume backed by host path `/mnt/notes-postgres-data` |
|
||||||
|
| PersistentVolumeClaim | `postgres-pvc` | Claims the PV for use by the StatefulSet |
|
||||||
|
| Service (NodePort) | `notes-web-service` | Exposes the web app on port `30080` |
|
||||||
|
| Service (ClusterIP) | `postgres-service` | Internal access to PostgreSQL for the web app |
|
||||||
|
| Service (Headless) | `postgres-headless` | Required by the StatefulSet for stable DNS |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Networking and volumes
|
||||||
|
|
||||||
|
**Services:**
|
||||||
|
- `notes-web-service` — NodePort, exposes port `30080` externally → routes to pod port `5000`
|
||||||
|
- `postgres-service` — ClusterIP, internal only, port `5432` → the web app connects to this
|
||||||
|
- `postgres-headless` — Headless service (no ClusterIP) used by the StatefulSet
|
||||||
|
|
||||||
|
**Volume:**
|
||||||
|
- `postgres-pv` uses a `hostPath` at `/mnt/notes-postgres-data` on the node
|
||||||
|
- Data persists even if the PostgreSQL pod is restarted or recreated
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Container configuration
|
||||||
|
|
||||||
|
**notes-web:**
|
||||||
|
- Environment variables set the database connection: `DB_HOST`, `DB_PORT`, `DB_NAME`, `DB_USER`, `DB_PASS`
|
||||||
|
- `imagePullPolicy: Never` — uses the locally built image (no registry needed)
|
||||||
|
- Runs on port `5000`
|
||||||
|
|
||||||
|
**postgres:**
|
||||||
|
- `POSTGRES_DB`, `POSTGRES_USER`, `POSTGRES_PASSWORD` configure the database on first start
|
||||||
|
- Data directory `/var/lib/postgresql/data` is mounted from the PVC
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## How to use
|
||||||
|
|
||||||
|
### 1. Prepare (build image, create host directory)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
chmod +x prepare-app.sh start-app.sh stop-app.sh show-url.sh
|
||||||
|
./prepare-app.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Start the application
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./start-app.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Open in browser
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./show-url.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
Or open manually:
|
||||||
|
- **Minikube:** `minikube service notes-web-service -n notes-app`
|
||||||
|
- **Other:** `http://<node-ip>:30080`
|
||||||
|
|
||||||
|
### 4. Stop (keep objects, scale down)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl scale deployment notes-web -n notes-app --replicas=0
|
||||||
|
kubectl scale statefulset postgres -n notes-app --replicas=0
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5. Delete everything
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./stop-app.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## File overview
|
||||||
|
|
||||||
|
```
|
||||||
|
z2/
|
||||||
|
├── app/
|
||||||
|
│ ├── app.py # Flask application
|
||||||
|
│ ├── requirements.txt # Python dependencies
|
||||||
|
│ └── Dockerfile # Image definition for notes-web
|
||||||
|
├── namespace.yaml # Namespace: notes-app
|
||||||
|
├── deployment.yaml # Deployment: notes-web (Flask)
|
||||||
|
├── statefulset.yaml # StatefulSet + PV + PVC (PostgreSQL)
|
||||||
|
├── service.yaml # Services: notes-web-service, postgres-service
|
||||||
|
├── prepare-app.sh # Build image, create host directory
|
||||||
|
├── start-app.sh # Apply all Kubernetes objects
|
||||||
|
├── stop-app.sh # Delete all Kubernetes objects
|
||||||
|
├── show-url.sh # Print the URL to open the app
|
||||||
|
└── README.md # This file
|
||||||
|
```
|
||||||
12
Z2/z2/app/Dockerfile
Normal file
12
Z2/z2/app/Dockerfile
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
FROM python:3.11-slim
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
COPY requirements.txt .
|
||||||
|
RUN pip install --no-cache-dir -r requirements.txt
|
||||||
|
|
||||||
|
COPY app.py .
|
||||||
|
|
||||||
|
EXPOSE 5000
|
||||||
|
|
||||||
|
CMD ["python", "app.py"]
|
||||||
111
Z2/z2/app/app.py
Normal file
111
Z2/z2/app/app.py
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
import os
|
||||||
|
import psycopg2
|
||||||
|
from flask import Flask, request, redirect, url_for, render_template_string
|
||||||
|
|
||||||
|
app = Flask(__name__)
|
||||||
|
|
||||||
|
DB_HOST = os.environ.get("DB_HOST", "postgres-service")
|
||||||
|
DB_PORT = os.environ.get("DB_PORT", "5432")
|
||||||
|
DB_NAME = os.environ.get("DB_NAME", "notesdb")
|
||||||
|
DB_USER = os.environ.get("DB_USER", "notesuser")
|
||||||
|
DB_PASS = os.environ.get("DB_PASS", "notespass")
|
||||||
|
|
||||||
|
HTML = """
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Notes App</title>
|
||||||
|
<style>
|
||||||
|
body { font-family: Arial, sans-serif; max-width: 600px; margin: 40px auto; padding: 0 20px; }
|
||||||
|
h1 { color: #333; }
|
||||||
|
form { margin-bottom: 30px; }
|
||||||
|
textarea { width: 100%%; height: 80px; padding: 8px; font-size: 14px; box-sizing: border-box; }
|
||||||
|
button { padding: 8px 20px; background: #0066cc; color: white; border: none; cursor: pointer; font-size: 14px; }
|
||||||
|
button:hover { background: #0052a3; }
|
||||||
|
.note { border: 1px solid #ddd; padding: 12px; margin-bottom: 10px; border-radius: 4px; }
|
||||||
|
.note small { color: #888; }
|
||||||
|
.delete { background: #cc0000; float: right; padding: 4px 10px; font-size: 12px; }
|
||||||
|
.delete:hover { background: #aa0000; }
|
||||||
|
.error { color: red; margin-bottom: 10px; }
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>📝 Notes App</h1>
|
||||||
|
{% if error %}<p class="error">{{ error }}</p>{% endif %}
|
||||||
|
<form method="POST" action="/add">
|
||||||
|
<textarea name="content" placeholder="Write a note..." required></textarea><br><br>
|
||||||
|
<button type="submit">Add Note</button>
|
||||||
|
</form>
|
||||||
|
<h2>Notes ({{ notes|length }})</h2>
|
||||||
|
{% for note in notes %}
|
||||||
|
<div class="note">
|
||||||
|
<form method="POST" action="/delete/{{ note[0] }}" style="display:inline">
|
||||||
|
<button class="delete" type="submit">Delete</button>
|
||||||
|
</form>
|
||||||
|
<p>{{ note[1] }}</p>
|
||||||
|
<small>{{ note[2] }}</small>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
{% if not notes %}<p>No notes yet.</p>{% endif %}
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
"""
|
||||||
|
|
||||||
|
def get_conn():
|
||||||
|
return psycopg2.connect(
|
||||||
|
host=DB_HOST, port=DB_PORT,
|
||||||
|
dbname=DB_NAME, user=DB_USER, password=DB_PASS
|
||||||
|
)
|
||||||
|
|
||||||
|
def init_db():
|
||||||
|
conn = get_conn()
|
||||||
|
cur = conn.cursor()
|
||||||
|
cur.execute("""
|
||||||
|
CREATE TABLE IF NOT EXISTS notes (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
content TEXT NOT NULL,
|
||||||
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||||
|
)
|
||||||
|
""")
|
||||||
|
conn.commit()
|
||||||
|
cur.close()
|
||||||
|
conn.close()
|
||||||
|
|
||||||
|
@app.route("/")
|
||||||
|
def index():
|
||||||
|
try:
|
||||||
|
init_db()
|
||||||
|
conn = get_conn()
|
||||||
|
cur = conn.cursor()
|
||||||
|
cur.execute("SELECT id, content, created_at FROM notes ORDER BY created_at DESC")
|
||||||
|
notes = cur.fetchall()
|
||||||
|
cur.close()
|
||||||
|
conn.close()
|
||||||
|
return render_template_string(HTML, notes=notes, error=None)
|
||||||
|
except Exception as e:
|
||||||
|
return render_template_string(HTML, notes=[], error=f"DB error: {e}")
|
||||||
|
|
||||||
|
@app.route("/add", methods=["POST"])
|
||||||
|
def add():
|
||||||
|
content = request.form.get("content", "").strip()
|
||||||
|
if content:
|
||||||
|
conn = get_conn()
|
||||||
|
cur = conn.cursor()
|
||||||
|
cur.execute("INSERT INTO notes (content) VALUES (%s)", (content,))
|
||||||
|
conn.commit()
|
||||||
|
cur.close()
|
||||||
|
conn.close()
|
||||||
|
return redirect(url_for("index"))
|
||||||
|
|
||||||
|
@app.route("/delete/<int:note_id>", methods=["POST"])
|
||||||
|
def delete(note_id):
|
||||||
|
conn = get_conn()
|
||||||
|
cur = conn.cursor()
|
||||||
|
cur.execute("DELETE FROM notes WHERE id = %s", (note_id,))
|
||||||
|
conn.commit()
|
||||||
|
cur.close()
|
||||||
|
conn.close()
|
||||||
|
return redirect(url_for("index"))
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
app.run(host="0.0.0.0", port=5000)
|
||||||
2
Z2/z2/app/requirements.txt
Normal file
2
Z2/z2/app/requirements.txt
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
flask==3.0.0
|
||||||
|
psycopg2-binary==2.9.9
|
||||||
34
Z2/z2/deployment.yaml
Normal file
34
Z2/z2/deployment.yaml
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: notes-web
|
||||||
|
namespace: notes-app
|
||||||
|
labels:
|
||||||
|
app: notes-web
|
||||||
|
spec:
|
||||||
|
replicas: 2
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: notes-web
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: notes-web
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: notes-web
|
||||||
|
image: notes-web:latest
|
||||||
|
imagePullPolicy: Never
|
||||||
|
ports:
|
||||||
|
- containerPort: 5000
|
||||||
|
env:
|
||||||
|
- name: DB_HOST
|
||||||
|
value: "postgres-service"
|
||||||
|
- name: DB_PORT
|
||||||
|
value: "5432"
|
||||||
|
- name: DB_NAME
|
||||||
|
value: "notesdb"
|
||||||
|
- name: DB_USER
|
||||||
|
value: "notesuser"
|
||||||
|
- name: DB_PASS
|
||||||
|
value: "notespass"
|
||||||
4
Z2/z2/namespace.yaml
Normal file
4
Z2/z2/namespace.yaml
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: notes-app
|
||||||
134
Z2/z2/port-forward.log
Normal file
134
Z2/z2/port-forward.log
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
nohup: ignoring input
|
||||||
|
Unable to listen on port 8080: Listeners failed to create with the following errors: [unable to create listener: Error listen tcp4 1Handling connection for 8080
|
||||||
|
Handling connection for 8080
|
||||||
|
E0422 08:15:48.485727 143453 portforward.go:424] "Unhandled Error" err="an error occurred forwarding 8080 -> 5000: error forwarding port 5000 to pod 4ee1b087afb63a44c5fc2569518897054db6a76a1f05c60e69cb7fba21218b5f, uid : Error response from daemon: No such container: 4ee1b087afb63a44c5fc2569518897054db6a76a1f05c60e69cb7fba21218b5f"
|
||||||
|
E0422 08:15:48.485729 143453 portforward.go:424] "Unhandled Error" err="an error occurred forwarding 8080 -> 5000: error forwarding port 5000 to pod 4ee1b087afb63a44c5fc2569518897054db6a76a1f05c60e69cb7fba21218b5f, uid : Error response from daemon: No such container: 4ee1b087afb63a44c5fc2569518897054db6a76a1f05c60e69cb7fba21218b5f"
|
||||||
|
error: lost connection to pod
|
||||||
|
s "notes-web-service" not found
|
||||||
|
port-forward crashed, retrying in 2s...
|
||||||
|
Error from server (NotFound): services "notes-web-service" not found
|
||||||
|
port-forward crashed, retrying in 2s...
|
||||||
|
Error from server (NotFound): services "notes-web-service" not found
|
||||||
|
port-forward crashed, retrying in 2s...
|
||||||
|
Error from server (NotFound): services "notes-web-service" not found
|
||||||
|
port-forward crashed, retrying in 2s...
|
||||||
|
Error from server (NotFound): services "notes-web-service" not found
|
||||||
|
port-forward crashed, retrying in 2s...
|
||||||
|
Error from server (NotFound): services "notes-web-service" not found
|
||||||
|
port-forward crashed, retrying in 2s...
|
||||||
|
Error from server (NotFound): services "notes-web-service" not found
|
||||||
|
port-forward crashed, retrying in 2s...
|
||||||
|
Error from server (NotFound): services "notes-web-service" not found
|
||||||
|
port-forward crashed, retrying in 2s...
|
||||||
|
Error from server (NotFound): services "notes-web-service" not found
|
||||||
|
port-forward crashed, retrying in 2s...
|
||||||
|
Error from server (NotFound): services "notes-web-service" not found
|
||||||
|
port-forward crashed, retrying in 2s...
|
||||||
|
Error from server (NotFound): services "notes-web-service" not found
|
||||||
|
port-forward crashed, retrying in 2s...
|
||||||
|
Error from server (NotFound): services "notes-web-service" not found
|
||||||
|
port-forward crashed, retrying in 2s...
|
||||||
|
Error from server (NotFound): services "notes-web-service" not found
|
||||||
|
port-forward crashed, retrying in 2s...
|
||||||
|
Error from server (NotFound): services "notes-web-service" not found
|
||||||
|
port-forward crashed, retrying in 2s...
|
||||||
|
Error from server (NotFound): services "notes-web-service" not found
|
||||||
|
port-forward crashed, retrying in 2s...
|
||||||
|
Error from server (NotFound): services "notes-web-service" not found
|
||||||
|
port-forward crashed, retrying in 2s...
|
||||||
|
Error from server (NotFound): services "notes-web-service" not found
|
||||||
|
port-forward crashed, retrying in 2s...
|
||||||
|
Error from server (NotFound): services "notes-web-service" not found
|
||||||
|
port-forward crashed, retrying in 2s...
|
||||||
|
Error from server (NotFound): services "notes-web-service" not found
|
||||||
|
port-forward crashed, retrying in 2s...
|
||||||
|
Error from server (NotFound): namespaces "notes-app" not found
|
||||||
|
port-forward crashed, retrying in 2s...
|
||||||
|
Error from server (NotFound): namespaces "notes-app" not found
|
||||||
|
port-forward crashed, retrying in 2s...
|
||||||
|
Error from server (NotFound): namespaces "notes-app" not found
|
||||||
|
port-forward crashed, retrying in 2s...
|
||||||
|
Error from server (NotFound): namespaces "notes-app" not found
|
||||||
|
port-forward crashed, retrying in 2s...
|
||||||
|
Error from server (NotFound): namespaces "notes-app" not found
|
||||||
|
port-forward crashed, retrying in 2s...
|
||||||
|
Error from server (NotFound): namespaces "notes-app" not found
|
||||||
|
port-forward crashed, retrying in 2s...
|
||||||
|
Error from server (NotFound): namespaces "notes-app" not found
|
||||||
|
port-forward crashed, retrying in 2s...
|
||||||
|
Error from server (NotFound): namespaces "notes-app" not found
|
||||||
|
port-forward crashed, retrying in 2s...
|
||||||
|
Error from server (NotFound): namespaces "notes-app" not found
|
||||||
|
port-forward crashed, retrying in 2s...
|
||||||
|
Error from server (NotFound): namespaces "notes-app" not found
|
||||||
|
port-forward crashed, retrying in 2s...
|
||||||
|
Error from server (NotFound): namespaces "notes-app" not found
|
||||||
|
port-forward crashed, retrying in 2s...
|
||||||
|
Error from server (NotFound): namespaces "notes-app" not found
|
||||||
|
port-forward crashed, retrying in 2s...
|
||||||
|
Error from server (NotFound): namespaces "notes-app" not found
|
||||||
|
port-forward crashed, retrying in 2s...
|
||||||
|
Error from server (NotFound): namespaces "notes-app" not found
|
||||||
|
port-forward crashed, retrying in 2s...
|
||||||
|
Error from server (NotFound): namespaces "notes-app" not found
|
||||||
|
port-forward crashed, retrying in 2s...
|
||||||
|
Error from server (NotFound): namespaces "notes-app" not found
|
||||||
|
port-forward crashed, retrying in 2s...
|
||||||
|
Error from server (NotFound): namespaces "notes-app" not found
|
||||||
|
port-forward crashed, retrying in 2s...
|
||||||
|
Error from server (NotFound): namespaces "notes-app" not found
|
||||||
|
port-forward crashed, retrying in 2s...
|
||||||
|
Error from server (NotFound): namespaces "notes-app" not found
|
||||||
|
port-forward crashed, retrying in 2s...
|
||||||
|
Error from server (NotFound): namespaces "notes-app" not found
|
||||||
|
port-forward crashed, retrying in 2s...
|
||||||
|
Error from server (NotFound): namespaces "notes-app" not found
|
||||||
|
port-forward crashed, retrying in 2s...
|
||||||
|
Error from server (NotFound): namespaces "notes-app" not found
|
||||||
|
port-forward crashed, retrying in 2s...
|
||||||
|
Error from server (NotFound): namespaces "notes-app" not found
|
||||||
|
port-forward crashed, retrying in 2s...
|
||||||
|
Error from server (NotFound): namespaces "notes-app" not found
|
||||||
|
port-forward crashed, retrying in 2s...
|
||||||
|
Error from server (NotFound): namespaces "notes-app" not found
|
||||||
|
port-forward crashed, retrying in 2s...
|
||||||
|
Error from server (NotFound): namespaces "notes-app" not found
|
||||||
|
port-forward crashed, retrying in 2s...
|
||||||
|
Error from server (NotFound): namespaces "notes-app" not found
|
||||||
|
port-forward crashed, retrying in 2s...
|
||||||
|
Error from server (NotFound): namespaces "notes-app" not found
|
||||||
|
port-forward crashed, retrying in 2s...
|
||||||
|
Error from server (NotFound): namespaces "notes-app" not found
|
||||||
|
port-forward crashed, retrying in 2s...
|
||||||
|
Error from server (NotFound): namespaces "notes-app" not found
|
||||||
|
port-forward crashed, retrying in 2s...
|
||||||
|
Error from server (NotFound): namespaces "notes-app" not found
|
||||||
|
port-forward crashed, retrying in 2s...
|
||||||
|
Error from server (NotFound): namespaces "notes-app" not found
|
||||||
|
port-forward crashed, retrying in 2s...
|
||||||
|
Error from server (NotFound): namespaces "notes-app" not found
|
||||||
|
port-forward crashed, retrying in 2s...
|
||||||
|
Error from server (NotFound): namespaces "notes-app" not found
|
||||||
|
port-forward crashed, retrying in 2s...
|
||||||
|
Error from server (NotFound): services "notes-web-service" not found
|
||||||
|
port-forward crashed, retrying in 2s...
|
||||||
|
Error from server (NotFound): services "notes-web-service" not found
|
||||||
|
port-forward crashed, retrying in 2s...
|
||||||
|
error: unable to forward port because pod is not running. Current status=Pending
|
||||||
|
port-forward crashed, retrying in 2s...
|
||||||
|
Unable to listen on port 8080: Listeners failed to create with the following errors: [unable to create listener: Error listen tcp4 127.0.0.1:8080: bind: address already in use unable to create listener: Error listen tcp6 [::1]:8080: bind: address already in use]
|
||||||
|
error: unable to listen on any of the requested ports: [{8080 5000}]
|
||||||
|
port-forward crashed, retrying in 2s...
|
||||||
|
Unable to listen on port 8080: Listeners failed to create with the following errors: [unable to create listener: Error listen tcp4 127.0.0.1:8080: bind: address already in use unable to create listener: Error listen tcp6 [::1]:8080: bind: address already in use]
|
||||||
|
error: unable to listen on any of the requested ports: [{8080 5000}]
|
||||||
|
port-forward crashed, retrying in 2s...
|
||||||
|
Forwarding from 127.0.0.1:8080 -> 5000
|
||||||
|
Forwarding from [::1]:8080 -> 5000
|
||||||
|
Handling connection for 8080
|
||||||
|
Handling connection for 8080
|
||||||
|
Handling connection for 8080
|
||||||
|
Handling connection for 8080
|
||||||
|
Handling connection for 8080
|
||||||
|
Handling connection for 8080
|
||||||
|
Handling connection for 8080
|
||||||
|
E0422 08:16:00.690760 146224 portforward.go:404] "Unhandled Error" err="error copying from local connection to remote stream: writeto tcp6 [::1]:8080->[::1]:39644: read tcp6 [::1]:8080->[::1]:39644: read: connection reset by peer"
|
||||||
20
Z2/z2/prepare-app.sh
Normal file
20
Z2/z2/prepare-app.sh
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
echo "==> Building Docker image for notes-web..."
|
||||||
|
docker build -t notes-web:latest ./app
|
||||||
|
|
||||||
|
echo "==> Loading image into Minikube (if using Minikube)..."
|
||||||
|
if command -v minikube &>/dev/null; then
|
||||||
|
minikube image load notes-web:latest
|
||||||
|
echo " Image loaded into Minikube."
|
||||||
|
else
|
||||||
|
echo " Minikube not found, skipping image load."
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "==> Creating host directory for PersistentVolume..."
|
||||||
|
sudo mkdir -p /mnt/notes-postgres-data
|
||||||
|
sudo chmod 777 /mnt/notes-postgres-data
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Preparation complete. Run ./start-app.sh to start the application."
|
||||||
27
Z2/z2/service.yaml
Normal file
27
Z2/z2/service.yaml
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: notes-web-service
|
||||||
|
namespace: notes-app
|
||||||
|
spec:
|
||||||
|
type: NodePort
|
||||||
|
selector:
|
||||||
|
app: notes-web
|
||||||
|
ports:
|
||||||
|
- port: 80
|
||||||
|
targetPort: 5000
|
||||||
|
nodePort: 30080
|
||||||
|
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: postgres-service
|
||||||
|
namespace: notes-app
|
||||||
|
spec:
|
||||||
|
type: ClusterIP
|
||||||
|
selector:
|
||||||
|
app: postgres
|
||||||
|
ports:
|
||||||
|
- port: 5432
|
||||||
|
targetPort: 5432
|
||||||
9
Z2/z2/show-url.sh
Normal file
9
Z2/z2/show-url.sh
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
if command -v minikube &>/dev/null; then
|
||||||
|
echo "==> Minikube detected. Opening service URL..."
|
||||||
|
minikube service notes-web-service -n notes-app --url
|
||||||
|
else
|
||||||
|
NODE_IP=$(kubectl get nodes -o jsonpath='{.items[0].status.addresses[?(@.type=="InternalIP")].address}')
|
||||||
|
echo "==> App available at: http://${NODE_IP}:30080"
|
||||||
|
fi
|
||||||
24
Z2/z2/start-app.sh
Normal file
24
Z2/z2/start-app.sh
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
echo "==> Creating Namespace..."
|
||||||
|
kubectl apply -f namespace.yaml
|
||||||
|
|
||||||
|
echo "==> Creating PersistentVolume, PersistentVolumeClaim and StatefulSet (PostgreSQL)..."
|
||||||
|
kubectl apply -f statefulset.yaml
|
||||||
|
|
||||||
|
echo "==> Waiting for PostgreSQL to be ready..."
|
||||||
|
kubectl rollout status statefulset/postgres -n notes-app --timeout=120s
|
||||||
|
|
||||||
|
echo "==> Creating Deployment (Notes web app)..."
|
||||||
|
kubectl apply -f deployment.yaml
|
||||||
|
|
||||||
|
echo "==> Creating Services..."
|
||||||
|
kubectl apply -f service.yaml
|
||||||
|
|
||||||
|
echo "==> Waiting for web app to be ready..."
|
||||||
|
kubectl rollout status deployment/notes-web -n notes-app --timeout=120s
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Application is running."
|
||||||
|
echo "Run ./show-url.sh or see README.md for how to open the app in your browser."
|
||||||
79
Z2/z2/statefulset.yaml
Normal file
79
Z2/z2/statefulset.yaml
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolume
|
||||||
|
metadata:
|
||||||
|
name: postgres-pv
|
||||||
|
namespace: notes-app
|
||||||
|
spec:
|
||||||
|
capacity:
|
||||||
|
storage: 1Gi
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteOnce
|
||||||
|
persistentVolumeReclaimPolicy: Retain
|
||||||
|
storageClassName: manual
|
||||||
|
hostPath:
|
||||||
|
path: /mnt/notes-postgres-data
|
||||||
|
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
metadata:
|
||||||
|
name: postgres-pvc
|
||||||
|
namespace: notes-app
|
||||||
|
spec:
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteOnce
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: 1Gi
|
||||||
|
storageClassName: manual
|
||||||
|
|
||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: StatefulSet
|
||||||
|
metadata:
|
||||||
|
name: postgres
|
||||||
|
namespace: notes-app
|
||||||
|
spec:
|
||||||
|
serviceName: postgres-headless
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: postgres
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: postgres
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: postgres
|
||||||
|
image: postgres:15-alpine
|
||||||
|
ports:
|
||||||
|
- containerPort: 5432
|
||||||
|
env:
|
||||||
|
- name: POSTGRES_DB
|
||||||
|
value: "notesdb"
|
||||||
|
- name: POSTGRES_USER
|
||||||
|
value: "notesuser"
|
||||||
|
- name: POSTGRES_PASSWORD
|
||||||
|
value: "notespass"
|
||||||
|
volumeMounts:
|
||||||
|
- name: postgres-storage
|
||||||
|
mountPath: /var/lib/postgresql/data
|
||||||
|
volumes:
|
||||||
|
- name: postgres-storage
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: postgres-pvc
|
||||||
|
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: postgres-headless
|
||||||
|
namespace: notes-app
|
||||||
|
spec:
|
||||||
|
clusterIP: None
|
||||||
|
selector:
|
||||||
|
app: postgres
|
||||||
|
ports:
|
||||||
|
- port: 5432
|
||||||
|
targetPort: 5432
|
||||||
26
Z2/z2/status.sh
Normal file
26
Z2/z2/status.sh
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
echo -e "\n\033[1;34m=== CLUSTER STATUS REPORT ===\033[0m"
|
||||||
|
date
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "=== NAMESPACE ==="
|
||||||
|
kubectl get namespace notes-app
|
||||||
|
|
||||||
|
echo "=== DEPLOYMENT ==="
|
||||||
|
kubectl get deployment -n notes-app
|
||||||
|
|
||||||
|
echo "=== STATEFULSET ==="
|
||||||
|
kubectl get statefulset -n notes-app
|
||||||
|
|
||||||
|
echo "=== PV ==="
|
||||||
|
kubectl get pv postgres-pv
|
||||||
|
|
||||||
|
echo "=== PVC ==="
|
||||||
|
kubectl get pvc -n notes-app
|
||||||
|
|
||||||
|
echo "=== SERVICES ==="
|
||||||
|
kubectl get svc -n notes-app
|
||||||
|
|
||||||
|
echo "=== PODS ==="
|
||||||
|
kubectl get pods -n notes-app -o wide
|
||||||
12
Z2/z2/stop-app.sh
Normal file
12
Z2/z2/stop-app.sh
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
echo "==> Deleting all objects in namespace notes-app..."
|
||||||
|
kubectl delete -f service.yaml --ignore-not-found
|
||||||
|
kubectl delete -f deployment.yaml --ignore-not-found
|
||||||
|
kubectl delete -f statefulset.yaml --ignore-not-found
|
||||||
|
kubectl delete -f namespace.yaml --ignore-not-found
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "All Kubernetes objects removed."
|
||||||
|
echo "Note: The host directory /mnt/notes-postgres-data was NOT deleted."
|
||||||
|
echo "To also remove it, run: sudo rm -rf /mnt/notes-postgres-data"
|
||||||
Loading…
Reference in New Issue
Block a user