明确需求
需求点 | 量 |
---|---|
标签数量 | 150个 |
标签计算任务数量 | 150个 |
数据抽取相关任务数量 | 10个 |
最少支持并发任务数量 | 5个 |
日数据增量 | 260G |
如果一个Spark任务需要计算260G的数据, 需要260G的内存吗?
给出一段 Spark 代码
rdd1 = sc.readTextFile(...)
rdd2 = rdd1.map(...)
rdd3 = rdd2.flatMap(...)
分析执行策略, 简化的逻辑如下
rdd3 = rdd2.flatMap(...)
rdd3 = rdd1.map(...).flatMap(...)
rdd3 = sc.readTestFile(...).map(...).flatMap(...)
按照这个逻辑, 没有必要把所有的数据都加载出来, 再逐个数据集去计算
得出结论, 如果计算 260G 的数据, 可能和计算 60G 的数据, 所需要的内存一样, Spark 会逐个取数据, 逐个计算, 计算完成后抛弃, 再取下一条
真的是这样吗? 再看一段代码
给出一段Spark代码, 这段代码多了一个Shuffle算子
rdd1 = sc.readTextFile()
rdd2 = rdd1.map(...)
rdd3 = rdd2.flatMap(...)
rdd4 = rdd3.reduceByKey(...)
分析执行过程
rdd4 = sc.readTestFile(...).map(...).flatMap(...).reduceByKey(...)
flatMap 出去的数据可能要汇总一下, 才能流入 reduceByKey
得出结论, 如果计算 260G 的数据, 和计算 60G 的数据, 所需要的内存确实不一样, 有 Shuffle 的情况下要稍微多一些才行
那么, 如何设计集群规模?
Spark 这样启动
spark-submit \
--class org.apache.spark.examples.SparkPi \
--master yarn \
--deploy-mode cluster \
--executor-memory 16G \
--executor-cores 4 \
--executor-num 10 \
--total-executor-cores 100 \
http://path/to/examples.jar \
1000
executor-memory
, executor-cores
, executor-num
设置的原则
executor-memory
是 executor-cores
的 2-4 倍, 取决于 Spark 任务是否有很多计算executor-num
来控制整个 Job 的内存占用所以, 可以得到如下表格
点 | 量 |
---|---|
Executor cores | 4 cores |
Executor num | 10 |
Executor memory | 16 G |
Spark parallelism | 128 |
Driver memory | 6 G |
Total cores | exenum * execores = 40 |
Total memory | exenum * exemem = 160 |
Pre job needs | 40 core + 160 G |
Cluster | (40, 160) * 5 * 1.2 = (240,1080) = 240 核心, 1080 G 内存 |
假设我们公司很有钱, 选择在京东上买新的 Dell 服务器, 选择了一个比较好的机器如下
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-a4O6pACR-1653908983049)(assets/20200216173643.png)]
配置如下
类型 | 型号 | 容量 | 数量 |
---|---|---|---|
CPU | Intel 至强 E5-2690V4 | 14 cores | 2颗 |
内存 | Dell ECC DDR4 | 32 G | 4条(可扩展至24条) |
硬盘 | Dell SAS 3.5英寸 | 4 TB | 3块(可扩展至8块) |
所以, 单台服务器可以有 128G 内存, 28 cores, 那我们需要的集群数量如下
类型 | 数量 |
---|---|
Master | 3 |
Worker | 10 |
Edge | 2 (可 1U 低配) |
这样的话, 我们集群的总资源量就如下, 可以看到, 已经非常够用了
类型 | 大小 |
---|---|
CPU | 280 cores |
内存 | 1280 G |
硬盘 | 120 T |
按照如下方式分配是比较推荐的, 而且一般生产级别的大数据集群, 一定是要 HA 的
Master 1-2 | Master 3 | Work 1-10 | Gateway | Utility 1 | |
---|---|---|---|---|---|
NameNode | ✔️ | ||||
JournalNode | ✔️ | ✔️ | |||
FailoverController | ✔️ | ||||
ResourceManager | ✔️ | ||||
HMaster | ✔️ | ✔️ | |||
Zookeeper | ✔️ | ✔️ | |||
JobHistory | ✔️ | ||||
SparkHistory | ✔️ | ||||
DataNode | ✔️ | ||||
NodeManager | ✔️ | ||||
HRegionsServer | ✔️ | ||||
Hue | ✔️ | ||||
Oozie | ✔️ | ||||
HiveServer2 | ✔️ | ||||
Flume | ✔️ | ||||
用户画像系统 | ✔️ | ||||
ClouderaManager | ✔️ | ||||
ManagementService | ✔️ | ||||
HiveMetastore | ✔️ |
所以, Hadoop 是 Yahoo! 一个半内部的项目, 不是商业产品, 其部署和运维都需要专业的团队
想要部署和运维 Hadoop 的集群有一些难点如下
所以, 第一个发现这个问题的人并不是我们, 而是 Cloudera 的老板
而 Hortonworks 和 Cloudera 所负责的事情大致如下
但是他们的产品又是不同的, 如下
所以, 现在如果想要部署一个 Hadoop 的集群, 我们大致有三种选择
一 : 想要部署 Apache 版本的工具是最难的
二 : 想要部署 CDH 集群, 其实也并不容易, 因为 CM 是主从结构的, 分为如下两个部分
所以, 我们需要做如下这件事
三 : 想要部署 HDP 的集群, 理论上比 CM 更难一些
四 : 大家有没有发现, 这三种部署方式都有一个事情要做
想象一下, 4000 个节点, 你准备怎么处理?
例如, 在 4000 个节点中执行同样的 Shell 脚本, 无论怎么做, 其实都挺折腾的, 不是吗?
五 : 那为什么我们不能直接使用 Apache 版本的工具, 使用 Shell 脚本去安装呢?
而上述这些功能, Ambari 和 SCM 都提供了, 所以我们当时的生产环境中, 运行的是 Cloudera Manager
从现在就开始要搭建一个测试集群了, 回顾前面的课程, 先来说说虚拟机的痛点
卒????
为了解决这些问题, 本项目中为大家引入 Vagrant
大家想一下, 如果我们可以通过 Vagrant, 使用一个配置文件来创建虚拟机, 是不是就能做到如下事情
所以, 不仅仅是为了让大家学习, 很多企业中也使用 Vagrant 构建测试环境, 保证每个人的环境一致
安装步骤如下
https://releases.hashicorp.com/vagrant/2.2.7/vagrant_2.2.7_x86_64.msi
Files/Setup
中Vagrant 中的概念
作用: 帮助我们管理虚拟机, 自动化的创建虚拟机, 自动化的初始化虚拟机, 提供了命令帮助我们管理虚拟机
vagrant up
, 使用这个命令, 即可创建一个符合 Vagrantfile 配置的虚拟机Vagrant 初体验, 创建一个虚拟机
步骤
Vagrant 还有一个很强大的功能, 就是在创建虚拟机完毕时, 执行初始化任务
目前, 除了 Shell 的 Provision, Vagrant 还支持 Ansible, Chef, Docker, Puppet 等
接下来, 要使用 Vagrant 构建一个集群了, 在开始之前, 根据我们的情况, 要规划一下集群
主机名 | 角色 | 配置 |
---|---|---|
master01 | Master | 1 cores, 16G -> 6G, 32G -> 8G |
workder 01 - 02 | Worker | 1 cores, 16G -> 4G, 32G -> 5G |
然后, 进行集群搭建
这个时候, 我们已经建立起来了测试集群, 但是有一个问题, 似乎无法在外部登录
原因是, Vagrant 自动创建出来的虚拟机是关闭了 SSH 登录功能的, 只能使用 vagrant ssh
登录, 这是为了保障安全性, 但是测试集群的话, 其实我们还是需要它方便, 解决办法也很简单, 修改 SSH 配置, 再打包一下系统, 让 Vagrant 下次创建的时候使用我们修改过的系统
下面再次查看, 即可使用 MobaXterm 登录虚拟机
好了, 我们现在要开始安装 CM 服务了, 大概有如下步骤
好了, 这些痛点我们都懂, 于是引入 Ansible, Ansible 非常重要, 几乎是运维领域的银弹, 但是如果大家不打算在运维领域发展, 了解即可, Ansible 可以帮助我们做如下事情
Ansible 有如下概念
名称 | 解释 |
---|---|
Playbook | 剧本, 是 Ansible 中的总控, 根配置文件比如说这次运行 Ansible 的最终任务是搭建好一个 CM 集群, 那我们应该就有一个 Playbook 叫做 cm_playbook.yml |
Roles | Ansible 任务中的角色例如为了完成 CM 集群的搭建, 可能要配置操作系统, 那应该就把配置操作系统所需要执行的所有配置都放在一个叫做 system_common 的 Roles 中 |
Inventory | Ansible 中的服务器地址配置Ansible 需要在多个主机中执行任务, Inventory 的作用就是告诉 Ansible 主机的地址等信息 |
首先来看看 PlayBook
- name: Create hosts file in locally
hosts: 192.168.56.101
any_errors_fatal: True
become: yes
roles:
- hosts
- name: Set yum locally
hosts: cdh_cluster
any_errors_fatal: True
become: yes
roles:
- yum_locally
192.168.56.101
中配置 hosts 文件
cdh_cluster
所对应的机器中配置本地 Yum 仓库
cdh_cluster
是一个分组, 这个分组在 Inventory
中配置
hosts
和 yum_locally
就是角色
然后再来看看 Roles yum_locally
- name: Set yum repo locally
yum_repository:
name: itcast-locally
description: Local yum repo
baseurl: http://master01/
failovermethod: priority
file: itcast
priority: 1
gpgcheck: no
enabled: yes
- name: Clean yum meata
command: yum clean all
yum clean all
清理 Yum 缓存Ansible 是一个非常知名的自动化运维工具, 不仅仅只是为了搭建测试环境, 在测试环境和正式环境中, 其应用都很广泛, 先来看看在正式环境中该如何使用 Ansible
ansible-playbook --inventory-file=/vagrant/inventory -v /vagrant/playbooks/cdh_cm.yml
明白了如何在正式环境使用 Ansible 以后, 使用 Vagrant 搭建测试环境的时候也可以使用 Ansible 脚本, Vagrant 提供了对应的 Provision
当然, 我们也可以使用 Roles 来封装一下这个任务
脚本已经为大家编写好了, 因为大家只需要了解这个东西, 所以, 不再深入去讲, 大家有兴趣可以自行研究
如果实在是机器的资源有限, 运行速度很慢, 或者无法执行 Yarn 任务, 有以下两种做法
这些问题其实并不是问题, 当给集群足够资源时, 自然会解决, 如果有 32G 的内存, 建议如下分配