Skip to content

Latest commit

 

History

History
966 lines (901 loc) · 29.9 KB

File metadata and controls

966 lines (901 loc) · 29.9 KB

部署架构文档

一、部署架构概览

1.1 生产环境架构图

┌─────────────────────────────────────────────────────────────────────────────┐
│                              Internet / VPN                                  │
└────────────────────────────────┬────────────────────────────────────────────┘
                                  │
                    ┌─────────────▼────────────────┐
                    │    Load Balancer (NGINX)     │
                    │    - SSL Termination         │
                    │    - Layer 7 LB              │
                    └─────────────┬────────────────┘
                                  │
┌─────────────────────────────────┼────────────────────────────────────────────┐
│  Kubernetes Cluster             │                                            │
│                                 │                                            │
│  ┌──────────────────────────────▼─────────────────────────────────────┐     │
│  │                    Ingress Controller                              │     │
│  │                    (nginx-ingress)                                 │     │
│  └──────────────────────────────┬─────────────────────────────────────┘     │
│                                 │                                            │
│         ┌───────────────────────┼───────────────────────┐                   │
│         │                       │                       │                   │
│  ┌──────▼──────────┐  ┌────────▼──────────┐  ┌────────▼──────────┐        │
│  │  API Service    │  │  API Service      │  │  API Service      │        │
│  │  Pod 1          │  │  Pod 2            │  │  Pod 3            │        │
│  │  (Spring Boot)  │  │  (Spring Boot)    │  │  (Spring Boot)    │        │
│  └──────┬──────────┘  └────────┬──────────┘  └────────┬──────────┘        │
│         │                       │                       │                   │
│         └───────────────────────┼───────────────────────┘                   │
│                                 │                                            │
│              ┌──────────────────┼──────────────────┐                        │
│              │                  │                  │                        │
│     ┌────────▼────────┐  ┌──────▼─────────┐  ┌───▼────────────┐           │
│     │  PostgreSQL     │  │   Redis        │  │  Kafka Connect │           │
│     │  StatefulSet    │  │   Cluster      │  │  Deployment    │           │
│     │  (3 replicas)   │  │   (6 pods)     │  │  (3 workers)   │           │
│     └─────────────────┘  └────────────────┘  └───┬────────────┘           │
│                                                   │                         │
│                                    ┌──────────────▼─────────────┐          │
│                                    │     Kafka Cluster          │          │
│                                    │     StatefulSet            │          │
│                                    │     (3 brokers)            │          │
│                                    └────────────────────────────┘          │
│                                                                              │
└──────────────────────────────────────────────────────────────────────────────┘
                                    │
                     ┌──────────────┼──────────────┐
                     │              │              │
            ┌────────▼────────┐ ┌──▼──────────┐ ┌▼────────────┐
            │  Source DBs     │ │  Source DBs │ │ Target DBs  │
            │  (MySQL)        │ │  (Oracle)   │ │ (PostgreSQL)│
            └─────────────────┘ └─────────────┘ └─────────────┘

1.2 网络拓扑

┌─────────────────────────────────────────────────────────────┐
│  DMZ Zone (Public Network)                                  │
│  ┌─────────────┐                                            │
│  │ Load Balancer│ (Public IP)                               │
│  └──────┬──────┘                                            │
└─────────┼───────────────────────────────────────────────────┘
          │
┌─────────▼───────────────────────────────────────────────────┐
│  Application Zone (Private Network: 10.1.0.0/16)            │
│  ┌───────────────────────────────────────────────────┐      │
│  │  K8s Nodes (10.1.1.0/24)                          │      │
│  │  - node-1: 10.1.1.10                              │      │
│  │  - node-2: 10.1.1.11                              │      │
│  │  - node-3: 10.1.1.12                              │      │
│  └───────────────────────────────────────────────────┘      │
└──────────────────────────────────────────────────────────────┘
          │
