hadoop没有datanode_Hadoop运行在Kubernetes平台实践

Hadoop与Kubernetes就好像江湖里的两大绝世高手,一个是成名已久的长者,至今仍然名声远扬,一个则是初出茅庐的青涩少年,骨骼惊奇,不走寻常路,一出手便惊诧了整个武林。Hadoop与Kubernetes之间有很深的渊源,因为都出自IT豪门——Google,只不过,后者是亲儿子,正因为有大佬背书,所以Kubernetes一出山,江湖各路门派便都蜂拥而至,拥护称王。

不知道是因为Hadoop是干儿子的缘故还是因为“廉颇老矣”,总之,Hadoop朋友圈的后辈们如Spark、Storm等早都有了在Kubernetes上部署运行的各种资料和案例,但Hadoop却一直游离于Kubernetes体系之外,本文我们给出Hadoop在Kubernetes上的实践案例,以弥补这种缺憾。

Hadoop容器化的资料不少,但Hadoop部署在Kubernetes上的资料几乎没有,这主要是以下几个原因导致的:

  • 第一, Hadoop集群重度依赖DNS机制,一些组件还使用了反向域名解析,以确定集群中的节点身份,这对Hadoop在Kubernetes上的建模和运行带来极大挑战,需要深入了解Hadoop集群工作原理并且精通Kubernetes,才能很好解决这一难题。
  • 第二, Hadoop新的Map-Reduce计算框架Yarn的模型出现的比较晚,它的集群机制要比HDFS复杂,资料也相对较少,增加了Hadoop整体建模与迁移Kubernetes平台的难度。
  • 第三, Hadoop与Kubernetes分别属于两个不同的领域,一个是传统的大数据领域,一个是新兴的容器与微服务架构领域,这两个领域之间交集本来很小,加之Hadoop最近几年已经失去焦点(这点从百度搜索关键词就能发现),所以,没有多少人关注和研究Hadoop在Kubernetes的部署问题,也是情理之中的事情。

Hadoop 2.0其实是由两套完整的集群所组成,一个是基本的HDFS文件集群,一个是YARN资源调度集群,如下图所示:

0d14cb206eb1860dfbbf5356287d389e.png

因此在Kubernetes建模之前,我们需要分别对这两种集群的工作机制和运行原理做出深入的分析,下图是HDFS集群的架构图:

c9a030c889b425c40d79bfa11b9a5e64.png

我们看到,HDFS集群是由NameNode(Master节点)和Datanode(数据节点)等两类节点所组成,其中,客户端程序(Client)以及DataNode节点会访问NameNode,因此,NameNode节点需要建模为Kubernetes Service以提供服务,以下是对应的Service定义文件:

apiVersion: v1 
kind: Service 
metadata: 
name: k8s-hadoop-master 
spec: 
type: NodePort 
selector: 
app: k8s-hadoop-master 
ports: 
- name: rpc port: 9000 targetPort: 9000 
- name: http port: 50070 targetPort: 50070 nodePort: 32007 

其中,NameNode节点暴露2个服务端口:

  • 9000端口用于内部IPC通信,主要用于获取文件的元数据
  • 50070端口用于HTTP服务,为Hadoop 的Web管理使用

为了减少Hadoop镜像的数量,我们构建了一个镜像,并且通过容器的环境变量HADOOP_NODE_TYPE来区分不同的节点类型,从而启动不同的Hadoop组件,下面是镜像里的启动脚本startnode.sh的内容:

