本文将介绍如何使用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. 测试应用
- 访问
http://microservices.example.com/users
,查看用户服务。 - 访问
http://microservices.example.com/orders
,查看订单服务。 - 使用POST请求创建用户和订单,验证服务功能。
6. 总结
本文通过一个简单的Python微服务应用,详细介绍了如何使用Docker和Kubernetes进行容器化部署。通过实践,读者可以掌握Docker镜像构建、Kubernetes资源管理和微服务架构设计的基本技能。希望本文能为您的云原生之旅提供帮助