Docker 和 Kubernetes 部署最佳实践 2027:构建可靠的容器化应用

1. 容器化的核心概念

容器化是一种轻量级的虚拟化技术,它允许应用程序及其依赖项被打包到一个标准化的单元中,称为容器。Docker 是最流行的容器化平台,而 Kubernetes 则是最流行的容器编排平台。

1.1 容器化的优势

  • 一致性:容器在任何环境中都以相同的方式运行
  • 隔离性:容器之间相互隔离,提高安全性
  • 可移植性:容器可以在不同的环境中轻松移动
  • 资源效率:容器比虚拟机更轻量,占用更少的资源
  • 快速部署:容器可以在几秒钟内启动和停止

2. Docker 最佳实践

2.1 Dockerfile 优化

# 使用官方基础镜像
FROM openjdk:25-jdk-slim

# 设置工作目录
WORKDIR /app

# 复制依赖文件
COPY pom.xml .
COPY mvnw .
COPY .mvn .mvn

# 下载依赖
RUN ./mvnw dependency:go-offline

# 复制源代码
COPY src src

# 构建应用
RUN ./mvnw package -DskipTests

# 暴露端口
EXPOSE 8080

# 运行应用
CMD ["java", "-jar", "target/app.jar"]

2.2 多阶段构建

# 构建阶段
FROM maven:3.9-eclipse-temurin-25 as builder
WORKDIR /app
COPY . .
RUN mvn package -DskipTests

# 运行阶段
FROM eclipse-temurin:25-jre-slim
WORKDIR /app
COPY --from=builder /app/target/app.jar .
EXPOSE 8080
CMD ["java", "-jar", "app.jar"]

2.3 镜像管理

  • 使用官方镜像:优先使用官方基础镜像
  • 固定版本:指定具体的镜像版本,避免使用 latest 标签
  • 定期更新:定期更新基础镜像,获取安全补丁
  • 镜像大小:使用 Alpine 等轻量级基础镜像
  • 镜像扫描:使用工具扫描镜像中的安全漏洞

3. Kubernetes 部署最佳实践

3.1 部署配置

apiVersion: apps/v1
kind: Deployment
metadata:
  name: user-service
  labels:
    app: user-service
spec:
  replicas: 3
  selector:
    matchLabels:
      app: user-service
  template:
    metadata:
      labels:
        app: user-service
    spec:
      containers:
      - name: user-service
        image: user-service:1.0.0
        ports:
        - containerPort: 8080
        resources:
          limits:
            memory: "512Mi"
            cpu: "500m"
          requests:
            memory: "256Mi"
            cpu: "200m"
        readinessProbe:
          httpGet:
            path: /actuator/health
            port: 8080
          initialDelaySeconds: 30
          periodSeconds: 10
        livenessProbe:
          httpGet:
            path: /actuator/health
            port: 8080
          initialDelaySeconds: 60
          periodSeconds: 30
        env:
        - name: SPRING_PROFILES_ACTIVE
          value: "production"
        - name: DATABASE_URL
          valueFrom:
            configMapKeyRef:
              name: app-config
              key: database.url
        - name: DATABASE_PASSWORD
          valueFrom:
            secretKeyRef:
              name: app-secrets
              key: database.password

3.2 服务配置

apiVersion: v1
kind: Service
metadata:
  name: user-service
spec:
  selector:
    app: user-service
  ports:
  - port: 80
    targetPort: 8080
  type: ClusterIP

3.3 配置管理

apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
data:
  database.url: "jdbc:mysql://mysql:3306/app"
  redis.url: "redis://redis:6379"
  spring.profiles.active: "production"

---
apiVersion: v1
kind: Secret
metadata:
  name: app-secrets
type: Opaque
data:
  database.password: c2VjcmV0
  redis.password: c2VjcmV0

4. 水平扩展

4.1 自动缩放

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: user-service-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: user-service
  minReplicas: 2
  maxReplicas: 10
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 70
  - type: Resource
    resource:
      name: memory
      target:
        type: Utilization
        averageUtilization: 80

4.2 手动缩放

# 手动缩放副本数
kubectl scale deployment user-service --replicas=5

# 查看部署状态
kubectl get deployments

5. 服务发现与负载均衡

5.1 服务发现

  • DNS 服务发现:Kubernetes 内置 DNS 服务,通过服务名称解析 IP 地址
  • 环境变量:Kubernetes 为每个服务创建环境变量
  • 服务网格:使用 Istio 等服务网格增强服务发现能力