#!/usr/bin/env bash 
sed -i "s/@HDFS_MASTER_SERVICE@/$HDFS_MASTER_SERVICE/g" $HADOOP_HOME/etc/hadoop/core-site.xml 
sed -i "s/@HDOOP_YARN_MASTER@/$HDOOP_YARN_MASTER/g" $HADOOP_HOME/etc/hadoop/yarn-site.xml 
yarn-master 
HADOOP_NODE="${HADOOP_NODE_TYPE}" 
if [ $HADOOP_NODE = "datanode" ]; then echo "Start DataNode ..." hdfs datanode  -regular else 
if [  $HADOOP_NODE = "namenode" ]; then echo "Start NameNode ..." hdfs namenode 
else if [ $HADOOP_NODE = "resourceman" ]; then echo "Start Yarn Resource Manager ..." yarn resourcemanager else if [ $HADOOP_NODE = "yarnnode" ]; then echo "Start Yarn Resource Node  ..." yarn nodemanager    else echo "not recoginized nodetype " fi fi 
fi   fi 

我们注意到,启动命令里把Hadoop配置文件(core-site.xml与yarn-site.xml)中的HDFS Master节点地址用环境变量中的参数HDFS_MASTER_SERVICE来替换,YARN Master节点地址则用HDOOP_YARN_MASTER来替换。下图是Hadoop HDFS 2节点集群的完整建模示意图:

fd197e875f6fdee68aa4af946d3a8790.png

图中的圆圈表示Pod,可以看到,Datanode并没有建模Kubernetes Service,而是建模为独立的Pod,这是因为Datanode并不直接被客户端所访问,因此无需建模Service。当Datanode运行在Pod容器里的时候,我们需要修改配置文件中的以下参数,取消DataNode节点所在主机的主机名(DNS)与对应IP地址的检查机制:

dfs.namenode.datanode.registration.ip-hostname-check=false 

如果上述参数没有修改,就会出现DataNode集群“分裂”的假象,因为Pod的主机名无法对应Pod的IP地址,因此界面会显示2个节点,这两个节点都状态都为异常状态。

下面是HDFS Master节点Service对应的Pod定义:

apiVersion: v1 
kind: Pod 
metadata: 
name: k8s-hadoop-master 
labels: 
app: k8s-hadoop-master 
spec: 
containers: 
- name: k8s-hadoop-master image: kubeguide/hadoop imagePullPolicy: IfNotPresent ports: - containerPort: 9000 - containerPort: 50070     env: - name: HADOOP_NODE_TYPE value: namenode - name: HDFS_MASTER_SERVICE valueFrom: configMapKeyRef: name: ku8-hadoop-conf key: HDFS_MASTER_SERVICE - name: HDOOP_YARN_MASTER valueFrom: configMapKeyRef: name: ku8-hadoop-conf key: HDOOP_YARN_MASTER 
restartPolicy: Always 

下面是HDFS的Datanode的节点定义(hadoop-datanode-1):

apiVersion: v1 
kind: Pod 
metadata: 
name: hadoop-datanode-1 
labels: app: hadoop-datanode-1 
spec: 
containers: 
- name: hadoop-datanode-1 image: kubeguide/hadoop imagePullPolicy: IfNotPresent ports: - containerPort: 9000 - containerPort: 50070     env: - name: HADOOP_NODE_TYPE value: datanode - name: HDFS_MASTER_SERVICE valueFrom: configMapKeyRef: name: ku8-hadoop-conf key: HDFS_MASTER_SERVICE - name: HDOOP_YARN_MASTER valueFrom: configMapKeyRef: name: ku8-hadoop-conf key: HDOOP_YARN_MASTER         
restartPolicy: Always 

实际上,Datanode可以用DaemonSet方式在每个Kubernerntes节点上部署一个,在这里为了清晰起见,就没有用这个方式 定义。接下来,我们来看看Yarn框架如何建模,下图是Yarn框架的集群架构图:

698bc5241f79fc2658046c042977e64b.png

我们看到,Yarn集群中存在两种角色的节点:ResourceManager以及NodeManger,前者属于Yarn集群的头脑(Master),后者是工作承载节点(Work Node),这个架构虽然与HDFS很相似,但因为一个重要细节的差别,无法沿用HDFS的建模方式,这个细节就是Yarn集群中的ResourceManager要对NodeManger节点进行严格验证,即NodeManger节点的节点所在主机的主机名(DNS)与对应IP地址严格匹配,简单来说,就是要符合如下规则:

