9.1 容器化概述

9.1.1 容器化架构

graph TB
    A[应用代码] --> B[Quarkus 应用]
    B --> C[容器镜像]
    C --> D[容器运行时]
    D --> E[Kubernetes 集群]
    
    F[Docker] --> C
    G[Podman] --> C
    H[Buildah] --> C
    
    E --> I[Pod]
    E --> J[Service]
    E --> K[Ingress]
    E --> L[ConfigMap]
    E --> M[Secret]

9.1.2 Quarkus 容器化优势

  • 快速启动时间:毫秒级启动
  • 低内存占用:原生镜像内存使用极低
  • 小镜像体积:优化的镜像层
  • 云原生支持:完美适配 Kubernetes

9.2 Docker 容器化

9.2.1 Dockerfile 配置

JVM 模式 Dockerfile

# 多阶段构建 - JVM 模式
FROM registry.access.redhat.com/ubi8/openjdk-17:1.15 AS builder

# 复制源代码
COPY --chown=185 . /app
WORKDIR /app

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

# 运行时镜像
FROM registry.access.redhat.com/ubi8/openjdk-17-runtime:1.15

# 设置环境变量
ENV LANGUAGE='en_US:en'
ENV JAVA_OPTS_APPEND="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager"

# 复制应用 JAR
COPY --from=builder --chown=185 /app/target/quarkus-app/lib/ /deployments/lib/
COPY --from=builder --chown=185 /app/target/quarkus-app/*.jar /deployments/
COPY --from=builder --chown=185 /app/target/quarkus-app/app/ /deployments/app/
COPY --from=builder --chown=185 /app/target/quarkus-app/quarkus/ /deployments/quarkus/

# 暴露端口
EXPOSE 8080

# 设置用户
USER 185

# 启动命令
ENTRYPOINT ["java", "-jar", "/deployments/quarkus-run.jar"]

原生镜像 Dockerfile

# 多阶段构建 - 原生模式
FROM quay.io/quarkus/ubi-quarkus-graalvm-builder-image:22.3-java17 AS builder

# 复制源代码
COPY --chown=quarkus:quarkus . /app
WORKDIR /app

# 构建原生镜像
RUN ./mvnw clean package -Pnative -DskipTests

# 运行时镜像
FROM quay.io/quarkus/quarkus-micro-image:2.0

# 复制原生可执行文件
COPY --from=builder --chown=1001 /app/target/*-runner /application

# 暴露端口
EXPOSE 8080

# 设置用户
USER 1001

# 启动命令
ENTRYPOINT ["./application", "-Dquarkus.http.host=0.0.0.0"]

9.2.2 Docker Compose 配置

# docker-compose.yml
version: '3.8'

services:
  # Quarkus 应用
  quarkus-app:
    build:
      context: .
      dockerfile: src/main/docker/Dockerfile.jvm
    ports:
      - "8080:8080"
    environment:
      - QUARKUS_DATASOURCE_JDBC_URL=jdbc:postgresql://postgres:5432/quarkus
      - QUARKUS_DATASOURCE_USERNAME=quarkus
      - QUARKUS_DATASOURCE_PASSWORD=quarkus
      - QUARKUS_REDIS_HOSTS=redis://redis:6379
    depends_on:
      - postgres
      - redis
    networks:
      - quarkus-network
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8080/q/health"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s

  # PostgreSQL 数据库
  postgres:
    image: postgres:15-alpine
    environment:
      - POSTGRES_DB=quarkus
      - POSTGRES_USER=quarkus
      - POSTGRES_PASSWORD=quarkus
    ports:
      - "5432:5432"
    volumes:
      - postgres_data:/var/lib/postgresql/data
      - ./init.sql:/docker-entrypoint-initdb.d/init.sql
    networks:
      - quarkus-network
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U quarkus"]
      interval: 10s
      timeout: 5s
      retries: 5

  # Redis 缓存
  redis:
    image: redis:7-alpine
    ports:
      - "6379:6379"
    volumes:
      - redis_data:/data
    networks:
      - quarkus-network
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      timeout: 5s
      retries: 3

  # Prometheus 监控
  prometheus:
    image: prom/prometheus:latest
    ports:
      - "9090:9090"
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml
      - prometheus_data:/prometheus
    networks:
      - quarkus-network
    command:
      - '--config.file=/etc/prometheus/prometheus.yml'
      - '--storage.tsdb.path=/prometheus'
      - '--web.console.libraries=/etc/prometheus/console_libraries'
      - '--web.console.templates=/etc/prometheus/consoles'
      - '--web.enable-lifecycle'

  # Grafana 可视化
  grafana:
    image: grafana/grafana:latest
    ports:
      - "3000:3000"
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=admin
    volumes:
      - grafana_data:/var/lib/grafana
      - ./grafana/dashboards:/etc/grafana/provisioning/dashboards
      - ./grafana/datasources:/etc/grafana/provisioning/datasources
    networks:
      - quarkus-network

volumes:
  postgres_data:
  redis_data:
  prometheus_data:
  grafana_data:

networks:
  quarkus-network:
    driver: bridge

9.2.3 容器构建脚本

#!/bin/bash
# build-container.sh

set -e

# 配置变量
APP_NAME="quarkus-demo"
VERSION="1.0.0"
REGISTRY="your-registry.com"
NAMESPACE="your-namespace"

# 构建模式:jvm 或 native
BUILD_MODE=${1:-jvm}

echo "构建 Quarkus 应用容器镜像..."
echo "应用名称: $APP_NAME"
echo "版本: $VERSION"
echo "构建模式: $BUILD_MODE"

# 清理之前的构建
echo "清理之前的构建..."
./mvnw clean

# 根据构建模式选择 Dockerfile
if [ "$BUILD_MODE" = "native" ]; then
    DOCKERFILE="src/main/docker/Dockerfile.native"
    IMAGE_TAG="$REGISTRY/$NAMESPACE/$APP_NAME:$VERSION-native"
    echo "构建原生镜像..."
else
    DOCKERFILE="src/main/docker/Dockerfile.jvm"
    IMAGE_TAG="$REGISTRY/$NAMESPACE/$APP_NAME:$VERSION-jvm"
    echo "构建 JVM 镜像..."
fi

# 构建 Docker 镜像
echo "构建 Docker 镜像: $IMAGE_TAG"
docker build -f $DOCKERFILE -t $IMAGE_TAG .

# 标记为 latest
LATEST_TAG="$REGISTRY/$NAMESPACE/$APP_NAME:latest-$BUILD_MODE"
docker tag $IMAGE_TAG $LATEST_TAG

echo "镜像构建完成:"
echo "  - $IMAGE_TAG"
echo "  - $LATEST_TAG"

# 推送到镜像仓库(可选)
read -p "是否推送到镜像仓库? (y/N): " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
    echo "推送镜像到仓库..."
    docker push $IMAGE_TAG
    docker push $LATEST_TAG
    echo "镜像推送完成"
fi

echo "容器构建流程完成"

9.3 Kubernetes 部署

9.3.1 基础部署配置

Deployment 配置

# k8s/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: quarkus-demo
  namespace: default
  labels:
    app: quarkus-demo
    version: v1
spec:
  replicas: 3
  selector:
    matchLabels:
      app: quarkus-demo
  template:
    metadata:
      labels:
        app: quarkus-demo
        version: v1
    spec:
      containers:
      - name: quarkus-demo
        image: your-registry.com/your-namespace/quarkus-demo:1.0.0-jvm
        ports:
        - containerPort: 8080
          name: http
        env:
        - name: QUARKUS_DATASOURCE_JDBC_URL
          valueFrom:
            configMapKeyRef:
              name: quarkus-config
              key: database.url
        - name: QUARKUS_DATASOURCE_USERNAME
          valueFrom:
            secretKeyRef:
              name: quarkus-secret
              key: database.username
        - name: QUARKUS_DATASOURCE_PASSWORD
          valueFrom:
            secretKeyRef:
              name: quarkus-secret
              key: database.password
        - name: QUARKUS_LOG_LEVEL
          value: "INFO"
        - name: JAVA_OPTS_APPEND
          value: "-Dquarkus.http.host=0.0.0.0 -Xmx512m -Xms256m"
        resources:
          requests:
            memory: "256Mi"
            cpu: "250m"
          limits:
            memory: "512Mi"
            cpu: "500m"
        livenessProbe:
          httpGet:
            path: /q/health/live
            port: 8080
          initialDelaySeconds: 30
          periodSeconds: 10
          timeoutSeconds: 5
          failureThreshold: 3
        readinessProbe:
          httpGet:
            path: /q/health/ready
            port: 8080
          initialDelaySeconds: 10
          periodSeconds: 5
          timeoutSeconds: 3
          failureThreshold: 3
        startupProbe:
          httpGet:
            path: /q/health/started
            port: 8080
          initialDelaySeconds: 10
          periodSeconds: 5
          timeoutSeconds: 3
          failureThreshold: 30
      restartPolicy: Always
      terminationGracePeriodSeconds: 30

Service 配置

# k8s/service.yaml
apiVersion: v1
kind: Service
metadata:
  name: quarkus-demo-service
  namespace: default
  labels:
    app: quarkus-demo
spec:
  selector:
    app: quarkus-demo
  ports:
  - name: http
    port: 80
    targetPort: 8080
    protocol: TCP
  type: ClusterIP

Ingress 配置

# k8s/ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: quarkus-demo-ingress
  namespace: default
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
    nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
    cert-manager.io/cluster-issuer: "letsencrypt-prod"
spec:
  tls:
  - hosts:
    - api.yourdomain.com
    secretName: quarkus-demo-tls
  rules:
  - host: api.yourdomain.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: quarkus-demo-service
            port:
              number: 80

9.3.2 配置管理

ConfigMap 配置

# k8s/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: quarkus-config
  namespace: default
data:
  application.properties: |
    # 数据库配置
    quarkus.datasource.db-kind=postgresql
    quarkus.datasource.jdbc.url=jdbc:postgresql://postgres-service:5432/quarkus
    quarkus.datasource.jdbc.max-size=20
    quarkus.datasource.jdbc.min-size=5
    
    # Redis 配置
    quarkus.redis.hosts=redis://redis-service:6379
    quarkus.redis.timeout=10s
    
    # 日志配置
    quarkus.log.console.enable=true
    quarkus.log.console.format=%d{HH:mm:ss} %-5p [%c{2.}] (%t) %s%e%n
    quarkus.log.console.level=INFO
    
    # 监控配置
    quarkus.micrometer.export.prometheus.enabled=true
    quarkus.micrometer.export.prometheus.path=/q/metrics
    
    # 健康检查配置
    quarkus.health.extensions.enabled=true
    quarkus.health.openapi.included=true
  
  database.url: "jdbc:postgresql://postgres-service:5432/quarkus"
  redis.url: "redis://redis-service:6379"
  log.level: "INFO"

Secret 配置

# k8s/secret.yaml
apiVersion: v1
kind: Secret
metadata:
  name: quarkus-secret
  namespace: default
type: Opaque
data:
  database.username: cXVhcmt1cw==  # base64 encoded 'quarkus'
  database.password: cXVhcmt1cw==  # base64 encoded 'quarkus'
  jwt.secret: bXlfc3VwZXJfc2VjcmV0X2tleQ==  # base64 encoded 'my_super_secret_key'
  redis.password: ""  # 空密码

9.3.3 部署脚本

#!/bin/bash
# deploy.sh

set -e

# 配置变量
NAMESPACE="default"
APP_NAME="quarkus-demo"
KUBECONFIG=${KUBECONFIG:-~/.kube/config}

echo "部署 Quarkus 应用到 Kubernetes..."
echo "命名空间: $NAMESPACE"
echo "应用名称: $APP_NAME"

# 检查 kubectl 连接
echo "检查 Kubernetes 连接..."
kubectl cluster-info --kubeconfig=$KUBECONFIG

# 创建命名空间(如果不存在)
echo "确保命名空间存在..."
kubectl create namespace $NAMESPACE --dry-run=client -o yaml | kubectl apply -f -

# 应用配置
echo "应用 ConfigMap 和 Secret..."
kubectl apply -f k8s/configmap.yaml -n $NAMESPACE
kubectl apply -f k8s/secret.yaml -n $NAMESPACE

# 部署应用
echo "部署应用..."
kubectl apply -f k8s/deployment.yaml -n $NAMESPACE
kubectl apply -f k8s/service.yaml -n $NAMESPACE
kubectl apply -f k8s/ingress.yaml -n $NAMESPACE

# 等待部署完成
echo "等待部署完成..."
kubectl rollout status deployment/$APP_NAME -n $NAMESPACE --timeout=300s

# 检查部署状态
echo "检查部署状态..."
kubectl get pods -l app=$APP_NAME -n $NAMESPACE
kubectl get services -l app=$APP_NAME -n $NAMESPACE
kubectl get ingress -n $NAMESPACE

echo "部署完成!"

# 获取访问信息
echo "\n访问信息:"
echo "内部访问: http://$APP_NAME-service.$NAMESPACE.svc.cluster.local"
echo "外部访问: https://api.yourdomain.com"
echo "\n健康检查:"
echo "kubectl port-forward service/$APP_NAME-service 8080:80 -n $NAMESPACE"
echo "curl http://localhost:8080/q/health"

9.4 云原生特性

9.4.1 自动扩缩容配置

HorizontalPodAutoscaler

# k8s/hpa.yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: quarkus-demo-hpa
  namespace: default
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: quarkus-demo
  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
  behavior:
    scaleDown:
      stabilizationWindowSeconds: 300
      policies:
      - type: Percent
        value: 10
        periodSeconds: 60
    scaleUp:
      stabilizationWindowSeconds: 60
      policies:
      - type: Percent
        value: 50
        periodSeconds: 60
      - type: Pods
        value: 2
        periodSeconds: 60
      selectPolicy: Max

VerticalPodAutoscaler

# k8s/vpa.yaml
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
  name: quarkus-demo-vpa
  namespace: default
spec:
  targetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: quarkus-demo
  updatePolicy:
    updateMode: "Auto"
  resourcePolicy:
    containerPolicies:
    - containerName: quarkus-demo
      minAllowed:
        cpu: 100m
        memory: 128Mi
      maxAllowed:
        cpu: 1
        memory: 1Gi
      controlledResources: ["cpu", "memory"]

9.4.2 服务网格集成

Istio 配置

# istio/virtual-service.yaml
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: quarkus-demo-vs
  namespace: default
spec:
  hosts:
  - api.yourdomain.com
  gateways:
  - quarkus-demo-gateway
  http:
  - match:
    - uri:
        prefix: /api/v1
    route:
    - destination:
        host: quarkus-demo-service
        port:
          number: 80
      weight: 90
    - destination:
        host: quarkus-demo-service-canary
        port:
          number: 80
      weight: 10
    fault:
      delay:
        percentage:
          value: 0.1
        fixedDelay: 5s
    retries:
      attempts: 3
      perTryTimeout: 2s
    timeout: 10s
---
apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
  name: quarkus-demo-gateway
  namespace: default
spec:
  selector:
    istio: ingressgateway
  servers:
  - port:
      number: 443
      name: https
      protocol: HTTPS
    tls:
      mode: SIMPLE
      credentialName: quarkus-demo-tls
    hosts:
    - api.yourdomain.com

目标规则

# istio/destination-rule.yaml
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: quarkus-demo-dr
  namespace: default
spec:
  host: quarkus-demo-service
  trafficPolicy:
    connectionPool:
      tcp:
        maxConnections: 100
      http:
        http1MaxPendingRequests: 50
        maxRequestsPerConnection: 10
    loadBalancer:
      simple: LEAST_CONN
    outlierDetection:
      consecutiveErrors: 3
      interval: 30s
      baseEjectionTime: 30s
      maxEjectionPercent: 50
  subsets:
  - name: v1
    labels:
      version: v1
  - name: canary
    labels:
      version: canary

9.4.3 监控和可观测性

ServiceMonitor 配置

# monitoring/service-monitor.yaml
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: quarkus-demo-metrics
  namespace: default
  labels:
    app: quarkus-demo
spec:
  selector:
    matchLabels:
      app: quarkus-demo
  endpoints:
  - port: http
    path: /q/metrics
    interval: 30s
    scrapeTimeout: 10s

Grafana Dashboard 配置

{
  "dashboard": {
    "id": null,
    "title": "Quarkus Application Metrics",
    "tags": ["quarkus", "microservices"],
    "timezone": "browser",
    "panels": [
      {
        "id": 1,
        "title": "HTTP Requests Rate",
        "type": "graph",
        "targets": [
          {
            "expr": "rate(http_server_requests_seconds_count{job=\"quarkus-demo\"}[5m])",
            "legendFormat": "{{method}} {{uri}}"
          }
        ]
      },
      {
        "id": 2,
        "title": "Response Time",
        "type": "graph",
        "targets": [
          {
            "expr": "histogram_quantile(0.95, rate(http_server_requests_seconds_bucket{job=\"quarkus-demo\"}[5m]))",
            "legendFormat": "95th percentile"
          }
        ]
      }
    ]
  }
}

9.5 CI/CD 集成

9.5.1 GitHub Actions 工作流

# .github/workflows/ci-cd.yml
name: CI/CD Pipeline

on:
  push:
    branches: [ main, develop ]
  pull_request:
    branches: [ main ]

env:
  REGISTRY: ghcr.io
  IMAGE_NAME: ${{ github.repository }}

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v3
    
    - name: Set up JDK 17
      uses: actions/setup-java@v3
      with:
        java-version: '17'
        distribution: 'temurin'
        
    - name: Cache Maven packages
      uses: actions/cache@v3
      with:
        path: ~/.m2
        key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
        restore-keys: ${{ runner.os }}-m2
        
    - name: Run tests
      run: ./mvnw clean test
      
    - name: Generate test report
      uses: dorny/test-reporter@v1
      if: success() || failure()
      with:
        name: Maven Tests
        path: target/surefire-reports/*.xml
        reporter: java-junit

  build-and-push:
    needs: test
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main'
    
    steps:
    - uses: actions/checkout@v3
    
    - name: Set up JDK 17
      uses: actions/setup-java@v3
      with:
        java-version: '17'
        distribution: 'temurin'
        
    - name: Log in to Container Registry
      uses: docker/login-action@v2
      with:
        registry: ${{ env.REGISTRY }}
        username: ${{ github.actor }}
        password: ${{ secrets.GITHUB_TOKEN }}
        
    - name: Extract metadata
      id: meta
      uses: docker/metadata-action@v4
      with:
        images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
        tags: |
          type=ref,event=branch
          type=ref,event=pr
          type=sha,prefix={{branch}}-
          type=raw,value=latest,enable={{is_default_branch}}
          
    - name: Build and push Docker image
      uses: docker/build-push-action@v4
      with:
        context: .
        file: src/main/docker/Dockerfile.jvm
        push: true
        tags: ${{ steps.meta.outputs.tags }}
        labels: ${{ steps.meta.outputs.labels }}

  deploy:
    needs: build-and-push
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main'
    
    steps:
    - uses: actions/checkout@v3
    
    - name: Set up kubectl
      uses: azure/setup-kubectl@v3
      with:
        version: 'latest'
        
    - name: Configure kubectl
      run: |
        echo "${{ secrets.KUBE_CONFIG }}" | base64 -d > kubeconfig
        export KUBECONFIG=kubeconfig
        
    - name: Deploy to Kubernetes
      run: |
        export KUBECONFIG=kubeconfig
        sed -i "s|IMAGE_TAG|${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}|g" k8s/deployment.yaml
        kubectl apply -f k8s/
        kubectl rollout status deployment/quarkus-demo -n default

9.5.2 GitLab CI/CD 配置

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

variables:
  MAVEN_OPTS: "-Dmaven.repo.local=$CI_PROJECT_DIR/.m2/repository"
  MAVEN_CLI_OPTS: "--batch-mode --errors --fail-at-end --show-version"
  DOCKER_DRIVER: overlay2
  DOCKER_TLS_CERTDIR: "/certs"

cache:
  paths:
    - .m2/repository/
    - target/

test:
  stage: test
  image: maven:3.8.6-openjdk-17
  script:
    - ./mvnw $MAVEN_CLI_OPTS clean test
  artifacts:
    reports:
      junit:
        - target/surefire-reports/TEST-*.xml
    paths:
      - target/
  coverage: '/Total.*?([0-9]{1,3})%/'

build-image:
  stage: build
  image: docker:20.10.16
  services:
    - docker:20.10.16-dind
  before_script:
    - echo $CI_REGISTRY_PASSWORD | docker login -u $CI_REGISTRY_USER --password-stdin $CI_REGISTRY
  script:
    - docker build -f src/main/docker/Dockerfile.jvm -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA .
    - docker tag $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA $CI_REGISTRY_IMAGE:latest
    - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
    - docker push $CI_REGISTRY_IMAGE:latest
  only:
    - main

deploy-staging:
  stage: deploy
  image: bitnami/kubectl:latest
  script:
    - kubectl config use-context $KUBE_CONTEXT
    - sed -i "s|IMAGE_TAG|$CI_REGISTRY_IMAGE:$CI_COMMIT_SHA|g" k8s/deployment.yaml
    - kubectl apply -f k8s/ -n staging
    - kubectl rollout status deployment/quarkus-demo -n staging
  environment:
    name: staging
    url: https://staging-api.yourdomain.com
  only:
    - main

deploy-production:
  stage: deploy
  image: bitnami/kubectl:latest
  script:
    - kubectl config use-context $KUBE_CONTEXT
    - sed -i "s|IMAGE_TAG|$CI_REGISTRY_IMAGE:$CI_COMMIT_SHA|g" k8s/deployment.yaml
    - kubectl apply -f k8s/ -n production
    - kubectl rollout status deployment/quarkus-demo -n production
  environment:
    name: production
    url: https://api.yourdomain.com
  when: manual
  only:
    - main

9.6 本章小结

9.6.1 核心概念回顾

  • 容器化优势:快速启动、低资源占用、一致性部署
  • Kubernetes 部署:声明式配置、自动化管理
  • 云原生特性:弹性扩缩容、服务网格、可观测性
  • CI/CD 集成:自动化构建、测试、部署流程

9.6.2 技术要点总结

  1. 多阶段构建:优化镜像大小和安全性
  2. 健康检查:确保应用可用性和可靠性
  3. 配置管理:分离配置和代码,支持多环境
  4. 监控集成:全面的应用和基础设施监控
  5. 自动扩缩容:根据负载自动调整资源

9.6.3 最佳实践

  • 使用非 root 用户运行容器
  • 实施资源限制和请求
  • 配置适当的健康检查
  • 使用 Secret 管理敏感信息
  • 实施滚动更新策略
  • 监控应用性能和资源使用

9.6.4 下一章预告

下一章将深入探讨 性能优化与生产实践,包括: - JVM 调优策略 - 原生镜像优化 - 缓存策略 - 数据库优化 - 生产环境最佳实践

通过本章学习,你已经掌握了 Quarkus 应用的容器化和云原生部署技能,能够构建可扩展、高可用的微服务应用。