ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

CentOS 7 下用 Shell 脚本一键部署 Docker Redis 集群实战

CentOS 7 下用 Shell 脚本一键部署 Docker Redis 集群实战 简介这份资源提供了一套基于 Docker 的 Redis 集群一键部署方案面向需要在 CentOS 7.x 环境下快速搭建 Redis 集群的运维与后端开发人员。通过将参数传递给安装脚本即可自动完成部署流程省去手动配置节点、网络与容器的繁琐步骤适合具备一定 Linux 与 Docker 基础、希望提升部署效率的读者。资源包共 6 个文件包含 3 个 shell 脚本、1 个 tar 镜像包、1 个 conf 配置文件与 1 个 md 说明文档压缩包约 22.46MB脚本负责自动化构建与卸载镜像包用于离线加载配置文件与说明文档则辅助参数调整和快速上手。目前已有 1055 人学习下载说明该方案在实际环境中具备一定参考价值。读者可借助脚本快速复现集群部署、理解容器化 Redis 的编排思路并参考说明文档完成参数定制与日常维护减少重复搭建与排错的时间成本。1. 为什么我宁愿写 200 行 shell也不手动敲 12 条 docker 命令上周帮朋友的公司救火他们测试环境里那套 Redis 集群又双叒叕挂了。三个节点只剩一个活着运维翻遍聊天记录才找到半年前某位离职同事留下的部署笔记——里面只有一句「按官方文档跑就行」。我花了四十分钟重新拉起一套三主三从顺手把整个过程写成了一个 shell 脚本。这件事让我再次确认一个判断在 CentOS 7.x 这种老而弥坚的生产环境里用 docker 部署 Redis 集群真正值钱的不是那几条docker run而是把节点创建、网络配置、集群握手、槽位分配、故障兜底全部固化成一个可重复执行的脚本。这份资源就是干这个的一个面向 CentOS 7.x 的 shell 脚本用 docker 一键拉起 Redis 集群。它解决的核心痛点是「环境漂移」——今天手动部署成功明天换台机器就失败后天重启容器集群就散架。适合谁适合手里有一批 CentOS 7 服务器、需要快速搭 Redis 集群做开发测试或中小规模生产、又不想引入 k8s 那套重装备的工程师。如果你正在搜「docker 安装 redis 主从」「centos7 docker 安装」这类词说明你已经踩到手动部署的门槛了往下看。2. 脚本拆开看从镜像拉取到集群握手的完整链路2.1 先想清楚为什么是 docker shell而不是 docker compose 或 k8s很多人第一反应是用 docker compose一个 yaml 文件声明六个服务看起来优雅。但 Redis 集群有个特殊之处节点之间需要互相通信集群模式下的节点会把自己的 IP 和端口广播给其他节点。docker compose 默认创建的网络里容器 IP 是动态分配的重启后可能变化一旦 IP 变了集群的 nodes.conf 里记录的旧地址就对不上节点会认为自己被孤立。我见过太多次「compose 重启后集群直接分裂」的翻车现场。k8s 当然能解决StatefulSet 加 headless service 是标准方案但为了一个 Redis 集群去维护一套 k8s对多数中小团队来说是杀鸡用牛刀。shell 脚本的好处是透明每一步做了什么、IP 怎么定的、端口怎么映射的全在明面上。出问题的时候你能直接docker exec进去看而不是隔着一层编排系统猜。所以这个脚本的选型逻辑是用--network host或者自定义 bridge 加固定 IP让每个 Redis 节点的地址在重启后保持不变。这是整个方案能稳定运行的地基后面所有步骤都建立在这个前提上。2.2 环境准备CentOS 7.x 上把 docker 装利索CentOS 7 的默认 yum 源里 docker 版本很老而且 CentOS 7 已经停止维护官方源基本不可用。常见做法是换成国内镜像源再装。这里给一段我常用的初始化脚本片段#!/bin/bash # 换 yum 源为阿里云CentOS 7 官方源已下线不换会报 Could not resolve host mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.bak curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo # 安装 docker 依赖 yum install -y yum-utils device-mapper-persistent-data lvm2 # 添加 docker 官方源国内用阿里云镜像加速 yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo # 安装 docker-ce指定一个稳定版本避免 latest 带来的不确定性 yum install -y docker-ce-20.10.24 docker-ce-cli-20.10.24 containerd.io # 启动并设置开机自启 systemctl start docker systemctl enable docker # 配置镜像加速否则拉取 redis 镜像可能超时 mkdir -p /etc/docker cat /etc/docker/daemon.json EOF { registry-mirrors: [https://docker.mirrors.ustc.edu.cn], exec-opts: [native.cgroupdriversystemd] } EOF systemctl daemon-reload systemctl restart docker这段脚本里几个参数值得说清楚。docker-ce-20.10.24是我在 CentOS 7 上验证过比较稳的版本太新的版本对内核有要求CentOS 7 默认内核 3.10 可能跑不起来。native.cgroupdriversystemd是为了和系统 cgroup 驱动保持一致不设置的话某些情况下容器资源限制会失效。镜像加速地址用中科大的阿里云的也行看网络情况。装完之后用docker info确认两件事Cgroup Driver 是 systemdRegistry Mirrors 里有你配的地址。这两个不对后面集群大概率出玄学问题。2.3 集群拓扑设计三主三从的端口与目录规划Redis 集群最少需要三个主节点每个主节点配一个从节点所以六节点是标准起步配置。端口规划上我习惯用 7001 到 7006奇数端口做主偶数做从这样一眼能看出角色。数据目录统一放在/data/redis-cluster/{port}/下每个节点独立目录避免挂载冲突。脚本里这部分通常用一个数组来定义#!/bin/bash # 定义集群节点端口 角色 NODES( 7001 master 7002 slave 7003 master 7004 slave 7005 master 7006 slave ) # 基础目录 BASE_DIR/data/redis-cluster # redis 密码生产环境务必改掉 REDIS_PASSYourStrongPassword123 # docker 网络名用自定义 bridge 方便固定 IP NET_NAMEredis-cluster-net # 子网段避开公司内网常用段 SUBNET172.31.0.0/16为什么用自定义 bridge 而不是 host 网络host 网络下容器直接用宿主机端口简单但端口冲突风险高而且六个节点全暴露在宿主机上管理混乱。自定义 bridge 加固定 IP每个容器有独立 IP端口映射清晰重启后 IP 不变集群稳定性好很多。子网段选 172.31 是为了避开常见的 172.17docker 默认和 172.18减少和已有网络冲突的概率。2.4 核心部署逻辑创建网络、生成配置、启动容器脚本的主体分三步走。第一步创建 docker 网络第二步为每个节点生成 redis.conf第三步启动容器并组集群。#!/bin/bash # 创建自定义网络指定子网 docker network create --subnet$SUBNET $NET_NAME 2/dev/null || echo 网络已存在 # 遍历节点生成配置并启动 IP_INDEX10 for node in ${NODES[]}; do PORT$(echo $node | awk {print $1}) ROLE$(echo $node | awk {print $2}) NODE_DIR$BASE_DIR/$PORT mkdir -p $NODE_DIR NODE_IP172.31.0.$IP_INDEX # 生成 redis.conf cat $NODE_DIR/redis.conf EOF port $PORT bind 0.0.0.0 protected-mode no cluster-enabled yes cluster-config-file nodes.conf cluster-node-timeout 5000 appendonly yes requirepass $REDIS_PASS masterauth $REDIS_PASS daemonize no EOF # 启动容器固定 IP挂载配置和数据目录 docker run -d \ --name redis-$PORT \ --network $NET_NAME \ --ip $NODE_IP \ -p $PORT:$PORT \ -p $((PORT10000)):$((PORT10000)) \ -v $NODE_DIR/redis.conf:/usr/local/etc/redis/redis.conf \ -v $NODE_DIR:/data \ redis:6.2.14 \ redis-server /usr/local/etc/redis/redis.conf IP_INDEX$((IP_INDEX1)) done这里有几个关键点。cluster-enabled yes是集群模式开关不开这个后面redis-cli --cluster会直接报错。cluster-node-timeout 5000是节点超时判定5 秒是常用值网络抖动大的环境可以调到 10000。requirepass和masterauth必须同时设置只设一个的话主从复制会失败这是血泪经验。端口映射里PORT10000是集群总线端口用于节点间 gossip 通信不映射的话集群握手会卡住。镜像用redis:6.2.14而不是 latest是因为 7.x 版本在 CentOS 7 老内核上有过兼容性问题6.2 系列稳定且功能完整。2.5 集群握手与槽位分配最后一步别急着收工容器都起来之后还差最后一步让六个节点互相认识并分配 16384 个哈希槽。#!/bin/bash # 等待所有节点就绪 sleep 5 # 拼接所有节点地址 CLUSTER_NODES for node in ${NODES[]}; do PORT$(echo $node | awk {print $1}) CLUSTER_NODES$CLUSTER_NODES 172.31.0.$((10${PORT:2:1}-1)):$PORT done # 执行集群创建--cluster-replicas 1 表示每个主节点配一个从 docker exec redis-7001 redis-cli -a $REDIS_PASS --cluster create \ $CLUSTER_NODES \ --cluster-replicas 1 \ --cluster-yes--cluster-replicas 1这个参数决定了主从比例1 表示一主一从。--cluster-yes是自动确认槽位分配方案不加的话会交互式问你 yes/no脚本就卡住了。执行完用docker exec redis-7001 redis-cli -a $REDIS_PASS cluster info看cluster_state是不是 ok是 ok 才算真正成功。3. 避坑指南这五个坑我替你踩过了3.1 坑一集群创建时报「Node is not empty」现象是执行--cluster create时提示某个节点不是空的拒绝加入。原因通常是之前部署失败残留了nodes.conf文件节点以为自己已经是某个集群的成员。解决办法是删掉每个节点目录下的nodes.conf和appendonly.aof重启容器再组集群。脚本里可以在启动前加一句rm -f $NODE_DIR/nodes.conf做清理。3.2 坑二主从复制一直处于 connecting 状态cluster nodes看到从节点状态是connecting而不是connected。九成是密码问题masterauth没设或者和requirepass不一致。另一个可能是防火墙挡了集群总线端口也就是PORT10000那个。检查firewalld状态或者直接systemctl stop firewalld测试。生产环境建议用firewall-cmd放行端口段而不是关防火墙。3.3 坑三CentOS 7 内核参数导致容器启动失败报错类似Error response from daemon: OCI runtime create failed。CentOS 7 默认内核 3.10 对某些 cgroup 特性支持不完整。常见做法是升级内核到 4.x 以上或者给 docker 加--exec-opt native.cgroupdrivercgroupfs。我一般直接升级内核yum install kernel-lt从 elrepo 源装长期支持版重启后问题消失。3.4 坑四重启宿主机后集群全部下线容器设置了--restart always吗没有的话宿主机重启后容器不会自动起来。脚本里docker run要加--restart always。另外即使容器起来了如果 IP 变了集群还是会散。这就是为什么前面强调用固定 IP 的自定义网络——只要子网不变容器 IP 就不变集群能自动恢复。3.5 坑五redis-cli 连接报「NOAUTH Authentication required」用redis-cli -p 7001直接连没带-a密码。集群模式下每个节点都有密码连接时必须带-a $REDIS_PASS而且要用-c参数开启集群模式跳转否则操作非本节点槽位的数据会报MOVED错误。正确姿势是redis-cli -c -a $REDIS_PASS -p 7001。4. 进阶技巧把脚本变成可运维的工具4.1 加一个健康检查函数别等挂了才知道脚本跑完不是终点日常运维需要能快速判断集群状态。我习惯在脚本里加一个check_cluster函数#!/bin/bash check_cluster() { STATE$(docker exec redis-7001 redis-cli -a $REDIS_PASS cluster info | grep cluster_state | cut -d: -f2 | tr -d \r) if [ $STATE ok ]; then echo 集群状态正常 docker exec redis-7001 redis-cli -a $REDIS_PASS cluster nodes | awk {print $2, $3, $9} else echo 集群异常当前状态: $STATE exit 1 fi }这个函数先看cluster_state是 ok 再列出每个节点的角色和连接状态。awk那行提取的是节点 ID、IP:端口、以及连接状态标记。日常巡检直接跑这个比登进去一个个看快得多。4.2 用 shell 脚本做槽位迁移和节点扩缩容集群跑起来之后加节点是常见需求。redis-cli --cluster add-node可以加新节点但加完还要手动迁移槽位。我一般写个包装函数add_node() { NEW_IP$1 NEW_PORT$2 # 加入集群指定一个现有节点作为引路人 docker exec redis-7001 redis-cli -a $REDIS_PASS --cluster add-node \ $NEW_IP:$NEW_PORT 172.31.0.10:7001 # 迁移 1000 个槽位到新节点具体数量按需调整 docker exec redis-7001 redis-cli -a $REDIS_PASS --cluster reshard \ 172.31.0.10:7001 \ --cluster-from all \ --cluster-to $(docker exec redis-7001 redis-cli -a $REDIS_PASS cluster nodes | grep $NEW_IP:$NEW_PORT | awk {print $1}) \ --cluster-slots 1000 \ --cluster-yes }--cluster-from all表示从所有现有主节点均匀抽取槽位--cluster-to需要填新节点的 ID所以先用cluster nodes查出 ID 再传进去。这个操作在生产环境要谨慎迁移过程中会有短暂的槽位不可用建议在低峰期做。4.3 验证方法用 redis-benchmark 压一把再交付部署完别急着说「好了」跑个基准测试确认读写正常docker exec redis-7001 redis-benchmark -h 172.31.0.10 -p 7001 -a $REDIS_PASS \ -c 50 -n 10000 -t set,get -q --cluster-c 50是 50 个并发连接-n 10000是每个命令跑一万次--cluster开启集群模式。看输出里 set 和 get 的每秒操作数如果数字正常且没有报错说明集群读写链路是通的。这一步能提前暴露密码错误、槽位缺失、网络不通等问题。从那以后我每次交付 Redis 集群前都强制走一遍「集群状态检查 基准测试」这两步不跑完不算完。希望这个脚本和这些踩坑记录能帮你省下几个小时的排查时间。本文还有配套的精品资源点击获取
返回列表