5.2 负载均衡

  • ClusterIP:默认类型,仅在集群内部访问
  • NodePort:在每个节点上开放一个端口,外部可访问
  • LoadBalancer:使用云提供商的负载均衡器
  • Ingress:管理外部访问

6. 存储管理

6.1 存储类型

  • EmptyDir:临时存储,Pod 重启后数据丢失
  • HostPath:使用节点上的文件系统
  • PersistentVolumeClaim:持久化存储
  • ConfigMap:存储配置信息
  • Secret:存储敏感信息

6.2 持久化存储

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mysql-pvc
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi
  storageClassName: standard

---
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:8.0
        ports:
        - containerPort: 3306
        volumeMounts:
        - name: mysql-data
          mountPath: /var/lib/mysql
        env:
        - name: MYSQL_ROOT_PASSWORD
          valueFrom:
            secretKeyRef:
              name: mysql-secrets
              key: root.password
      volumes:
      - name: mysql-data
        persistentVolumeClaim:
          claimName: mysql-pvc

7. CI/CD 集成

7.1 GitHub Actions 配置

# .github/workflows/deploy.yml
name: Deploy

on:
  push:
    branches: [ main ]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v3
    - name: Set up JDK 25
      uses: actions/setup-java@v3
      with:
        java-version: '25'
        distribution: 'temurin'
    - name: Build with Maven
      run: mvn clean package -DskipTests
    - name: Build Docker image
      run: docker build -t user-service:${{ github.sha }} .
    - name: Login to Docker Hub
      run: echo "${{ secrets.DOCKER_PASSWORD }}" | docker login -u "${{ secrets.DOCKER_USERNAME }}" --password-stdin
    - name: Push Docker image
      run: |
        docker tag user-service:${{ github.sha }} user-service:latest
        docker push user-service:${{ github.sha }}
        docker push user-service:latest
  deploy:
    needs: build
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v3
    - name: Set up Kubectl
      uses: azure/setup-kubectl@v3
    - name: Configure Kubernetes context
      run: |
        echo "${{ secrets.KUBE_CONFIG }}" > kubeconfig.yml
        kubectl config use-context my-cluster
    - name: Update deployment
      run: |
        kubectl set image deployment/user-service user-service=user-service:${{ github.sha }}
        kubectl rollout status deployment/user-service

7.2 GitLab CI/CD 配置

# .gitlab-ci.yml
stages:
  - build
  - test
  - deploy

build:
  stage: build
  image: maven:3.9-eclipse-temurin-25
  script:
    - mvn clean package -DskipTests
    - docker build -t user-service:${CI_COMMIT_SHA} .
    - docker tag user-service:${CI_COMMIT_SHA} user-service:latest
    - docker login -u ${DOCKER_USERNAME} -p ${DOCKER_PASSWORD}
    - docker push user-service:${CI_COMMIT_SHA}
    - docker push user-service:latest

test:
  stage: test
  image: maven:3.9-eclipse-temurin-25
  script:
    - mvn test

deploy:
  stage: deploy
  image: bitnami/kubectl:latest
  script:
    - echo "${KUBE_CONFIG}" > kubeconfig.yml
    - kubectl config use-context my-cluster
    - kubectl set image deployment/user-service user-service=user-service:${CI_COMMIT_SHA}
    - kubectl rollout status deployment/user-service
  environment:
    name: production
  only:
    - main

8. 监控与日志

8.1 监控配置

apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: user-service-monitor
  namespace: monitoring
spec:
  selector:
    matchLabels:
      app: user-service
  endpoints:
  - port: http
    path: /actuator/prometheus
    interval: 15s

---
apiVersion: monitoring.coreos.com/v1
kind: PodMonitor
metadata:
  name: user-service-pod-monitor
  namespace: monitoring
spec:
  selector:
    matchLabels:
      app: user-service
  podMetricsEndpoints:
  - port: http
    path: /actuator/prometheus
    interval: 15s

8.2 日志管理

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: fluentd
  namespace: kube-system