NodeManger建立TCP连接时所用的IP地址,必须是该节点主机名对应的IP地址,即主机DNS名称解析后返回节点的IP地址。

所以我们采用了Kubernetes里较为特殊的一种Service——Headless Service来解决这个问题,即为每个NodeManger节点建模一个Headless Service与对应的Pod,下面是一个ResourceManager与两个NodeManger节点所组成的Yarn集群的建模示意图:

9527131c92d45bb38119222eb119b232.png

Headless Service的特殊之处在于这种Service没有分配Cluster IP,在Kuberntes DNS里Ping这种Service的名称时,会返回后面对应的Pod的IP地址,如果后面有多个Pod实例,则会随机轮询返回其中一个的Pod地址,我们用Headless Service建模NodeManger的时候,还有一个细节需要注意,即Pod的名字(容器的主机名)必须与对应的Headless Service的名字一样,这样一来,当运行在容器里的NodeManger进程向ResourceManager发起TCP连接的过程中会用到容器的主机名,而这个主机名恰好是NodeManger Service的服务名,而这个服务名解析出来的IP地址又刚好是容器的IP地址,这样一来,就巧妙的解决了Yarn集群的DNS限制问题。

下面以yarn-node-1为例,给出对应的Service与Pod的YAM文件,首先是yarn-node-1对应的Headless Service的YAM定义:

apiVersion: v1 
kind: Service 
metadata: 
name: yarn-node-1 
spec: 
clusterIP: None 
selector: 
app: yarn-node-1 
ports: - port: 8040 

注意到定义中“clusterIP:None”这句话,表明这是一个Headless Service,没有自己的Cluster IP地址,下面给出YAM文件定义:

apiVersion: v1 
kind: Pod 
metadata: 
name: yarn-node-1 
labels: 
app: yarn-node-1 
spec: 
containers: 
- name: yarn-node-1 image: kubeguide/hadoop imagePullPolicy: IfNotPresent ports: - containerPort: 8040 - containerPort: 8041    - containerPort: 8042         env: - name: HADOOP_NODE_TYPE value: yarnnode - name: HDFS_MASTER_SERVICE valueFrom: configMapKeyRef: name: ku8-hadoop-conf key: HDFS_MASTER_SERVICE - name: HDOOP_YARN_MASTER valueFrom: configMapKeyRef: name: ku8-hadoop-conf key: HDOOP_YARN_MASTER           
restartPolicy: Always 

ResourceManager的YAML定义没有什么特殊的地方,其中Service定义如下:

apiVersion: v1 
kind: Service 
metadata: 
name: ku8-yarn-master 
spec: 
type: NodePort 
selector: 
app: yarn-master 
ports: - name: "8030" port: 8030 - name: "8031" port: 8031 - name: "8032" port: 8032      - name: http port: 8088 targetPort: 8088 nodePort: 32088 

对应的Pod定义如下:

apiVersion: v1 
kind: Pod 
metadata: 
name: yarn-master 
labels: 
app: yarn-master 
spec: 
containers: 
- name: yarn-master image: kubeguide/hadoop imagePullPolicy: IfNotPresent ports: - containerPort: 9000 - containerPort: 50070     env: - name: HADOOP_NODE_TYPE value: resourceman - name: HDFS_MASTER_SERVICE valueFrom: configMapKeyRef: name: ku8-hadoop-conf key: HDFS_MASTER_SERVICE - name: HDOOP_YARN_MASTER valueFrom: configMapKeyRef: name: ku8-hadoop-conf key: HDOOP_YARN_MASTER           
restartPolicy: Always 

目前这个方案,还遗留了一个问题有待解决:HDFS NameNode节点重启后的文件系统格式化问题,这个问题可以通过启动脚本来解决,即判断HDFS文件系统是否已经格式化过,如果没有,就启动时候执行格式化命令,否则跳过格式化命令。