┌─────────▼───────────────────────────────────────────────────┐
│  Data Zone (Private Network: 10.2.0.0/16)                   │
│  ┌───────────────────────────────────────────────────┐      │
│  │  PostgreSQL Cluster (10.2.1.0/24)                 │      │
│  │  - pg-master: 10.2.1.10                           │      │
│  │  - pg-slave1: 10.2.1.11                           │      │
│  │  - pg-slave2: 10.2.1.12                           │      │
│  └───────────────────────────────────────────────────┘      │
│  ┌───────────────────────────────────────────────────┐      │
│  │  Redis Cluster (10.2.2.0/24)                      │      │
│  │  - redis-1: 10.2.2.10                             │      │
│  │  - redis-2: 10.2.2.11                             │      │
│  │  - redis-3: 10.2.2.12                             │      │
│  └───────────────────────────────────────────────────┘      │
│  ┌───────────────────────────────────────────────────┐      │
│  │  Kafka Cluster (10.2.3.0/24)                      │      │
│  │  - kafka-1: 10.2.3.10                             │      │
│  │  - kafka-2: 10.2.3.11                             │      │
│  │  - kafka-3: 10.2.3.12                             │      │
│  └───────────────────────────────────────────────────┘      │
└──────────────────────────────────────────────────────────────┘

二、Kubernetes部署

2.1 命名空间设计

# namespaces.yaml
apiVersion: v1
kind: Namespace
metadata:
  name: db-sync-prod
  labels:
    name: db-sync-prod
    environment: production
---
apiVersion: v1
kind: Namespace
metadata:
  name: db-sync-staging
  labels:
    name: db-sync-staging
    environment: staging

2.2 Spring Boot API Deployment

# api-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: db-sync-api
  namespace: db-sync-prod
  labels:
    app: db-sync-api
    version: v1.0.0
spec:
  replicas: 3
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
  selector:
    matchLabels:
      app: db-sync-api
  template:
    metadata:
      labels:
        app: db-sync-api
        version: v1.0.0
      annotations:
        prometheus.io/scrape: "true"
        prometheus.io/port: "8080"
        prometheus.io/path: "/actuator/prometheus"
    spec:
      serviceAccountName: db-sync-api
      containers:
      - name: api
        image: your-registry.com/db-sync-api:v1.0.0
        imagePullPolicy: Always
        ports:
        - name: http
          containerPort: 8080
          protocol: TCP
        - name: actuator
          containerPort: 8081
          protocol: TCP
        env:
        - name: SPRING_PROFILES_ACTIVE
          value: "prod"
        - name: JAVA_OPTS
          value: "-Xms2g -Xmx4g -XX:+UseG1GC -XX:MaxGCPauseMillis=200"
        - name: DB_HOST
          valueFrom:
            configMapKeyRef:
              name: db-sync-config
              key: db.host
        - name: DB_PASSWORD
          valueFrom:
            secretKeyRef:
              name: db-sync-secrets
              key: db.password
        - name: KAFKA_BOOTSTRAP_SERVERS
          valueFrom:
            configMapKeyRef:
              name: db-sync-config
              key: kafka.bootstrap.servers
        - name: REDIS_HOST
          valueFrom:
            configMapKeyRef:
              name: db-sync-config
              key: redis.host
        resources:
          requests:
            memory: "2Gi"
            cpu: "1000m"
          limits:
            memory: "4Gi"
            cpu: "2000m"
        livenessProbe:
          httpGet:
            path: /actuator/health/liveness
            port: 8081
          initialDelaySeconds: 60
          periodSeconds: 10
          timeoutSeconds: 5
          failureThreshold: 3
        readinessProbe:
          httpGet:
            path: /actuator/health/readiness
            port: 8081
          initialDelaySeconds: 30
          periodSeconds: 5
          timeoutSeconds: 3
          failureThreshold: 3
        volumeMounts:
        - name: config
          mountPath: /app/config
          readOnly: true
        - name: logs
          mountPath: /app/logs
      volumes:
      - name: config
        configMap:
          name: db-sync-config
      - name: logs
        emptyDir: {}
      affinity:
        podAntiAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
          - weight: 100
            podAffinityTerm:
              labelSelector:
                matchExpressions:
                - key: app
                  operator: In
                  values:
                  - db-sync-api
              topologyKey: kubernetes.io/hostname

2.3 Service定义

# api-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: db-sync-api
  namespace: db-sync-prod
  labels:
    app: db-sync-api
spec:
  type: ClusterIP
  ports:
  - name: http
    port: 80
    targetPort: 8080
    protocol: TCP
  - name: actuator
    port: 8081
    targetPort: 8081
    protocol: TCP
  selector:
    app: db-sync-api
  sessionAffinity: None

2.4 Ingress配置

# ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: db-sync-ingress
  namespace: db-sync-prod
  annotations:
    kubernetes.io/ingress.class: "nginx"
    cert-manager.io/cluster-issuer: "letsencrypt-prod"
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
    nginx.ingress.kubernetes.io/rate-limit: "100"
    nginx.ingress.kubernetes.io/limit-rps: "10"
