强曰为道

与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

17 - 容器化部署

容器化部署

17.1 Docker 单实例部署

基础部署

# 最简启动
docker run -d --name redis -p 6379:6379 redis:7.2

# 带配置的启动
docker run -d --name redis \
  -p 6379:6379 \
  -v /data/redis/data:/data \
  -v /data/redis/redis.conf:/usr/local/etc/redis/redis.conf \
  redis:7.2 redis-server /usr/local/etc/redis/redis.conf

生产级 Docker 部署

docker run -d --name redis \
  --restart always \
  -p 6379:6379 \
  -v /data/redis/data:/data \
  -v /data/redis/redis.conf:/usr/local/etc/redis/redis.conf \
  --memory 4g \
  --cpus 2 \
  --ulimit nofile=65535:65535 \
  redis:7.2 redis-server /usr/local/etc/redis/redis.conf \
  --requirepass "YourStr0ngP@ssword" \
  --appendonly yes \
  --maxmemory 3gb \
  --maxmemory-policy allkeys-lru

常用 Docker 参数

参数说明
-d后台运行
--restart always自动重启
-v host:container挂载卷(数据持久化)
--memory 4g内存限制
--cpus 2CPU 限制
--ulimit nofile=65535:65535文件描述符限制
-p host:container端口映射
--network host使用宿主机网络(高性能)

17.2 Docker Compose 方案

主从复制方案

# docker-compose-replication.yml
version: '3.8'

x-redis-common: &redis-common
  image: redis:7.2
  restart: always
  networks:
    - redis-net
  sysctls:
    net.core.somaxconn: 1024
  ulimits:
    nofile:
      soft: 65535
      hard: 65535

services:
  redis-master:
    <<: *redis-common
    container_name: redis-master
    ports:
      - "6379:6379"
    volumes:
      - ./master/data:/data
      - ./master/redis.conf:/usr/local/etc/redis/redis.conf
    command: redis-server /usr/local/etc/redis/redis.conf
    healthcheck:
      test: ["CMD", "redis-cli", "-a", "mypassword", "ping"]
      interval: 10s
      timeout: 3s
      retries: 3

  redis-slave-1:
    <<: *redis-common
    container_name: redis-slave-1
    ports:
      - "6380:6379"
    volumes:
      - ./slave1/data:/data
    command: redis-server --replicaof redis-master 6379 --masterauth mypassword --appendonly yes --requirepass mypassword
    depends_on:
      - redis-master

  redis-slave-2:
    <<: *redis-common
    container_name: redis-slave-2
    ports:
      - "6381:6379"
    volumes:
      - ./slave2/data:/data
    command: redis-server --replicaof redis-master 6379 --masterauth mypassword --appendonly yes --requirepass mypassword
    depends_on:
      - redis-master

networks:
  redis-net:
    driver: bridge

哨兵方案

# docker-compose-sentinel.yml
version: '3.8'

x-redis-common: &redis-common
  image: redis:7.2
  restart: always
  networks:
    - redis-net

x-sentinel-common: &sentinel-common
  image: redis:7.2
  restart: always
  networks:
    - redis-net
  command: redis-sentinel /etc/redis/sentinel.conf

services:
  redis-master:
    <<: *redis-common
    container_name: redis-master
    ports:
      - "6379:6379"
    volumes:
      - ./master/data:/data
    command: redis-server --requirepass mypassword --appendonly yes

  redis-slave-1:
    <<: *redis-common
    container_name: redis-slave-1
    ports:
      - "6380:6379"
    command: redis-server --replicaof redis-master 6379 --masterauth mypassword --requirepass mypassword --appendonly yes
    depends_on:
      - redis-master

  redis-slave-2:
    <<: *redis-common
    container_name: redis-slave-2
    ports:
      - "6381:6379"
    command: redis-server --replicaof redis-master 6379 --masterauth mypassword --requirepass mypassword --appendonly yes
    depends_on:
      - redis-master

  sentinel-1:
    <<: *sentinel-common
    container_name: sentinel-1
    ports:
      - "26379:26379"
    volumes:
      - ./sentinel1/sentinel.conf:/etc/redis/sentinel.conf
    depends_on:
      - redis-master
      - redis-slave-1
      - redis-slave-2

  sentinel-2:
    <<: *sentinel-common
    container_name: sentinel-2
    ports:
      - "26380:26379"
    volumes:
      - ./sentinel2/sentinel.conf:/etc/redis/sentinel.conf
    depends_on:
      - redis-master
      - redis-slave-1
      - redis-slave-2

  sentinel-3:
    <<: *sentinel-common
    container_name: sentinel-3
    ports:
      - "26381:26379"
    volumes:
      - ./sentinel3/sentinel.conf:/etc/redis/sentinel.conf
    depends_on:
      - redis-master
      - redis-slave-1
      - redis-slave-2

networks:
  redis-net:
    driver: bridge

哨兵配置文件模板:

# sentinel.conf
port 26379
sentinel monitor mymaster redis-master 6379 2
sentinel auth-pass mymaster mypassword
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 60000
sentinel parallel-syncs mymaster 1

