iT邦幫忙

2024 iThome 鐵人賽

DAY 24
0
Kubernetes

K8s 資料庫管理系統系列 第 24

day 24 k8s奧運資料庫管理系統

  • 分享至 

  • xImage
  •  

今天是第二十四天我們可以寫一個k8s奧運資料庫管理系統,以下是我的程式碼

1. 系統架構

  • MySQL 資料庫:儲存奧運比賽數據,如運動員、比賽結果、國家、比賽年份等。
  • Flask API:提供操作資料庫的接口,讓使用者可以通過 HTTP 請求管理奧運資料。
  • Kubernetes:管理應用程序的部署、擴展和高可用性。

2. 資料庫結構

以下是基本的資料庫設計,包含幾個與奧運會相關的資料表:

CREATE DATABASE olympics;

USE olympics;

CREATE TABLE athletes (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(100) NOT NULL,
    country VARCHAR(100) NOT NULL,
    sport VARCHAR(100) NOT NULL,
    age INT NOT NULL,
    medals INT DEFAULT 0
);

CREATE TABLE events (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(100) NOT NULL,
    year INT NOT NULL,
    location VARCHAR(100) NOT NULL
);

CREATE TABLE results (
    id INT AUTO_INCREMENT PRIMARY KEY,
    athlete_id INT,
    event_id INT,
    result VARCHAR(100) NOT NULL,
    FOREIGN KEY (athlete_id) REFERENCES athletes(id),
    FOREIGN KEY (event_id) REFERENCES events(id)
);

3. Flask API 設計

以下是一個簡單的 Python Flask API,用於管理資料庫中的奧運資料。這個 API 可以被容器化,並在 K8s 中部署。

from flask import Flask, request, jsonify
import mysql.connector

app = Flask(__name__)

# 連接 MySQL 資料庫
def get_db_connection():
    conn = mysql.connector.connect(
        host='mysql',
        user='root',
        password='password',
        database='olympics'
    )
    return conn

# 查詢運動員
@app.route('/athletes', methods=['GET'])
def get_athletes():
    conn = get_db_connection()
    cursor = conn.cursor(dictionary=True)
    cursor.execute('SELECT * FROM athletes')
    athletes = cursor.fetchall()
    cursor.close()
    conn.close()
    return jsonify(athletes)

# 新增運動員
@app.route('/athletes', methods=['POST'])
def add_athlete():
    new_athlete = request.get_json()
    conn = get_db_connection()
    cursor = conn.cursor()
    cursor.execute(
        'INSERT INTO athletes (name, country, sport, age) VALUES (%s, %s, %s, %s)',
        (new_athlete['name'], new_athlete['country'], new_athlete['sport'], new_athlete['age'])
    )
    conn.commit()
    cursor.close()
    conn.close()
    return 'Athlete added!', 201

# 查詢比賽事件
@app.route('/events', methods=['GET'])
def get_events():
    conn = get_db_connection()
    cursor = conn.cursor(dictionary=True)
    cursor.execute('SELECT * FROM events')
    events = cursor.fetchall()
    cursor.close()
    conn.close()
    return jsonify(events)

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)

4. Docker 檔案

將 Flask 應用程式與 MySQL 容器化。這是 Flask API 的 Dockerfile

dockerfile
# 使用 Python 3.9 映像
FROM python:3.9-slim

# 設定工作目錄
WORKDIR /app

# 複製需要的檔案
COPY requirements.txt requirements.txt
COPY app.py app.py

# 安裝必要套件
RUN pip install -r requirements.txt

# 暴露 Flask 的埠號
EXPOSE 5000

# 執行 Flask 應用程式
CMD ["python", "app.py"]

對應的 requirements.txt:

Flask==2.0.2
mysql-connector-python==8.0.26

5. Kubernetes 部署檔案

以下是用於 K8s 的 mysqlflask 的部署與服務定義檔案。

MySQL 部署與服務 (mysql-deployment.yaml):

apiVersion: apps/v1
kind: Deployment
metadata:
  name: mysql
spec:
  selector:
    matchLabels:
      app: mysql
  replicas: 1
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
      - name: mysql
        image: mysql:5.7
        env:
        - name: MYSQL_ROOT_PASSWORD
          value: password
        - name: MYSQL_DATABASE
          value: olympics
        ports:
        - containerPort: 3306
---
apiVersion: v1
kind: Service
metadata:
  name: mysql
spec:
  ports:
    - port: 3306
  selector:
    app: mysql

Flask 部署與服務 (flask-deployment.yaml):

apiVersion: apps/v1
kind: Deployment
metadata:
  name: flask
spec:
  selector:
    matchLabels:
      app: flask
  replicas: 1
  template:
    metadata:
      labels:
        app: flask
    spec:
      containers:
      - name: flask
        image: your-flask-image
        ports:
        - containerPort: 5000
