今天是第二十二天我們可以寫一個k8s選課資料庫管理系統,以下是我的程式碼
創建一個 mysql-deployment.yaml 檔案來部署 MySQL。
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mysql-pv-claim
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mysql
spec:
  selector:
    matchLabels:
      app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
      - name: mysql
        image: mysql:5.7
        env:
        - name: MYSQL_ROOT_PASSWORD
          value: "password"
        - name: MYSQL_DATABASE
          value: "course_db"
        - name: MYSQL_USER
          value: "admin"
        - name: MYSQL_PASSWORD
          value: "password"
        ports:
        - containerPort: 3306
        volumeMounts:
        - name: mysql-persistent-storage
          mountPath: /var/lib/mysql
      volumes:
      - name: mysql-persistent-storage
        persistentVolumeClaim:
          claimName: mysql-pv-claim
---
apiVersion: v1
kind: Service
metadata:
  name: mysql
spec:
  ports:
    - port: 3306
  selector:
    app: mysql
創建一個簡單的 Flask API,與 MySQL 互動。首先,撰寫 app.py:
from flask import Flask, request, jsonify
import mysql.connector
app = Flask(__name__)
def get_db_connection():
    conn = mysql.connector.connect(
        host='mysql',  # Kubernetes 服務名稱
        user='admin',
        password='password',
        database='course_db'
    )
    return conn
@app.route('/courses', methods=['GET'])
def get_courses():
    conn = get_db_connection()
    cursor = conn.cursor()
    cursor.execute('SELECT * FROM courses')
    courses = cursor.fetchall()
    cursor.close()
    conn.close()
    return jsonify(courses)
@app.route('/enroll', methods=['POST'])
def enroll_course():
    student_id = request.json['student_id']
    course_id = request.json['course_id']
    conn = get_db_connection()
    cursor = conn.cursor()
    cursor.execute('INSERT INTO enrollments (student_id, course_id) VALUES (%s, %s)', (student_id, course_id))
    conn.commit()
    cursor.close()
    conn.close()
    return 'Enrolled successfully!', 201
if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)
創建 Dockerfile 來打包 Flask API:
FROM python:3.8-slim
WORKDIR /app
COPY requirements.txt requirements.txt
RUN pip install -r requirements.txt
COPY . .
CMD ["python", "app.py"]
requirements.txt:
Flask
mysql-connector-python
接著,創建 flask-deployment.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
  name: flask-api
spec:
  selector:
    matchLabels:
      app: flask-api
  template:
    metadata:
      labels:
        app: flask-api
    spec:
      containers:
      - name: flask-api
        image: your-dockerhub-username/flask-api:latest
        ports:
        - containerPort: 5000
---
apiVersion: v1
kind: Service
metadata:
  name: flask-api
spec:
  ports:
    - port: 5000
  selector:
    app: flask-api
創建一個簡單的 index.html:
<!DOCTYPE html>
<html>
<head>
    <title>選課系統</title>
</head>
<body>
    <h1>選課系統</h1>
    <form id="enrollForm">
        學生 ID: <input type="text" id="student_id"><br><br>
        課程 ID: <input type="text" id="course_id"><br><br>
        <button type="submit">選課</button>
    </form>
    <h2>已選課程</h2>
    <ul id="coursesList"></ul>
    <script>
        document.getElementById('enrollForm').onsubmit = function(event) {
            event.preventDefault();
            const studentId = document.getElementById('student_id').value;
            const courseId = document.getElementById('course_id').value;
            fetch('/enroll', {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ student_id: studentId, course_id: courseId })
            })
            .then(response => response.text())
            .then(data => alert(data));
        };
        fetch('/courses')
            .then(response => response.json())
            .then(courses => {
                const coursesList = document.getElementById('coursesList');
                courses.forEach(course => {
                    const li = document.createElement('li');
                    li.textContent = `課程 ID: ${course[0]}, 課程名稱: ${course[1]}`;
                    coursesList.appendChild(li);
                });
            });
    </script>