spec:
  tls:
  - hosts:
    - api.dbsync.example.com
    secretName: dbsync-tls-secret
  rules:
  - host: api.dbsync.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: db-sync-api
            port:
              number: 80

2.5 ConfigMap和Secret

# configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: db-sync-config
  namespace: db-sync-prod
data:
  application.yaml: |
    server:
      port: 8080
    management:
      server:
        port: 8081
      endpoints:
        web:
          exposure:
            include: health,info,prometheus,metrics
    spring:
      application:
        name: db-sync-api
      datasource:
        url: jdbc:postgresql://${DB_HOST}:5432/dbsync_metadata
        username: dbsync_user
        hikari:
          maximum-pool-size: 20
          minimum-idle: 5
          connection-timeout: 30000
      kafka:
        bootstrap-servers: ${KAFKA_BOOTSTRAP_SERVERS}
      data:
        redis:
          host: ${REDIS_HOST}
          port: 6379
          database: 0
          timeout: 3000ms

  db.host: "postgresql-primary.db-sync-prod.svc.cluster.local"
  kafka.bootstrap.servers: "kafka-0.kafka-headless.db-sync-prod.svc.cluster.local:9092,kafka-1.kafka-headless.db-sync-prod.svc.cluster.local:9092,kafka-2.kafka-headless.db-sync-prod.svc.cluster.local:9092"
  redis.host: "redis-cluster.db-sync-prod.svc.cluster.local"
---
# secret.yaml
apiVersion: v1
kind: Secret
metadata:
  name: db-sync-secrets
  namespace: db-sync-prod
type: Opaque
stringData:
  db.password: "your-secure-password"
  redis.password: "your-redis-password"
  jwt.secret: "your-jwt-secret-key"

2.6 Kafka Connect Deployment

# kafka-connect-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: kafka-connect
  namespace: db-sync-prod
  labels:
    app: kafka-connect
spec:
  replicas: 3
  selector:
    matchLabels:
      app: kafka-connect
  template:
    metadata:
      labels:
        app: kafka-connect
    spec:
      containers:
      - name: kafka-connect
        image: debezium/connect:2.5
        ports:
        - containerPort: 8083
          name: rest-api
        env:
        - name: BOOTSTRAP_SERVERS
          value: "kafka-0.kafka-headless:9092,kafka-1.kafka-headless:9092,kafka-2.kafka-headless:9092"
        - name: GROUP_ID
          value: "db-sync-connect-cluster"
        - name: CONFIG_STORAGE_TOPIC
          value: "db-sync-connect-configs"
        - name: OFFSET_STORAGE_TOPIC
          value: "db-sync-connect-offsets"
        - name: STATUS_STORAGE_TOPIC
          value: "db-sync-connect-status"
        - name: CONFIG_STORAGE_REPLICATION_FACTOR
          value: "3"
        - name: OFFSET_STORAGE_REPLICATION_FACTOR
          value: "3"
        - name: STATUS_STORAGE_REPLICATION_FACTOR
          value: "3"
        - name: CONNECT_KEY_CONVERTER
          value: "org.apache.kafka.connect.json.JsonConverter"
        - name: CONNECT_VALUE_CONVERTER
          value: "org.apache.kafka.connect.json.JsonConverter"
        - name: CONNECT_KEY_CONVERTER_SCHEMAS_ENABLE
          value: "false"
        - name: CONNECT_VALUE_CONVERTER_SCHEMAS_ENABLE
          value: "false"
        resources:
          requests:
            memory: "2Gi"
            cpu: "1000m"
          limits:
            memory: "4Gi"
            cpu: "2000m"
        livenessProbe:
          httpGet:
            path: /
            port: 8083
          initialDelaySeconds: 60
          periodSeconds: 10
        readinessProbe:
          httpGet:
            path: /
            port: 8083
          initialDelaySeconds: 30
          periodSeconds: 5
---
apiVersion: v1
kind: Service
metadata:
  name: kafka-connect
  namespace: db-sync-prod
spec:
  type: ClusterIP
  ports:
  - port: 8083
    targetPort: 8083
  selector:
    app: kafka-connect

2.7 PostgreSQL StatefulSet

# postgresql-statefulset.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: postgresql
  namespace: db-sync-prod
