基于HDFS的小型Spark集群搭建

软件版本:jdk8 + hadoop-2.6.4.tar.gz + scala-2.11.6.tgz + spark-2.0.0-bin-hadoop2.6.tgz + Anaconda3-4.1.1-Linux-x86_64.sh (官网均可下,亲测可兼容)

服务器购买

什么云都可以,我在阿里云买了三台服务器,须在同一内网下(同一账号购买的ECS加入同一安全组,加入专有网络,用内网传输速度贼快),安装Ubuntu16.04 64位

通过putty远程连接三台服务器,开始环境配置

基础环境配置

1. 创建新用户

# 不推荐使用root用户
# 刚开始在root下,修改/etc/sudoers文件
nano /etc/sudoers
# 在 User privilege specification 下添上hduser	ALL=(ALL:ALL) ALL 添加root权限
# 然后创建新用户
adduser hduser
# 输入相关信息(可直接回车),输入密码
# 切换hduser
su hduser

2. 修改hostname和hosts文件

sudo nano /etc/hostname
# 三台服务器分别输入
master data1 data2
# 再修改hosts
sudo nano /etc/hosts
# 除了第一行,其他全部删掉 然后输入
master的私网ip master
data1的私网ip	data1
data2的私网ip	data2
# 配置之后 ping 一下用户名看是否生效 只有内网互通的服务器才能ping通
ping master
ping data1
ping data2

3. 配置ssh无密码登录

# 关闭防火墙
sudo ufw disable
sudo apt-get install openssh-server
sudo apt-get update
ssh-keygen -t rsa -P "" 
# 提示选择目录时,按 Enter 键,那么 id_rsa 和 id_rsa.pub 会生成到 /home/hduser/.ssh 目录下。在家目录下使用 ls -a 命令可以看到该目录。
cd root/.ssh
cat id_rsa.pub>>authorized_keys # 将 id_rsa.pub 追加到 authorized_keys
# 在master机器下,其他两台机器同理
ssh-copy-id hduser@data1(data2) # 将自己的id_rsa.pub直接添加到到其他两台机器的authorized_keys中
# 验证ssh无密码通信
ssh data1(data2) # 可无密码登录就算成功

Hadoop单节点

4. 安装JDK

sudo apt-get update
sudo apt-get install default-jdk
java -version
# 安装成功会显示java版本

5. 下载安装Hadoop

# 下载
wget https://archive.apache.org/dist/hadoop/common/hadoop-2.6.4/hadoop-2.6.4.tar.gz
# 解压
sudo tar -zxvf hadoop-2.6.4.tar.gz
# 要是下载太慢,可以在本地下好再传过去
# 转移目录
sudo mv hadoop-2.6.4 /usr/local/hadoop
# 设置环境目录
sudo nano /home/hduser/.bashrc
# 在最后添加以下内容
export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64
export HADOOP_HOME=/usr/local/hadoop
export PATH=$PATH:$HADOOP_HOME/bin
export PATH=$PATH:$HADOOP_HOME/sbin
export HADOOP_MAPRED_HOME=$HADOOP_HOME
export HADOOP_COMMON_HOME=$HADOOP_HOME
export HADOOP_HDFS_HOME=$HADOOP_HOME
export YARN_HOME=$HADOOP_HOME
export HADOOP_COMMON_HOME=$HADOOP_HOME
export HADOOP_HDFS_HOME=$HADOOP_HOME
export YARN_HOME=$HADOOP_HOME
export HADOOP_COMMON_LIB_NATIVE_DIR=$HADOOP_HOME/lib/native
export HADOOP_OPTS="-Djava.library.path=$HADOOP_HOME/lib"
export JAVA_LIBRARY_PATH=$HADOOP_HOME/lib/native:$JAVA_LIBRARY_PATH
# ~/.bashrc修改生效
source ~/.bashrc

6. 修改Hadoop组态设定档

# 1.修改hadoop-env.sh
sudo nano /usr/local/hadoop/etc/hadoop/hadoop-env.sh
# 找到这一句,修改后面的路径
export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64
# 2.修改core-site.xml
sudo nano /usr/local/hadoop/etc/hadoop/core-site.xml
# 修改最后的设置项
<configuration>
        <property>
                <name>fs.default.name</name>
                <value>hdfs://localhost:9000</value>
        </property>
