Hadoop系列 大数据依旧在热炒,hadoop虽然不是唯一的代表,却也是各家必谈之资本,玩玩大数据。
通过ambari部署hadoop集群 在cloudlab119-123上部署集群,其中119作为ambari server控制端。
安装部署:
1 2 3 4 5 $ cd /etc/yum.repo.d $ wget http://public-repo-1 .hortonworks.com/ambari/centos6/2 .x/updates/2.0 .0 /ambari.repo $ yum install -y ambari-server $ ambari-server setup $ ambari-server start
配置,打开http://cloudlab119:8080,默认密码admin:admin。在cloudlab119上对所有节点做免密码认证:
1 2 3 $ vi /etc/hosts $ ssh-keygen -t rsa -P '' -f ~/.ssh/hadoop119 $ for i in {119 ,120 ,121 ,122 ,123 }; do ssh-copy-id -i ~/.ssh/hadoop119.pub root@cloudlab$i ; done ;
按提示建议操作,如ntpd、iptables、关闭THP:
1 2 3 4 5 $ chkconfig ntpd on $ service ntpd start $ service iptables stop $ chkconfig iptables off $ echo never > /sys/kernel/mm/redhat_transparent_hugepage/enabled
按提示一步步操作即可,但中间如果出现下载包失败,则会导致整个安装失败,所以最好提前把官方源同步到本地,做镜像后安装。
1 2 3 4 5 6 7 8 9 10 $ yum install -y yum-utils createrepo $ mkdir -p /var/www/html/ambari/centos6 && cd $_ $ reposync -r Updates-ambari-2.0 .0 $ createrepo Updates-ambari-2.0 .0 $ mkdir -p /var/www/html/hdp/centos6 && cd $_ $ reposync -r HDP-2.2 $ reposync -r HDP-UTILS-1.1 .0.20 $ createrepo HDP-2.2 $ createrepo HDP-UTILS-1.1 .0.20 $ vim /etc/yum.repo.d/ambari.repo
安装之后,发现某几台服务器内存占用率非常高,可以通过Ambari增加Host节点,然后迁移部分的组件到新的机器。
通过Docker部署集群 可以自己做docker image,简单起见可以先用sequenceiq的image。
单节点测试:
1 2 3 4 5 $ docker pull sequenceiq/hadoop-docker:2.7 .0 $ docker run -it sequenceiq/hadoop-docker:2.7 .0 /etc/bootstrap.sh -bash $ cd $HADOOP_PREFIX $ bin/hadoop jar share/hadoop/mapreduce/hadoop-mapreduce-examples-2.7 .0 .jar grep input output 'dfs[a-z.]+' $ bin/hdfs dfs -cat output/*
多节点部署,可以用ambari镜像,准备好blueprint.json:
1 { "host_groups" : [
{ "name" : "host_group_1",
"components" : [
{ "name" : "ZOOKEEPER_SERVER" },
{ "name" : "ZOOKEEPER_CLIENT" },
{ "name" : "AMBARI_SERVER" },
{ "name" : "HDFS_CLIENT" },
{ "name" : "NODEMANAGER" },
{ "name" : "MAPREDUCE2_CLIENT" },
{ "name" : "APP_TIMELINE_SERVER" },
{ "name" : "DATANODE" },
{ "name" : "YARN_CLIENT" },
{ "name" : "RESOURCEMANAGER" } ],
"cardinality" : "1" },
{ "name" : "host_group_2",
"components" : [
{ "name" : "ZOOKEEPER_SERVER" },
{ "name" : "ZOOKEEPER_CLIENT" },
{ "name" : "SECONDARY_NAMENODE" },
{ "name" : "NODEMANAGER" },
{ "name" : "YARN_CLIENT" },
{ "name" : "DATANODE" }],
"cardinality" : "1" },
{ "name" : "host_group_3",
"components" : [
{ "name" : "ZOOKEEPER_SERVER" },
{ "name" : "ZOOKEEPER_CLIENT" },
{ "name" : "NAMENODE" },
{ "name" : "NODEMANAGER" },
{ "name" : "YARN_CLIENT" },
{ "name" : "DATANODE" }],
"cardinality" : "1" } ],
"Blueprints" : {
"blueprint_name" : "blueprint-c1",
"stack_name" : "HDP",
"stack_version" : "2.2" } }
可以在ambari server上查找:http://172.17.0.13:8080/api/v1/blueprints
。
创建集群:
1 2 3 4 5 6 7 8 9 10 11 12 13 $ docker pull sequenceiq/ambari:1.7 .0 $ curl -Lo .amb https://github.com/sequenceiq/docker-ambari/raw/master/ambari-functions && . .amb $ amb-start-cluster 3 $ amb-shell ambshell > host list ambshell > blueprint add --url http://172.17 .42.1 /bp.json ambshell > cluster build --blueprint blueprint-c1 ambshell > cluster assign --hostGroup host_group_1 --host amb0.mycorp.kom ambshell > cluster assign --hostGroup host_group_2 --host amb1.mycorp.kom ambshell > cluster assign --hostGroup host_group_3 --host amb2.mycorp.kom ambshell > blueprint show --id blueprint-c1 ambshell > cluster preview ambshell > cluster create
中间安装过程如果出现失败,可以到ambari-server上看详细情况,当然也可以直接向之前方式一样,通过GUI安装部署;或者开着浏览器看amb-shell执行过程。 如果实在VM上远程使用,可以在docker所在机器上做NAT映射直接访问:
1 $ iptables -t nat -A PREROUTING -d 10.101 .29.26 -p tcp --dport 8000 -j DNAT --to-destination 172.17 .0.20 :8080
做个简单的测试:
1 2 3 4 $ docker exec -it 9572938 bb253 /bin/bash bash bash bash
HDFS HDFS由NameNode、SNameNode和DataNode组成,HA的时候还有另一个NameNode(StandBy)。SNameNode专门从NameNode获取FSImage和Edits,为NameNode合并生成新的FSImage。
HDFS有个超级用户,就是启动NameNode的那个linux账号。
基本Shell操作 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 $ ps -elf | grep NameNode $ su -s /bin/sh -c 'hadoop fs -ls /' hdfs $ su hdfs $ useradd -G hdfs promise $ hdfs dfs -mkdir /user/promise $ hdfs dfs -chown promise:hdfs /user/promise $ hdfs dfs -ls /user/ $ hdfs dfs -mkdir -p /user/promise/dev/hello $ hdfs dfs -chmod -R 777 /user/promise/dev $ hdfs dfs -ls /user/promise/dev/ $ echo “helloworld” > hello.txt $ hdfs dfs -put hello.txt /user/promise/helloworld.txt $ hdfs dfs -put - hdfs://192.168 .182.119 /user/promise/test.txt $ hdfs dfs -cat hdfs://192.168 .182.119 /user/promise/test.txt $ hdfs dfs -cat /user/promise/helloworld.txt $ hdfs dfs -get /user/promise/helloworld.txt hello2.txt $ hdfs dfs -tail -f /user/promise/helloworld.txt $ hdfs dfs -appendToFile - /user/promise/helloworld.txt
webhdfs操作 启用了webhdfs之后(hdfs-site
中dfs.webhdfs.enabled=true
),可以通过HTTP方式访问HDFS:
1 2 3 $ curl -i "http://192.168.182.119:50070/webhdfs/v1/user/promise/?op=LISTSTATUS" $ curl -i -L "http://192.168.182.119:50070/webhdfs/v1/user/promise/helloworld.txt?op=OPEN" $ curl -i -X PUT "http://192.168.182.119:50070/webhdfs/v1/user/promise/hello?user.name=promise&op=MKDIRS"
通过HTTP方式创建和追加文件都需要通过2阶段实现:先在NameNode上创建,获得DataNode URI后再向URI上传文件。
1 2 $ curl -i -X PUT "http://192.168.182.119:50070/webhdfs/v1/user/promise/hello/hi.txt?op=CREATE" $ curl -i -X PUT -T hi.txt "http://192.168.182.119:50075/webhdfs/v1/user/promise/hello/hi.txt?user.name=promise&op=CREATE&namenoderpcaddress=192.168.182.119:8020&overwrite=false"
查看离线的FSImage和Edits: 1 2 3 4 $ hdfs oiv -p XML -i /hadoop/hdfs/namenode/current/fsimage_0000000000000018887 -o fsimage.xml $ hdfs oiv -i /hadoop/hdfs/namenode/current/fsimage_0000000000000018887 $ hdfs dfs -ls webhdfs://127.0 .0.1 :5978 / $ hdfs oev -i /hadoop/hdfs/namenode/current/edits_0000000000000000001-0000000000000005150 -o edits.xml
使用Java API Java在大型软件系统开发中有利于更清晰的架构设计和团队分工,而且有大量的第三方优质框架可用;可惜在命令里写HelloWorld很啰嗦,方便起见,直接用maven生成基本文件结构。
1 2 3 4 5 6 7 $ export PATH=$PATH :/opt/apache-maven-3.3 .3 /bin/ $ export JAVA_HOME=/usr/jdk64/jdk1.7.0 _67/ $ export MAVEN_OPTS="-Xms256m -Xmx512m" $ mkdir ~/dev && cd $_ $ mvn archetype:generate -DgroupId=org.tecstack -DartifactId=hellohdfs -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false $ cd hellohdfs && mvn package $ vim ./src/main/java/org/tecstack/App.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 package org.tecstack;import org.apache.hadoop.conf.Configuration;import org.apache.hadoop.fs.FileStatus;import org.apache.hadoop.fs.FileSystem;import org.apache.hadoop.fs.Path; * Hello HDFS * */ public class App { public static void main ( String[] args ) { try { Configuration conf=new Configuration(); FileSystem hdfs=FileSystem.get(conf); Path dst =new Path("/user/promise/helloworld.txt" ); FileStatus files[]=hdfs.listStatus(dst); for (FileStatus file:files) { System.out.println(file.getPath()); } } catch (Exception e) { e.printStackTrace(); } } }
在pom.xml
增加hadoop依赖包:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 <project xmlns ="http://maven.apache.org/POM/4.0.0" xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation ="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd" > <modelVersion > 4.0.0</modelVersion > <groupId > org.tecstack</groupId > <artifactId > hellohdfs</artifactId > <packaging > jar</packaging > <version > 1.0-SNAPSHOT</version > <name > hellohdfs</name > <url > http://maven.apache.org</url > <dependencies > <dependency > <groupId > org.apache.hadoop</groupId > <artifactId > hadoop-common</artifactId > <version > 2.6.0</version > </dependency > <dependency > <groupId > org.apache.hadoop</groupId > <artifactId > hadoop-hdfs</artifactId > <version > 2.6.0</version > </dependency > <dependency > <groupId > org.apache.hadoop</groupId > <artifactId > hadoop-client</artifactId > <version > 2.6.0</version > </dependency > <dependency > <groupId > junit</groupId > <artifactId > junit</artifactId > <version > 3.8.1</version > <scope > test</scope > </dependency > </dependencies > </project >
打包运行:
1 2 3 4 5 6 7 $ mvn package $ mkdir -p src/main/resources $ scp cloudlab119:/etc/hadoop/conf/core-site.xml src/main/resources $ mvn exec :java -Dexec.mainClass="org.tecstack.App" -Dexec.cleanupDaemonThreads=false $ mvn dependency:copy-dependencies $ mvn resources:resources $ mvn eclipse:eclipse
关于maven的exec插件,也可以通过配置pom.xml
的plugin的参数简化执行:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 <build > <plugins > <plugin > <groupId > org.codehaus.mojo</groupId > <artifactId > exec-maven-plugin</artifactId > <version > 1.4.0</version > <executions > <execution > <goals > <goal > java</goal > </goals > </execution > </executions > <configuration > <mainClass > org.tecstack.App</mainClass > <cleanupDaemonThreads > false</cleanupDaemonThreads > </configuration > </plugin > </plugins > </build >
之后运行只需要mvn exec:java
,如果需要定制更多参数,比如JVM内存,单独启动进程执行等,可以使用exec:exec
插件,具体看[codehaus官网][http://mojo.codehaus.org/exec-maven-plugin/usage.html]。
HUE交互界面 Hue是一个基于Django开发的webapp,通过WebHDFS或HttpFS的一种访问HDFS的数据,在HDFS HA部署方式中只能使用HttpFS。 如通过WebHDFS方式访问,需要修改hdfs-site.xml
:
1 2 3 4 <property > <name > dfs.webhdfs.enabled</name > <value > true</value > </property >
修改core-site.xml
使Hue账号可以代理其他用户:
1 2 3 4 5 6 7 8 <property > <name > hadoop.proxyuser.hue.hosts</name > <value > *</value > </property > <property > <name > hadoop.proxyuser.hue.groups</name > <value > *</value > </property >
修改完参数需要重新启动HDFS,通过Ambari操作很方便。
1 2 3 $ yum install -y hue hue-server $ vim /etc/hue/conf/hue.ini $ service hue start
默认登陆账号为admin:admin
,可以通过hdfs为该账号创建一个专用的文件夹/user/hue
进行测试,正式环境中可以考虑与其他身份系统对接。
1 2 3 4 $ su hdfs $ hdfs dfs -mkdir /user/hue $ hdfs dfs -chown -R admin:hadoop /user/hue $ hdfs dfs -ls /user/
导入数据到HBase 通过hcat建立数据库表结构,通过pig导入数据。
建立数据文件data.tsv
:
1 row1 c1 c2
row2 c1 c2
row3 c1 c2
row4 c1 c2
row5 c1 c2
row6 c1 c2
row7 c1 c2
row8 c1 c2
row9 c1 c2
row10 c1 c2
准备建表DDL,simple.ddl
:
1 CREATE TABLE simple_hcat_load_table (id STRING, c1 STRING, c2 STRING)
STORED BY 'org.apache.hadoop.hive.hbase.HBaseStorageHandler'
WITH SERDEPROPERTIES ( 'hbase.columns.mapping' = 'd:c1,d:c2' )
TBLPROPERTIES (
'hbase.table.name' = 'simple_hcat_load_table'
);
准备导入脚本,simple.bulkload.pig
:
1 A = LOAD 'hdfs:///tmp/data.tsv' USING PigStorage('\t') AS (id:chararray, c1:chararray, c2:chararray);
-- DUMP A;
STORE A INTO 'hbase://simple_hcat_load_table' USING org.apache.hive.hcatalog.pig.HCatStorer();
把文件放到HDFS,建表,导入:
1 2 3 4 $ su - hdfs $ hdfs dfs -put data.tsv /tmp/ $ hcat -f simple.ddl $ pig -useHCatalog simple.bulkload.pig
通过Hue的HCat可以查看数据库和表数据,也可以通过HBase Shell:
1 2 3 4 5 $ su - hdfs $ hbase shell hbase > list hbase > scan 'simple_hcat_load_table' hbase > describe 'simple_hcat_load_table'
也可以通过Hive Shell:
1 2 3 4 5 $ su - hdfs $ hive hive > show tables; hive > select count(*) from simple_hcat_load_table; hive > desc simple_hcat_load_table;
如果建表过程中出现类似java.lang.NoClassDefFoundError: org/apache/hadoop/hbase/HBaseConfiguration
如下的找不到类情况,检查hcat的配置文件是否有HBase目录:vim /usr/bin/hcat
。
1 2 3 ... export HBASE_HOME=/usr/hdp/2.2 .4.2 -2 /hbase...
此外,由于Hue集成的HCat调用的是Hive下的hcat,需要在/etc/hive-hcatalog/conf/hcat-env.sh
中指定HBASE_HOME
:
1 2 3 ... HBASE_HOME=${HBASE_HOME:-/usr/hdp/current/hbase-client} ...
pig在使用MapReduce模式执行时,可以根据log打开MR Job跟踪,如果也出现java.lang.NoClassDefFoundError
类错误,说明mapreduce服务的classpath有缺漏,可以通过Ambari修改MapReduce服务Advanced mapred-site
配置中的mapreduce.application.classpath
,比如出现HBase相关类找不到,则添加HBase相关的库/usr/hdp/2.2.4.2-2/hbase/lib/*
,然后重启MapReduce服务即可。
如果出现执行权限错误,需要检查如下配置是否存在:hive-site.xml
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 <property > <name > hive.security.metastore.authorization.manager</name > <value > org.apache.hadoop.hive.ql.security.authorization.StorageBasedAuthorizationProvider </value > </property > <property > <name > hive.security.metastore.authenticator.manager</name > <value > org.apache.hadoop.hive.ql.security.HadoopDefaultMetastoreAuthenticator </value > </property > <property > <name > hive.metastore.pre.event.listeners</name > <value > org.apache.hadoop.hive.ql.security.authorization.AuthorizationPreEventListener </value > </property > <property > <name > hive.metastore.execute.setugi</name > <value > true</value > </property >
webhcat-site.xml
: 正式环境中可以明确具体使用的账号名称,最小化权限。
1 2 3 4 5 6 7 8 <property > <name > webhcat.proxyuser.hue.hosts</name > <value > *</value > </property > <property > <name > webhcat.proxyuser.hue.groups</name > <value > *</value > </property >
core-site.xml
:
1 2 3 4 5 6 7 8 <property > <name > hadoop.proxyuser.hcat.group</name > <value > *</value > </property > <property > <name > hadoop.proxyuser.hcat.hosts</name > <value > *</value > </property >
使用小结 Hadoop系架构经过引入YARN,真正实现了数据和应用的分离,在YARN架构上可以实现出了原来的MapReduce之外的更多App,比如流式处理、实时处理、图计算等,如此可以真正实现“把应用挪到数据旁边高效执行”,构建大数据平台。此外,做数据分析时可以发现周边工具很丰富,比如hue统一的综合管理界面、从数据文件识别结构并管理数据的hcat、数据处理高级语言pig、支持SQL的Hive,使得在Hadoop平台上做数据分析非常方便(可以参考这里 )。 另外,对比YARN利用OS进程隔离分配资源之外,Mesos 结合了Container技术实现容器隔离分配资源,以此实现更通用的框架(用各种语言写的各种计算框架)。当然YARN也进入了DCE ,通过docker实现容器隔离。不过正式应用还是有待Linux kernel本身功能的成熟,以及docker之类管理工具的完善。 最后,数据处理优选python scikit-learn系工具,当大到一定程度,或需要多人同时工作时,hadoop系平台是个不错的选择。
参考
Ambari Official Docs
HDFS Official Doc
Hadoop-docker from sequenceiq
Ambari Docs on Apache
Sample BluePrint
安装配置Hue
手动安装HDP
Ambari Blueprint
导入数据到HBase
Apache Mesos
YARN DCE