spec:
  serviceName: postgresql-headless
  replicas: 3
  selector:
    matchLabels:
      app: postgresql
  template:
    metadata:
      labels:
        app: postgresql
    spec:
      containers:
      - name: postgresql
        image: postgres:15-alpine
        ports:
        - containerPort: 5432
          name: postgresql
        env:
        - name: POSTGRES_DB
          value: "dbsync_metadata"
        - name: POSTGRES_USER
          value: "dbsync_user"
        - name: POSTGRES_PASSWORD
          valueFrom:
            secretKeyRef:
              name: db-sync-secrets
              key: db.password
        - name: PGDATA
          value: "/var/lib/postgresql/data/pgdata"
        volumeMounts:
        - name: data
          mountPath: /var/lib/postgresql/data
        resources:
          requests:
            memory: "2Gi"
            cpu: "1000m"
          limits:
            memory: "4Gi"
            cpu: "2000m"
  volumeClaimTemplates:
  - metadata:
      name: data
    spec:
      accessModes: ["ReadWriteOnce"]
      storageClassName: "ssd-storage"
      resources:
        requests:
          storage: 100Gi
---
apiVersion: v1
kind: Service
metadata:
  name: postgresql-headless
  namespace: db-sync-prod
spec:
  type: ClusterIP
  clusterIP: None
  ports:
  - port: 5432
    targetPort: 5432
  selector:
    app: postgresql
---
apiVersion: v1
kind: Service
metadata:
  name: postgresql-primary
  namespace: db-sync-prod
spec:
  type: ClusterIP
  ports:
  - port: 5432
    targetPort: 5432
  selector:
    app: postgresql
    role: primary

2.8 Kafka StatefulSet

# kafka-statefulset.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: kafka
  namespace: db-sync-prod
spec:
  serviceName: kafka-headless
  replicas: 3
  selector:
    matchLabels:
      app: kafka
  template:
    metadata:
      labels:
        app: kafka
    spec:
      containers:
      - name: kafka
        image: confluentinc/cp-kafka:7.5.0
        ports:
        - containerPort: 9092
          name: plaintext
        - containerPort: 9093
          name: ssl
        env:
        - name: KAFKA_BROKER_ID
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
        - name: KAFKA_ZOOKEEPER_CONNECT
          value: "zookeeper:2181"
        - name: KAFKA_ADVERTISED_LISTENERS
          value: "PLAINTEXT://$(POD_NAME).kafka-headless:9092"
        - name: KAFKA_LISTENERS
          value: "PLAINTEXT://0.0.0.0:9092"
        - name: KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR
          value: "3"
        - name: KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR
          value: "3"
        - name: KAFKA_TRANSACTION_STATE_LOG_MIN_ISR
          value: "2"
        - name: KAFKA_MIN_INSYNC_REPLICAS
          value: "2"
        - name: KAFKA_LOG_RETENTION_HOURS
          value: "168"  # 7天
        - name: KAFKA_LOG_SEGMENT_BYTES
          value: "1073741824"  # 1GB
        volumeMounts:
        - name: data
          mountPath: /var/lib/kafka/data
        resources:
          requests:
            memory: "4Gi"
            cpu: "2000m"
          limits:
            memory: "8Gi"
            cpu: "4000m"
  volumeClaimTemplates:
  - metadata:
      name: data
    spec:
      accessModes: ["ReadWriteOnce"]
      storageClassName: "ssd-storage"
      resources:
        requests:
          storage: 500Gi

三、Docker Compose部署(开发/测试环境)

3.1 docker-compose.yml

version: '3.8'