</configuration>
# 3.修改yarn-site.xml
sudo nano /usr/local/hadoop/etc/hadoop/yarn-site.xml
# 修改最后的设置项
<configuration>
<!-- Site specific YARN configuration properties -->
<property>
	<name>yarn.nodemanager.aux-services</name>
	<value>mapreduce_shuffle</value>
</property>
<property>
	<name>yarn.nodemanager.aux-services.mapreduce.shuffle.class</name>
	<value>org.apache.hadoop.mapred.ShuffleHandler</value>
</property>
</configuration>
# 4.修改mapred-site.xml
sudo cp /usr/local/hadoop/etc/hadoop/mapred-site.xml.template /usr/local/hadoop/etc/hadoop/mapred-site.xml
sudo gedit /usr/local/hadoop/etc/hadoop/mapred-site.xml
# 修改最后的设置项
<configuration>
        <property>
                <name>mapreduce.framework.name</name>
                <value>yarn</value>
        </property>
</configuration>
# 5.修改hdfs-site.xml
sudo nano /usr/local/hadoop/etc/hadoop/hdfs-site.xml
# 修改最后的设置项
<configuration>
<property>
	<name>dfs.replication</name>
	<value>1</value> # 这是hdfs的数据备份数量,默认是3,由于我不需要备份,所以我这里设置成1
</property>
<property>
	<name>dfs.namenode.name.dir</name>
	<value>file:/usr/local/hadoop/hadoop_data/hdfs/namenode</value>
</property>
<property>
	<name>dfs.datanode.data.dir</name>
	<value>file:/usr/local/hadoop/hadoop_data/hdfs/datanode</value>
</property>
</configuration>
# 6.建立与格式化HDFS目录
# 创建名称节点和数据节点目录
sudo mkdir -p /usr/local/hadoop/hadoop_data/hdfs/namenode
sudo mkdir -p /usr/local/hadoop/hadoop_data/hdfs/datanode
# 设置文件的拥有者为hduser
sudo chown hduser:hduser -R /usr/local/hadoop
# 格式化目录
hadoop namenode -format

7. 启动单节点hadoop

# 先启动dfs
start-dfs.sh
# 在启动yarn
start-yarn.sh
# 或者一起启动
start-all.sh
# 查看运行
jps
# 应该有NameNode,DataNode,SecondaryNameNode,NodeManger,ResourceManger等
# 在阿里云控制台 配置安全组规则, 加入TCP 8088(Hadoop Resource-manager Web),50070(NameNode HDFS Web),8080(Spark),8888(jupyter)规则
# 在本地浏览器输入
http://公网ip:8088/
# 能看到Nodes有一个Node在运行。
http://公网ip:50070/
# 能看到有一个Live Node

以上操作每台机器都要,如果每台机器都能成功运行hadoop单节点,则第一阶段配置成功

Hadoop多节点

8. 修改Hadoop组态设定档

# 1. 修改core-site.xml
sudo nano /usr/local/hadoop/etc/hadoop/core-site.xml
# 修改最后localhost为master
<configuration>
        <property>
                <name>fs.default.name</name>
                <value>hdfs://master:9000</value>
        </property>
</configuration>
# 2.修改yarn-site.xml
sudo nano /usr/local/hadoop/etc/hadoop/yarn-site.xml
# 在设置项中添加以下内容
<property>
	<name>yarn.resourcemanager.resource-tracker.address</name>
	<value>master:8025</value>
</property>
<property>
	<name>yarn.resourcemanager.scheduler.address</name>
	<value>master:8030</value>
</property>
<property>
	<name>yarn.resourcemanager.address</name>
	<value>master:8050</value>
</property>
# 3.mapred-site.xml
sudo nano /usr/local/hadoop/etc/hadoop/mapred-site.xml
# 将之前的设置改成
<configuration>
        <property>
                <name>mapred.job.tracker</name>
                <value>master:54311</value>
        </property>
</configuration>
# 4.修改hdfs-site.xml
sudo nano /usr/local/hadoop/etc/hadoop/hdfs-site.xml
# 最后的设置项中,如果是master则删掉datanode设置项,如果是data则删掉namenode设置项
# 所有服务器都进行上述设置后转到master,进行master独有的设置
# 5.设置master档案
sudo nano /usr/local/hadoop/etc/hadoop/master
# 输入  
master
# 6.设置slaves档案 
sudo nano /usr/local/hadoop/etc/hadoop/slaves
# 输入 
data1
data2

9. master通过ssh登录data1、data2建立HDFS目录

