iT邦幫忙

2024 iThome 鐵人賽

DAY 15
0
Kubernetes

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

day 12 K8s租車公司資料庫管理系統

  • 分享至 

  • xImage
  •  

今天是第十二天我們可以寫一個k8s租車公司資料庫管理系統,以下是我的程式碼

  1. 資料庫 (Database): 一個 MySQL 或 PostgreSQL 資料庫,用於儲存租車公司業務的關鍵數據,如客戶資訊、車輛、租賃訂單等。
  2. 應用程式 (Application): 用於與資料庫互動的後端 API 和管理界面。
  3. Kubernetes 部署 (Kubernetes Deployment): 用於在 K8s 集群上管理這些應用程式和資料庫。

1. 資料庫 (MySQL) Kubernetes 部署範例

首先,建立一個 MySQL 資料庫來儲存租車公司的數據。你可以使用一個 MySQL Helm chart 或直接編寫一個 Kubernetes 的 StatefulSet 部署。

MySQL 部署範例 (mysql-deployment.yaml)

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: mysql
  labels:
    app: mysql
spec:
  serviceName: "mysql"
  replicas: 1
  selector:
    matchLabels:
      app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
      - name: mysql
        image: mysql:5.7
        env:
        - name: MYSQL_ROOT_PASSWORD
          value: "password123"
        - name: MYSQL_DATABASE
          value: "rentaldb"
        ports:
        - containerPort: 3306
          name: mysql
        volumeMounts:
        - name: mysql-persistent-storage
          mountPath: /var/lib/mysql
  volumeClaimTemplates:
  - metadata:
      name: mysql-persistent-storage
    spec:
      accessModes: [ "ReadWriteOnce" ]
      resources:
        requests:
          storage: 5Gi

這個 StatefulSet 定義了一個 MySQL 5.7 容器,並附帶了一個持久的儲存卷(Persistent Volume)來保存資料。你可以在 MYSQL_DATABASE 環境變數中指定租車公司的數據庫名稱。

2. 應用程式後端 (Flask + Python) Docker 化

後端服務可以使用 Python 的 Flask 框架來處理 API 請求,並與資料庫互動。這個範例展示了如何將一個 Flask 應用程式容器化。

Flask 應用程式範例 (app.py)

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

app = Flask(__name__)

def get_db_connection():
    connection = mysql.connector.connect(
        host="mysql",  # MySQL 服務名稱
        user="root",
        password="password123",
        database="rentaldb"
    )
    return connection

@app.route('/cars', methods=['GET'])
def get_cars():
    conn = get_db_connection()
    cursor = conn.cursor(dictionary=True)
    cursor.execute('SELECT * FROM cars')
    cars = cursor.fetchall()
    cursor.close()
    conn.close()
    return jsonify(cars)

@app.route('/rent', methods=['POST'])
def rent_car():
    conn = get_db_connection()
    cursor = conn.cursor()
    data = request.get_json()
    cursor.execute('INSERT INTO rentals (car_id, customer_id, rental_date) VALUES (%s, %s, NOW())',
                   (data['car_id'], data['customer_id']))
    conn.commit()
    cursor.close()
    conn.close()
    return jsonify({"message": "Car rented successfully!"}), 201

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

Dockerfile 用來將這個應用程式容器化:

Dockerfile
FROM python:3.9-slim

WORKDIR /app

COPY requirements.txt requirements.txt
RUN pip install -r requirements.txt

COPY . .

CMD ["python", "app.py"]

requirements.txt 依賴庫清單:

Flask==2.0.1
mysql-connector-python==8.0.26

3. Kubernetes 部署 Flask 應用

接下來,我們將 Flask 應用部署到 Kubernetes。

Flask 應用程式部署 (flask-deployment.yaml)

apiVersion: apps/v1
kind: Deployment
metadata:
  name: flask-app
  labels:
    app: flask-app
spec:
  replicas: 2
  selector:
    matchLabels:
      app: flask-app
  template:
    metadata:
      labels:
        app: flask-app
    spec:
      containers:
      - name: flask-app
        image: <your-dockerhub-username>/flask-app:latest
        ports:
        - containerPort: 5000
        env:
        - name: MYSQL_HOST
          value: "mysql"
        - name: MYSQL_USER
          value: "root"
        - name: MYSQL_PASSWORD
          value: "password123"
        - name: MYSQL_DB
          value: "rentaldb"
---
apiVersion: v1
kind: Service
metadata:
  name: flask-service
spec:
  selector:
    app: flask-app
  ports:
  - protocol: TCP
    port: 80
    targetPort: 5000
  type: LoadBalancer

這個 Deployment 定義了 Flask 應用程式的副本數量,並且它與 MySQL 資料庫相連。Service 則用來暴露 Flask 應用程式,以便外部流量可以通過 LoadBalancer 存取。

4. Kubernetes Helm 或 CI/CD 自動化

我可以使用 Helm 來自動化這個部署,或建立一個 CI/CD 流程(例如使用 GitHub Actions 或 Jenkins),以便在每次程式碼變更時,自動重建 Docker 容器並更新 Kubernetes 部署。

1. MySQL 部署程式碼

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: mysql
  labels:
    app: mysql
spec:
  serviceName: "mysql"
  replicas: 1
  selector:
    matchLabels:
      app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
      - name: mysql
        image: mysql:5.7
        env:
        - name: MYSQL_ROOT_PASSWORD
          value: "password123"
        - name: MYSQL_DATABASE
          value: "rentaldb"
        ports:
        - containerPort: 3306
          name: mysql
        volumeMounts:
        - name: mysql-persistent-storage
          mountPath: /var/lib/mysql
  volumeClaimTemplates:
  - metadata:
      name: mysql-persistent-storage
    spec:
      accessModes: [ "ReadWriteOnce" ]
      resources:
        requests:
          storage: 5Gi

