helm安装hadoop

参考: https://github.com/kubernetes/charts/tree/master/stable/hadoop

本文文档均参照以上github上的操作步骤完成,附加了需要注意的地方、测试经验、亲和性、挂载以及扩容缩容等操作。

需求:利用helm编排快速安装hadoop,可进行快速的删除并重新安装;hadoop的datanode的pod安装在指定的机器node节点上;一个node节点上有且只有一个datanode的pod;能够对datanode进行扩容、缩容;暴露nameNode的服务给外界web进行访问。

分析:

1. 进行快速的删除并重新安装---数据挂载的问题;

2. datanode的pod安装在指定的机器node节点上---node亲和性解决;

3.一个node节点上有且只有一个datanode的pod---pod的反亲和性

4. 扩容、缩容---scale命令使用,但是得对hadoop的数据进行测试;

5.暴露nameNode的服务给外界web进行访问---在headlessService之外创建service服务;

1. hadoop的安装

参考文档中一个命令就启动了,其它的都是附加参数;附加参数不提,文档中介绍的够详细了,我们先说一下启动脚本需要注意的地方;

helm install --name hadoop$(./calc_resources.sh 50)  stable/hadoop

其实helm环境安装好之后(可以查看我的博客),helm install就不用关心了;stable/hadoop其实是一个阿里的远程仓库(你自己搭建一个helm仓库就理解了);只需要关心. /calc_resources.sh脚本,该脚本主要是获取一些机器的参数等,执行时注意脚本的路径以及授权(chmod +x );$(. /calc_resources.sh 50)是向脚本中传递50这一参数,然后执行;

在执行脚本之前,linux环境需要安装几个工具

[root@node01 ~] yum install epel-release

[root@node01 ~] yum install bc

[root@node01 ~] yum install jq

最好先下载使用的hadoop镜像(检测是否可以下载成功)

[root@node01 ~] docker pull danisla/hadoop:2.7.3

然后直接启动就可以了,理论上应该没什么问题,你通过查看pod、statefulset、svc的状态可以看到hadoop的启动状态。

原理:

helm利用chart编排hadoop的pod和服务

hadoop的镜像不必多说,应该是将hadoop的完整安装包封装进入docker镜像中,无非是几个主要的配置文件等启动时通过挂载configMap传入进去即可;

