基于Docker和Kubernetes的Python微服务实践

时间:2025-03-22 14:05:40

本文将介绍如何使用Docker和Kubernetes构建一个简单的Python微服务应用。我们将创建两个微服务:一个用户服务(User Service)和一个订单服务(Order Service),并通过Kubernetes进行部署和管理。每个微服务都会通过REST API进行通信,并使用MySQL作为数据库。所有代码均附有详细注释,方便读者理解和实践。


1. 项目结构

microservices/
├── user-service/
│   ├── app/
│   │   ├── __init__.py
│   │   ├── routes.py
│   │   └── models.py
│   ├── requirements.txt
│   ├── Dockerfile
│   └── k8s/
│       ├── deployment.yaml
│       ├── service.yaml
│       └── db-secret.yaml
├── order-service/
│   ├── app/
│   │   ├── __init__.py
│   │   ├── routes.py
│   │   └── models.py
│   ├── requirements.txt
│   ├── Dockerfile
│   └── k8s/
│       ├── deployment.yaml
│       ├── service.yaml
│       └── db-secret.yaml
├── k8s/
│   ├── ingress.yaml
│   └── mysql.yaml
└── README.md

2. 编写用户服务(User Service)

2.1 用户服务代码

user-service/app/__init__.py中初始化Flask应用:

from flask import Flask
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:password@mysql/userdb'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

db = SQLAlchemy(app)

from app import routes

user-service/app/models.py中定义用户模型:

from app import db

class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(80), unique=True, nullable=False)

    def __repr__(self):
        return f'<User {self.username}>'

user-service/app/routes.py中定义路由:

from flask import jsonify, request
from app import app, db
from app.models import User

@app.route('/users', methods=['GET'])
def get_users():
    users = User.query.all()
    return jsonify([{'id': user.id, 'username': user.username} for user in users])

@app.route('/users', methods=['POST'])
def create_user():
    data = request.get_json()
    new_user = User(username=data['username'])
    db.session.add(new_user)
    db.session.commit()
    return jsonify({'id': new_user.id, 'username': new_user.username}), 201

2.2 用户服务Dockerfile

user-service/Dockerfile中定义镜像构建过程:

FROM python:3.9-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
CMD ["flask", "run", "--host=0.0.0.0"]

2.3 用户服务Kubernetes配置

user-service/k8s/deployment.yaml中定义Deployment:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: user-service
spec:
  replicas: 2
  selector:
    matchLabels:
      app: user-service
  template:
    metadata:
      labels:
        app: user-service
    spec:
      containers:
      - name: user-service
        image: my-registry/user-service:1.0
        ports:
        - containerPort: 5000

user-service/k8s/service.yaml中定义Service:

apiVersion: v1
kind: Service
metadata:
  name: user-service
spec:
  selector:
    app: user-service
  ports:
  - protocol: TCP
    port: 80
    targetPort: 5000

3. 编写订单服务(Order Service)

3.1 订单服务代码

order-service/app/__init__.py中初始化Flask应用:

from flask import Flask
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:password@mysql/orderdb'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

db = SQLAlchemy(app)

from app import routes

order-service/app/models.py中定义订单模型:

from app import db

class Order(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    product = db.Column(db.String(80), nullable=False)
    quantity = db.Column(db.Integer, nullable=False)

    def __repr__(self):
        return f'<Order {self.product}>'

order-service/app/routes.py中定义路由:

from flask import jsonify, request
from app import app, db
from app.models import Order

@app.route('/orders', methods=['GET'])
def get_orders():
    orders = Order.query.all()
    return jsonify([{'id': order.id, 'product': order.product, 'quantity': order.quantity} for order in orders])

@app.route('/orders', methods=['POST'])
def create_order():
    data = request.get_json()
    new_order = Order(product=data['product'], quantity=data['quantity'])
    db.session.add(new_order)
    db.session.commit()
    return jsonify({'id': new_order.id, 'product': new_order.product, 'quantity': new_order.quantity}), 201

3.2 订单服务Dockerfile

order-service/Dockerfile中定义镜像构建过程:

FROM python:3.9-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
CMD ["flask", "run", "--host=0.0.0.0"]

3.3 订单服务Kubernetes配置

order-service/k8s/deployment.yaml中定义Deployment:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: order-service
spec:
  replicas: 2
  selector:
    matchLabels:
      app: order-service
  template:
    metadata:
      labels:
        app: order-service
    spec:
      containers:
      - name: order-service
        image: my-registry/order-service:1.0
        ports:
        - containerPort: 5000

order-service/k8s/service.yaml中定义Service:

apiVersion: v1
kind: Service
metadata:
  name: order-service
spec:
  selector:
    app: order-service
  ports:
  - protocol: TCP
    port: 80
    targetPort: 5000

4. 部署到Kubernetes

4.1 部署MySQL

k8s/mysql.yaml中定义MySQL Deployment和Service:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: mysql
spec:
  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: password
        ports:
        - containerPort: 3306
---
apiVersion: v1
kind: Service
metadata:
  name: mysql
spec:
  selector:
    app: mysql
  ports:
  - protocol: TCP
    port: 3306
    targetPort: 3306

4.2 部署Ingress

k8s/ingress.yaml中定义Ingress:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: microservices-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - host: microservices.example.com
    http:
      paths:
      - path: /users
        pathType: Prefix
        backend:
          service:
            name: user-service
            port:
              number: 80
      - path: /orders
        pathType: Prefix
        backend:
          service:
            name: order-service
            port:
              number: 80

4.3 部署应用

运行以下命令部署所有资源:

kubectl apply -f k8s/mysql.yaml
kubectl apply -f user-service/k8s/
kubectl apply -f order-service/k8s/
kubectl apply -f k8s/ingress.yaml

5. 测试应用

  1. 访问http://microservices.example.com/users,查看用户服务。
  2. 访问http://microservices.example.com/orders,查看订单服务。
  3. 使用POST请求创建用户和订单,验证服务功能。

6. 总结

本文通过一个简单的Python微服务应用,详细介绍了如何使用Docker和Kubernetes进行容器化部署。通过实践,读者可以掌握Docker镜像构建、Kubernetes资源管理和微服务架构设计的基本技能。希望本文能为您的云原生之旅提供帮助