services:
  # PostgreSQL元数据库
  postgres:
    image: postgres:15-alpine
    container_name: dbsync-postgres
    environment:
      POSTGRES_DB: dbsync_metadata
      POSTGRES_USER: dbsync_user
      POSTGRES_PASSWORD: dbsync_pass
    ports:
      - "5432:5432"
    volumes:
      - postgres-data:/var/lib/postgresql/data
      - ./init-scripts:/docker-entrypoint-initdb.d
    networks:
      - dbsync-network
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U dbsync_user -d dbsync_metadata"]
      interval: 10s
      timeout: 5s
      retries: 5

  # Redis
  redis:
    image: redis:7-alpine
    container_name: dbsync-redis
    command: redis-server --appendonly yes
    ports:
      - "6379:6379"
    volumes:
      - redis-data:/data
    networks:
      - dbsync-network
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 5s
      timeout: 3s
      retries: 5

  # Zookeeper(Kafka依赖)
  zookeeper:
    image: confluentinc/cp-zookeeper:7.5.0
    container_name: dbsync-zookeeper
    environment:
      ZOOKEEPER_CLIENT_PORT: 2181
      ZOOKEEPER_TICK_TIME: 2000
    ports:
      - "2181:2181"
    volumes:
      - zookeeper-data:/var/lib/zookeeper/data
      - zookeeper-logs:/var/lib/zookeeper/log
    networks:
      - dbsync-network

  # Kafka
  kafka:
    image: confluentinc/cp-kafka:7.5.0
    container_name: dbsync-kafka
    depends_on:
      - zookeeper
    ports:
      - "9092:9092"
      - "9093:9093"
    environment:
      KAFKA_BROKER_ID: 1
      KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
      KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:9092,PLAINTEXT_HOST://localhost:9093
      KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT
      KAFKA_INTER_BROKER_LISTENER_NAME: PLAINTEXT
      KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
      KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: 1
      KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: 1
    volumes:
      - kafka-data:/var/lib/kafka/data
    networks:
      - dbsync-network
    healthcheck:
      test: ["CMD-SHELL", "kafka-broker-api-versions --bootstrap-server localhost:9092"]
      interval: 10s
      timeout: 10s
      retries: 5

  # Kafka Connect
  kafka-connect:
    image: debezium/connect:2.5
    container_name: dbsync-kafka-connect
    depends_on:
      kafka:
        condition: service_healthy
    ports:
      - "8083:8083"
    environment:
      BOOTSTRAP_SERVERS: kafka:9092
      GROUP_ID: db-sync-connect-cluster
      CONFIG_STORAGE_TOPIC: db-sync-connect-configs
      OFFSET_STORAGE_TOPIC: db-sync-connect-offsets
      STATUS_STORAGE_TOPIC: db-sync-connect-status
      CONFIG_STORAGE_REPLICATION_FACTOR: 1
      OFFSET_STORAGE_REPLICATION_FACTOR: 1
      STATUS_STORAGE_REPLICATION_FACTOR: 1
      CONNECT_KEY_CONVERTER: org.apache.kafka.connect.json.JsonConverter
      CONNECT_VALUE_CONVERTER: org.apache.kafka.connect.json.JsonConverter
      CONNECT_KEY_CONVERTER_SCHEMAS_ENABLE: false
      CONNECT_VALUE_CONVERTER_SCHEMAS_ENABLE: false
    networks:
      - dbsync-network
    healthcheck:
      test: ["CMD-SHELL", "curl -f http://localhost:8083/ || exit 1"]
      interval: 10s
      timeout: 5s
      retries: 5

  # Spring Boot API
  api:
    build:
      context: ../db-sync-api
      dockerfile: Dockerfile
    container_name: dbsync-api
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_healthy
      kafka:
        condition: service_healthy
      kafka-connect:
        condition: service_healthy
    ports:
      - "8080:8080"
      - "8081:8081"
    environment:
      SPRING_PROFILES_ACTIVE: dev
      SPRING_DATASOURCE_URL: jdbc:postgresql://postgres:5432/dbsync_metadata
      SPRING_DATASOURCE_USERNAME: dbsync_user
      SPRING_DATASOURCE_PASSWORD: dbsync_pass
      SPRING_KAFKA_BOOTSTRAP_SERVERS: kafka:9092
      SPRING_DATA_REDIS_HOST: redis
      KAFKA_CONNECT_URL: http://kafka-connect:8083
    networks:
      - dbsync-network
    volumes:
      - ./logs:/app/logs

  # Prometheus(监控)
  prometheus:
    image: prom/prometheus:latest
    container_name: dbsync-prometheus
    ports:
      - "9090:9090"
    volumes:
      - ./monitoring/prometheus.yml:/etc/prometheus/prometheus.yml
      - prometheus-data:/prometheus
    command:
      - '--config.file=/etc/prometheus/prometheus.yml'
      - '--storage.tsdb.path=/prometheus'
    networks:
      - dbsync-network

  # Grafana(可视化)
  grafana:
    image: grafana/grafana:latest
    container_name: dbsync-grafana
    ports:
      - "3000:3000"
    environment:
      GF_SECURITY_ADMIN_USER: admin
      GF_SECURITY_ADMIN_PASSWORD: admin
    volumes:
      - grafana-data:/var/lib/grafana
      - ./monitoring/grafana/dashboards:/etc/grafana/provisioning/dashboards
      - ./monitoring/grafana/datasources:/etc/grafana/provisioning/datasources
    networks:
      - dbsync-network
    depends_on:
      - prometheus