</body>
</html>
將此前端部署在 Nginx 上,並創建 nginx-deployment.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
  name: frontend
spec:
  selector:
    matchLabels:
      app: frontend
  template:
    metadata:
      labels:
        app: frontend
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        volumeMounts:
        - name: html
          mountPath: /usr/share/nginx/html
      volumes:
      - name: html
        configMap:
          name: frontend-html
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: frontend-html
data:
  index.html: |
    # (Paste index.html content here)
---
apiVersion: v1
kind: Service
metadata:
  name: frontend
spec:
  ports:
    - port: 80
  selector:
    app: frontend
運行以下指令將部署所有服務:
kubectl apply -f mysql-deployment.yaml
kubectl apply -f flask-deployment.yaml
kubectl apply -f nginx-deployment.yaml
這樣,Kubernetes 就會運行選課系統,前端透過 Nginx 提供服務,後端 Flask API 處理選課請求,並與 MySQL 進行互動。
在 mysql-deployment.yaml 中,定義了 MySQL 資料庫的 Kubernetes 資源。這裡主要包含以下幾個部分:
這段程式碼是用來申請一塊持久性存儲空間,用於 MySQL 存儲資料。
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mysql-pv-claim
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi
PersistentVolumeClaim (PVC):它用來請求一塊 10GB 的持久存儲。這塊存儲將會被用來保存 MySQL 資料庫的數據,即使 Pod 被重啟,數據也不會丟失。accessModes:設置為 ReadWriteOnce,表示這塊存儲可以被一個節點讀寫。MySQL 被打包成一個容器,這裡通過 Deployment 創建和管理 MySQL Pod。
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mysql
spec:
  selector:
    matchLabels:
      app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
      - name: mysql
        image: mysql:5.7
        env:
        - name: MYSQL_ROOT_PASSWORD
          value: "password"
        - name: MYSQL_DATABASE
          value: "course_db"
        - name: MYSQL_USER
          value: "admin"
        - name: MYSQL_PASSWORD
          value: "password"
        ports:
        - containerPort: 3306
        volumeMounts:
        - name: mysql-persistent-storage
          mountPath: /var/lib/mysql
      volumes:
      - name: mysql-persistent-storage
        persistentVolumeClaim:
          claimName: mysql-pv-claim
Deployment:定義了 MySQL 容器的部署,管理 MySQL 的 Pod。image: mysql:5.7:指定 MySQL 的 Docker 鏡像版本。env:環境變量,用來設定 MySQL 的 root 密碼、資料庫名稱以及用戶憑證。volumeMounts:將 PVC 持久化存儲掛載到容器內 /var/lib/mysql 目錄,這是 MySQL 存放數據的地方。apiVersion: v1
kind: Service
metadata:
  name: mysql
spec:
  ports:
    - port: 3306
  selector:
    app: mysql
Service:定義了如何對外暴露 MySQL 服務,讓其他 Pod(如 Flask API)可以通過 Kubernetes 的內部 DNS 名稱(mysql)來訪問資料庫。port: 3306:指定 MySQL 使用的默認端口。Flask API 是一個簡單的應用,它用來與 MySQL 資料庫互動,處理選課相關的操作。
from flask import Flask, request, jsonify
import mysql.connector
app = Flask(__name__)
Flask:引入 Flask 框架來處理 HTTP 請求。mysql.connector:用來與 MySQL 資料庫連接。app = Flask(__name__):初始化 Flask 應用,並且可以設定各種路由。def get_db_connection():
    conn = mysql.connector.connect(
        host='mysql',  # Kubernetes 服務名稱
        user='admin',
        password='password',
        database='course_db'
    )
    return conn
