更新记录:
2025/4/14:增加 SSH免密配置部分遗漏步骤。
叠甲部分
1. **教程定位说明**
本指南为大数据技术学习实践文档,主要服务于技术验证与初学者学习测试场景。记录内容基于单机多容器部署模式,适用于个人学习及小型实验环境搭建。如需应用于生产环境,请结合分布式架构设计要求、硬件资源规划及企业安全规范进行全方位改造(或者出门右拐)。
2. **环境兼容性声明**
实验环境基于Windows Subsystem for Linux (WSL) 2.0构建,采用Docker容器化部署方案实现多节点模拟。传统物理机部署、虚拟机集群或其他容器运行时(如Podman)使用时,需重点注意以下差异点:
- 网络拓扑结构的适配调整
- 系统资源隔离机制的差异性配置
建议在实际部署前完成目标环境的功能验证测试。
并且每个人的软硬件环境的差异,本教程不保证能100%可直接照搬成功,大概率需要根据自身情况做出适量调整。
3、作者是个清澈愚蠢的大学生,石粒有限,是个菜鸟,如有错误欢迎指出(不包括这句话的“石粒”二字)。
目录
一、环境准备与基础配置
1.1 WSL环境搭建(可选)
(直接使用Linux操作系统的可跳过这一整个部分)
1.1.1 什么是WSL
WSL(Windows subsystem for Linux,适用于 Linux 的 Windows 子系统)是 Windows 的一项功能,可用于在 Windows 计算机上运行 Linux 环境,而无需单独的虚拟机或双引导。 WSL 旨在为希望同时使用 Windows 和 Linux 的开发人员提供无缝高效的体验。
1.1.2 与传统虚拟机相比,WSL 具有的优势
与 Windows 系统的深度集成
可在 Windows 和 Linux 系统间无缝切换,支持子系统与宿主机文件系统(路径为 /mnt)的无缝双向访问。
允许用户在 Windows 和 Linux 系统之间无缝地运行命令和程序,允许在Linux终端直接调用 Windows 应用程序,在Windows操作系统直接运行 Linux 应用。
便捷的开发环境支持
WSL2借助Hyper-V直接在Windows系统托管 Linux 内核,适用于Linux的几乎所有应用软件、程序和命令均可以在WSL内直接运行。支持共享网络命名空间、环境、CPU、GPU、内存等核心资源
可在 WSL 中直接运行 Linux 应用程序、实用工具以及 Bash 命令行工具,无需额外修改。
与常见的集成开发工具如JetBrains 系列、Visual Studio系列(VSCode)等完全兼容,可直接在Windows操作系统的集成开发环境上进行Linux端的开发。
支持 GPU 加速,NVIDIA 提供的 CUDA 程序包允许在 WSL 中运行深度学习框架(如 PyTorch 和 TensorFlow)。
高效的资源利用
相较于 VMware,WSL 消耗更少的系统资源,同时提供更轻量的体验。
通过 WSL2 配合 Docker 部署,可以高效利用硬件资源,支持 CUDA 加速和深度学习框架运行,同时实现与 Windows 开发工具的无缝集成,为后续大数据实验提供了灵活高效的运行环境。
1.1.3 系统配置要求
Windows 10 版本 2004 或更高(建议使用Windows 11)
启用Hyper-V虚拟化支持
至少16GB内存(推荐32GB,毕竟是大数据集群,内存不够可以考虑少搭建几个节点)
存储空间建议分配30GB以上
1.1.4 WSL安装
# PowerShell管理员模式执行
wsl --install -d Ubuntu-22.04
推荐在使用前对WSL进行配置与优化,涉及到不同人的软硬件区别,此处不过多介绍,请自行查找相关教程。
(PS 不想折腾直接往下也不是不行)
1.2 WSL(Linux系统)初始配置
使用wsl -u root命令指定以root用户进入WSL
wsl -u root
更新ubuntu apt
sudo apt update
sudo apt upgrade
sudo apt full-upgrade
添加 hadoop 用户
adduser hadoop
(没有特殊要求的话,输完密码一路按Y)
为该用户添加Sudo权限
chmod u+w /etc/sudoers
编辑sudoers文件,在root配置行加入下面内容
(这里仅为了方便后续操作,不是很推荐这种做法哈,这步可以不要)
vim /etc/sudoers
hadoop ALL=(ALL) NOPASSWD:ALL
其中hadoop ALL=(ALL) NOPASSWD:ALL表示允许用户hadoop执行sudo命令,并且在执行的时候无需输入密码。
当然要更方便的方法也有,连sudo都可以不用,但个人觉得如果要这样不如直接root
后续可以直接使用wsl -u hadoop命令进入WSL进行集群部署
exit
wsl -u hadoop
1.3 安装Docker
查看系统是否帮你默认安装过docker
docker version
如果有请先卸载操作系统默认安装的docker,此处不过多赘述
安装必要支持
sudo apt install apt-transport-https ca-certificates curl software-properties-common gnupg lsb-release
添加Docker GPG密钥
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
添加apt源
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker. List > /dev/null
更新源
sudo apt update
安装docker
sudo apt install docker-ce docker-ce-cli containerd.io docker-compose-plugin
ps:此处作者用的官方密钥和源,作者实验时下载速度较慢,仅有500多KB,可以自行更换国内镜像源
查看docker版本
sudo docker version
查看docker运行状态,并设置开机自启动
sudo systemctl status docker
sudo systemctl enable docker
修改Docker仓库源为国内镜像源(如果需要)
创建或修改 /etc/docker/daemon.json
文件
{
"registry-mirrors": [
"https://......."
]
}
重载docker让配置生效
sudo vim /etc/docker/daemon.json
sudo systemctl daemon-reload
sudo systemctl restart docker
二、配置初始镜像
2.1 创建于初始配置
抓取ubuntu 22.04的镜像作为基础搭建hadoop环境
sudo docker pull ubuntu:22.04
使用该ubuntu镜像启动并进入容器
sudo docker run -it --name hadoopPR ubuntu:22.04
更新软件
apt update
apt upgrade
apt full-upgrade
安装一些必要工具
apt install -y net-tools telnet iputils-ping vim wget tzdata
安装JDK 8
apt install openjdk-8-jdk
在环境变量中引用jdk,编辑bash命令行配置文件
vim ~/.bashrc
在最后添加下面内容
export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64/
export PATH=$PATH:$JAVA_HOME/bin
验证jdk
java -version
创建root密码
passwd
2.2 ssh免密登录
安装ssh所需软件
apt install -y openssh-server
修改配置文件允许root登录
vim /etc/ssh/sshd_config
修改下面内容:
PermitRootLogin yes # 允许 Root 登录
PasswordAuthentication no # 启用密码认证
PubkeyAuthentication yes # 启用密钥认证
重启ssh
service ssh restart
实现shh自启动
在 /root 目录下新建一个 start_ssh.sh文件,并给予该文件可执行权限。
touch /root/start_ssh.sh
chmod +x /root/start_ssh.sh
vim /root/start_ssh.sh
start_ssh.sh 脚本的内容,如下:
#!/bin/bash
LOGTIME=$(date "+%Y-%m-%d %H:%M:%S")
echo "[$LOGTIME] startup run..." >>/root/start_ssh.log
service ssh start >>/root/start_ssh.log
#service mysql start >>/root/star_mysql.log //其他服务也可这么实现
将start_ssh.sh脚本添加到启动文件中
vim /root/.bashrc
在 .bashrc
文件末尾加入如下内容:
# startup run
if [ -f /root/start_ssh.sh ]; then
./root/start_ssh.sh
fi
生成公钥
cd /root/.ssh
ssh-keygen -t rsa
发送到本机
ssh-copy-id 127.0.0.1
2.3 保存初始镜像
exit
sudo docker commit hadoopPR hadoop_pr:v1
此后搭建大数据集群时可直接使用该镜像代替基础的Ubuntu镜像
三、docker网络配置与容器实例化
创建docker网络(wsl环境)
sudo docker network create --subnet=172.13.0.0/16 hadoop_network
创建1 master 3slave容器
(集群规模读者可以根据自身硬件条件做出适当调整,此处以4节点为例)
#master
sudo docker run \
--privileged \
-d -it -h master \
--network hadoop_network \
--ip 172.13.0.2 \
--name master \
--add-host=slave1:172.13.0.3 \
--add-host=slave2:172.13.0.4 \
--add-host=slave3:172.13.0.5 \
-p 9000:9000 \
-p 9870:9870 \
-p 8088:8088 \
-p 8030:8030 \
-p 9092:9092 \
-p 3306:3306 \
-p 60000:60000 \
-p 16010:16010 \
-p 9083:9083 \
-p 10000:10000 \
-p 7077:7077 \
-p 18080:18080 \
-p 81:80 \
-p 8081:8080 \
master:v2 /bin/bash
#slave1
sudo docker run --privileged -d -it -h slave1 --network hadoop_network --ip 172.13.0.3 --name slave1 --add-host=master:172.13.0.2 --add-host=slave2:172.13.0.4 --add-host=slave3:172.13.0.5 hadoop_pr:v1 /bin/bash
#slave2
sudo docker run --privileged -d -it -h slave2 --name slave2 --network hadoop_network --ip 172.13.0.4 --add-host=master:172.13.0.2 --add-host=slave1:172.13.0.3 --add-host=slave3:172.13.0.5 hadoop_pr:v1 /bin/bash
#slave3
sudo docker run --privileged -d -it -h slave3 --name slave3 --network hadoop_network --ip 172.13.0.5 --add-host=master:172.13.0.2 --add-host=slave1:172.13.0.3 --add-host=slave2:172.13.0.4 hadoop_pr:v1 /bin/bash
停止容器
sudo docker stop master slave1 slave2 slave3
启动容器
(分别使用四个窗口打开)
(即 开4个power shell,每个power shell都使用 wsl -u hadoop进入)
sudo docker start -i -a master
sudo docker start -i -a slave1
sudo docker start -i -a slave2
sudo docker start -i -a slave3
若无需窗口则直接docker start,后续需要进入再使用exec进入,此处为方便部署,先多开窗口操控每个容器。
四、Zookeeper集群安装
下载
wget http://archive.apache.org/dist/zookeeper/zookeeper-3.5.7/apache-zookeeper-3.5.7-bin.tar.gz
解压与重命名
tar -zxvf apache-zookeeper-3.5.7-bin.tar.gz -C /usr/local
mv /usr/local/apache-zookeeper-3.5.7-bin /usr/local/zookeeper
创建zookeeper数据存储目录
mkdir /usr/local/zookeeper/data
重命名配置文件
mv /usr/local/zookeeper/conf/zoo_sample.cfg /usr/local/zookeeper/conf/zoo.cfg
修改配置文件zoo.cfg
vim /usr/local/zookeeper/conf/zoo.cfg
对应修改以下内容
tickTime=2000
dataDir=/usr/local/zookeeper/data
clientPort=2181
initLimit=5
syncLimit=2
server.1=master:2888:3888
server.2=slave1:2888:3888
server.3=slave2:2888:3888
server.4=slave3:2888:3888
分发zookeeper
cd /usr/local
scp -r zookeeper slave1:/usr/local
scp -r zookeeper slave2:/usr/local
scp -r zookeeper slave3:/usr/local
myid的配置,创建文件myid,内容写1(node1节点写1,node2节点写2,以此类推,用于不同节点上zookeeper的标识,每个节点(容器)都要执行一遍)
vim /usr/local/zookeeper/data/myid
编辑/etc/profile
文件
export ZOOKEEPER_HOME=/usr/local/zookeeper
export PATH=$PATH:$ZOOKEEPER_HOME/bin
source /etc/profile
zookeeper快捷控制脚本,在容器外执行,不需要每次都进入到容器启动集群
sudo vim /usr/local/bin/zkpctl
Zookeeper集群管理脚本
#!/bin/bash
# 配置
nodes=("master" "slave1" "slave2" "slave3") # 节点列表
zk_server="/usr/local/zookeeper/bin/zkServer.sh" # ZK服务路径
stop_timeout=3 # 正常停止超时时间
# ================================
# 颜色定义
RED='\033[31m'
GREEN='\033[32m'
YELLOW='\033[33m'
CYAN='\033[36m'
BOLD='\033[1m'
NC='\033[0m' # 颜色重置
# 检查容器是否存在
check_container() {
docker ps -a --format '{{.Names}}' | grep -q "^$1$"
}
# 日志输出函数
log() {
local color_code="$1"
local message="$2"
echo -e "${color_code}${message}${NC}"
}
# 启动节点服务
start_node() {
local node=$1
log "$YELLOW" "▌ 正在启动 $node..."
if check_container "$node"; then
if docker exec -it "$node" bash -c "$zk_server start" &> /dev/null; then
log "$GREEN" " ✔ 已成功启动"
return 0
else
log "$RED" " ✖ 启动失败"
return 1
fi
else
log "$RED" " ⚠ 容器不存在"
return 2
fi
}
# 停止节点服务
stop_node() {
local node=$1
log "$YELLOW" "▌ 正在停止 $node..."
# 正常停止尝试
if docker exec -it "$node" $zk_server stop &> /dev/null; then
sleep $stop_timeout
if docker exec -it "$node" pgrep -f zookeeper &> /dev/null; then
log "$RED" " ✖ 正常停止失败"
docker exec -it "$node" pkill -9 -f "org.apache.zookeeper.server.quorum.QuorumPeerMain" &> /dev/null
sleep 1
fi
fi
# 最终验证
if docker exec -it "$node" pgrep -f zookeeper &> /dev/null; then
log "$RED" " ✖ 终止失败"
return 1
else
log "$GREEN" " ✔ 已停止"
return 0
fi
}
# 状态检测
check_status() {
echo -e "${BOLD}节点 容器状态 服务状态${NC}"
echo "-----------------------------------------"
for node in "${nodes[@]}"; do
# 容器状态
if check_container "$node"; then
container_status="${GREEN}运行中${NC}"
# 服务状态
if docker exec -it "$node" pgrep -f zookeeper &> /dev/null; then
service_info=$(docker exec -it $node $zk_server status 2>&1)
mode=$(grep "Mode" <<< "$service_info" | cut -d':' -f2 | tr -d ' ' || echo "unknown")
case "$mode" in
"leader") service_status="${CYAN}leader ${NC}" ;;
"follower") service_status="${CYAN}follower${NC}" ;;
*) service_status="${YELLOW}$mode${NC}" ;;
esac
else
service_status="${YELLOW}未运行${NC}"
fi
else
container_status="${RED}未运行${NC}"
service_status="${RED}不可用${NC}"
fi
printf "%-10s | %-16b | %b\n" "$node" "$container_status" "$service_status"
done
}
# 主逻辑
main() {
case "$1" in
start )
log "$YELLOW" "========= 启动Zookeeper集群 ========="
for node in "${nodes[@]}"; do
start_node "$node"
sleep 1
done
log "$YELLOW" "\n▌ 启动结果:"
check_status
;;
stop )
log "$YELLOW" "========= 停止Zookeeper集群 ========="
reversed_nodes=($(printf '%s\n' "${nodes[@]}" | tac | tr '\n' ' '))
for node in "${reversed_nodes[@]}"; do
if check_container "$node"; then
stop_node "$node"
else
log "$YELLOW" " ⚠ 容器未运行(跳过)"
fi
sleep 1
done
log "$YELLOW" "\n▌ 停止结果:"
check_status
;;
status )
log "$YELLOW" "========= 集群状态概览 ========="
check_status
;;
* )
echo -e "${BOLD}用法:${NC}"
echo -e " ${GREEN}sudo zkpctl start ${CYAN}- 顺序启动集群 (master -> slaves)"
echo -e " ${GREEN}sudo zkpctl stop ${CYAN}- 逆序停止集群 (slaves -> master)"
echo -e " ${GREEN}sudo zkpctl status ${CYAN}- 显示实时状态"
exit 1
;;
esac
echo -e "\n${GREEN}✅ 操作执行完成${NC}"
}
# 执行入口
main "$@"
sudo chmod +x /usr/local/bin/zkpctl
使用方法
sudo zkpctl start 顺序启动集群
sudo zkpctl stop 逆序停止集群
sudo zkpctl status 查看详细状态
五、Kafka集群安装
master节点上下载
wget http://archive.apache.org/dist/kafka/2.4.1/kafka_2.12-2.4.1.tgz
解压
tar -zxvf kafka_2.12-2.4.1.tgz -C /usr/local/
mv /usr/local/kafka_2.12-2.4.1 /usr/local/Kafka
修改配置文件 server.properties
vim /usr/local/kafka/config/server.properties
修改以下内容
broker.id=1
listeners=PLAINTEXT://master:9092
log.dirs=/usr/local/kafka/data
zookeeper.connect=master:2181,slave1:2181,slave2:2181,slave3:2181
分发
cd /usr/local/
scp -r kafka slave1:/usr/local/
scp -r kafka slave2:/usr/local/
scp -r kafka slave3:/usr/local/
slave1上修改配置文件 server.properties
vim /usr/local/kafka/config/server.properties
broker.id=2
listeners=PLAINTEXT://slave1:9092
slave2、3依此类推
编辑/etc/profile
文件
export KAFKA_HOME=/usr/local/kafka
export PATH=$PATH:$KAFKA_HOME/bin
source /etc/profile
快捷控制脚本,在容器外执行,不需要每次都进入到容器启动
sudo vim /usr/local/bin/kfkctl
#!/bin/bash
# 节点列表配置
nodes=("master" "slave1" "slave2" "slave3")
kafka_home="/usr/local/kafka"
zk_servers="master:2181,slave1:2181,slave2:2181,slave3:2181"
# 颜色定义
RED='\033[31m'
GREEN='\033[32m'
YELLOW='\033[33m'
NC='\033[0m'
# 动态生成broker.id(根据主机名末位数字+1)
gen_broker_id() {
hostname=$(docker exec -i "$1" hostname)
num=$(echo "$hostname" | sed 's/[^0-9]*//g')
echo $((num +1))
}
# 生成节点专用配置
generate_config() {
local node=$1
local broker_id=$(gen_broker_id "$node")
docker exec -i "$node" bash <<EOF
mkdir -p $kafka_home/data
cat > $kafka_home/config/server.properties <<CONF
# Auto-generated by cluster manager
broker.id=$broker_id
listeners=PLAINTEXT://0.0.0.0:9092
advertised.listeners=PLAINTEXT://$node:9092
log.dirs=$kafka_home/data
num.partitions=3
default.replication.factor=3
min.insync.replicas=2
zookeeper.connect=$zk_servers
auto.create.topics.enable=false
log.retention.hours=168
CONF
EOF
}
start_node() {
local node=$1
echo -e "${YELLOW}▶ 启动节点: $node ${NC}"
# 检查容器状态
if ! docker ps -q -f name="^${node}$" | grep -q .; then
echo -e "${RED}✖ 容器未运行!${NC}"
return
fi
# 生成动态配置
generate_config "$node"
# 启动服务(带日志轮转)
docker exec -d "$node" bash -c \
"exec $kafka_home/bin/kafka-server-start.sh $kafka_home/config/server.properties \
2>&1 | cronolog $kafka_home/logs/kafka-%Y%m%d.log"
# 进程验证
sleep 3
if docker exec -i "$node" pgrep -f "kafka\.Kafka" >/dev/null; then
echo -e "${GREEN}✔ 启动成功${NC}"
else
echo -e "${RED}✖ 启动失败!${NC}"
docker exec -i "$node" tail -n 10 "$kafka_home/logs/kafka-$(date +%Y%m%d).log"
fi
}
# 根据参数执行操作
case "$1" in
start)
echo -e "\n${YELLOW}========= 启动Kafka集群 =========${NC}"
for node in "${nodes[@]}"; do
start_node "$node"
done
;;
stop)
echo -e "\n${YELLOW}========= 停止Kafka集群 =========${NC}"
for node in "${nodes[@]}"; do
echo -e "${YELLOW}▌ 停止节点: $node ${NC}"
docker exec -i "$node" $kafka_home/bin/kafka-server-stop.sh
sleep 2
docker exec -i "$node" pkill -9 -f "kafka.Kafka" || true
done
;;
status)
echo -e "\n${YELLOW}========= Kafka集群状态 =========${NC}"
for node in "${nodes[@]}"; do
if docker exec -i "$node" pgrep -f "kafka.Kafka" >/dev/null; then
echo -e "$node: ${GREEN}运行中${NC}"
else
echo -e "$node: ${RED}未运行${NC}"
fi
done
;;
*)
echo "用法: $0 {start|stop|status}"
exit 1
esac
echo -e "\n${GREEN}✅ 操作完成${NC}"
sudo chmod +x /usr/local/bin/kfkctl
使用方法
sudo kfkctl start 启动集群
sudo kfkctl stop 停止集群
sudo kfkctl status 查看详细状态
六、Flume集群安装
下载
wget http://archive.apache.org/dist/flume/1.9.0/apache-flume-1.9.0-bin.tar.gz
解压
tar -zxvf apache-flume-1.9.0-bin.tar.gz -C /usr/local/
mv /usr/local/apache-flume-1.9.0-bin /usr/local/flume
修改flume-env.sh
文件
cp /usr/local/flume/conf/flume-env.sh.template /usr/local/flume/conf/flume-env.sh
vim /usr/local/flume/conf/flume-env.sh
export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64
创建Flume配置文件(请根据自身实际情况和需求编写配置文件,下面)
vim /usr/local/flume/conf/flume-kafka.conf
# 定义Agent的组件
agent.sources = source1
agent.channels = channel1
agent.sinks = sink1
# 配置Source
agent.sources.source1.type = exec
agent.sources.source1.command = tail -F /var/log/syslog
agent.sources.source1.channels = channel1
# 配置Channel
agent.channels.channel1.type = memory
agent.channels.channel1.capacity = 1000
agent.channels.channel1.transactionCapacity = 100
# 配置Sink
agent.sinks.sink1.type = org.apache.flume.sink.kafka.KafkaSink
agent.sinks.sink1.topic = flume-topic
agent.sinks.sink1.brokerList = master:9092,slave1:9092,slave2:9092,slave3:9092
agent.sinks.sink1.channel = channel1
分发
scp -r /usr/local/flume slave1:/usr/local/
scp -r /usr/local/flume slave2:/usr/local/
scp -r /usr/local/flume slave3:/usr/local/
编辑/etc/profile
文件
export FLUME_HOME=/usr/local/flume
export PATH=$PATH:$FLUME_HOME/bin
source /etc/profile
七、Hadoop集群安装
下载
wget https://mirrors.tuna.tsinghua.edu.cn/apache/hadoop/common/hadoop-3.2.1/hadoop-3.2.1.tar.gz
解压
tar -zxvf hadoop-3.2.1.tar.gz -C /usr/local
mv /usr/local/hadoop-3.2.1 /usr/local/hadoop
创建目录(所有节点)
mkdir -p /usr/local/hadoop /data/{nn,dn,nm-log,nm-local}
chmod -R 755 /data/
修改配置文件(仅作最简单演示,请根据自身情况完善配置)
cd /usr/local/Hadoop/etc/Hadoop/
vim hadoop-env.sh
在文件开始处加入以下内容
export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64
export HADOOP_HOME=/usr/local/hadoop
export HADOOP_CONF_DIR=$HADOOP_HOME/etc/hadoop
export YARN_CONF_DIR=$HADOOP_HOME/etc/hadoop
export YARN_LOG_DIR=$HADOOP_HOME/logs/yarn
export HADOOP_LOG_DIR=$HADOOP_HOME/logs/hdfs
export HDFS_NAMENODE_USER=root
export HDFS_DATANODE_USER=root
export HDFS_SECONDARYNAMENODE_USER=root
export YARN_RESOURCEMANAGER_USER=root
export YARN_NODEMANAGER_USER=root
export YARN_PROXYSERVER_USER=root
自行在各个节点创建创建上面提到的HADOOP_CONF_DIR目录和HADOOP_LOG_DIR目录(mkdir)
定义工作节点(master要不要都可以,看自身需求)
vim workers
master
slave1
slave2
slave3
其他配置文件(仅作参考,请根据自身情况配置)
vim core-site.xml
<configuration>
<!-- 指定HDFS入口(重要:绑定到容器master主机名) -->
<property>
<name>fs.defaultFS</name>
<value>hdfs://master:9000</value>
</property>
<!-- Zookeeper集成配置 -->
<property>
<name>ha.zookeeper.quorum</name>
<value>master:2181,slave1:2181,slave2:2181,slave3:2181</value>
</property>
<property>
<name>hadoop.tmp.dir</name>
<value>/opt/hadoop_data/tmp</value>
</property>
</configuration>
vim hdfs-site.xml
<configuration>
<!-- master节点额外属性 -->
<property>
<name>dfs.namenode.name.dir</name>
<value>/data/nn</value>
</property>
<!-- 所有节点通用 -->
<property>
<name>dfs.datanode.data.dir</name>
<value>/data/dn</value>
<!-- 对应Docker容器内/data/dn目录 -->
</property>
<!-- 适配容器网络 -->
<property>
<name>dfs.client.use.datanode.hostname</name>
<value>true</value>
</property>
</configuration>
vim yarn-site.xml
<property>
<name>yarn.resourcemanager.hostname</name>
<value>master</value>
</property>
<!-- 关键调整:避免节点通信失败 -->
<property>
<name>yarn.nodemanager.hostname</name>
<value>0.0.0.0</value>
</property>
vim mapred-site.xml
<property>
<name>mapreduce.jobhistory.address</name>
<value>master:10020</value>
</property>
<property>
<name>yarn.app.mapreduce.am.env</name>
<value>HADOOP_MAPRED_HOME=/usr/local/hadoop</value>
</property>
分发
cd /usr/local
scp -r hadoop slave1:/usr/local/
scp -r hadoop slave2:/usr/local/
scp -r hadoop slave3:/usr/local/
编辑/etc/profile文件
export HADOOP_HOME=/usr/local/hadoop
export PATH=$PATH:$HADOOP_HOME/bin:$HADOOP_HOME/sbin
source /etc/profile
脚本
sudo vim /usr/local/bin/hdpctl
#!/bin/bash
# 配置区域
MASTER_CONTAINER="master"
HADOOP_HOME="/usr/local/hadoop"
DOCKER_USER="root"
# 颜色定义
RED='\033[31m'
GREEN='\033[32m'
YELLOW='\033[33m'
CYAN='\033[36m'
NC='\033[0m'
#=============================== 核心功能 ===============================#
validate_container() {
if ! docker ps -q -f name="^${1}$" | grep -q .; then
echo -e "${RED}✖ 容器 ${CYAN}${1} ${RED}未运行!${NC}" >&2
return 1
fi
return 0
}
start_cluster() {
echo -e "${YELLOW}▶ 正在启动集群服务..."
docker exec -u $DOCKER_USER $MASTER_CONTAINER $HADOOP_HOME/sbin/start-dfs.sh
sleep 5 # 延长等待时间确保NameNode初始化
docker exec -u $DOCKER_USER $MASTER_CONTAINER $HADOOP_HOME/sbin/start-yarn.sh
}
stop_cluster() {
echo -e "${YELLOW}▶ 正在停止集群服务..."
docker exec -u $DOCKER_USER $MASTER_CONTAINER $HADOOP_HOME/sbin/stop-yarn.sh
docker exec -u $DOCKER_USER $MASTER_CONTAINER $HADOOP_HOME/sbin/stop-dfs.sh
}
show_cluster_status() {
# 获取HDFS报告并标准化输出(忽略警告)
hdfs_output=$(docker exec -u $DOCKER_USER $MASTER_CONTAINER \
$HADOOP_HOME/bin/hdfs dfsadmin -report 2> >(grep -v "WARN\|ERROR" >&2))
# 精确提取存活DataNode数量
live_dns=$(echo "$hdfs_output" | awk 'tolower($0) ~ /live datanodes/ && /\([0-9]+\)/ {
gsub(/[^0-9]/, "", $NF); print $NF; exit}')
live_dns=${live_dns:-0} # 处理空值情况
# 总文件数(直接通过DFS命令获取更准确)
total_files=$(docker exec -u $DOCKER_USER $MASTER_CONTAINER $HADOOP_HOME/bin/hdfs dfs -ls -R / 2>/dev/null | grep -c "^-")
# 安全模式检测
safe_mode=$(echo "$hdfs_output" | grep "Safe mode is ON" | wc -l | awk '{print $1 ? "ON" : "OFF"}')
echo -e "\n${CYAN}═════════ HDFS 核心状态 ═════════${NC}"
echo -e "📂 ${GREEN}总文件数: ${YELLOW}${total_files}${NC}"
echo -e "🖥️ ${GREEN}活跃节点: ${YELLOW}${live_dns}个${NC}"
echo -e "🔒 ${GREEN}安全模式: ${safe_mode}${NC}"
# 服务进程状态检查
check_service() {
local service=$1 nodes=($2)
echo -e "\n${CYAN}═════════ ${service}状态 ═════════${NC}"
for node in "${nodes[@]}"; do
if validate_container $node &>/dev/null; then
count=$(docker exec $node sh -c "jps | grep -c $service")
status="${GREEN}✅ 运行中 (进程数 ${count})${NC}"
else
status="${RED}❌ 容器未运行${NC}"
fi
echo -e "│ ${node}: $status"
done
}
check_service "NameNode" "$MASTER_CONTAINER"
check_service "DataNode" "slave1 slave2 slave3"
}
#=============================== 主逻辑 ===============================#
case $1 in
start)
validate_container $MASTER_CONTAINER && start_cluster
;;
stop)
validate_container $MASTER_CONTAINER && stop_cluster
;;
status)
validate_container $MASTER_CONTAINER && show_cluster_status
;;
*)
echo -e "${YELLOW}使用方法: ${NC}$0 {start|stop|status}"
exit 1
esac
# 统一显示简略状态(仅启动/停止时)
if [[ "$1" != "status" ]]; then
sleep 3
if validate_container $MASTER_CONTAINER; then
current_dns=$(docker exec -u $DOCKER_USER $MASTER_CONTAINER \
$HADOOP_HOME/bin/hdfs dfsadmin -report 2>/dev/null | awk \
'tolower($0) ~ /live datanodes/ && /\([0-9]+\)/ {gsub(/[^0-9]/,"",$NF); print $NF}')
echo -e "${CYAN}当前存活DataNode: ${YELLOW}${current_dns:-0}个${NC}"
fi
fi
exit 0
sudo chmod +x /usr/local/bin/hdpctl
使用方法类似
八、HBase
下载
wget http://archive.apache.org/dist/hbase/2.2.6/hbase-2.2.6-bin.tar.gz
解压
tar -zxvf hbase-2.2.6-bin.tar.gz -C /usr/local/
mv /usr/local/hbase-2.2.6 /usr/local/hbase
修改hbase-env.sh
vim /usr/local/hbase/conf/hbase-env.sh
export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64
export PATH=$JAVA_HOME/bin:$PATH
export HBASE_MANAGES_ZK=false
export HBASE_DISABLE_HADOOP_CLASSPATH_LOOKUP="true"
export HBASE_OPTS="-XX:+UseConcMarkSweepGC -XX:ParallelGCThreads=4"
配置hbase-site.xml
vim /usr/local/hbase/conf/hbase-site.xml
<configuration>
<!-- HBase数据存储路径,对应HDFS地址 -->
<property>
<name>hbase.rootdir</name>
<value>hdfs://master:9000/hbase</value>
</property>
<!-- 开启分布式模式 -->
<property>
<name>hbase.cluster.distributed</name>
<value>true</value>
</property>
<!-- Zookeeper集群地址(您的容器主机名) -->
<property>
<name>hbase.zookeeper.quorum</name>
<value>master,slave1,slave2,slave3</value>
</property>
<!-- Zookeeper数据目录(需提前创建) -->
<property>
<name>hbase.zookeeper.property.dataDir</name>
<value>/usr/local/zookeeper/data</value>
</property>
<!-- 兼容性设置 -->
<property>
<name>hbase.unsafe.stream.capability.enforce</name>
<value>false</value>
</property>
<!-- 绑定容器IP防止外部访问问题 -->
<property>
<name>hbase.master.ipc.address</name>
<value>0.0.0.0</value>
</property>
<property>
<name>hbase.master</name>
<value>master:60000</value>
</property>
</configuration>
配置RegionServers节点
vim /conf/regionservers
master
slave1
slave2
slave3
分发
scp -r /usr/local/hbase slave1:/usr/local/
scp -r /usr/local/hbase slave2:/usr/local/
scp -r /usr/local/hbase slave3:/usr/local/
编辑/etc/profile文件
export HBASE_HOME=/usr/local/hbase
export PATH=$PATH:$HBASE_HOME/bin
source /etc/profile
脚本
sudo vim /usr/local/bin/hbsctl
#!/bin/bash
# 配置区域
MASTER_CONTAINER="master" # Master节点容器名
SLAVE_CONTAINERS=("slave1" "slave2" "slave3") # RegionServer节点
HBASE_HOME="/usr/local/hbase" # HBase安装路径
DOCKER_USER="hadoop" # Docker容器执行用户
# 颜色定义
GREEN='\033[32m'
RED='\033[31m'
YELLOW='\033[33m'
CYAN='\033[36m'
NC='\033[0m'
#=============================== 核心函数 ===============================#
# 检查容器状态
check_container() {
if ! docker ps -q -f name="^${1}$" | grep -q .; then
echo -e "${RED}✖ 容器 ${CYAN}${1} ${RED}未运行!${NC}" >&2
return 1
fi
return 0
}
# 启动HBase集群
start_hbase() {
echo -e "${YELLOW}▶ 启动HBase集群..."
if check_container "$MASTER_CONTAINER"; then
docker exec -u $DOCKER_USER $MASTER_CONTAINER $HBASE_HOME/bin/start-hbase.sh
echo -e "${GREEN}✔ HBase Master已启动${NC}"
fi
# 确认RegionServer自动启动(依赖于HBase配置)
echo -e "${CYAN}等待RegionServer注册...${NC}"
sleep 10 # 等待RegionServer启动
}
# 停止HBase集群
stop_hbase() {
echo -e "${YELLOW}▶ 停止HBase集群..."
if check_container "$MASTER_CONTAINER"; then
docker exec -u $DOCKER_USER $MASTER_CONTAINER $HBASE_HOME/bin/stop-hbase.sh
echo -e "${GREEN}✔ HBase Master已停止${NC}"
else
echo -e "${RED}⚠ Master容器未运行,可能无法彻底停止服务${NC}"
fi
}
# 查询实时状态
status_hbase() {
# 检查HMaster进程
master_status="${RED}✖ 未运行${NC}"
if check_container "$MASTER_CONTAINER"; then
if docker exec $MASTER_CONTAINER pgrep -f HMaster >/dev/null; then
master_status="${GREEN}✅ 运行中${NC} (端口:16010)"
fi
fi
# 检查RegionServer进程
rs_status=()
for node in "${SLAVE_CONTAINERS[@]}"; do
status="${RED}✖ 未运行${NC}"
if check_container "$node"; then
if docker exec $node pgrep -f HRegionServer >/dev/null; then
rs_count=$((rs_count +1))
status="${GREEN}✅ 运行中${NC}"
fi
fi
rs_status+=("│ ${node}: $status")
done
# 输出状态看板
echo -e "\n${CYAN}═════════ HBase 状态报告 ═════════${NC}"
echo -e "🖥️ ${CYAN}HMaster状态: ${master_status}${NC}"
echo -e "\n${CYAN}══ RegionServer节点状态 ══════════${NC}"
printf "%s\n" "${rs_status[@]}"
# 提示Web访问
echo -e "\n${YELLOW}🌐 访问HBase Web控制台: http://宿主机IP:16010${NC}"
}
#=============================== 主逻辑 ===============================#
case "$1" in
start)
start_hbase
;;
stop)
stop_hbase
;;
status)
status_hbase
;;
*)
echo -e "${YELLOW}用法: $0 {start|stop|status}"
exit 1
esac
exit 0
sudo chmod +x /usr/local/bin/hbsctl
九、Hive
9.1 安装MySQL
(master上,也可以在WSl即宿主机上,改一下配置文件就行)
(此处MySQL也可以创建单独的MySQL容器)
预先配置root密码
echo "mysql-community-server mysql-community-server/root-pass password 你的密码" | debconf-set-selections
echo "mysql-community-server mysql-community-server/re-root-pass password 你的密码" | debconf-set-selections
apt install -y mysql-server
(ps:别问为什么apt,累了,懒了,有较高要求的请自展神通)
启动MySQL服务
service mysql start
mysql -u root -p你的密码 <<EOF
DELETE FROM mysql.user WHERE User='';
DROP DATABASE IF EXISTS test;
DELETE FROM mysql.db WHERE Db='test' OR Db='test\\_%';
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '你的密码';
FLUSH PRIVILEGES;
EOF
修改MySQL配置文件
sed -i '/^bind-address/s/127.0.0.1/0.0.0.0/' /etc/mysql/mysql.conf.d/mysqld.cnf
service mysql restart
创建Hive元数据库
mysql -uroot -p你的密码 <<EOF
CREATE DATABASE IF NOT EXISTS hive_meta DEFAULT CHARSET utf8;
CREATE USER 'root'@'%' IDENTIFIED BY 'your_strong_password';
GRANT ALL PRIVILEGES ON hive_meta.* TO 'root'@'%';
FLUSH PRIVILEGES;
EOF
如果是在master内安装MySQL的话,由于docker的Linux是瘦过身的,MySQL可能不会正常自启动,为了避免每次都要进容器开MySQL,配置一下MySQL自启动
echo '#!/bin/bash
LOGTIME=$(date "+%Y-%m-%d %H:%M:%S")
echo "[$LOGTIME] Starting MySQL..." >> /root/start_mysql.log
service mysql start >> /root/start_mysql.log 2>&1' > /root/start_mysql.sh
chmod +x /root/start_mysql.sh
echo '
if [ -f /root/start_mysql.sh ]; then
/root/start_mysql.sh
fi' >> /root/.bashrc
9.2 安装Hive
wget http://archive.apache.org/dist/hive/hive-3.1.2/apache-hive-3.1.2-bin.tar.gz
解压
tar -zxvf apache-hive-3.1.2-bin.tar.gz -C /usr/local/
mv /usr/local/apache-hive-3.1.2-bin /usr/local/hive
解决Guava版本冲突
移除Hive自带的低版本Guava,复制Hadoop的Guava库到Hive
例:
rm /usr/local/hive/lib/guava-19.0.jar
cp /usr/local/hadoop/share/hadoop/common/lib/guava-27.0-jre.jar /usr/local/hive/lib/
下载MySQL驱动
wget https://repo1.maven.org/maven2/mysql/mysql-connector-java/8.0.28/mysql-connector-java-8.0.28.jar
mv mysql-connector-java-8.0.28.jar /usr/local/hive/lib/
修改Hive配置文件
vim /usr/local/hive/conf/hive-site.xml
<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>
<!-- MySQL连接配置 -->
<property>
<name>javax.jdo.option.ConnectionURL</name>
<value>jdbc:mysql://master:3306/hive_meta?createDatabaseIfNotExist=true&useSSL=false&allowPublicKeyRetrieval=true</value>
</property>
<property>
<name>javax.jdo.option.ConnectionDriverName</name>
<value>com.mysql.cj.jdbc.Driver</value>
</property>
<property>
<name>javax.jdo.option.ConnectionUserName</name>
<value>root</value> <!-- 直接使用root用户 -->
</property>
<property>
<name>javax.jdo.option.ConnectionPassword</name>
<value>你的密码</value> <!-- 你的MySQL root密码 -->
</property>
<!-- HDFS相关路径 -->
<property>
<name>hive.metastore.warehouse.dir</name>
<value>/user/hive/warehouse</value>
</property>
<property>
<name>hive.exec.scratchdir</name>
<value>/user/hive/tmp</value>
</property>
<!-- 权限验证关闭(避免root用户问题) -->
<property>
<name>hive.metastore.schema.verification</name>
<value>false</value>
</property>
<property>
<name>hive.server2.enable.doAs</name>
<value>false</value> <!-- 关闭Impersonation -->
</property>
</configuration>
hadoop配置调整(重启HDFS/YARN生效)
<property>
<name>hadoop.proxyuser.root.groups</name>
<value>*</value>
</property>
<property>
<name>hadoop.proxyuser.root.hosts</name>
<value>*</value>
</property>
执行Schema初始化(预期看到: schemaTool completed)
/usr/local/hive/bin/schematool -dbType mysql -initSchema
编辑/etc/profile文件
export HIVE_HOME=/usr/local/hive
export PATH=$PATH:$HIVE_HOME/bin
source /etc/profile
脚本
sudo vim /usr/local/bin/hivectl
#!/bin/bash
MASTER_CONTAINER="master"
HIVE_HOME="/usr/local/hive"
DOCKER_USER="root"
HIVE_PROCESS_PATTERN="org.apache.hadoop.hive.metastore.HiveMetaStore"
RED='\033[31m'; GREEN='\033[32m'; YELLOW='\033[33m'; CYAN='\033[36m'; NC='\033[0m'
check_container() {
docker ps -q -f name="^${MASTER_CONTAINER}$" || {
echo -e "${RED}✖ 容器 ${MASTER_CONTAINER} 未运行!${NC}" >&2; return 1
}
}
start_hive() {
check_container || return 1
pid=$(docker exec -u $DOCKER_USER $MASTER_CONTAINER pgrep -f "$HIVE_PROCESS_PATTERN")
if [ -n "$pid" ]; then
echo -e "${YELLOW}⚠ 服务已在运行 (PID: $pid)${NC}"; return 0
fi
echo -e "${YELLOW}▶ 启动Hive Metastore服务...${NC}"
docker exec -u $DOCKER_USER $MASTER_CONTAINER bash -c \
"export HADOOP_HOME=/usr/local/hadoop && \
source /etc/environment && \
nohup $HIVE_HOME/bin/hive --service metastore > /tmp/hive-metastore.log 2>&1 &"
sleep 7
pid=$(docker exec -u $DOCKER_USER $MASTER_CONTAINER pgrep -f "$HIVE_PROCESS_PATTERN")
if [ -n "$pid" ]; then
echo -e "${GREEN}✔ 启动成功 (PID: $pid)${NC}"
docker exec $MASTER_CONTAINER netstat -tuln | grep 9083 || \
echo -e "${YELLOW}⚠ 9083端口未监听,但进程存在${NC}"
else
echo -e "${RED}✖ 启动失败!步骤排查:${NC}"
echo -e "1. Hadoop路径测试: ${CYAN}docker exec master ls /usr/local/hadoop/bin/hadoop${NC}"
echo -e "2. 日志诊断: ${CYAN}docker exec master grep -i error /tmp/hive-metastore.log${NC}"
fi
}
stop_hive() {
check_container || return 1
echo -e "${YELLOW}▶ 停止Hive Metastore服务...${NC}"
pid=$(docker exec -u $DOCKER_USER $MASTER_CONTAINER pgrep -f "$HIVE_PROCESS_PATTERN")
if [ -n "$pid" ]; then
docker exec -u $DOCKER_USER $MASTER_CONTAINER kill -9 $pid
echo -e "${GREEN}✔ 已终止 (PID: $pid)${NC}"
else
echo -e "${YELLOW}⚠ 无运行中的服务${NC}"
fi
}
status_hive() {
check_container || return 1
echo -e "${CYAN}═════════ Hive服务状态 ═════════${NC}"
# 使用进程和端口双重验证MySQL状态
mysql_pid=$(docker exec -u $DOCKER_USER $MASTER_CONTAINER pgrep mysqld)
mysql_port=$(docker exec -u $DOCKER_USER $MASTER_CONTAINER netstat -tuln | grep 3306)
if [ -n "$mysql_pid" ]; then
echo -e "MySQL状态: ${GREEN}✅ 运行中 (PID: $mysql_pid)${NC}"
[ -n "$mysql_port" ] && echo -e "监听端口: ${GREEN}✅ 3306${NC}" || echo -e "监听端口: ${RED}✖ 未检测到${NC}"
else
echo -e "MySQL状态: ${RED}✖ 未运行${NC}"
# 检测Metastore进程及端口
pid=$(docker exec -u $DOCKER_USER $MASTER_CONTAINER pgrep -f "$HIVE_PROCESS_PATTERN")
if [ -n "$pid" ]; then
echo -e "Metastore状态: ${GREEN}✅ 运行中 (PID: $pid)${NC}"
port_check=$(docker exec -u $DOCKER_USER $MASTER_CONTAINER netstat -tuln | grep 9083)
[ -n "$port_check" ] && echo -e "监听端口: ${GREEN}✅ 9083${NC}" || echo -e "监听端口: ${RED}✖ 未检测到${NC}"
else
echo -e "Metastore状态: ${RED}✖ 未运行${NC}"
fi
}
case "$1" in
start) start_hive ;;
stop) stop_hive ;;
status) status_hive ;;
restart) stop_hive && start_hive ;;
*) echo -e "用法: $0 {start|stop|status|restart}" ;;
esac
sudo chmod +x /usr/local/bin/hivectl
十、Spark
下载
wget https://mirrors.tuna.tsinghua.edu.cn/apache/spark/spark-3.4.4/spark-3.4.4-bin-hadoop3-scala2.13.tgz
解压
tar -zxvf spark-3.4.4-bin-hadoop3-scala2.13.tgz -C /usr/local
mv /usr/local/spark-3.4.4-bin-hadoop3-scala2.13 /usr/local/spark
修改配置
cp /usr/local/spark/conf/spark-env.sh.template /usr/local/spark/conf/spark-env.sh
vim /usr/local/spark/conf/spark-env.sh
#设置JAVA安装目录
JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64
#HADOOP软件配置文件目录,读取HDFS上文件和运行YARN集群
export HADOOP_HOME=/usr/local/hadoop
export HADOOP_CONF_DIR=$HADOOP_HOME/etc/hadoop
export YARN_CONF_DIR=$HADOOP_HOME/etc/hadoop
#指定spark老大Master的IP和提交任务的通信端口
export SPARK_MASTER_HOST=master
export SPARK_MASTER_PORT=7077
export SPARK_LOCAL_IP=master
export LD_LIBRARY_PATH=$HADOOP_HOME/lib/native:$LD_LIBRARY_PATH
SPARK_WORKER_MEMORY=4g
export SPARK_MASTER_WEBUI_PORT=8989
export SPARK_UI_PORT=8990
cp /usr/local/spark/conf/workers.template /usr/local/spark/conf/workers
vim /usr/local/spark/conf/workers
master
slave1
slave2
slave3
cp /usr/local/spark/conf/spark-defaults.conf.template /usr/local/spark/conf/spark-defaults.conf
vim /usr/local/spark/conf/spark-defaults.conf
追加
spark.eventLog.enabled true
spark.eventLog.dir hdfs://master:9000/spark-logs
spark.history.fs.logDirectory hdfs://master:9000/spark-logs
spark.history.ui.port 18080
创建HDFS目录
hadoop fs -mkdir -p /spark-logs
hadoop fs -chmod -R 777 /spark-logs
分发
cd /usr/local
scp -r spark/ slave1:/usr/local
scp -r spark/ slave2:/usr/local
scp -r spark/ slave3:/usr/local
修改各个节点的SPARK_LOCAL_IP为自身ip
如 slave1节点: export SPARK_LOCAL_IP=slave1
编辑/etc/profile文件
export SPARK_HOME=/usr/local/spark
export PATH=$PATH:$SPARK_HOME/bin:$SPARK_HOME/sbin
export PYSPARK_PYTHON=/usr/bin/python3
export PYSPARK_DRIVER_PYTHON=/usr/bin/python3
source /etc/profile
脚本
sudo vim /usr/local/bin/spkctl
#!/bin/bash
# 配置区域
MASTER_CONTAINER="master"
SLAVE_CONTAINERS=("master" "slave1" "slave2" "slave3")
SPARK_HOME="/usr/local/spark"
DOCKER_USER="root"
LOG_FILE="/var/log/sparkctl.log"
# 颜色定义
GREEN='\033[32m'
RED='\033[31m'
YELLOW='\033[33m'
CYAN='\033[36m'
NC='\033[0m'
# 日志记录函数
log() {
echo "[$(date '+%F %T')] $1" | tee -a $LOG_FILE
}
# 容器状态检查
check_container() {
if ! docker ps -q -f name="^${1}$" | grep -q .; then
log "${RED}ERROR: Container ${CYAN}${1} ${RED}is not running${NC}"
return 1
fi
return 0
}
# 启动Spark集群
start_spark() {
log "${YELLOW}▶ Starting Spark cluster..."
# 启动Master和Workers
if check_container $MASTER_CONTAINER; then
docker exec -u $DOCKER_USER $MASTER_CONTAINER $SPARK_HOME/sbin/start-all.sh
log "${GREEN}Spark Master and Workers started successfully${NC}"
# 启动历史服务器
docker exec -u $DOCKER_USER $MASTER_CONTAINER $SPARK_HOME/sbin/start-history-server.sh
log "${GREEN}Spark History Server started successfully${NC}"
fi
}
# 停止Spark集群
stop_spark() {
log "${YELLOW}▶ Stopping Spark cluster..."
# 停止Workers和Master
if check_container $MASTER_CONTAINER; then
docker exec -u $DOCKER_USER $MASTER_CONTAINER $SPARK_HOME/sbin/stop-all.sh
log "${GREEN}Spark Master and Workers stopped successfully${NC}"
# 停止历史服务器
docker exec -u $DOCKER_USER $MASTER_CONTAINER $SPARK_HOME/sbin/stop-history-server.sh
log "${GREEN}Spark History Server stopped successfully${NC}"
fi
}
# 检查集群状态
status_spark() {
log "${CYAN}═══════════ Spark 集群状态 ═══════════${NC}"
# Master节点状态
if check_container $MASTER_CONTAINER; then
master_proc=$(docker exec $MASTER_CONTAINER jps | grep -E 'Master|HistoryServer')
echo -e "${CYAN}[Master]${NC}"
echo -e "├─ Spark Master: $(echo "$master_proc" | grep Master | awk '{print $2? "✅" : "❌"}')"
echo -e "└─ HistoryServer: $(echo "$master_proc" | grep HistoryServer | awk '{print $2? "✅" : "❌"}')"
fi
# Worker节点状态
echo -e "\n${CYAN}[Workers]${NC}"
for node in "${SLAVE_CONTAINERS[@]}"; do
if check_container $node; then
worker_status=$(docker exec $node jps | grep -c "Worker")
echo -e "├─ ${node}: ${worker_status:+${GREEN}✅${NC}} ${worker_status:-${RED}❌${NC}}"
else
echo -e "├─ ${node}: ${RED}❌ Container offline${NC}"
fi
done
# 访问提示
echo -e "\n${GREEN}Spark Web UI:${NC} http://<宿主机IP>:8080"
echo -e "${GREEN}History Server:${NC} http://<宿主机IP>:18080"
}
# 主逻辑
case "$1" in
start)
start_spark
;;
stop)
stop_spark
;;
status)
status_spark
;;
*)
echo -e "${YELLOW}Usage: $0 {start|stop|status}"
exit 1
esac
exit 0
sudo chmod +x /usr/local/bin/spkctl
结语
至此,集群配置已基本完成。如果一切正常,你就可以愉快地使用 docker commit
保存镜像,方便日后快速复现整个集群环境。
当需要再次使用该集群时,只需执行:
sudo docker start master slave1 slave2 slave3
随后运行对应的控制脚本,即可启动对应服务。
由于在创建 master 容器时已进行端口映射,因此在 WSL 内可直接通过 localhost:端口号
访问对应功能。或者安装对应客户端即可(如Hadoop)。
如确实需要进入某个容器进行操作的,可使用 docker exec命令
此外,也推荐使用 JetBrains Gateway 连接 WSL,这样你就可以在 Windows 上使用 JetBrains 全家桶优雅地操作你的大数据集群了。
例子:在Windows上使用pycharm连接WSL,并编写简单Kafka生产者代码
最后
就介样了,累死我了,这是我第一次写文章,没想到一下子就写了3万字,我知道文章里有很多不合理的地方,后续会慢慢改进,看在我这么累的份上轻点骂,谢谢。