networks:
  dbsync-network:
    driver: bridge

volumes:
  postgres-data:
  redis-data:
  zookeeper-data:
  zookeeper-logs:
  kafka-data:
  prometheus-data:
  grafana-data:

3.2 启动脚本

#!/bin/bash
# start.sh

echo "Starting DB Sync Platform..."

# 创建必要的目录
mkdir -p logs
mkdir -p init-scripts
mkdir -p monitoring/grafana/dashboards
mkdir -p monitoring/grafana/datasources

# 启动所有服务
docker-compose up -d

# 等待服务启动
echo "Waiting for services to be ready..."
sleep 30

# 检查服务状态
docker-compose ps

echo "DB Sync Platform started successfully!"
echo "API: http://localhost:8080"
echo "Kafka Connect: http://localhost:8083"
echo "Prometheus: http://localhost:9090"
echo "Grafana: http://localhost:3000 (admin/admin)"

四、监控配置

4.1 Prometheus配置

# monitoring/prometheus.yml
global:
  scrape_interval: 15s
  evaluation_interval: 15s

scrape_configs:
  # Spring Boot API
  - job_name: 'db-sync-api'
    metrics_path: '/actuator/prometheus'
    static_configs:
      - targets: ['api:8081']
        labels:
          application: 'db-sync-api'
          environment: 'prod'

  # Kafka Connect
  - job_name: 'kafka-connect'
    static_configs:
      - targets: ['kafka-connect:8083']

  # PostgreSQL Exporter
  - job_name: 'postgresql'
    static_configs:
      - targets: ['postgres-exporter:9187']

  # Redis Exporter
  - job_name: 'redis'
    static_configs:
      - targets: ['redis-exporter:9121']

  # Kafka Exporter
  - job_name: 'kafka'
    static_configs:
      - targets: ['kafka-exporter:9308']

4.2 Grafana Dashboard配置

详见 monitoring/grafana/dashboards/db-sync-dashboard.json

五、CI/CD流水线

5.1 GitLab CI配置

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

variables:
  MAVEN_OPTS: "-Dmaven.repo.local=.m2/repository"
  DOCKER_REGISTRY: "your-registry.com"
  IMAGE_NAME: "db-sync-api"

# Maven编译
build:
  stage: build
  image: maven:3.9-openjdk-17
  script:
    - mvn clean compile
  cache:
    paths:
      - .m2/repository
  only:
    - branches

# 单元测试
test:
  stage: test
  image: maven:3.9-openjdk-17
  script:
    - mvn test
  artifacts:
    reports:
      junit: '**/target/surefire-reports/TEST-*.xml'
  coverage: '/Total.*?(\d+\.?\d*)%/'
  only:
    - branches

# 打包Docker镜像
package:
  stage: package
  image: docker:latest
  services:
    - docker:dind
  script:
    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $DOCKER_REGISTRY
    - docker build -t $DOCKER_REGISTRY/$IMAGE_NAME:$CI_COMMIT_SHA .
    - docker tag $DOCKER_REGISTRY/$IMAGE_NAME:$CI_COMMIT_SHA $DOCKER_REGISTRY/$IMAGE_NAME:latest
    - docker push $DOCKER_REGISTRY/$IMAGE_NAME:$CI_COMMIT_SHA
    - docker push $DOCKER_REGISTRY/$IMAGE_NAME:latest
  only:
    - main
    - develop

# 部署到Kubernetes
deploy-staging:
  stage: deploy
  image: bitnami/kubectl:latest
  script:
    - kubectl config use-context staging
    - kubectl set image deployment/db-sync-api api=$DOCKER_REGISTRY/$IMAGE_NAME:$CI_COMMIT_SHA -n db-sync-staging
    - kubectl rollout status deployment/db-sync-api -n db-sync-staging
  environment:
    name: staging
  only:
    - develop

deploy-production:
  stage: deploy
  image: bitnami/kubectl:latest
  script:
    - kubectl config use-context production
    - kubectl set image deployment/db-sync-api api=$DOCKER_REGISTRY/$IMAGE_NAME:$CI_COMMIT_SHA -n db-sync-prod
    - kubectl rollout status deployment/db-sync-api -n db-sync-prod
  environment:
    name: production
  when: manual
  only:
    - main

文档版本:v1.0 最后更新:2025-01-30