hadoop编排主要使用了statefulset、headless Service、pvc、configMap等;也是正常有状态服务常用的编排方式,statefulset可以控制pod启动的顺序以及进行编号(所谓有状态,就是每个pod都不一样),headless Service可以获取到所有pod的域名地址进行访问,pvc进行动态挂载,configMap传递配置文件及参数(首先将configMap中挂载的文件挂载进入容器内的相关路径下;然后启动bootstrap.sh(设置环境变量,将这些临时挂载的文件放入到hadoop的相关目录下,然后根据nn、dn等进行相关的操作)等。

2. 数据挂载

因为有状态服务,所以最先考虑的是挺先进的pv与pvc的概念,但是给pass掉了;因为使用任何一个文件系统作为挂载的话,必然会有网络问题或者维护成本的问题;

这样只能考虑本地:empty、localVolume与storageClass

empty因为不会制定具体的挂载路径,跟我们需求不吻合,pass掉;storageClass技术好像很新,k8s的一些低版本好像不是很吻合,应用起来也没有运行成功,所以也放弃掉了(要是哪位大神研究明白了可以给我留个言哈);最后选择了localVolume,但是还存在一个问题,因为localVolume挂载的数据在pod删除掉之后并不会删除,这对于hdfs本身倒无所谓,因为它自身会同步;但是如何要删除掉集群,再创建时,由于数据的存在,会出现数据不同步(可能)或创建失败的问题;所以调研到了podHook【https://jimmysong.io/kubernetes-handbook/concepts/pod-hook.html】与helmHook【https://www.kubernetes.org.cn/2726.html 】;选择podHook是因为helm Hook是一个job,启动一个容器,而我们想要删除掉所有datanode的pod的挂载数据;具体的配置如何,修改了templates/hdfs-dn-statefulset.yaml文件来实现,每个pod创建时会清空挂载的数据,然后启动pod,以此来达到数据的同步或者删除;

话不多说,直接看配置文件;

[root@node01 ~] vihadoop1/templates/hdfs-dn-statefulset.yaml

   containers:

     - name: hdfs-dn

       image: {{ .Values.image }}

       lifecycle:

         postStart:

           exec:

              command:["/bin/sh","-c","rm -rf /root/hdfs/datanode/*"]

         preStop:

           exec:

              command:

                - "/bin/bash"

                - "touch"

                -"/root/hdfs/datanode/preStop"

在containers参数下添加子参数lifecycle参数,lifecyle中定义了容器启动后与关闭前的操作,postStart生效了,preStop不生效,不过有一个生命周期生效就满足我的需求了;

3. datanode选择node节点

[root@node01 ~]kubectl label nodes node03cluster=hadoop --overwrite

[root@node01 ~]kubectl get nodes -l cluster=hadoop

[root@node01 ~] vi templates/hdfs-dn-statefulset.yaml

   affinity:

       nodeAffinity:

         requiredDuringSchedulingIgnoredDuringExecution:

           nodeSelectorTerms:

           - matchExpressions:

              - key: cluster

                operator: In

                values:

                - hadoop

       podAntiAffinity:

       {{- if eq .Values.antiAffinity "hard" }}

在affinity节点下添加子节点nodeAffinity(与podAffinity同级)

4. datanode的pod不存在一个node节点上

因为pod已经定义好了pod的互斥性,只需要看是否强制性就好了;

修改value.yml中的antiAffinity:"soft"为”hard”,我们即可以搞定强制pod不在一个node节点上。

5. 扩容缩容

按顺序进行扩容或缩容(与rc的区别)

[root@node01 ~]kubectl scale statefulsethadoop-1-hadoop-hdfs-dn --replicas 2

扩容、缩容很简单,只需要更改后面的副本个数即可;

但我们需要测试扩容、缩容对于hadoop数据的影响;

测试目的:确定在扩容缩容时hadoop的文件副本数会随着增加或缩减

测试过程:

有两种方式:一是在容器外部直接调用命令进行操作;二是进入容器内部进行操作,不过本质上都是一样的

方法一:kubectl exec -n default -it hadoop-1-hadoop-hdfs-nn-0 --/usr/local/hadoop/bin/hdfs dfsadmin –report

方法二:进入容器内部

[root@node01 ~]kubectl exec -n default -ithadoop-1-hadoop-hdfs-nn-0/bin/bash

[root@node01 ~]cd /usr/local/hadoop/bin

[root@node01 ~]/usr/local/hadoop/bin:hadoop fs -ls /

[root@node01 ~]hadoop fs -put aa /

[root@node01 ~]hdfs fsck /bb -files -blocks#查看实际存活副本数

[root@node01 ~]cd /usr/local/hadoop/sbin

[root@node01 ~] ./start-balancer.sh#立刻进行副本的平衡(可能还是需要一段时间)

datanode节点掉之后,namenode会重试几百次之后断掉与datanode的连接;

6. 暴露服务

hadoop基本对外端口及api:

所有操作都是连接namenode节点进行操作;

namenode:

  50015:web页面查看接口

  50010:api命令操作接口

datanode:

  50075:web页面访问接口

  无操作接口命令

  rm与nn无关,用户rm进行mapreduce任务;rm管理nm;nm数量与dn数量无关,理论上一对一即可,一个nm管理一个dn资源  

我们这儿先为namenode中的50070在外端访问提供服务,只需要重新创建个service,然后将headless service粘贴过来即可,改name,将clustername:null去掉,添加type:nodeType,加nodePort;文件最后放入template中即可。

[root@node01 ~] cat nameNodeSvc.yaml

# A headless service to create DNS records

apiVersion: v1

kind: Service

metadata:

 name: {{ template "hadoop.fullname" . }}-hdfs-nn-s

 labels:

   app: {{ template "hadoop.name" . }}

   chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+""_" }}

   release: {{ .Release.Name }}

   heritage: {{ .Release.Service }}

   component: hdfs-nn

spec:

 type: NodePort

 ports:

  -name: dfs

   port: 9000

   protocol: TCP

  -name: webhdfs

   port: 50070

   targetPort: 50070

   nodePort: 30070

 selector:

   app: {{ template "hadoop.name" . }}

   release: {{ .Release.Name }}

   component: hdfs-nn

7.知识点

小知识1.helm安装方式

helm安装主要有四种方式:

安装仓库中的 chart,例如:helm install stable/nginx

通过tar 包安装,例如:helm install ./nginx-1.2.3.tgz

通过chart 本地目录安装,例如:helm install ./nginx

通过URL 安装,例如:helm install https://example.com/charts/nginx-1.2.3.tgz

8.注意

1.彻底删除需要添加--purge,helm del –purge hadoop

2.安装失败,需要删除时,时间会有点长,因为pod在不停的启动;假如你是个急性子,强制停止了del命令进程,必须先删除pod,再删除statefulset,再删除svc,将所有resources都删除掉;

3.挂载的hdfs/datanode中有数据时,datenode时启动不了的;

4.node亲和性,pod运行期间若node的标签发生改变,pod继续运行

5.ue以及其他的编辑器中的格式可能和linux中不一样,导致yml格式错误

 


Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