說明:

  • StatefulSet: 用於管理有狀態的應用程式,像資料庫這種需要持久化儲存的應用程式。這樣,資料庫會有固定的名稱和存儲持久性。
  • replicas: 1: 我們只需要一個 MySQL 副本運行,因此設置為1。
  • template: 定義了 MySQL 容器的部署方式:
    • image: mysql:5.7: 使用 MySQL 5.7 的 Docker 映像。
    • MYSQL_ROOT_PASSWORD: 設置 MySQL root 用戶的密碼。
    • MYSQL_DATABASE: 初始化一個名為 rentaldb 的資料庫。
    • volumeMounts: 將 MySQL 的資料庫文件存儲到 /var/lib/mysql 中,並將此存儲對應到 Kubernetes 的 Persistent Volume。

這段程式碼的主要目的是確保資料庫服務在 Kubernetes 集群上運行,並且資料持久化。

2. Flask 應用程式 (Python + MySQL)

這段程式碼定義了 Flask 後端應用程式,負責處理租車公司系統的 API。

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

app = Flask(__name__)

def get_db_connection():
    connection = mysql.connector.connect(
        host="mysql",  # MySQL 服務名稱
        user="root",
        password="password123",
        database="rentaldb"
    )
    return connection

說明:

  • Flask: 是一個用於構建 Web 應用的 Python 微框架。
  • mysql.connector: 用來與 MySQL 資料庫進行互動。
  • get_db_connection(): 這個函數用來建立與 MySQL 資料庫的連接,並使用指定的主機、使用者、密碼和資料庫名稱進行連接。
@app.route('/cars', methods=['GET'])
def get_cars():
    conn = get_db_connection()
    cursor = conn.cursor(dictionary=True)
    cursor.execute('SELECT * FROM cars')
    cars = cursor.fetchall()
    cursor.close()
    conn.close()
    return jsonify(cars)

說明:

  • /cars 路徑: 處理 HTTP GET 請求,用來查詢資料庫中的所有車輛信息。
  • cursor.execute('SELECT * FROM cars'): 這行 SQL 查詢會從 cars 表中選取所有的車輛。
  • fetchall(): 這會返回所有的查詢結果,並將其以字典格式轉換成 JSON,回傳給用戶。
@app.route('/rent', methods=['POST'])
def rent_car():
    conn = get_db_connection()
    cursor = conn.cursor()
    data = request.get_json()
    cursor.execute('INSERT INTO rentals (car_id, customer_id, rental_date) VALUES (%s, %s, NOW())',
                   (data['car_id'], data['customer_id']))
    conn.commit()
    cursor.close()
    conn.close()
    return jsonify({"message": "Car rented successfully!"}), 201

說明:

  • /rent 路徑: 處理 HTTP POST 請求,用來租借一輛車。
  • request.get_json(): 從請求中提取 JSON 數據,這裡會包含 car_idcustomer_id
  • cursor.execute('INSERT INTO rentals...'): 執行插入操作,將租借訂單資料寫入 rentals 資料表,並設置租賃日期為當前時間 (NOW())。

3. Flask 應用程式 Dockerfile

這個 Dockerfile 用來將 Flask 應用程式容器化。

Dockerfile
FROM python:3.9-slim

WORKDIR /app

COPY requirements.txt requirements.txt
RUN pip install -r requirements.txt

COPY . .

CMD ["python", "app.py"]

說明:

  • FROM python:3.9-slim: 使用 Python 3.9 的輕量級映像作為基礎映像。
  • WORKDIR /app: 設置工作目錄為 /app
  • COPY requirements.txtRUN pip install -r requirements.txt: 複製依賴庫列表並安裝它們。
  • COPY . .: 將當前目錄中的所有文件複製到容器內的 /app 目錄。
  • CMD ["python", "app.py"]: 容器啟動時執行 app.py 來運行 Flask 應用程式。

4. Kubernetes Flask 應用程式部署

apiVersion: apps/v1
kind: Deployment
metadata:
  name: flask-app
  labels:
    app: flask-app
spec:
  replicas: 2
  selector:
    matchLabels:
      app: flask-app
  template:
    metadata:
      labels:
        app: flask-app
    spec:
      containers:
      - name: flask-app
        image: <your-dockerhub-username>/flask-app:latest
        ports:
        - containerPort: 5000
        env:
        - name: MYSQL_HOST
          value: "mysql"
        - name: MYSQL_USER
          value: "root"
        - name: MYSQL_PASSWORD
          value: "password123"
        - name: MYSQL_DB
          value: "rentaldb"
---
apiVersion: v1
kind: Service
metadata:
  name: flask-service
spec:
  selector:
    app: flask-app
  ports:
  - protocol: TCP
    port: 80
    targetPort: 5000
  type: LoadBalancer

說明:

  • Deployment: 用於在 Kubernetes 中管理 Flask 應用程式。這裡指定了應用程式副本為2(replicas: 2),即會有兩個 Flask 副本運行。
  • containers: 每個容器會運行一個 Flask 應用,並暴露 5000 端口。
  • 環境變數 (env): 用來將 MySQL 的連接信息(主機、用戶、密碼和資料庫名稱)傳遞給應用程式。
  • Service: 用來暴露應用程式。type: LoadBalancer 指定將服務暴露給外部使用者,並映射到 Kubernetes 的外部負載均衡器。

這樣的架構可以確保 Flask 應用程式與 MySQL 資料庫運行於 Kubernetes 集群中,並且應用程式的多副本能夠均衡處理請求,保證高可用性。


上一篇
day 14 K8s銀行提款資料庫管理系統
系列文
K8s 資料庫管理系統15
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言