spec:
  selector:
    matchLabels:
      name: fluentd
  template:
    metadata:
      labels:
        name: fluentd
    spec:
      containers:
      - name: fluentd
        image: fluent/fluentd-kubernetes-daemonset:v1.14-debian-elasticsearch7
        env:
        - name:  FLUENT_ELASTICSEARCH_HOST
          value: "elasticsearch.monitoring.svc.cluster.local"
        - name:  FLUENT_ELASTICSEARCH_PORT
          value: "9200"
        volumeMounts:
        - name: varlog
          mountPath: /var/log
        - name: varlibdockercontainers
          mountPath: /var/lib/docker/containers
          readOnly: true
      volumes:
      - name: varlog
        hostPath:
          path: /var/log
      - name: varlibdockercontainers
        hostPath:
          path: /var/lib/docker/containers

9. 安全最佳实践

9.1 容器安全

  • 使用官方镜像:避免使用不可信的镜像
  • 最小化镜像:只包含必要的组件
  • 非 root 用户:使用非 root 用户运行容器
  • 限制权限:使用最小权限原则
  • 镜像扫描:定期扫描镜像中的安全漏洞

9.2 网络安全

  • 网络策略:限制容器间通信
  • TLS 加密:使用 HTTPS
  • 防火墙:配置适当的防火墙规则
  • 入侵检测:使用入侵检测系统

9.3 集群安全

  • RBAC:使用基于角色的访问控制
  • ** secrets 管理**:使用 secrets 存储敏感信息
  • Pod 安全策略:限制 Pod 的权限
  • 定期审计:定期审计集群配置

10. 实际应用案例

10.1 微服务部署

# 部署多个微服务
apiVersion: apps/v1
kind: Deployment
metadata:
  name: order-service
spec:
  replicas: 3
  selector:
    matchLabels:
      app: order-service
  template:
    metadata:
      labels:
        app: order-service
    spec:
      containers:
      - name: order-service
        image: order-service:1.0.0
        ports:
        - containerPort: 8080
        resources:
          limits:
            memory: "512Mi"
            cpu: "500m"
          requests:
            memory: "256Mi"
            cpu: "200m"
        readinessProbe:
          httpGet:
            path: /actuator/health
            port: 8080
        livenessProbe:
          httpGet:
            path: /actuator/health
            port: 8080

---
apiVersion: v1
kind: Service
metadata:
  name: order-service
spec:
  selector:
    app: order-service
  ports:
  - port: 80
    targetPort: 8080
  type: ClusterIP

10.2 数据库部署

# 部署 MySQL 数据库
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: mysql
spec:
  serviceName: mysql
  replicas: 1
  selector:
    matchLabels:
      app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
      - name: mysql
        image: mysql:8.0
        ports:
        - containerPort: 3306
        volumeMounts:
        - name: mysql-data
          mountPath: /var/lib/mysql
        env:
        - name: MYSQL_ROOT_PASSWORD
          valueFrom:
            secretKeyRef:
              name: mysql-secrets
              key: root.password
        - name: MYSQL_DATABASE
          value: "app"
  volumeClaimTemplates:
  - metadata:
      name: mysql-data
    spec:
      accessModes:
      - ReadWriteOnce
      resources:
        requests:
          storage: 10Gi
      storageClassName: standard

---
apiVersion: v1
kind: Service
metadata:
  name: mysql
spec:
  selector:
    app: mysql
  ports:
  - port: 3306
    targetPort: 3306
  clusterIP: None

11. 总结与最佳实践

11.1 最佳实践

  1. 容器化:使用 Docker 容器化应用,提高部署一致性
  2. 镜像管理:使用官方镜像,定期更新,扫描漏洞
  3. Kubernetes 部署:使用 Deployment、Service、ConfigMap 等资源
  4. 水平扩展:使用 HPA 实现自动缩放
  5. 服务发现:使用 Kubernetes 内置的服务发现机制
  6. 存储管理:使用 PersistentVolumeClaim 管理持久化存储
  7. CI/CD 集成:实现自动化的构建和部署
  8. 监控与日志:使用 Prometheus、Grafana、ELK 等工具
  9. 安全:从容器、网络、集群层面加强安全措施
  10. 备份与恢复:定期备份数据,制定恢复策略

11.2 注意事项

  1. 资源配置:合理配置容器的资源请求和限制
  2. 健康检查:配置适当的 readiness 和 liveness 探针
  3. 滚动更新:使用滚动更新策略,减少服务中断
  4. 命名规范:使用统一的命名规范,提高可维护性
  5. 文档:编写详细的部署文档,便于团队协作

别叫我大神,叫我 Alex 就好。这其实可以更优雅一点,通过合理使用 Docker 和 Kubernetes,我们可以构建出更可靠、更高效的容器化应用。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