微服务架构:使用Docker+Kubernetes部署应用
大家好,我是欧阳瑞(Rich Own)。今天想和大家聊聊微服务架构以及如何使用Docker和Kubernetes进行部署。作为一个全栈开发者,我经历过单体应用到微服务的转型,深刻体会到微服务带来的好处。
什么是微服务架构?
微服务架构是一种将应用程序拆分成多个小型、独立服务的架构风格。每个服务:
- 独立部署
- 独立扩展
- 拥有自己的数据库
- 通过API进行通信
微服务的优势
| 独立部署 | 一个服务更新不会影响其他服务 |
| 技术多样性 | 不同服务可以使用不同技术栈 |
| 弹性扩展 | 可以根据需求独立扩展每个服务 |
| 容错性 | 单个服务故障不会导致整个系统崩溃 |
| 团队自治 | 每个团队可以独立负责一个服务 |
Docker入门
什么是Docker?
Docker是一个容器化平台,可以将应用及其依赖打包成一个独立的容器。
安装Docker
# Ubuntu/Debian
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
# Mac
brew install docker
# 验证安装
docker –version
创建Dockerfile
# 使用Node.js官方镜像作为基础镜像
FROM node:18-alpine
# 设置工作目录
WORKDIR /app
# 复制package.json和package-lock.json
COPY package*.json ./
# 安装依赖
RUN npm ci –only=production
# 复制应用代码
COPY . .
# 暴露端口
EXPOSE 3000
# 启动命令
CMD ["node", "server.js"]
构建和运行容器
# 构建镜像
docker build -t my-node-app .
# 运行容器
docker run -p 3000:3000 my-node-app
# 后台运行
docker run -d -p 3000:3000 my-node-app
# 查看运行中的容器
docker ps
# 查看日志
docker logs <container-id>
Docker Compose
什么是Docker Compose?
Docker Compose可以定义和运行多个容器的应用。
创建docker-compose.yml
version: '3.8'
services:
web:
build: .
ports:
– "3000:3000"
environment:
– NODE_ENV=production
– DATABASE_URL=postgres://user:password@db:5432/mydb
depends_on:
– db
restart: unless-stopped
db:
image: postgres:15-alpine
volumes:
– postgres_data:/var/lib/postgresql/data
environment:
– POSTGRES_USER=user
– POSTGRES_PASSWORD=password
– POSTGRES_DB=mydb
restart: unless-stopped
volumes:
postgres_data:
运行Docker Compose
# 启动所有服务
docker-compose up -d
# 查看服务状态
docker-compose ps
# 查看日志
docker-compose logs -f
# 停止服务
docker-compose down
Kubernetes入门
什么是Kubernetes?
Kubernetes(简称K8s)是一个容器编排平台,可以自动化部署、扩展和管理容器化应用。
安装Minikube(本地开发)
# 安装Minikube
curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-darwin-amd64
sudo install minikube-darwin-amd64 /usr/local/bin/minikube
# 启动Minikube
minikube start
# 安装kubectl
brew install kubectl
# 验证安装
kubectl cluster-info
创建Deployment
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-deployment
labels:
app: web
spec:
replicas: 3
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
– name: web
image: my-node-app:latest
ports:
– containerPort: 3000
env:
– name: NODE_ENV
value: "production"
– name: DATABASE_URL
value: "postgres://user:password@postgres-service:5432/mydb"
resources:
requests:
memory: "128Mi"
cpu: "250m"
limits:
memory: "256Mi"
cpu: "500m"
创建Service
# service.yaml
apiVersion: v1
kind: Service
metadata:
name: web-service
spec:
selector:
app: web
ports:
– port: 80
targetPort: 3000
type: LoadBalancer
创建StatefulSet(数据库)
# statefulset.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: postgres
spec:
serviceName: postgres-service
replicas: 1
selector:
matchLabels:
app: postgres
template:
metadata:
labels:
app: postgres
spec:
containers:
– name: postgres
image: postgres:15-alpine
ports:
– containerPort: 5432
env:
– name: POSTGRES_USER
value: "user"
– name: POSTGRES_PASSWORD
value: "password"
– name: POSTGRES_DB
value: "mydb"
volumeMounts:
– name: postgres-data
mountPath: /var/lib/postgresql/data
volumeClaimTemplates:
– metadata:
name: postgres-data
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 10Gi
应用配置
# 应用Deployment
kubectl apply -f deployment.yaml
# 应用Service
kubectl apply -f service.yaml
# 应用StatefulSet
kubectl apply -f statefulset.yaml
# 查看Pod状态
kubectl get pods
# 查看Service
kubectl get services
# 查看日志
kubectl logs <pod-name>
# 进入Pod
kubectl exec -it <pod-name> — /bin/sh
Kubernetes进阶
水平自动扩展
# hpa.yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: web-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: web-deployment
minReplicas: 3
maxReplicas: 10
metrics:
– type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
– type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80
配置管理
# configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
NODE_ENV: production
API_URL: https://api.example.com
# secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: app-secret
type: Opaque
data:
DATABASE_PASSWORD: cGFzc3dvcmQ= # base64 encoded
健康检查
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-deployment
spec:
template:
spec:
containers:
– name: web
image: my-node-app:latest
ports:
– containerPort: 3000
livenessProbe:
httpGet:
path: /health
port: 3000
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /ready
port: 3000
initialDelaySeconds: 5
periodSeconds: 5
完整的微服务架构示例
架构图
┌─────────────────────────────────────────────────────────────┐
│ Load Balancer │
└───────────────────────────┬─────────────────────────────────┘
│
┌───────────────┼───────────────┐
▼ ▼ ▼
┌───────────┐ ┌───────────┐ ┌───────────┐
│ API GW │ │ API GW │ │ API GW │
└─────┬─────┘ └─────┬─────┘ └─────┬─────┘
│ │ │
┌─────┴─────────────────┴─────────────────┴─────┐
│ │
┌───▼───┐ ┌───────┐ ┌─────────┐ ┌─────────┐
│ User │ │ Order │ │ Product │ │ Payment │
│Service│ │Service│ │ Service │ │ Service │
└───┬───┘ └───┬───┘ └────┬────┘ └────┬────┘
│ │ │ │
▼ ▼ ▼ ▼
┌─────────────────────────────────────────────────┐
│ PostgreSQL Cluster │
└─────────────────────────────────────────────────┘
服务间通信
// 使用gRPC进行服务间通信
const grpc = require('@grpc/grpc-js');
const protoLoader = require('@grpc/proto-loader');
const packageDefinition = protoLoader.loadSync('order.proto');
const orderProto = grpc.loadPackageDefinition(packageDefinition);
const client = new orderProto.OrderService(
'order-service:50051',
grpc.credentials.createInsecure()
);
client.createOrder({ userId: '123', items: ['item1'] }, (error, response) => {
if (!error) {
console.log('Order created:', response);
}
});
CI/CD集成
# .github/workflows/deploy.yml
name: Deploy to Kubernetes
on:
push:
branches:
– main
jobs:
build:
runs-on: ubuntu-latest
steps:
– uses: actions/checkout@v3
– name: Build Docker image
run: |
docker build -t ${{ secrets.DOCKER_REGISTRY }}/my-app:${{ github.sha }} .
– name: Push Docker image
run: |
echo "${{ secrets.DOCKER_PASSWORD }}" | docker login ${{ secrets.DOCKER_REGISTRY }} -u "${{ secrets.DOCKER_USERNAME }}" –password-stdin
docker push ${{ secrets.DOCKER_REGISTRY }}/my-app:${{ github.sha }}
– name: Deploy to Kubernetes
run: |
kubectl set image deployment/web-deployment web=${{ secrets.DOCKER_REGISTRY }}/my-app:${{ github.sha }}
总结
微服务架构配合Docker和Kubernetes,可以构建出高度可扩展、高可用的应用系统。虽然学习曲线比较陡峭,但一旦掌握,就能体会到它带来的巨大优势。
我的鬃狮蜥Hash对微服务也有自己的理解——它把晒太阳、吃饭、睡觉分成了三个独立的"服务",每个服务都能独立运行,互不影响。这也许就是微服务的精髓吧!
如果你对微服务或Kubernetes有任何问题,欢迎留言交流!我是欧阳瑞,极客之路,永无止境!
技术栈:Docker · Kubernetes · Docker Compose · Minikube · gRPC