安装完毕后,我们可以通过浏览器访问Hadoop的HDFS管理界面,点击主页上的Overview页签会显示我们熟悉的HDFS界面:

44e3735b43bceacafb02c95ff118e097.png

切换到Datanodes页签,可以看到每个Datanodes的的信息以及当前状态:

7f2d6d07fde72c6a1f30cc9ea2f93847.png

接下来,我们可以登录到NameNode所在的Pod里并执行HDSF命令进行功能性验证,下面的命令执行结果是建立一个HDFS目录,并且上传一个文件到此目录中:

  1. root@hadoop-master:/usr/local/hadoop/bin# hadoop fs -ls /
  2. root@hadoop-master:/usr/local/hadoop/bin# hadoop fs -mkdir /leader-us
  3. root@hadoop-master:/usr/local/hadoop/bin# hadoop fs -ls /
  4. Found 1 items
  5. drwxr-xr-x - root supergroup 0 2017-02-17 07:32 /leader-us
  6. root@hadoop-master:/usr/local/hadoop/bin# hadoop fs -put hdfs.cmd /leader-us

然后,我们可以在HDFS管理界面中浏览HDFS文件系统,验证刚才的操作结果:

3085a2244562cdd01508ca5008113144.png

接下来,我们再登录到hadoop-master对应的Pod上,启动一个Map-Reduce测试作业——wordcount,作业启动后,我们可以在Yarn的管理界面中看到作业的执行信息,如下图所示:

69b5eeb5977c5cec957173d03ca8f2bd.png

当作业执行完成后,可以通过界面看到详细的统计信息,比如wordcount的执行结果如下图所示:

ba4d175532ab4aac2a67b4e124b9c592.png

最后,我们进行了裸机版Hadoop集群与Kubernetes之上的Hadoop集群的性能对比测试,测试环境为十台服务器组成的集群,具体参数如下:

硬件:

  • CPU:2*E5-2640v3-8Core
  • 内存:16*16G DDR4
  • 网卡:2*10GE多模光口
  • 硬盘:12*3T SATA

软件:

  • BigCloud Enterprise Linux 7(GNU/Linux 3.10.0-514.el7.x86_64 x86_64)
  • Hadoop2.7.2
  • Kubernetes 1.7.4+ Calico V3.0.1

我们执行了以下这些标准测试项:

  • TestDFSIO:分布式系统读写测试
  • NNBench:NameNode测试
  • MRBench:MapReduce测试
  • WordCount:单词频率统计任务测试
  • TeraSort:TeraSort任务测试

综合测试下来,Hadoop跑在Kuberntes集群上时,性能有所下降,以TestDFSIO的测试为例,下面是Hadoop集群文件读取的性能测试对比:

080bdbfe2b4f1befc40962a9487b01d5.png

我们看到,Kubernetes集群上的文件读性能与物理机相比,下降了差不多30%左右,并且任务执行时间也增加不少,再来对比文件写入的性能,测试结果如下下图所示:

d3fe3b81848bdf4c80f4c9181322eecf.png

我们看到,写文件性能的差距并不大,这里的主要原因是在测试过程中,HDFS写磁盘的速度远远低于读磁盘的速度,因此无法拉开差距。

之所以部署在Kuberntes上的Hadoop集群的性能会有所下降,主要一个原因是容器虚拟网络所带来的性能损耗,如果用Host Only模型,则两者之间的差距会进一步缩小,下图是TestDFSIO测试中Hadoop集群文件读取的性能测试对比:

e533b69706828d9628ace2d02e6f99ce.png

因此我们建议在生产环境中采用Host Only的网络模型,以提升Hadoop的集群性能。

攻下Hadoop在Kubernetes上的部署,并且在生产中加以验证,我们可以很自豪的说,现在没有什么能够难倒应用向Kubernetes的迁移的步伐,采用统一的PaaS构建企业的应用集群和大数据集群,实现资源的共享和服务的统一管理将会大大的提升企业的业务部署速度和管理的效率。

