微服务架构:使用Docker+Kubernetes部署应用
微服务架构:使用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 downKubernetes入门
什么是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/shKubernetes进阶
水平自动扩展
# 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