# masterSSH连线至data1并建立HDFS目录
ssh data1
sudo rm -rf /usr/local/hadoop/hadoop_data/hdfs
sudo mkdir -p /usr/local/hadoop/hadoop_data/hdfs/datanode
sudo chown hduser:hduser -R /usr/local/hadoop
exit
# masterSSH连线至data2并建立HDFS目录
ssh data2
sudo rm -rf /usr/local/hadoop/hadoop_data/hdfs
sudo mkdir -p /usr/local/hadoop/hadoop_data/hdfs/datanode
sudo chown hduser:hduser -R /usr/local/hadoop
exit
# master重新建立NameNode HDFS目录
sudo rm -rf /usr/local/hadoop/hadoop_data/hdfs
mkdir -p /usr/local/hadoop/hadoop_data/hdfs/namenode
sudo chown -R hduser:hduser /usr/local/hadoop
# 格式化NameNode HDFS 目录
hadoop namenode -format
# 启动 hadoop
启动start-dfs.sh,再启动 start-yarn.sh
或一起 start-all.sh
像之前那样 再打开本地浏览器输入http://master的公网ip:8088/ 看到有两个节点(datanode)
http://master的公网ip:50070/ 看到有两个活动节点
就算成功

Spark安装

10. Scala与Spark的安装(在master机器上操作)

# 下载 scala-2.11.6   下载速度过慢可从本地下好传过去
wget http://www.scala-lang.org/files/archive/scala-2.11.6.tgz
# 解压
tar -zvxf scala-2.11.6.tgz
# 移动目录
sudo mv scala-2.11.6 /usr/local/scala
# 设置环境变量
sudo nano /home/hduser/.bashrc
# 在最后加上两行
export SCALA_HOME=/usr/local/scala
export PATH=$PATH:$SCALA_HOME/bin
# 让用户环境变量生效
source /home/hduser/.bashrc
# 下载 spark-2.0.0-bin-hadoop2.6.tgz
wget http://apache.stu.edu.tw/spark/spark-2.0.0/spark-2.0.0-bin-hadoop2.6.tgz
tar -zvxf spark-2.0.0-bin-hadoop2.6.tgz
sudo mv spark-2.0.0-bin-hadoop2.6 /usr/local/spark
sudo nano /home/hduser/.bashrc
# 在最后加上两行
export SPARK_HOME=/usr/local/spark
export PATH=$PATH:$SPARK_HOME/bin
# 让用户环境变量生效
source /home/hduser/.bashrc

# 进入spark交互界面
pyspark
# 离开spark交互界面
exit()

11. spark设置

# 设置spark显示信息级别为warn
cd /usr/local/spark/conf
cp log4j.properties.template log4j.properties
sudo nano log4j.properties
# 找到 log4j.rootCategory这一项,将其值由INFO改为WARN
# 配置spark
cp spark-env.sh.template spark-env.sh
sudo nano spark-env.sh
# 在最后添上
export SPARK_MASTER_IP=master # 设置master的IP或服务器名称
export SPARK_WORKER_CORES=1   # 设置每个worker使用的CPU核心数
export SAPRK_WORKER_MEMORY=1g # 设置每个worker使用的内存

12. 将配置好的Spark由master传到data服务器

# 传到data1
# 先创建目录
ssh data1
sudo mkdir /usr/local/spark
sudo chown hduser:hduser /usr/local/spark
exit
# 通过scp传输
sudo scp -r /usr/local/spark hduser@data1: /usr/local
# data2 同上

# 最后编辑slaves文件 
sudo nano /usr/local/spark/conf/slaves
# 输入
data1
data2

13. 测试运行Spark集群

# 先开启hdfs
start-dfs.sh
# 在hdfs创建测试目录
hadoop fs -mkdir -p /user/hduser/test/input
# 上传文件到hdfs
hadoop fs -copyFromLocal /usr/local/spark/README.md /user/hduser/test/input
# 启动 Spark Standalone Cluster (不依赖hadoop yarn运行的spark集群)
/usr/local/spark/sbin/start-all.sh  # 为了跟hadoop的命令区分开来没有设置环境变量
# 或者分别启动 /usr/local/spark/sbin/start-master.sh(start-slaves.sh)
# 在Spark Standalone运行spark
pyspark --master spark://master:7077

input: sc.master
output: u'spark://master:7077'
input: textFile= sc.textFile("file:/usr/local/spark/README.md") # 从本地读取文件
input: textFile.count()
output: 99
input: textFile= sc.textFile("hdfs://master:9000/user/hduser/test/input/README.md") # 从HDFS读取文件
input: textFile.count()
output: 99
exit()