集群方案

# docker-compose-cluster.yml
version: '3.8'

x-redis-node: &redis-node
  image: redis:7.2
  restart: always
  networks:
    - redis-cluster
  command: >
    redis-server
    --cluster-enabled yes
    --cluster-config-file nodes.conf
    --cluster-node-timeout 5000
    --appendonly yes
    --requirepass mypassword
    --masterauth mypassword

services:
  redis-node-1:
    <<: *redis-node
    container_name: redis-node-1
    ports:
      - "6371:6379"
    volumes:
      - ./node1/data:/data

  redis-node-2:
    <<: *redis-node
    container_name: redis-node-2
    ports:
      - "6372:6379"
    volumes:
      - ./node2/data:/data

  redis-node-3:
    <<: *redis-node
    container_name: redis-node-3
    ports:
      - "6373:6379"
    volumes:
      - ./node3/data:/data

  redis-node-4:
    <<: *redis-node
    container_name: redis-node-4
    ports:
      - "6374:6379"
    volumes:
      - ./node4/data:/data

  redis-node-5:
    <<: *redis-node
    container_name: redis-node-5
    ports:
      - "6375:6379"
    volumes:
      - ./node5/data:/data

  redis-node-6:
    <<: *redis-node
    container_name: redis-node-6
    ports:
      - "6376:6379"
    volumes:
      - ./node6/data:/data

networks:
  redis-cluster:
    driver: bridge
# 创建集群
docker-compose -f docker-compose-cluster.yml up -d

# 等待所有节点启动后
docker exec -it redis-node-1 redis-cli -a mypassword --cluster create \
  redis-node-1:6379 redis-node-2:6379 redis-node-3:6379 \
  redis-node-4:6379 redis-node-5:6379 redis-node-6:6379 \
  --cluster-replicas 1 --cluster-yes

17.3 Kubernetes 部署

使用 Bitnami Helm Chart

# 添加 Helm 仓库
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo update

# 安装 Redis 主从
helm install redis bitnami/redis \
  --set auth.password=mypassword \
  --set master.persistence.size=10Gi \
  --set replica.replicaCount=2 \
  --set replica.persistence.size=10Gi \
  --set sentinel.enabled=true \
  --namespace redis --create-namespace

# 安装 Redis Cluster
helm install redis-cluster bitnami/redis-cluster \
  --set password=mypassword \
  --set cluster.nodes=6 \
  --set cluster.replicas=1 \
  --set persistence.size=10Gi \
  --namespace redis --create-namespace

Redis Operator(Spotahome)

# redis-operator-deployment.yml
apiVersion: databases.spotahome.com/v1
kind: RedisFailover
metadata:
  name: my-redis
  namespace: redis
spec:
  sentinel:
    replicas: 3
    resources:
      requests:
        cpu: 100m
        memory: 128Mi
      limits:
        cpu: 300m
        memory: 256Mi
  redis:
    replicas: 3
    resources:
      requests:
        cpu: 500m
        memory: 1Gi
      limits:
        cpu: 1000m
        memory: 2Gi
    storage:
      persistentVolumeClaim:
        spec:
          accessModes:
            - ReadWriteOnce
          resources:
            requests:
              storage: 10Gi
# 安装 Redis Operator
helm repo add redis-operator https://spotahome.github.io/redis-operator
helm install redis-operator redis-operator/redis-operator

# 部署 Redis Failover
kubectl apply -f redis-operator-deployment.yml

17.4 数据持久化策略

Docker 数据卷

# 使用命名卷
docker volume create redis-data
docker run -d --name redis -v redis-data:/data redis:7.2

# 使用绑定挂载
docker run -d --name redis -v /host/redis/data:/data redis:7.2

# 备份
docker exec redis redis-cli BGSAVE
docker cp redis:/data/dump.rdb ./backup/

# 恢复
docker cp ./backup/dump.rdb redis:/data/
docker restart redis

17.5 网络优化

# docker-compose.yml 优化
services:
  redis:
    image: redis:7.2
    # 使用 host 网络(性能最佳,但牺牲网络隔离)
    network_mode: host
    
    # 或使用自定义网络
    networks:
      redis-net:
        ipv4_address: 172.20.0.10
# Linux 内核参数优化
sysctl -w net.core.somaxconn=1024
sysctl -w vm.overcommit_memory=1
echo never > /sys/kernel/mm/transparent_hugepage/enabled

📌 业务场景

场景一:开发环境快速启动

docker-compose up -d
# 30 秒内拥有完整的 Redis 主从+哨兵环境

场景二:CI/CD 测试环境

# GitHub Actions
services:
  redis:
    image: redis:7.2
    ports:
      - 6379:6379
    options: >-
      --health-cmd "redis-cli ping"
      --health-interval 10s
      --health-timeout 5s
      --health-retries 5

场景三:K8s 生产环境

# 使用 Helm 部署高可用 Redis Cluster
helm install redis bitnami/redis-cluster \
  --set password=$REDIS_PASSWORD \
  --set cluster.nodes=6 \
  --set persistence.storageClass=fast-ssd

🔗 扩展阅读