hdfs+zookeeper+hbase分布式在k8s中部署

全栈工程师开发手册 (作者:栾鹏)
架构系列文章

本文内容已经过期, 有时间再更新新的

版本信息:java1.8+hadoop-2.7.7+zookeeper-3.4.9+hbase1.2.6.1

1、背景知识

先看下HBase的组成:

hdfs+zookeeper+hbase分布式在k8s中部署_第1张图片

Master:Master主要负责管理RegionServer集群,如负载均衡及资源分配等,它本身也可以以集群方式运行,但同一时刻只有一个master处于激活状态。当工作中的master宕掉后,zookeeper会切换到其它备选的master上。

RegionServer:负责具体数据块的读写操作。

ZooKeeper:负责集群元数据的维护并监控集群的状态以防止单点故障。部署HBase时可以使用自带的ZooKeeper也可以使用独立的集群,是HBase跑起来的先决条件。

HDFS:写入HBase中的数据最终都持久化到了HDFS中,也是HBase运行的先决条件。

github网址:https://github.com/626626cdllp/k8s/tree/master/hdfs%2Bzk%2Bhbase

下面的操作是在上述仓库中的内容

0、准备工作

当然我们要先准备好k8s环境,并且下面的部署,我们是将镜像上传到docker hub的私有仓库,所以需要你先在docker hub上注册,并创建一个私有仓库,我这里创建的私有仓库是luanpeng/cloud

部署是在k8s命名空间是cloudai-2,所以需要先创建命名空间

kubectl create ns cloudai-2

在本地docker login 输入账号密码登录docker,这样才能将镜像成功的push到自己的私有仓库

创建能拉取docker hub镜像的秘钥.将下面的xxxxx改成你自己的密码,这样才能从私有仓库中拉取镜像到k8s

kubectl  create secret docker-registry hubsecret  --docker-username=luanpeng --docker-password=xxxxx [email protected] -n cloudai-2

1、制作hadoop镜像

先去http://www.oracle.com/technetwork/java/javase/downloads/index.html下载java1.8,我这里下载的是jdk-8u181-linux-x64.tar.gz

再去http://mirror.bit.edu.cn/apache/hadoop/common/下载,hadoop,我下载的是hadoop-2.7.7.tar.gz

将下载的jdk-8u181-linux-x64.tar.gz、hadoop-2.7.7.tar.gz放在hdfs-deploy目录下,在hdfs-deploy目录下执行

docker build -t hadoop-base:1.0.0 .

生成镜像。

将镜像推送到你的仓库,我这里推送到了在docker hub上创建的私有仓库luanpeng/cloud

docker tag hadoop-base:1.0.0 luanpeng/cloud:hadoop-base-1.0.0
docker push luanpeng/cloud:hadoop-base-1.0.0

2、HDFS集群部署

HDFS由namenode和datanode组成,我们使用上面创建的hadoop-base:1.0.0作为基础镜像在上面修改配置文件和添加初始化命令。

在hdfs-deploy/datanode目录下执行

docker build -t hadoop-hdfs-datanode:1.0.0 .

创建datanode镜像

在hdfs-deploy/namenode目录下执行

 docker build -t hadoop-hdfs-namenode:1.0.0 .

生成namenode镜像

将上述两个镜像推送到仓库中。

docker tag hadoop-hdfs-namenode:1.0.0 luanpeng/cloud:hadoop-hdfs-namenode-1.0.0
docker push luanpeng/cloud:hadoop-hdfs-namenode-1.0.0

docker tag hadoop-hdfs-datanode:1.0.0 luanpeng/cloud:hadoop-hdfs-datanode-1.0.0
docker push luanpeng/cloud:hadoop-hdfs-datanode-1.0.0

在hdfs-deploy目录下执行

将hdfs.yaml文件中的nodeName的值替换成自己k8s的节点名称,

kubectl create -f hdfs.yaml

部署分布式hdfs。在yaml文件中我们为namenode服务指定了一个集群ip。这个可以换成你的k8s允许的集群ip。

下面对HDFS进行测试是否可以正常使用:

# 查看HDFS pods,若处于running,则运行正常
kubectl get pods -n cloudai-2

# 进入容器内部
kubectl exec -it hdfs-datanode-1-ddcd479cb-gtjh8 /bin/bash -n cloudai-2

# 创建本地文件
echo "Hello" > hello

# 创建hdfs文件系统中的目录
hadoop fs -mkdir /test

# 将本地文件复制到HDFS文件系统中
hadoop fs -put hello /test
# 查看HDFS中的文件信息
hadoop fs -ls /test

