微服务架构:使用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

更多推荐