数据库部署

数据库部署

本节我们将部署微服务应用的数据层:MongoDB 和 Redis。

MongoDB 部署

MongoDB 用于存储业务数据,需要持久化存储和高可用配置。

StatefulSet 配置

apiVersion: v1
kind: Service
metadata:
  name: mongodb
  namespace: ecommerce
  labels:
    app: mongodb
spec:
  ports:
  - port: 27017
    targetPort: 27017
  clusterIP: None  # Headless Service
  selector:
    app: mongodb
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: mongodb
  namespace: ecommerce
spec:
  serviceName: mongodb
  replicas: 3
  selector:
    matchLabels:
      app: mongodb
  template:
    metadata:
      labels:
        app: mongodb
    spec:
      containers:
      - name: mongodb
        image: mongo:6.0
        ports:
        - containerPort: 27017
          name: mongodb
        env:
        - name: MONGO_INITDB_ROOT_USERNAME
          value: "admin"
        - name: MONGO_INITDB_ROOT_PASSWORD
          valueFrom:
            secretKeyRef:
              name: app-secrets
              key: mongo-password
        volumeMounts:
        - name: mongo-data
          mountPath: /data/db
        resources:
          requests:
            memory: "1Gi"
            cpu: "500m"
          limits:
            memory: "2Gi"
            cpu: "1000m"
        livenessProbe:
          exec:
            command:
            - mongosh
            - --eval
            - "db.adminCommand('ping')"
          initialDelaySeconds: 30
          periodSeconds: 10
        readinessProbe:
          exec:
            command:
            - mongosh
            - --eval
            - "db.adminCommand('ping')"
          initialDelaySeconds: 5
          periodSeconds: 5
  volumeClaimTemplates:
  - metadata:
      name: mongo-data
    spec:
      accessModes: ["ReadWriteOnce"]
      storageClassName: "fast-ssd"
      resources:
        requests:
          storage: 20Gi

初始化副本集

# 进入 MongoDB Pod
kubectl exec -it mongodb-0 -n ecommerce -- mongosh -u admin -p password

# 初始化副本集
rs.initiate({
  _id: "rs0",
  members: [
    { _id: 0, host: "mongodb-0.mongodb.ecommerce.svc.cluster.local:27017" },
    { _id: 1, host: "mongodb-1.mongodb.ecommerce.svc.cluster.local:27017" },
    { _id: 2, host: "mongodb-2.mongodb.ecommerce.svc.cluster.local:27017" }
  ]
})

# 查看副本集状态
rs.status()

创建应用数据库和用户

// 切换到 admin 数据库
use admin

// 创建应用用户
db.createUser({
  user: "ecommerce",
  pwd: "ecommerce-password",
  roles: [
    { role: "readWrite", db: "ecommerce" }
  ]
})

// 创建数据库
use ecommerce

// 创建集合和索引
db.products.createIndex({ "name": "text" })
db.products.createIndex({ "category": 1 })
db.orders.createIndex({ "userId": 1, "createdAt": -1 })

备份策略

apiVersion: batch/v1
kind: CronJob
metadata:
  name: mongodb-backup
  namespace: ecommerce
spec:
  schedule: "0 2 * * *"  # 每天凌晨2点
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: backup
            image: mongo:6.0
            command:
            - /bin/sh
            - -c
            - |
              mongodump \
                --host=mongodb-0.mongodb \
                --username=admin \
                --password=$MONGO_PASSWORD \
                --authenticationDatabase=admin \
                --out=/backup/$(date +%Y%m%d-%H%M%S)
            env:
            - name: MONGO_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: app-secrets
                  key: mongo-password
            volumeMounts:
            - name: backup
              mountPath: /backup
          volumes:
          - name: backup
            persistentVolumeClaim:
              claimName: mongodb-backup-pvc
          restartPolicy: OnFailure

Redis 部署

Redis 用于缓存和会话存储,需要高性能和持久化。

Deployment 配置

apiVersion: v1
kind: ConfigMap
metadata:
  name: redis-config
  namespace: ecommerce
data:
  redis.conf: |
    # 网络配置
    bind 0.0.0.0
    protected-mode yes
    port 6379
    
    # 持久化配置
    save 900 1
    save 300 10
    save 60 10000
    
    # AOF 持久化
    appendonly yes
    appendfsync everysec
    
    # 内存配置
    maxmemory 1gb
    maxmemory-policy allkeys-lru
    
    # 安全配置
    requirepass ${REDIS_PASSWORD}
---
apiVersion: v1
kind: Service
metadata:
  name: redis
  namespace: ecommerce
spec:
  type: ClusterIP
  ports:
  - port: 6379
    targetPort: 6379
  selector:
    app: redis
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: redis
  namespace: ecommerce