---
apiVersion: v1
kind: Service
metadata:
  name: flask
spec:
  type: LoadBalancer
  ports:
    - port: 5000
      targetPort: 5000
  selector:
    app: flask

6. 部署到 Kubernetes

確保 Kubernetes 環境已經配置好,並且你有 kubectl 訪問權限。接著執行以下命令將系統部署到 Kubernetes:

kubectl apply -f mysql-deployment.yaml
kubectl apply -f flask-deployment.yaml

7. 測試系統

系統成功部署後,使用 kubectl get svc 獲取 Flask 服務的外部 IP,然後可以透過該 IP 和端口測試 API。

範例:

curl http://<FLASK_SERVICE_IP>:5000/athletes

這樣就能取得所有運動員的數據,並可通過 POST 請求新增運動員。

8. 擴展與優化

  • 持久性存儲:使用 Persistent Volume (PV) 和 Persistent Volume Claim (PVC) 來存儲 MySQL 資料庫的數據,避免資料丟失。
  • 自動擴展:配置 Horizontal Pod Autoscaler (HPA) 根據流量自動擴展 Flask 和 MySQL。
  • 安全性:為 API 增加身份驗證機制並加強資料庫訪問的安全性。

1. 資料庫結構

CREATE DATABASE olympics;

USE olympics;

CREATE TABLE athletes (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(100) NOT NULL,
    country VARCHAR(100) NOT NULL,
    sport VARCHAR(100) NOT NULL,
    age INT NOT NULL,
    medals INT DEFAULT 0
);

CREATE TABLE events (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(100) NOT NULL,
    year INT NOT NULL,
    location VARCHAR(100) NOT NULL
);

CREATE TABLE results (
    id INT AUTO_INCREMENT PRIMARY KEY,
    athlete_id INT,
    event_id INT,
    result VARCHAR(100) NOT NULL,
    FOREIGN KEY (athlete_id) REFERENCES athletes(id),
    FOREIGN KEY (event_id) REFERENCES events(id)
);

資料庫結構解釋:

  • athletes: 儲存運動員的資訊,包括他們的姓名 (name)、國家 (country)、運動項目 (sport)、年齡 (age) 以及贏得的獎牌數量 (medals)。

    • id: 每個運動員的唯一識別碼,透過 AUTO_INCREMENT 自動生成。
  • events: 儲存奧運會中的比賽事件,如比賽名稱 (name)、年份 (year) 和舉辦地點 (location)。

  • results: 記錄運動員參與比賽的結果,儲存運動員 ID (athlete_id)、比賽 ID (event_id) 和結果 (result)。

    • athlete_idevent_id 都是外鍵,分別參照 athletesevents 表中的 id

2. Flask API 程式碼

from flask import Flask, request, jsonify
import mysql.connector

app = Flask(__name__)

# 連接 MySQL 資料庫
def get_db_connection():
    conn = mysql.connector.connect(
        host='mysql',
        user='root',
        password='password',
        database='olympics'
    )
    return conn

解釋:

  • Flask 應用Flask 是一個輕量級的 Python Web 框架,用於構建 Web 應用程式。在這裡,我們使用 Flask 構建一個 REST API 來操作奧運資料庫。
  • MySQL 連接mysql.connector.connect() 函數建立與 MySQL 資料庫的連接,連接參數包括 MySQL 容器的主機 (host),使用者 (user),密碼 (password) 以及資料庫名稱 (database)。
# 查詢運動員
@app.route('/athletes', methods=['GET'])
def get_athletes():
    conn = get_db_connection()
    cursor = conn.cursor(dictionary=True)
    cursor.execute('SELECT * FROM athletes')
    athletes = cursor.fetchall()
    cursor.close()
    conn.close()
    return jsonify(athletes)

解釋:

  • 路由與查詢運動員:這個 GET 請求處理 /athletes 路徑,用來查詢所有運動員。當有人發送請求到這個路徑時:
    • get_db_connection() 連接資料庫。
    • 使用 SQL 查詢 'SELECT * FROM athletes' 取得所有運動員的資料。
    • 使用 jsonify() 轉換結果為 JSON 格式,返回給客戶端。
# 新增運動員
@app.route('/athletes', methods=['POST'])
def add_athlete():
    new_athlete = request.get_json()
    conn = get_db_connection()
    cursor = conn.cursor()
    cursor.execute(
        'INSERT INTO athletes (name, country, sport, age) VALUES (%s, %s, %s, %s)',
        (new_athlete['name'], new_athlete['country'], new_athlete['sport'], new_athlete['age'])
    )
    conn.commit()
    cursor.close()
    conn.close()
    return 'Athlete added!', 201

