RE·从零开始的...基于WSL2+Docker的大数据生态系统部署指南

更新记录:

2025/4/14:增加 SSH免密配置部分遗漏步骤。

 叠甲部分

1. **教程定位说明**
本指南为大数据技术学习实践文档,主要服务于技术验证与初学者学习测试场景。记录内容基于单机多容器部署模式,适用于个人学习及小型实验环境搭建。如需应用于生产环境,请结合分布式架构设计要求、硬件资源规划及企业安全规范进行全方位改造(或者出门右拐)。

2. **环境兼容性声明**
实验环境基于Windows Subsystem for Linux (WSL) 2.0构建,采用Docker容器化部署方案实现多节点模拟。传统物理机部署、虚拟机集群或其他容器运行时(如Podman)使用时,需重点注意以下差异点:
- 网络拓扑结构的适配调整
- 系统资源隔离机制的差异性配置
建议在实际部署前完成目标环境的功能验证测试。

并且每个人的软硬件环境的差异,本教程不保证能100%可直接照搬成功,大概率需要根据自身情况做出适量调整。

3、作者是个清澈愚蠢的大学生,石粒有限,是个菜鸟,如有错误欢迎指出(不包括这句话的“石粒”二字)。

目录

一、环境准备与基础配置

1.1 WSL环境搭建(可选)

1.1.1 什么是WSL

1.1.2 与传统虚拟机相比,WSL 具有的优势

1.1.3 系统配置要求

1.1.4 WSL安装

1.2 WSL(Linux系统)初始配置

1.3 安装Docker

二、配置初始镜像

2.1  创建于初始配置

2.2  ssh免密登录

2.3 保存初始镜像

三、docker网络配置与容器实例化

四、Zookeeper集群安装

五、Kafka集群安装

六、Flume集群安装

七、Hadoop集群安装

八、HBase

九、Hive

9.1 安装MySQL

9.2 安装Hive

十、Spark

结语


一、环境准备与基础配置

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&amp;useSSL=false&amp;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万字,我知道文章里有很多不合理的地方,后续会慢慢改进,看在我这么累的份上轻点骂,谢谢。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值