spec:
  replicas: 1
  selector:
    matchLabels:
      app: redis
  template:
    metadata:
      labels:
        app: redis
    spec:
      containers:
      - name: redis
        image: redis:7.2-alpine
        ports:
        - containerPort: 6379
          name: redis
        command:
        - redis-server
        - /etc/redis/redis.conf
        env:
        - name: REDIS_PASSWORD
          valueFrom:
            secretKeyRef:
              name: app-secrets
              key: redis-password
        volumeMounts:
        - name: redis-config
          mountPath: /etc/redis
        - name: redis-data
          mountPath: /data
        resources:
          requests:
            memory: "512Mi"
            cpu: "250m"
          limits:
            memory: "1Gi"
            cpu: "500m"
        livenessProbe:
          exec:
            command:
            - redis-cli
            - ping
          initialDelaySeconds: 30
          periodSeconds: 10
        readinessProbe:
          exec:
            command:
            - redis-cli
            - ping
          initialDelaySeconds: 5
          periodSeconds: 5
      volumes:
      - name: redis-config
        configMap:
          name: redis-config
      - name: redis-data
        persistentVolumeClaim:
          claimName: redis-pvc
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: redis-pvc
  namespace: ecommerce
spec:
  accessModes:
  - ReadWriteOnce
  storageClassName: fast-ssd
  resources:
    requests:
      storage: 10Gi

Redis 哨兵模式(高可用)

apiVersion: v1
kind: ConfigMap
metadata:
  name: redis-sentinel-config
  namespace: ecommerce
data:
  sentinel.conf: |
    port 26379
    sentinel monitor mymaster redis-0.redis 6379 2
    sentinel down-after-milliseconds mymaster 5000
    sentinel parallel-syncs mymaster 1
    sentinel failover-timeout mymaster 10000
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: redis-sentinel
  namespace: ecommerce
spec:
  serviceName: redis-sentinel
  replicas: 3
  selector:
    matchLabels:
      app: redis-sentinel
  template:
    metadata:
      labels:
        app: redis-sentinel
    spec:
      containers:
      - name: sentinel
        image: redis:7.2-alpine
        command:
        - redis-sentinel
        - /etc/redis/sentinel.conf
        ports:
        - containerPort: 26379
          name: sentinel
        volumeMounts:
        - name: sentinel-config
          mountPath: /etc/redis
      volumes:
      - name: sentinel-config
        configMap:
          name: redis-sentinel-config

部署验证

MongoDB 验证

# 检查 Pod 状态
kubectl get pods -n ecommerce -l app=mongodb

# 查看日志
kubectl logs mongodb-0 -n ecommerce

# 测试连接
kubectl run -it --rm mongo-test --image=mongo:6.0 --restart=Never -n ecommerce -- \
  mongosh mongodb://admin:password@mongodb-0.mongodb:27017/admin

# 查看副本集状态
kubectl exec mongodb-0 -n ecommerce -- mongosh -u admin -p password --eval "rs.status()"

Redis 验证

# 检查 Pod 状态
kubectl get pods -n ecommerce -l app=redis

# 查看日志
kubectl logs -l app=redis -n ecommerce

# 测试连接
kubectl run -it --rm redis-test --image=redis:7.2-alpine --restart=Never -n ecommerce -- \
  redis-cli -h redis -a password ping

# 测试读写
kubectl run -it --rm redis-test --image=redis:7.2-alpine --restart=Never -n ecommerce -- \
  redis-cli -h redis -a password set test "hello"

性能优化

MongoDB 优化

# 1. 使用 WiredTiger 存储引擎(默认)
storage:
  wiredTiger:
    engineConfig:
      cacheSizeGB: 1.5

# 2. 连接池配置
maxPoolSize: 50
minPoolSize: 10

# 3. 索引优化
db.collection.createIndex({ field: 1 }, { background: true })

Redis 优化

# 1. 禁用透明大页
echo never > /sys/kernel/mm/transparent_hugepage/enabled

# 2. 调整 TCP backlog
net.core.somaxconn=65535

# 3. 关闭 AOF
appendonly no  # 如果可以接受少量数据丢失

监控配置

Prometheus Exporter

# MongoDB Exporter
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mongodb-exporter
  namespace: ecommerce
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mongodb-exporter
  template:
    metadata:
      labels:
        app: mongodb-exporter
      annotations:
        prometheus.io/scrape: "true"
        prometheus.io/port: "9216"
    spec:
      containers:
      - name: exporter
        image: percona/mongodb_exporter:0.40
        ports:
        - containerPort: 9216
        env:
        - name: MONGODB_URI
          value: "mongodb://admin:password@mongodb:27017"
---
# Redis Exporter
apiVersion: apps/v1
kind: Deployment
metadata:
  name: redis-exporter
  namespace: ecommerce
spec:
  replicas: 1
  selector:
    matchLabels:
      app: redis-exporter
  template:
    metadata:
      labels:
        app: redis-exporter
      annotations:
        prometheus.io/scrape: "true"
        prometheus.io/port: "9121"
    spec:
      containers:
      - name: exporter
        image: oliver006/redis_exporter:latest
        ports:
        - containerPort: 9121
        env:
        - name: REDIS_ADDR
          value: "redis:6379"
        - name: REDIS_PASSWORD
          valueFrom:
            secretKeyRef:
              name: app-secrets
              key: redis-password

小结

本节我们部署了微服务的数据层:

MongoDB:3副本 StatefulSet,副本集配置,自动备份
Redis:单实例 + 哨兵高可用方案
持久化:PVC 存储,定期备份
监控:Prometheus Exporter 集成
优化:性能调优和资源限制

下一节我们将部署微服务应用层。