解釋:

  • 新增運動員:這是一個 POST 請求,用於將新的運動員資料插入資料庫。
    • request.get_json() 取得請求的 JSON 資料(即運動員的資料)。
    • 使用 SQL 的 INSERT INTO 語句將新運動員資料插入 athletes 資料表。
    • conn.commit() 確認並保存變更,返回 201 狀態碼(表示資料成功創建)。
# 查詢比賽事件
@app.route('/events', methods=['GET'])
def get_events():
    conn = get_db_connection()
    cursor = conn.cursor(dictionary=True)
    cursor.execute('SELECT * FROM events')
    events = cursor.fetchall()
    cursor.close()
    conn.close()
    return jsonify(events)

解釋:

  • 查詢比賽事件:這是另一個 GET 路由,用於查詢 events 表中的比賽事件資料。與 get_athletes() 類似,這個函數連接資料庫,執行 SQL 查詢並返回結果。
if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)

解釋:

  • 啟動 Flask 應用程式app.run() 用於啟動 Flask 應用,並將其綁定到 0.0.0.0 地址(即允許所有外部 IP 訪問),在 5000 埠上運行。

3. Docker 檔案

dockerfile
# 使用 Python 3.9 映像
FROM python:3.9-slim

# 設定工作目錄
WORKDIR /app

# 複製需要的檔案
COPY requirements.txt requirements.txt
COPY app.py app.py

# 安裝必要套件
RUN pip install -r requirements.txt

# 暴露 Flask 的埠號
EXPOSE 5000

# 執行 Flask 應用程式
CMD ["python", "app.py"]

解釋:

  • Dockerfile 定義了如何將 Flask 應用程式容器化:
    • FROM python:3.9-slim:使用 Python 3.9 的輕量版本作為基礎映像。
    • WORKDIR /app:設定工作目錄為 /app,所有後續操作都會在此目錄下執行。
    • COPY requirements.txt app.py:將 Flask 應用程式的依賴 (requirements.txt) 和應用程式主檔 (app.py) 複製到容器中。
    • RUN pip install -r requirements.txt:安裝應用程式的依賴套件。
    • EXPOSE 5000:暴露 Flask 應用使用的 5000 埠。
    • CMD ["python", "app.py"]:運行 Flask 應用程式。

4. Kubernetes 部署檔案

MySQL 部署 (mysql-deployment.yaml)

apiVersion: apps/v1
kind: Deployment
metadata:
  name: mysql
spec:
  selector:
    matchLabels:
      app: mysql
  replicas: 1
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
      - name: mysql
        image: mysql:5.7
        env:
        - name: MYSQL_ROOT_PASSWORD
          value: password
        - name: MYSQL_DATABASE
          value: olympics
        ports:
        - containerPort: 3306
---
apiVersion: v1
kind: Service
metadata:
  name: mysql
spec:
  ports:
    - port: 3306
  selector:
    app: mysql

解釋:

  • MySQL 部署:這個 Deployment 用來在 Kubernetes 中部署 MySQL 資料庫。
    • replicas 設為 1,表示只需啟動一個 MySQL Pod。
    • env 參數設置了 MySQL 的根密碼以及要創建的資料庫 (olympics)。
    • Service 部分則暴露 MySQL 的 3306 埠號,允許其他應用訪問 MySQL。

Flask 部署 (flask-deployment.yaml)

apiVersion: apps/v1
kind: Deployment
metadata:
  name: flask
spec:
  selector:
    matchLabels:
      app: flask
  replicas: 1
  template:
    metadata:
      labels:
        app: flask
   

 spec:
      containers:
      - name: flask
        image: flask-app:latest
        ports:
        - containerPort: 5000
        env:
        - name: FLASK_ENV
          value: production
---
apiVersion: v1
kind: Service
metadata:
  name: flask
spec:
  ports:
    - port: 5000
  selector:
    app: flask

解釋:

  • Flask 部署:這個 Deployment 用於在 Kubernetes 中部署 Flask 應用程式。
    • 與 MySQL 類似,啟動一個 Flask Pod,並通過 Service 暴露 5000 埠。

總結:

  • 資料庫結構 定義了如何儲存運動員、比賽事件以及結果的關聯。
  • Flask API 提供了查詢和新增資料的端點,並連接到 MySQL 資料庫。
  • Dockerfile 將 Flask 應用程式容器化,方便在不同環境中部署。
  • Kubernetes 部署檔案 負責 MySQL 和 Flask 應用程式的分散式部署與管理。

上一篇
day 23 k8s 音樂庫資料庫管理系統
下一篇
day 25 k8s 財政部稅務資料庫管理系統
系列文
K8s 資料庫管理系統30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言