感兴趣的可以自己来我的Java架构群,可以获取免费的学习资料,群号:855801563对Java技术,架构技术感兴趣的同学,欢迎加群,一起学习,相互讨论。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/561142.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

git 修改commit_Git从8到13 深入了解Git特性

上一章简单的介绍了一些常用的Git命令,这一章主要是深入了解一下Git的稍微高级的一些知识和指令。8.首先我们先来通过查看Git目录里面的文件来深入了解一下Git版本控制的构造。 查看HEAD可以知道当前所在的分支。在config文件里面存储着Git里面的一些配置信息&#…

eclipse maven打包jar 部分jsp无法访问_Maven系列教材 (九)- 在Eclipse中创建maven风格的java web项目...

Maven系列教材 (九)- 在Eclipse中创建maven风格的java web项目步骤1:删除j2ee目录步骤2:新建Maven 项目步骤3:这个界面点下一步步骤4: 这个界面使用webapp,点下一步 步骤5:这一步填写如图所示的信息步骤6:此时得到的maven web 项目的问题步骤…

final关键字_深入分析Java中的final关键字

Java中被final修饰的变量与普通变量有何区别?被final修饰的变量不可更改、被final修饰的方法不可重写是怎样做到的?带着疑问我们一点点拨开云雾。一、final的内存定义及规则对于final关键字,编译器、处理器从读写两个角度限制了其使用规则&am…

嵌入式和fpga哪个好前景_Java 和 go 哪个就业前景好一点?面向金钱编程,这个回答太现实...

有个朋友问我:ava 和 go 哪个就业前景好一点?现在纠结中,差不多一年半就要毕业了。我也问了几个朋友程序员朋友:朋友A: 可以参考 Boss 直聘,面向金钱编程,我身边的 Java 都是 15k 左右,反正干就…

php解决mysql主从同步_Mysql读写分离,主从同步实现

随着用户量的增多,数据库操作往往会成为一个系统的瓶颈所在,因此我们可以通过实现数据库的读写分离来提高系统的性能。通过设置主从数据库实现读写分离,主库负责“写”操作,从库负责“读”操作,根据压力情况&#xff0…

验证码图片显示不出来怎么办_pr 的蒙版不显示了怎么办?

小白自学pr一路会遇到很多坑,我也是在一个个坑里爬过的。画好的蒙版不显示了,这只能算是一个小坑。解决方法很简单,只需要记住一条:在pr里想要调整或者显示什么东西,首先必须要选中它。举例说明:我给小猫的…

gb2312编码表_汉字编码输入系统模型(一)

通过前面介绍的通信系统模型来分析汉字编码输入系统,将汉字编码输入系统的特殊性整合到通信系统模型中,从而建立起一种基于信息论的汉字编码输入系统模型(参见图3.2),以便指导我们的汉字编码输入实践,设计和…

java中sql语句怎么把开始和结束时间作为参数写sql查询_JDBC数据库连接怎么操作?...

之前一直听说过JDBC,但从来不知道它是何物的小伙伴们看过来啦!一、概述JDBC(Java Data Base Connectivity,java数据库连接)是一种用于执行SQL语句的Java API,可以为多种关系数据库提供统一访问,它由一组用Java语言编写的类和接口组…

spring boot整合shiro继承redis_spring-boot-plus集成Shiro+JWT权限管理

SpringBootShiroJWT权限管理ShiroApache Shiro是一个强大且易用的Java安全框架,执行身份验证、授权、密码和会话管理。使用Shiro的易于理解的API,您可以快速、轻松地获得任何应用程序,从最小的移动应用程序到最大的网络和企业应用程序。三个核心组件:Subject, Secur…

java 整数变负数_一文帮你读懂Java整数的存储原理

前言大家应该都知道,整数包括负数,零,和正数。在Java中,基本类型中byte(8位)、short(16位)、int(32位)、long(64位)属于整数,并且没有无符号数,均是有符号的。对于计算机来说,它只认识二进制&am…