# 你已经在一个datanode里面向hdfs文件系统中加入了一个目录和文件,hdfs文件系统是分布式的。所以在其他的datanode的pod里面应该也能访问到,所以你可以 kubectl exec 到其它datanode中查看文件信息,如:
退出上面的pod,重新进入另一个pod
kubectl exec -it hdfs-datanode-2-7b8d8599b9-5jgml /bin/bash -n cloudai-2

root@hdfs-datanode-2-nek2l:/# hadoop fs -ls /test
Found 1 items
-rw-r--r--   2 hdfs hadoop          6 2015-11-27 08:36 /test/hello

删除hdfs目录
hadoop fs -rm -r /test

zookeeper集群部署

首先要知道zookeeper的配置文件

配置-zoo.cfg

这是zookeeper的主要配置文件,因为Zookeeper是一个集群服务,集群的每个节点都需要这个配置文件。为了避免出差错,zoo.cfg这个配置文件里没有跟特定节点相关的配置,所以每个节点上的这个zoo.cfg都是一模一样的配置。这样就非常便于管理了,比如我们可以把这个文件提交到版本控制里管理起来。其实这给我们设计集群系统的时候也是个提示:集群系统一般有很多配置,应该尽量将通用的配置和特定每个服务的配置(比如服务标识)分离,这样通用的配置在不同服务之间copy就ok了。ok,下面来介绍一些配置点:

clientPort=2181

client port,顾名思义,就是客户端连接zookeeper服务的端口。这是一个TCP port。

dataDir=/data

dataLogDir=/datalog

dataLogDir如果没提供的话使用的则是dataDir。zookeeper的持久化都存储在这两个目录里。dataLogDir里是放到的顺序日志(WAL)。而dataDir里放的是内存数据结构的snapshot,便于快速恢复。为了达到性能最大化,一般建议把dataDir和dataLogDir分到不同的磁盘上,这样就可以充分利用磁盘顺序写的特性。

下面是集群中服务的列表

server.1=127.0.0.1:20881:30881
server.2=127.0.0.1:20882:30882
server.3=127.0.0.1:20883:30883

在上面的例子中,我把三个zookeeper服务放到同一台机器上。上面的配置中有两个TCP port。后面一个是用于Zookeeper选举用的,而前一个是Leader和Follower或Observer交换数据使用的。我们还注意到server.后面的数字。这个就是myid(关于myid是什么下一节会介绍)。

上面这几个是一些基本配置。

还有像 tickTime,这是个时间单位定量。比如tickTime=1000,这就表示在zookeeper里1 tick表示1000 ms,所有其他用到时间的地方都会用多少tick来表示。

比如 syncLimit = 2 就表示fowller与leader的心跳时间是2 tick。

maxClientCnxns – 对于一个客户端的连接数限制,默认是60,这在大部分时候是足够了。但是在我们实际使用中发现,在测试环境经常超过这个数,经过调查发现有的团队将几十个应用全部部署到一台机器上,以方便测试,于是这个数字就超过了。

minSessionTimeout, maxSessionTimeout – 一般,客户端连接zookeeper的时候,都会设置一个session timeout,如果超过这个时间client没有与zookeeper server有联系,则这个session会被设置为过期(如果这个session上有临时节点,则会被全部删除,这就是实现集群感知的基础,后面的文章会介绍这一点)。但是这个时间不是客户端可以无限制设置的,服务器可以设置这两个参数来限制客户端设置的范围。

autopurge.snapRetainCount,autopurge.purgeInterval – 客户端在与zookeeper交互过程中会产生非常多的日志,而且zookeeper也会将内存中的数据作为snapshot保存下来,这些数据是不会被自动删除的,这样磁盘中这样的数据就会越来越多。不过可以通过这两个参数来设置,让zookeeper自动删除数据。autopurge.purgeInterval就是设置多少小时清理一次。而autopurge.snapRetainCount是设置保留多少个snapshot,之前的则删除。

不过如果你的集群是一个非常繁忙的集群,然后又碰上这个删除操作,可能会影响zookeeper集群的性能,所以一般会让这个过程在访问低谷的时候进行,但是遗憾的是zookeeper并没有设置在哪个时间点运行的设置,所以有的时候我们会禁用这个自动删除的功能,而在服务器上配置一个cron,然后在凌晨来干这件事。

以上就是zoo.cfg里的一些配置了。下面就来介绍myid。

配置-myid

在dataDir里会放置一个myid文件,里面就一个数字,用来唯一标识这个服务。这个id是很重要的,一定要保证整个集群中唯一。zookeeper会根据这个id来取出server.x上的配置。比如当前id为1,则对应着zoo.cfg里的server.1的配置。

而且在后面我们介绍leader选举的时候,这个id的大小也是有意义的。

=========================================================

OK,上面就是配置的讲解了,现在我们可以启动zookeeper集群了。

