zookeeper 集群部署
·
1. 准备工作
首先确保服务器已安装JDK:
ZooKeeper 以 Java 版本运行,Java 版本要求为 1.6+;
# 未安装
下载地址:JDK 11
支持的操作系统包括: GNU/Linux, Solaris, FreeBSD, Windows。
官网首页: https://zookeeper.apache.org/
官网文档: https://zookeeper.apache.org/doc/current/
# https://archive.apache.org/dist/zookeeper/
# https://archive.apache.org/dist/zookeeper/zookeeper-3.8.5/
# 创建安装目录
mkdir -p /opt/zookeeper
# 进入安装目录
cd /opt/zookeeper
# 下载最新稳定版本 ZooKeeper 3.8.5
wget https://archive.apache.org/dist/zookeeper/zookeeper-3.8.5/apache-zookeeper-3.8.5-bin.tar.gz
# 解压
sudo tar -zxf zookeeper-3.4.11.tar.gz -C /opt/zookeeper
# 授权
sudo chown -R root:root /opt/zookeeper-3.8.5
# 删除不需要文档
sudo rm -rf /opt/zookeeper/zookeeper-3.8.5/bin/*.cmd
2.设置环境变量
# 编辑系统全局配置文件/etc/profile:
vi /etc/profile
# 编辑当前用户的配置文件~/.bashrc:
vi ~/.bashrc
# zookeeper-3.8.5 环境变量
export ZOOKEEPER_HOME=/opt/server/zookeeper-3.8.5
export PATH=$PATH:$ZOOKEEPER_HOME/bin
# 如果修改的是/etc/profile
source /etc/profile
# 如果修改的是~/.bashrc
source ~/.bashrc
3.创建数据和日志目录(所有节点)
# 我这边是三个节点在 ali_ecs1, ali_ecs2, ali_ecs3 上分别执行
sudo mkdir -p /opt/data/zookeeper/{data,logs}
4.配置 zoo.cfg(统一配置,分发到所有节点)
cat > /opt/zookeeper/conf/zoo.cfg << 'EOF'
# ------------------------------
# 基础计时与通信配置
# ------------------------------
# 基本时间单位(毫秒),集群所有计时参数均以此为基准
# 生产建议:1000-2000ms(值过小会导致心跳频繁,增大网络开销;过大则故障检测延迟高)
tickTime=2000
# 初始化连接超时时间(单位:tickTime),用于Follower与Leader建立初始连接
# 取值逻辑:initLimit * tickTime = 10*2000=20秒
initLimit=10
# 同步数据超时时间(单位:tickTime),用于Follower与Leader同步数据
# 取值逻辑:syncLimit * tickTime = 5*2000=10秒,同步通常比初始化快(生产建议2-5)
syncLimit=5
# 客户端连接端口(默认22181,便于统一管理)
clientPort=12181
# 数据快照存储目录(持久化数据,如znode节点信息)
dataDir=/opt/data/zookeeper/data
# 事务日志存储目录(比快照更频繁写入,性能敏感)
dataLogDir=/opt/data/zookeeper/logs
# ------------------------------
# 集群节点定义
# ------------------------------
# 格式:server.{myid}={主机名}:{通信端口}:{选举端口}
# - myid:与每个节点dataDir下的myid文件内容一致,唯一标识节点
# - 通信端口(2888):Follower与Leader之间同步数据/通信的端口
# - 选举端口(3888):节点间选举Leader时使用的端口
# 这里不使用 常规端口 是为了不被安全扫描
server.1=ali_ecs1:28880:38880
server.2=ali_ecs2:28880:38880
server.3=ali_ecs3:28880:38880
# ------------------------------
# 生产级基础优化
# ------------------------------
# 自动清理快照时保留的最近快照数量(默认3)
autopurge.snapRetainCount=5
# 自动清理快照和过期日志的间隔(单位:小时,默认0表示禁用)
autopurge.purgeInterval=24
# 限制允许使用的四字命令
4lw.commands.whitelist=stat,ruok,conf # 仅开放状态查询、存活检测、配置查看
# 禁用AdminServer 默认8080端口
admin.enableServer=false
# 单个客户端的最大并发连接数(默认60)
maxClientCnxns=60
# 客户端会话最小超时时间(单位:毫秒,必须≥2*tickTime)
minSessionTimeout=4000
# 客户端会话最大超时时间(单位:毫秒,必须≤20*tickTime)
maxSessionTimeout=40000
# Leader节点是否处理客户端请求(默认yes)
# 高并发场景建议开启:Leader同时承担数据处理,提升整体吞吐量(关闭则仅Follower处理)
leaderServes=yes
# 是否监听所有网卡的IP
quorumListenOnAllIPs=false
EOF
5 配置 logback.xml 日志规则
<!--
Copyright 2022 The Apache Software Foundation
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<configuration>
<!-- ============================================== -->
<!-- 核心参数配置 -->
<!-- ============================================== -->
<!-- 日志存储目录:与zoo.cfg中dataLogDir保持一致,集中管理 -->
<property name="zookeeper.log.dir" value="/opt/data/zookeeper/logs" />
<!-- 主日志文件名 -->
<property name="zookeeper.log.file" value="zookeeper-server.log" />
<!-- 日志级别:仅输出INFO及以上(警告、错误) -->
<property name="zookeeper.log.threshold" value="INFO" />
<!-- 单个日志文件最大大小(100MB:平衡文件数量与处理效率) -->
<property name="zookeeper.log.maxfilesize" value="100MB" />
<!-- 日志保留天数(7天:满足问题追溯需求,避免磁盘占用过大) -->
<property name="zookeeper.log.maxhistory" value="7" />
<!-- 日志总占用上限(2GB:防止日志无限制增长占满磁盘) -->
<property name="zookeeper.log.totalsizecap" value="2GB" />
<!-- 控制台日志阈值(仅输出WARN及以上:减少冗余,避免干扰) -->
<property name="zookeeper.console.threshold" value="WARN" />
<!-- ============================================== -->
<!-- 1. 控制台输出 -->
<!-- ============================================== -->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<!-- 日志格式:时间+节点ID+级别+线程+类名+消息 -->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [myid:%X{myid}] - %-5p [%t:%C{1}@%L] - %m%n</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>${zookeeper.console.threshold}</level> <!-- 仅输出WARN及以上 -->
</filter>
</appender>
<!-- ============================================== -->
<!-- 2. 滚动文件输出 -->
<!-- ============================================== -->
<appender name="ROLLINGFILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 主日志文件路径 -->
<File>${zookeeper.log.dir}/${zookeeper.log.file}</File>
<encoder>
<!-- 格式与控制台一致,确保文件日志可追溯 -->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [myid:%X{myid}] - %-5p [%t:%C{1}@%L] - %m%n</pattern>
</encoder>
<!-- 日志级别过滤(与阈值一致) -->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>${zookeeper.log.threshold}</level>
</filter>
<!-- 滚动策略:按时间(每日)+ 大小(100MB)滚动 -->
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!-- 滚动文件名格式:前缀+日期+序号(如zookeeper-server-2024-11-14.1.log) -->
<FileNamePattern>${zookeeper.log.dir}/${zookeeper.log.file}.%d{yyyy-MM-dd}.%i</FileNamePattern>
<maxFileSize>${zookeeper.log.maxfilesize}</maxFileSize> <!-- 单文件最大100MB -->
<maxHistory>${zookeeper.log.maxhistory}</maxHistory> <!-- 保留7天日志 -->
<totalSizeCap>${zookeeper.log.totalsizecap}</totalSizeCap> <!-- 总大小上限2GB -->
</rollingPolicy>
</appender>
<!-- ============================================== -->
<!-- 3. 异步日志输出 -->
<!-- ============================================== -->
<appender name="ASYNC" class="ch.qos.logback.classic.AsyncAppender">
<appender-ref ref="ROLLINGFILE" /> <!-- 异步输出到滚动文件 -->
<queueSize>1024</queueSize> <!-- 内存队列大小:缓冲1024条日志事件 -->
<discardingThreshold>0</discardingThreshold> <!-- 不丢弃任何日志确保完整性 -->
</appender>
<!-- ============================================== -->
<!-- 4. 审计日志 -->
<!-- ============================================== -->
<property name="zookeeper.auditlog.file" value="zookeeper-audit.log" />
<appender name="RFAAUDIT" class="ch.qos.logback.core.rolling.RollingFileAppender">
<File>${zookeeper.log.dir}/${zookeeper.auditlog.file}</File>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %p %c{2}: %m%n</pattern>
</encoder>
<!-- 审计日志滚动策略:保留更久(15天),单文件更小(50MB) -->
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<FileNamePattern>${zookeeper.log.dir}/${zookeeper.auditlog.file}.%d{yyyy-MM-dd}.%i</FileNamePattern>
<maxFileSize>50MB</maxFileSize>
<maxHistory>9</maxHistory>
</rollingPolicy>
</appender>
<!-- 审计日志记录器:仅审计相关日志输出到RFAAUDIT,不干扰主日志 -->
<logger name="org.apache.zookeeper.audit.Slf4jAuditLogger" additivity="false" level="INFO">
<appender-ref ref="RFAAUDIT" />
</logger>
<!-- ============================================== -->
<!-- 根日志器 -->
<!-- ============================================== -->
<root level="INFO">
<appender-ref ref="ASYNC" />
<!-- 可选:保留控制台输出(仅WARN及以上) -->
<!-- <appender-ref ref="CONSOLE" /> -->
</root>
</configuration>
6.设置 myid(每台机器不同!)
# 在 每台机器 上单独执行:
# 在 ali_ecs1 上:
echo "1" | sudo tee /opt/data/zookeeper/data/myid
# 在 ali_ecs2 上:
echo "2" | sudo tee /opt/data/zookeeper/data/myid
# 在 ali_ecs3 上:
echo "3" | sudo tee /opt/data/zookeeper/data/myid
7. 防火墙放行
# 移除原端口规则(以firewalld为例)
firewall-cmd --permanent --remove-port=2181/tcp
firewall-cmd --permanent --remove-port=2888/tcp
firewall-cmd --permanent --remove-port=3888/tcp
# 开放ZooKeeper必需端口(通信/选举/客户端)
firewall-cmd --permanent --add-port={28880,38880,12181}/tcp
# 重载防火墙
firewall-cmd --reload
# 验证(看输出中是否有这些端口)
firewall-cmd --list-all | grep -E '28880|38880|12181'
# 在ali_ecs2和ali_ecs3重复上述操作,确保所有节点间双向连通
8.创建启动和停止脚本
# 脚本存放目录
mkdir -p /opt/shell
chmod 755 /opt/shell
#!/bin/bash
# ======================================================================
# ZooKeeper 集群管理脚本
ZOO_HOME="/opt/server/zookeeper-3.8.5"
ZOO_CONF_DIR="$ZOO_HOME/conf"
ZOO_CFG="$ZOO_CONF_DIR/zoo.cfg"
CLIENT_PORT="12181"
parse_nodes() {
grep -E '^server\.[0-9]+=' "$ZOO_CFG" | awk -F'=' '{print $2}' | awk -F':' '{print $1}' | sort
}
get_node_mode() {
local node="$1"
local mode=$(echo "stat" | nc -w 3 "$node" "$CLIENT_PORT" 2>/dev/null | grep "^Mode:" | awk '{print $2}')
echo "${mode:-unknown}"
}
confirm_action() {
read -p "请确认要执行此操作,请输入 'yes' 继续: " confirm
if [ "$confirm" != "yes" ]; then
echo "操作取消"
exit 1
fi
}
# 关键修复:远程执行前 source /etc/profile
run_on_node() {
local node="$1"
local cmd="$2"
ssh "$node" "source /etc/profile 2>/dev/null; $cmd"
}
start() {
echo "[START] 启动 ZooKeeper 集群: $(parse_nodes)"
confirm_action
for node in $(parse_nodes); do
echo " → 正在启动节点: $node"
run_on_node "$node" "$ZOO_HOME/bin/zkServer.sh start"
done
echo "[INFO] 集群启动完成。请执行 'status' 验证状态。"
}
stop() {
echo "[STOP] 停止 ZooKeeper 集群: $(parse_nodes)"
confirm_action
for node in $(parse_nodes); do
echo " → 正在停止节点: $node"
run_on_node "$node" "$ZOO_HOME/bin/zkServer.sh stop"
done
echo "[INFO] 集群停止完成。"
}
restart() {
echo "[RESTART] 重启 ZooKeeper 集群"
stop && sleep 5 && start
}
status() {
echo "[STATUS] ZooKeeper 集群状态 (客户端端口: $CLIENT_PORT)"
local leader=""
local nodes=($(parse_nodes))
local total=${#nodes[@]}
local followers=0
for node in "${nodes[@]}"; do
mode=$(get_node_mode "$node")
if [ "$mode" = "leader" ]; then
echo " [✓] $node: LEADER"
leader="$node"
elif [ "$mode" = "follower" ]; then
echo " [✓] $node: FOLLOWER"
((followers++))
else
echo " [✗] $node: OFFLINE 或 端口未开放"
fi
done
if [ -n "$leader" ]; then
echo
echo " 集群健康: Leader=$leader | Follower=$followers | Total=$total"
else
echo
echo " 集群异常: 未检测到 Leader 节点"
exit 1
fi
}
case "$1" in
start|stop)
"$1"
;;
restart)
restart
;;
status)
status
;;
*)
echo "Usage: $0 {start|stop|restart|status}"
echo " start: 启动集群(需确认 'yes')"
echo " stop: 停止集群(需确认 'yes')"
echo " restart: 重启集群"
echo " status: 查看集群状态"
exit 1
;;
esac
# 脚本名为zk_cluster_mgr.sh
chmod +x /opt/shell/zk_cluster_mgr.sh
9.用脚本去启动 zookeeper
# 启动集群
./zk_cluster_mgr.sh start
[START] 启动 ZooKeeper 集群: ali_ecs1 ali_ecs2 ali_ecs3
请确认要执行此操作,请输入 'yes' 继续: yes
[INFO] 启动完成,请用 'status' 验证
./zk_cluster_mgr.sh stop
[STOP] 停止 ZooKeeper 集群: ali_ecs1 ali_ecs2 ali_ecs3
请确认要执行此操作,请输入 'yes' 继续: yes
[INFO] 停止完成
./zk_cluster_mgr.sh status
[STATUS] ZooKeeper 集群状态 (端口: 12181)
[✓] ali_ecs1: FOLLOWER
[✓] ali_ecs2: FOLLOWER
[✓] ali_ecs3: LEADER
集群健康: Leader=hadoop3 | Follower=2 | Total=3
更多推荐
所有评论(0)