主题
前后端分离架构
业务场景
云咖啡公司的订单系统已经上线,但目前的架构是单体应用,难以扩展。为了提升系统的可维护性和扩展性,我们需要将系统重构为前后端分离的微服务架构。
需求:
- 部署独立的前端应用
- 部署独立的后端 API 服务
- 配置 Ingress 实现路由
- 实现前后端通信
学习目标
完成本课程后,你将掌握:
- Ingress 的概念和使用
- 多服务之间的通信
- 环境变量的配置和使用
- 服务发现机制
- 前后端分离架构的设计
前置准备
1. 确认环境
bash
# 检查命名空间
kubectl get namespace cloud-cafe
# 检查现有资源
kubectl get all -n cloud-cafe
# 检查 Ingress Controller
kubectl get pods -n ingress-nginx2. 安装 Ingress Controller(如果未安装)
bash
# 检查 Ingress Controller 是否已安装
kubectl get pods -n ingress-nginx
# 如果没有安装,执行以下命令安装
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.9.4/deploy/static/provider/cloud/deploy.yaml
# 等待 Ingress Controller 就绪
kubectl wait --namespace ingress-nginx \
--for=condition=ready pod \
--selector=app.kubernetes.io/component=controller \
--timeout=120s
# 查看 Ingress Controller
kubectl get pods -n ingress-nginx📌 关于
kubectl wait命令的解释
kubectl wait用于阻塞等待资源达到指定状态,常用于脚本中确保资源就绪后再继续。常用参数:
参数 说明 示例 --for=condition=ready等待资源就绪 Pod、Deployment 等 --for=delete等待资源删除完成 清理资源时使用 --selector按标签选择资源 同 -l--timeout设置超时时间 超时后命令失败 使用场景:
bash# 等待 Deployment 就绪 kubectl wait deployment/nginx --for=condition=available --timeout=60s # 等待 Pod 删除完成(常用于清理) kubectl wait pod/nginx --for=delete --timeout=30s提示:超时时间格式可以是
30s、2m、1h
实战步骤
Step 1: 理解 Ingress
概念: Ingress 是 Kubernetes 的 API 对象,用于管理外部访问集群内服务的规则,提供 HTTP 和 HTTPS 路由。
1.1 查看 Ingress Controller
bash
# 查看 Ingress Controller Pod
kubectl get pods -n ingress-nginx
# 查看 Ingress Controller Service
kubectl get svc -n ingress-nginx
# 查看 Ingress Controller 日志
kubectl logs -n ingress-nginx -l app.kubernetes.io/component=controller观察要点:
- Ingress Controller 运行在
ingress-nginx命名空间 - Ingress Controller Service 的类型是 LoadBalancer 或 NodePort
Step 2: 部署前端应用
我们将部署一个简单的前端应用,使用 Nginx 提供静态文件服务。
2.1 创建前端页面
bash
# 创建前端页面 ConfigMap
kubectl create configmap frontend-html \
--from-literal=index.html='
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>云咖啡公司 - 在线点单</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: "Microsoft YaHei", Arial, sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
padding: 20px;
}
.container {
max-width: 1200px;
margin: 0 auto;
}
header {
text-align: center;
color: white;
margin-bottom: 40px;
}
h1 {
font-size: 48px;
margin-bottom: 10px;
}
.subtitle {
font-size: 24px;
opacity: 0.9;
}
.coffee-icon {
font-size: 80px;
margin: 20px 0;
}
.content {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 30px;
}
.card {
background: white;
border-radius: 15px;
padding: 30px;
box-shadow: 0 10px 30px rgba(0,0,0,0.2);
}
.card h2 {
color: #667eea;
margin-bottom: 20px;
font-size: 28px;
}
.menu-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 15px;
border-bottom: 1px solid #eee;
margin-bottom: 10px;
}
.menu-item:last-child {
border-bottom: none;
}
.menu-name {
font-size: 18px;
font-weight: bold;
}
.menu-price {
color: #f5576c;
font-size: 20px;
font-weight: bold;
}
.order-form {
display: flex;
flex-direction: column;
gap: 15px;
}
.form-group {
display: flex;
flex-direction: column;
gap: 5px;
}
label {
font-weight: bold;
color: #333;
}
input, select {
padding: 12px;
border: 2px solid #ddd;
border-radius: 8px;
font-size: 16px;
}
input:focus, select:focus {
outline: none;
border-color: #667eea;
}
button {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
padding: 15px;
border: none;
border-radius: 8px;
font-size: 18px;
font-weight: bold;
cursor: pointer;
transition: transform 0.2s;
}
button:hover {
transform: scale(1.02);
}
.orders-list {
margin-top: 20px;
}
.order-item {
background: #f8f9fa;
padding: 15px;
border-radius: 8px;
margin-bottom: 10px;
}
.order-item h4 {
color: #667eea;
margin-bottom: 5px;
}
.order-item p {
color: #666;
font-size: 14px;
}
.loading {
text-align: center;
padding: 20px;
color: #666;
}
.error {
background: #fee;
color: #c33;
padding: 15px;
border-radius: 8px;
margin-bottom: 15px;
}
.success {
background: #efe;
color: #3c3;
padding: 15px;
border-radius: 8px;
margin-bottom: 15px;
}
@media (max-width: 768px) {
.content {
grid-template-columns: 1fr;
}
}
</style>
</head>
<body>
<div class="container">
<header>
<div class="coffee-icon">☕</div>
<h1>云咖啡公司</h1>
<p class="subtitle">在线点单系统</p>
</header>
<div class="content">
<div class="card">
<h2>咖啡菜单</h2>
<div class="menu-item">
<span class="menu-name">焦糖玛奇朵</span>
<span class="menu-price">¥28</span>
</div>
<div class="menu-item">
<span class="menu-name">拿铁</span>
<span class="menu-price">¥25</span>
</div>
<div class="menu-item">
<span class="menu-name">美式咖啡</span>
<span class="menu-price">¥18</span>
</div>
<div class="menu-item">
<span class="menu-name">卡布奇诺</span>
<span class="menu-price">¥26</span>
</div>
<div class="menu-item">
<span class="menu-name">摩卡</span>
<span class="menu-price">¥30</span>
</div>
</div>
<div class="card">
<h2>在线点单</h2>
<div id="message"></div>
<form class="order-form" id="orderForm">
<div class="form-group">
<label for="customerName">客户姓名</label>
<input type="text" id="customerName" required placeholder="请输入您的姓名">
</div>
<div class="form-group">
<label for="coffeeType">咖啡类型</label>
<select id="coffeeType" required>
<option value="">请选择咖啡</option>
<option value="焦糖玛奇朵">焦糖玛奇朵 - ¥28</option>
<option value="拿铁">拿铁 - ¥25</option>
<option value="美式咖啡">美式咖啡 - ¥18</option>
<option value="卡布奇诺">卡布奇诺 - ¥26</option>
<option value="摩卡">摩卡 - ¥30</option>
</select>
</div>
<div class="form-group">
<label for="quantity">数量</label>
<input type="number" id="quantity" min="1" max="10" value="1" required>
</div>
<button type="submit">提交订单</button>
</form>
<div class="orders-list">
<h3>最近订单</h3>
<div id="ordersList">
<div class="loading">加载中...</div>
</div>
</div>
</div>
</div>
</div>
<script>
const API_BASE_URL = "/api";
// 显示消息
function showMessage(message, type = "success") {
const messageDiv = document.getElementById("message");
messageDiv.innerHTML = `<div class="${type}">${message}</div>`;
setTimeout(() => {
messageDiv.innerHTML = "";
}, 3000);
}
// 获取订单列表
async function loadOrders() {
try {
const response = await fetch(`${API_BASE_URL}/orders`);
const orders = await response.json();
const ordersList = document.getElementById("ordersList");
if (orders.length === 0) {
ordersList.innerHTML = "<p>暂无订单</p>";
} else {
ordersList.innerHTML = orders
.slice(-5)
.reverse()
.map(
(order) => `
<div class="order-item">
<h4>${order.customer_name}</h4>
<p>${order.coffee_type} x ${order.quantity} - ¥${order.total_price}</p>
<p>${new Date(order.order_time).toLocaleString("zh-CN")}</p>
</div>
`
)
.join("");
}
} catch (error) {
console.error("加载订单失败:", error);
document.getElementById("ordersList").innerHTML =
'<div class="error">加载订单失败</div>';
}
}
// 提交订单
document
.getElementById("orderForm")
.addEventListener("submit", async (e) => {
e.preventDefault();
const customerName = document.getElementById("customerName").value;
const coffeeType = document.getElementById("coffeeType").value;
const quantity = parseInt(document.getElementById("quantity").value);
// 计算价格
const prices = {
"焦糖玛奇朵": 28,
拿铁: 25,
美式咖啡: 18,
卡布奇诺: 26,
摩卡: 30,
};
const totalPrice = prices[coffeeType] * quantity;
try {
const response = await fetch(`${API_BASE_URL}/orders`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
customer_name: customerName,
coffee_type: coffeeType,
quantity: quantity,
total_price: totalPrice,
}),
});
const result = await response.json();
if (response.ok) {
showMessage(`订单提交成功!订单号: ${result.order_id}`);
document.getElementById("orderForm").reset();
loadOrders();
} else {
showMessage(`订单提交失败: ${result.error}`, "error");
}
} catch (error) {
console.error("提交订单失败:", error);
showMessage("提交订单失败,请稍后重试", "error");
}
});
// 页面加载时获取订单列表
loadOrders();
// 每 5 秒刷新订单列表
setInterval(loadOrders, 5000);
</script>
</body>
</html>
' \
-n cloud-cafe
# 查看 ConfigMap
kubectl get configmap frontend-html -n cloud-cafe2.2 部署前端应用
bash
# 创建前端应用 Deployment YAML 文件
cat > frontend-deployment.yaml << 'EOF'
# 前端应用 Deployment
# 用途:部署云咖啡官网前端(独立前端应用)
# 技术栈:Nginx 静态文件服务
# 特点:
# - 从 ConfigMap 加载前端页面
# - 包含健康检查配置
# 前置依赖:需要 frontend-html ConfigMap 已创建
apiVersion: apps/v1
kind: Deployment
metadata:
name: frontend
namespace: cloud-cafe
labels:
app: frontend
spec:
replicas: 2 # 2 个副本实现高可用
selector:
matchLabels:
app: frontend
template:
metadata:
labels:
app: frontend
spec:
containers:
- name: nginx
image: nginx:latest # Nginx 官方镜像
ports:
- containerPort: 80 # HTTP 端口
# 挂载前端页面
volumeMounts:
- name: html-content
mountPath: /usr/share/nginx/html # Nginx 默认文档根目录
# 资源限制
resources:
requests:
memory: "64Mi" # 最低内存要求
cpu: "100m" # 最低 CPU(0.1核)
limits:
memory: "128Mi" # 最大内存限制
cpu: "200m" # 最大 CPU(0.2核)
# 健康检查
livenessProbe:
httpGet:
path: / # 检查根路径
port: 80
initialDelaySeconds: 10 # 首次检查延迟
periodSeconds: 10 # 检查间隔
readinessProbe:
httpGet:
path: / # 就绪检查路径
port: 80
initialDelaySeconds: 5 # 首次检查延迟
periodSeconds: 5 # 检查间隔
# 使用 ConfigMap 作为卷
volumes:
- name: html-content
configMap:
name: frontend-html # 引用前端页面 ConfigMap
items:
- key: index.html # ConfigMap 中的键
path: index.html # 挂载后的文件名
EOF
# 应用 Deployment
kubectl apply -f frontend-deployment.yaml
# 等待前端应用就绪
kubectl rollout status deployment/frontend -n cloud-cafe
# 查看 Pod
kubectl get pods -n cloud-cafe2.3 创建前端应用 Service
bash
# 创建前端应用 Service
kubectl expose deployment frontend \
--port=80 \
--target-port=80 \
--name=frontend-svc \
-n cloud-cafe
# 查看 Service
kubectl get svc frontend-svc -n cloud-cafeStep 3: 更新后端服务
我们需要更新后端服务,添加 CORS 支持,以便前端可以调用后端 API。
首先,创建 order-backend-deployment.yaml 文件:
bash
# 创建/编辑后端服务 Deployment 文件
vim order-backend-deployment.yamlorder-backend-deployment.yaml 内容(添加 CORS 支持):
点击查看 order-backend-deployment.yaml 内容
yaml
# 订单后端服务 Deployment
# 本次修改:添加 CORS 支持,启用跨域访问
# 修改位置:
# 1. pip install 添加 flask-cors 依赖
# 2. Python 代码中导入并启用 CORS(app)
# 前置依赖:需要先创建 mysql-config、mysql-secret、app-config、order-backend-config
apiVersion: apps/v1
kind: Deployment
metadata:
name: order-backend
namespace: cloud-cafe
labels:
app: order-backend
spec:
replicas: 2
selector:
matchLabels:
app: order-backend
template:
metadata:
labels:
app: order-backend
spec:
containers:
- name: order-backend
image: python:3.9-slim
command: ["/bin/sh", "-c"]
args:
- |
# [修改开始] 添加 flask-cors 依赖,启用跨域支持
# CORS (Cross-Origin Resource Sharing) 允许前端从不同域名调用API
pip install flask pymysql flask-cors
# [修改结束]
cat > /app/app.py << 'PYEOF'
from flask import Flask, request, jsonify
# [新增开始] 导入 CORS 模块
from flask_cors import CORS
# [新增结束]
import pymysql
import os
app = Flask(__name__)
# [新增开始] 启用 CORS,允许所有来源访问(生产环境应限制特定域名)
CORS(app)
# [新增结束]
# 数据库配置
db_config = {
'host': os.getenv('DB_HOST', 'mysql-service'),
'port': int(os.getenv('DB_PORT', 3306)),
'user': os.getenv('DB_USER', 'cafeadmin'),
'password': os.getenv('DB_PASSWORD', 'userpassword123'),
'database': os.getenv('DB_NAME', 'cloudcafe')
}
def get_db_connection():
return pymysql.connect(**db_config)
@app.route('/health')
def health():
return jsonify({'status': 'healthy'})
@app.route('/orders', methods=['GET'])
def get_orders():
try:
conn = get_db_connection()
cursor = conn.cursor(pymysql.cursors.DictCursor)
cursor.execute('SELECT * FROM orders ORDER BY order_time DESC LIMIT 20')
orders = cursor.fetchall()
conn.close()
return jsonify(orders)
except Exception as e:
return jsonify({'error': str(e)}), 500
@app.route('/orders', methods=['POST'])
def create_order():
try:
data = request.json
conn = get_db_connection()
cursor = conn.cursor()
cursor.execute(
'INSERT INTO orders (customer_name, coffee_type, quantity, total_price) VALUES (%s, %s, %s, %s)',
(data['customer_name'], data['coffee_type'], data['quantity'], data['total_price'])
)
conn.commit()
order_id = cursor.lastrowid
conn.close()
return jsonify({'order_id': order_id, 'message': 'Order created successfully'}), 201
except Exception as e:
return jsonify({'error': str(e)}), 500
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)
PYEOF
python /app/app.py
ports:
- containerPort: 5000
env:
- name: DB_HOST
valueFrom:
configMapKeyRef:
name: app-config
key: DB_HOST
- name: DB_PORT
valueFrom:
configMapKeyRef:
name: app-config
key: DB_PORT
- name: DB_USER
valueFrom:
configMapKeyRef:
name: mysql-config
key: MYSQL_USER
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: mysql-secret
key: MYSQL_PASSWORD
- name: DB_NAME
valueFrom:
configMapKeyRef:
name: mysql-config
key: MYSQL_DATABASE
- name: FLASK_ENV
valueFrom:
configMapKeyRef:
name: order-backend-config
key: FLASK_ENV
- name: FLASK_DEBUG
valueFrom:
configMapKeyRef:
name: order-backend-config
key: FLASK_DEBUG
resources:
requests:
memory: "128Mi"
cpu: "100m"
limits:
memory: "256Mi"
cpu: "200m"
livenessProbe:
httpGet:
path: /health
port: 5000
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /health
port: 5000
initialDelaySeconds: 10
periodSeconds: 5
volumeMounts:
- name: app-logs
mountPath: /app/logs
volumes:
- name: app-logs
persistentVolumeClaim:
claimName: app-log-pvc保存文件后,应用配置:
bash
# 应用后端服务 Deployment
kubectl apply -f order-backend-deployment.yaml
# 等待后端服务更新完成
kubectl rollout status deployment/order-backend -n cloud-cafe
# 查看 Pod
kubectl get pods -n cloud-cafeStep 4: 配置 Ingress 路由
现在我们配置 Ingress,将外部请求路由到前端和后端服务。
bash
# 创建 Ingress YAML 文件
cat > cloud-cafe-ingress.yaml << 'EOF'
# 云咖啡应用 Ingress 配置
# 用途:配置 HTTP 路由规则,将外部请求转发到内部服务
# 路由规则:
# - / -> 前端服务 (frontend-svc:80)
# - /api -> 后端服务 (order-backend-svc:5000)
# 前置依赖:需要 Ingress Controller 已安装,前端和后端 Service 已创建
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: cloud-cafe-ingress
namespace: cloud-cafe
labels:
app: cloud-cafe
annotations:
# URL 重写规则(将请求路径重写为根路径)
nginx.ingress.kubernetes.io/rewrite-target: /
# 禁用 SSL 重定向(本示例使用 HTTP)
nginx.ingress.kubernetes.io/ssl-redirect: "false"
spec:
ingressClassName: nginx # 使用 nginx Ingress Controller
rules:
- host: cloudcafe.local # 虚拟主机名(需要配置 hosts 文件)
http:
paths:
# 前端路由规则
- path: /
pathType: Prefix # 前缀匹配
backend:
service:
name: frontend-svc # 前端 Service 名称
port:
number: 80 # 前端 Service 端口
# 后端 API 路由规则
- path: /api
pathType: Prefix # 前缀匹配
backend:
service:
name: order-backend-svc # 后端 Service 名称
port:
number: 5000 # 后端 Service 端口
EOF
# 应用 Ingress
kubectl apply -f cloud-cafe-ingress.yaml
# 查看 Ingress
kubectl get ingress -n cloud-cafe
# 查看 Ingress 详细信息
kubectl describe ingress cloud-cafe-ingress -n cloud-cafe观察要点:
- Ingress 创建了两个路由规则
/路由到前端服务/api路由到后端服务
Step 5: 测试前后端分离架构
5.1 获取 Ingress 访问地址
bash
# 获取 Ingress Controller 的 Service
kubectl get svc -n ingress-nginx
# 获取 Ingress Controller 的 NodePort
INGRESS_PORT=$(kubectl get svc -n ingress-nginx ingress-nginx-controller -o jsonpath='{.spec.ports[0].nodePort}')
# 获取节点 IP
NODE_IP=$(kubectl get nodes -o jsonpath='{.items[0].status.addresses[?(@.type=="InternalIP")].address}')
echo "访问地址: http://cloudcafe.local:$INGRESS_PORT"5.2 配置本地 hosts 文件
在宿主机上编辑 /etc/hosts(Linux/Mac)或 C:\Windows\System32\drivers\etc\hosts(Windows),添加以下内容:
192.168.56.10 cloudcafe.local注意: 将 192.168.56.10 替换为你的虚拟机 IP 地址。
5.3 测试前端访问
bash
# 测试前端访问
curl -H "Host: cloudcafe.local" http://$NODE_IP:$INGRESS_PORT预期输出: 应该看到前端页面的 HTML 内容
5.4 测试后端 API
bash
# 测试后端 API 健康检查
curl -H "Host: cloudcafe.local" http://$NODE_IP:$INGRESS_PORT/api/health
# 测试获取订单
curl -H "Host: cloudcafe.local" http://$NODE_IP:$INGRESS_PORT/api/orders
# 测试创建订单
curl -X POST -H "Host: cloudcafe.local" -H "Content-Type: application/json" \
-d '{"customer_name":"测试用户","coffee_type":"拿铁","quantity":2,"total_price":50.00}' \
http://$NODE_IP:$INGRESS_PORT/api/orders5.5 在浏览器中访问
在浏览器中访问:http://cloudcafe.local:xxxxx
你应该看到:
- 云咖啡公司的在线点单页面
- 左侧显示咖啡菜单
- 右侧显示点单表单和最近订单
- 可以提交订单,订单会实时显示在列表中
Step 6: 验证服务发现
Kubernetes 提供了内置的服务发现机制,让我们验证一下。
6.1 测试 DNS 解析
bash
# 创建测试 Pod
kubectl run test-dns --image=busybox --rm -it -n cloud-cafe -- nslookup frontend-svc
# 测试后端服务 DNS
kubectl run test-dns --image=busybox --rm -it -n cloud-cafe -- nslookup order-backend-svc
# 测试 MySQL 服务 DNS
kubectl run test-dns --image=busybox --rm -it -n cloud-cafe -- nslookup mysql-service预期输出: 应该能够解析到服务的 ClusterIP
6.2 测试服务间通信
bash
# 从前端 Pod 访问后端服务
kubectl exec -it $(kubectl get pod -l app=frontend -n cloud-cafe -o jsonpath='{.items[0].metadata.name}') -n cloud-cafe -- \
curl http://order-backend-svc:5000/health
# 从后端 Pod 访问 MySQL 服务
kubectl exec -it $(kubectl get pod -l app=order-backend -n cloud-cafe -o jsonpath='{.items[0].metadata.name}') -n cloud-cafe -- \
nc -zv mysql-service 3306预期输出:
- 前端 Pod 应该能够访问后端服务
- 后端 Pod 应该能够连接到 MySQL 服务
验证和测试
1. 检查所有资源状态
bash
# 查看 Deployment
kubectl get deployment -n cloud-cafe
# 查看 StatefulSet
kubectl get statefulset -n cloud-cafe
# 查看 Pod
kubectl get pods -n cloud-cafe
# 查看 Service
kubectl get svc -n cloud-cafe
# 查看 Ingress
kubectl get ingress -n cloud-cafe
# 查看 PVC
kubectl get pvc -n cloud-cafe2. 测试完整流程
bash
# 1. 访问前端页面
echo "访问前端页面: http://cloudcafe.local:$INGRESS_PORT"
# 2. 提交订单
curl -X POST -H "Host: cloudcafe.local" -H "Content-Type: application/json" \
-d '{"customer_name":"集成测试","coffee_type":"摩卡","quantity":1,"total_price":30.00}' \
http://$NODE_IP:$INGRESS_PORT/api/orders
# 3. 查询订单
curl -H "Host: cloudcafe.local" http://$NODE_IP:$INGRESS_PORT/api/orders
# 4. 验证数据库
MYSQL_POD=$(kubectl get pod -l app=mysql -n cloud-cafe -o jsonpath='{.items[0].metadata.name}')
kubectl exec -it $MYSQL_POD -n cloud-cafe -- mysql -ucafeadmin -puserpassword123 cloudcafe -e "SELECT * FROM orders ORDER BY order_time DESC LIMIT 5;"3. 测试高可用性
bash
# 删除一个前端 Pod
kubectl delete pod -l app=frontend -n cloud-cafe
# 删除一个后端 Pod
kubectl delete pod -l app=order-backend -n cloud-cafe
# 观察自动恢复
kubectl get pods -n cloud-cafe -w
# 测试服务是否仍然可用
curl -H "Host: cloudcafe.local" http://$NODE_IP:$INGRESS_PORT/api/health4. 查看 Ingress 日志
bash
# 查看 Ingress Controller 日志
kubectl logs -n ingress-nginx -l app.kubernetes.io/component=controller --tail=50
# 实时查看日志
kubectl logs -n ingress-nginx -l app.kubernetes.io/component=controller -f📝 总结和思考
本课程学到的知识点
- Ingress: 管理外部访问集群内服务的规则
- 前后端分离: 将前端和后端部署为独立的服务
- 服务发现: Kubernetes 内置的 DNS 服务发现机制
- CORS: 跨域资源共享,允许前端调用后端 API
- 路由配置: 使用 Ingress 配置 HTTP 路由规则
关键概念
- 微服务架构: 将应用拆分为多个独立的服务
- 服务间通信: 通过 Service 实现服务之间的通信
- 外部访问: 使用 Ingress 暴露服务到外部
- DNS 解析: Kubernetes 自动为 Service 创建 DNS 记录
思考题
- Ingress 和 Service 有什么区别?分别在什么场景下使用?
- 为什么需要配置 CORS?不配置会有什么问题?
- Kubernetes 的服务发现是如何工作的?
- 如何实现 HTTPS 访问?(提示:TLS 证书)
- 如何实现蓝绿部署或金丝雀发布?
最佳实践
- 使用 Ingress 统一管理路由: 避免使用多个 NodePort
- 配置健康检查: 确保服务可用性
- 合理设置副本数: 根据负载调整副本数
- 监控服务间通信: 使用日志和监控工具
下一步
本课程学习了如何实现前后端分离,构建微服务架构。
下一课程将学习如何添加缓存和负载均衡,提升系统性能和可用性。
下一课程: 05-高可用架构.md
清理环境
如果你想清理本课程创建的资源:
bash
# 删除 Ingress
kubectl delete ingress cloud-cafe-ingress -n cloud-cafe
# 删除前端应用
kubectl delete deployment frontend -n cloud-cafe
kubectl delete svc frontend-svc -n cloud-cafe
kubectl delete configmap frontend-html -n cloud-cafe
# 删除后端服务
kubectl delete deployment order-backend -n cloud-cafe
kubectl delete svc order-backend-svc -n cloud-cafe
# 删除数据库
kubectl delete statefulset mysql -n cloud-cafe
kubectl delete svc mysql-service -n cloud-cafe
# 删除 PVC
kubectl delete pvc mysql-pvc app-log-pvc -n cloud-cafe
# 删除 ConfigMap
kubectl delete configmap mysql-config app-config order-backend-config -n cloud-cafe
# 删除 Secret
kubectl delete secret mysql-secret mysql-secret-manual -n cloud-cafe
# 删除命名空间
kubectl delete namespace cloud-cafe提示: 如果你要继续学习下一个课程,建议保留这些资源,因为下一个课程会在此基础上进行。