/hdfs+zk+hbase/zookeeper-deploy/zookeeper-images/config-and-run.sh是zookeeper的启动脚本。是我们进入容器要运行的脚本。

有了配置文件,我们就可以在zookeeper镜像的基础上将我们的配置文件添加进去。这样就是我们自定义的zookeeper镜像了。

由于zookeeper版本不停的在变,所以先去http://mirror.bit.edu.cn/apache/zookeeper/上查看支持什么版本。对应的修改zookeeper-deploy/zookeeper-images/Dockerfile文件中的ZOOKEEPER_VERSION

在zookeeper-deploy/zookeeper-images/目录中执行

docker build -t hbase-zookeeper:1.0.0 .

修改完后创建镜像并push到私有仓库中

docker tag hbase-zookeeper:1.0.0 luanpeng/cloud:hbase-zookeeper-1.0.0
docker push luanpeng/cloud:hbase-zookeeper-1.0.0

在k8s上创建zookeeper集群。在yaml文件中修改nodeName为节点的名称

 kubectl create -f zookeeper.yaml

创建三个service和对应的RC。注意container中已经把ZooKeeper的data和log目录映射到了主机的对应目录上用于持久化存储。

创建完之后即可进行测试:

查看pod是否都处于running中
kubectl get pod -n cloudai-2

# 进入zookeeper对应的容器
kubectl exec -it zookeeper-1-6d644d55d4-4tvxt /bin/bash -n cloudai-2

# 找到zkCli.sh,用该客户端进行测试
/opt/zookeeper/bin/zkCli.sh
[zk: localhost:2181(CONNECTED) 0]

# 连接到k8s创建的zookeeper service (三个service任意一个都行)
[zk: localhost:2181(CONNECTED) 0] connect 172.16.11.2:2181
[zk: 10.233.9.2:2181(CONNECTED) 1]

# 查看目录信息
[zk: 10.233.9.2:2181(CONNECTED) 1] ls /
[zookeeper]
[zk: 10.233.9.2:2181(CONNECTED) 2] get /zookeeper

cZxid = 0x0
ctime = Thu Jan 01 00:00:00 UTC 1970
mZxid = 0x0
mtime = Thu Jan 01 00:00:00 UTC 1970
pZxid = 0x0
cversion = -1
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 0
numChildren = 1
[zk: 10.233.9.2:2181(CONNECTED) 3]

HBASE集群部署

以上准备工作做好后,下面部署hbase,一个hbase可以同时启动master、regionserver、thrift等多种后台服务

首先需要创建HBase的镜像,先去去https://mirrors.tuna.tsinghua.edu.cn/apache/hbase看看有什么版本的。这里我们用的是2.1.0

在hbase-master-region/hbase-images目录下执行

docker build -t hadoop-hbase:1.0.0 .

镜像生成后将镜像上传到私有仓库

docker tag hadoop-hbase:1.0.0 luanpeng/cloud:hadoop-hbase-1.0.0
docker push luanpeng/cloud:hadoop-hbase-1.0.0

在k8s上部署hbase

在hbase-master-region文件夹下执行

kubectl create -f hbase.yaml

接着就可以创建和查看HBase服务了:

# 查看pods
$kubectl get pods -n cloudai-2
。。。

# 查看service
$kubectl get service -n cloudai-2
。。。

进入zookeeper的pod

/opt/zookeeper/bin/zkCli.sh

ls /hbase
ls /hbase/rs
get /hbase/master

可以通过kubectl exec进入到HBase对应的容器中进行表操作以测试HBase的工作状态:

# 进入hbase-master-1容器中
kubectl exec -it hbase-master-deployment-1-5785b4c845-wfx7h /bin/bash -n cloudai-2

# 使用hbase shell对hbase进行操作
root@hbase:/opt/hbase/bin# hbase shell
...

# 通过status查看状态,这里显示的 2 dead 是之前测试时遗留的记录,无影响
hbase(main):001:0> status
2015-11-30 15:16:03,551 WARN  [main] util.NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable
servers, 2 dead, 1.5000 average load

# 创建表
hbase(main):002:0> create 'test','id','name'
row(s) in 0.8330 seconds

=> Hbase::Table - test

# 查看表
hbase(main):003:0> list
TABLE                                                                                                                                                                                
member                                                                                                                                                                               
test                                                                                                                                                                                 
row(s) in 0.0240 seconds

=> ["member", "test"]

# 插入数据
hbase(main):004:0> put 'test','test1','id:5','addon'
row(s) in 0.1540 seconds

# 查看数据
hbase(main):005:0> get 'test','test1'
COLUMN                                         CELL                                                                                                                                  
 id:5                                          timestamp=1448906130803, value=addon                                                                                                  
row(s) in 0.0490 seconds


到此完成

你可能感兴趣的:(架构,微服务架构)