server2019 sqlcmd命令安装_Ubuntu20.04LTS安装MS sql-server2019的方法

在本文中,我将向您展示如何在Ubuntu 20.04 Focal Fossa上安装Microsoft SQL Server。小广告:喜欢网络技术的朋友可以加W信:xfiles_sky一起学习进步。步骤一:更新ubuntu源sudo apt update && sudo apt upgrade步骤二&#…

servlet里面为什么有时候覆_为什么新来的经理强烈推荐?前后端分离知识,学到了...

引言前后端分离这个词相信大家都听过,不知道大家是怎么理解的呢。前阵子看项目的时候,有一段实现硬是没看懂,下面来给大家说一下一段愚蠢的经历哈。(我没正正式式写过前端,所以如果文章有错的地方希望可以在评论区友善交流~)一、交…

microstation添加txt文件_C开发实战-文件操作

文件概述文件几乎无处不在,主要分为磁盘文件和设备文件,典型的磁盘文件有文本文件和二进制文件,磁盘文件存储在外部存储介质(例如磁盘,硬盘,U盘等等)需要加载到内存中才能使用。无论是文本文件还是二进制文件在计算机内…

怎样配置mysql数据源_mysql怎样配置ODBC数据源

选中 sqlserver选择默认连接的数据库 7、配置完成,可以测试连接 扩展资料: spring中配置数据源的几种常见方式:工具/原料 事先配置相应的环境mysql(mysql安装程序)mysql-connector-odbc-3.51.20-win32.exe(mysql数据源dobc安装程序) 步骤/方法…

python字符串用法_笔记:python字符串的使用

Python 没有表示单个字符的字符类型,只有字符串类型str。字符串是用单引号或双引号括起来的一系列字符。单引号表示的字符串中可以包含双引号字符,但不能直接包含单引号字符(否则无法知道字符串的开始和结尾分别在哪里)。同样,双引号表示的字…

new出来的对象怎么回收_JVM的内存模型及垃圾回收算法

1、什么是jvm:虚拟出来的计算机,是jre的一部分,使用jvm是为了支持与操作系统无关,实现跨平台,jvm内部体系结构主要分为三个部分:类加载器子系统,运行时数据区和执行引擎。2、jvm内存区域运行时数…

条令考试小程序辅助器_可以自己编题的答题软件,自定义题库考试出题工具,微信答题小程序...

自制题库自己编题的答题小程序要如何制作?今天给大家介绍下可以自己编题的答题软件,自制题库软件在微信小程序里自己出题,然后给别人来答题。每个人都可以通过这个小程序系统出考题,然后给到别人答题(自己、同事、学生…

编写有效用例电子版_软件测试人员必须编写代码吗?

相信每一个刚入门软件测试的小伙伴都会琢磨一个问题:软件测试人员,要不要写代码?其实这个问题同样困扰着已经在测试行业闯荡了几年的测试小司机们。那今天,我就来给大家分析一下~01各种软件测试角色一般而言软件测试大体可以分为两…

bert 中文 代码 谷歌_ELECTRA中文预训练模型开源,110个参数,性能媲美BERT

感谢参考原文-http://bjbsair.com/2020-03-27/tech-info/7050/ 在去年11月份,NLP大神Manning联合谷歌做的ELECTRA一经发布,迅速火爆整个NLP圈,其中ELECTRA-small模型参数量仅为 BERT-base模型的1/10,性能却依然能与BERT、RoBERTa等…

监督学习和无监督学习_机器学习的要素是什么? 有监督学习和无监督学习两大类...

如前所述,机器学习是AI的一个子集,通常分为两大类:有监督学习和无监督学习。监督学习教学AI系统的常用技术是通过使用大量带标签的示例来训练它们。这些机器学习系统被馈入大量数据,这些数据已被注释以突出显示感兴趣的功能。这些…