# 再查看Spark Web UI,在本地浏览器输入 http://master公网ip:8080/
确认启动后有两个worker和刚刚执行的两个任务
# 记得关闭hdfs和spark 
stop-dfs.sh    
/usr/local/spark/sbin/stop-all.sh
到此spark集群搭建完成

通过Jupyter远程访问

通过以上操作spark集群已经搭建完成,可以提交任务运行,但是对于有数据分析需求的人来说显然还不够,我们还需要Jupyter,所以接下来几步是在集群上配置Jupyter,可以在本地远程访问spark集群。

14. 安装Anaconda

# 下载 Anaconda3-4.1.1-Linux-x86_64.sh(spark2.0.0不支持Python3.6及以上,这里是3.5.2)
wget https://repo.continuum.io/archive/Anaconda3-4.1.1-Linux-x86_64.sh
bash Anaconda3-4.1.1-Linux-x86_64.sh -b
# 配置环境变量
sudo nano /home/hduser/.bashrc
# 在最后输入
export ANACONDA_HOME=/home/hduser/anaconda3
export PATH=$ANACONDA_HOME/bin:$PATH
export PYSPARK_PYTHON=$ANACONDA_HOME/bin/python
# 使配置生效
source /home/hduser/.bashrc
# 查看python版本
python --version
output:Python 3.5.2 :: Anaconda 4.1.1(64-bit)
同样的操作在data服务器上也安装Anaconda

15. 配置远程访问

# 1. 输入ipython,在python命令行下输入
input[1]:from notebook.auth import passwd
input[2]: passwd()
# 输入密码,然后得到一个字符串
# 比如:‘sha1:3dec3e879823:06b051d35189879a41fecb2f9dd138abe2eea4d9’,保存这个字符串
input[3]: exit() # 退出python命令行
# 2. 生成jupyter的配置文件
jupyter notebook --generate-config
# 将会在home目录下生成一个隐藏文件夹.jupyter,该文件夹中有一个jupyter的配置文件
# 修改这个文件
sudo nano /home/hduser/.jupyter/jupyter_notebook_config.py
# 在底部添加
c.NotebookApp.ip = '*'
c.NotebookApp.password = u'sha1:3dec3e879823:06b051d35189879a41fecb2f9dd138abe2eea4d9' # 这个是之前的密码
c.NotebookApp.port = 8888 # jupyter远程访问端口  默认8888
c.InteractiveShellApp.matplotlib = 'inline'
# 退出
# 接下来输入
jupyter notebook
# 打开本地浏览器,输入http://master公网ip:8888/   输入之前输的密码,就实现了远程访问
# 可能会报错Permission denied: '/run/user/0/jupyter'  这时因为权限不够,只要给该文件夹添加权限就好
sudo chown -R hduser:hduser /run/user/0

16. 在jupyter中加入spark内核

# 到目前为止jupyter只有一个默认的python3的kernel,而且并没有连接任何spark
# 此处我们使用spark bin目录下的pyspark连接notebook,即启动./pyspark默认启动notebook.只需要在全局文件./bashrc中设置即可
# 打开./bashrc文件
sudo nano /home/hduser/.bashrc
# 在最后添加
export PYSPARK_DRIVER_PYTHON=jupyter 
export PYSPARK_DRIVER_PYTHON_OPTS="notebook"
# 使配置生效
source /home/hduser/.bashrc

# 安装扩展,可装可不装
pip install jupyter_contrib_nbextensions && jupyter contrib nbextension install --user

17. 最后测试

# 先开启hdfs
start-dfs.sh
# 启动 Spark Standalone Cluster 
/usr/local/spark/sbin/start-all.sh
# 在Spark Standalone运行spark
pyspark --master spark://master:7077
# 这时将启动jupyter
# 打开本地浏览器,输入http://master公网ip:8888/   输入之前输的密码
# 创建一个新文件
# 输入之前测试的代码

input: sc.master
output: u'spark://master:7077'
input: textFile= sc.textFile("file:/usr/local/spark/README.md") # 从本地读取文件
input: textFile.count()
output: 99
input: textFile= sc.textFile("hdfs://master:9000/user/hduser/test/input/README.md") # 从HDFS读取文件
input: textFile.count()
output: 99
exit()

如果能运行成功,则完美结束。