get_db_connection():用來建立與 MySQL 資料庫的連接。host='mysql' 表示 MySQL 是通過 Kubernetes 的內部 DNS 名稱來訪問。user、password、database:與 MySQL 連接所需的憑證。@app.route('/courses', methods=['GET'])
def get_courses():
    conn = get_db_connection()
    cursor = conn.cursor()
    cursor.execute('SELECT * FROM courses')
    courses = cursor.fetchall()
    cursor.close()
    conn.close()
    return jsonify(courses)
@app.route('/courses', methods=['GET']):定義了一個 GET 請求的 API,URL 是 /courses。這個 API 會查詢所有課程。cursor.execute('SELECT * FROM courses'):從 courses 資料表中查詢所有課程。jsonify(courses):將查詢結果轉換成 JSON 格式,回傳給客戶端。@app.route('/enroll', methods=['POST'])
def enroll_course():
    student_id = request.json['student_id']
    course_id = request.json['course_id']
    conn = get_db_connection()
    cursor = conn.cursor()
    cursor.execute('INSERT INTO enrollments (student_id, course_id) VALUES (%s, %s)', (student_id, course_id))
    conn.commit()
    cursor.close()
    conn.close()
    return 'Enrolled successfully!', 201
@app.route('/enroll', methods=['POST']):定義了一個 POST 請求的 API,URL 是 /enroll。這個 API 用來讓學生選課。student_id 和 course_id:從請求中提取學生和課程的 ID。INSERT INTO enrollments (student_id, course_id):將選課資訊插入到 enrollments 資料表中。前端是一個簡單的 HTML 頁面,通過 JavaScript 與 Flask API 互動。
<form id="enrollForm">
    學生 ID: <input type="text" id="student_id"><br><br>
    課程 ID: <input type="text" id="course_id"><br><br>
    <button type="submit">選課</button>
</form>
document.getElementById('enrollForm').onsubmit = function(event) {
    event.preventDefault();
    const studentId = document.getElementById('student_id').value;
    const courseId = document.getElementById('course_id').value;
    fetch('/enroll', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ student_id: studentId, course_id: courseId })
    })
    .then(response => response.text())
    .then(data => alert(data));
};
onsubmit:攔截表單的提交動作。fetch('/enroll', ...):向 /enroll API 發送 POST 請求,將選課資訊發送到伺服器。JSON.stringify():將 JavaScript 對象轉換為 JSON 格式,發送至後端。fetch('/courses')
    .then(response => response.json())
    .then(courses => {
        const coursesList = document.getElementById('coursesList');
        courses.forEach(course => {
            const li = document.createElement('li');
            li.textContent = `課程 ID: ${course[0]}, 課程名稱: ${course[1]}`;
            coursesList.appendChild(li);
        });
    });
fetch('/courses'):向 /courses API 發送 GET 請求,取得所有課程。前端的 HTML 和 JavaScript 被 Nginx 提供服務。
apiVersion: apps/v1
kind: Deployment
metadata:
  name: frontend
spec:
  selector:
    matchLabels:
      app: frontend
  template:
    metadata:
      labels:
        app: frontend
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        volumeMounts:
        - name: html
          mountPath: /usr/share/nginx/html
      volumes:
      - name: html
        configMap:
          name: frontend-html
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: frontend-html
data:
  index.html: |
    <!-- HTML 文件內容 -->
---
apiVersion: v1
kind: Service
metadata:
  name: frontend
spec:
  ports:
    - port: 80
  selector:
    app: frontend
nginx:用來提供靜態 HTML 文件服務。ConfigMap:將 index.html 內容儲存在 ConfigMap 中,並掛載到 Nginx 容器的 /usr/share/nginx/html 目錄下。Service:對外暴露 Nginx 服務,使用默認的 HTTP 端口 80。這個系統是一個簡單的選課系統,前端通過 Nginx 提供靜態頁面服務,後端 Flask API 用來處理資料庫操作,MySQL 資料庫存放課程和選課信息。每個部分都通過 Kubernetes 來管理和調度,使應用能夠在容器化環境中運行。