CDH(Cloudera's Distribution, including Apache Hadoop)是众多 Hadoop 发行版本中的一种,最新版本 CDH6.0.1 中的 Hadoop3.0.0 版本已经支持 OSS。CDH5 中的 Hadoop2.6 版本不支持 OSS。本文介绍如何配置 CDH5 支持 OSS 读写。

前提条件

您需要拥有一个已搭建好的 CDH5 集群。若没有已搭建好的 CDH5 集群,您需要参考官方文档,先搭建一个 CDH5 集群。本文以 CDH5.14.4 版本为例。

背景信息

由于 CDH5 的 httpclient 和 httpcore 这两个组件版本较低(4.2.5),Resource Manager 要求的 httpclient 和 httpcore 必须是低版本,而 OSS SDK 要求这两个组件的版本较高,因此,下面提供了一个 workaround 方案。

步骤一:增加 OSS 配置

您需要在所有的 CDH 节点执行以下操作:

  1. 查看 CDH5 安装目录${CDH_HOME}的结构:
    [root@cdh-master CDH-5.14.4-1.cdh5.14.4.p0.3]# ls -lh
    总用量 100K
    drwxr-xr-x  2 root root 4.0K 6月  12 21:03 bin
    drwxr-xr-x 27 root root 4.0K 6月  12 20:57 etc
    drwxr-xr-x  5 root root 4.0K 6月  12 20:57 include
    drwxr-xr-x  2 root root  68K 6月  12 21:09 jars
    drwxr-xr-x 38 root root 4.0K 6月  12 21:03 lib
    drwxr-xr-x  3 root root 4.0K 6月  12 20:57 lib64
    drwxr-xr-x  3 root root 4.0K 6月  12 20:51 libexec
    drwxr-xr-x  2 root root 4.0K 6月  12 21:02 meta
    drwxr-xr-x  4 root root 4.0K 6月  12 21:03 share                    
    说明 本文中所有 ${} 的内容为环境变量,请根据您实际的环境修改。
  2. 下载CDH 5.14.4 版本支持 OSS 的支持包至 CDH5 的安装目录中的 jars 文件夹中。
    这个支持包是根据 CDH5.14.4 中 Hadoop 的版本,并打了 Apache Hadoop 对 OSS 支持的补丁后编译得到的,其他 CDH5 的小版本对 OSS 的支持将陆续提供。
  3. 解压支持包:
    [root@cdh-master CDH-5.14.4-1.cdh5.14.4.p0.3]# tar -tvf hadoop-oss-cdh-5.14.4.tar.gz 
    drwxr-xr-x root/root 0 2018-10-08 18:16 hadoop-oss-cdh-5.14.4/
    -rw-r--r-- root/root 13277 2018-10-08 17:36 hadoop-oss-cdh-5.14.4/aliyun-java-sdk-sts-3.0.0.jar
    -rw-r--r-- root/root 326724 2018-10-08 18:16 hadoop-oss-cdh-5.14.4/httpcore-4.4.4.jar
    -rw-r--r-- root/root 524927 2018-10-08 17:36 hadoop-oss-cdh-5.14.4/aliyun-sdk-oss-3.4.1.jar
    -rw-r--r-- root/root 116337 2018-10-08 17:36 hadoop-oss-cdh-5.14.4/aliyun-java-sdk-core-3.4.0.jar
    -rw-r--r-- root/root 215492 2018-10-08 17:36 hadoop-oss-cdh-5.14.4/aliyun-java-sdk-ram-3.0.0.jar
    -rw-r--r-- root/root 788137 2018-10-08 17:36 hadoop-oss-cdh-5.14.4/aliyun-java-sdk-ecs-4.2.0.jar
    -rw-r--r-- root/root 70017 2018-10-08 17:36 hadoop-oss-cdh-5.14.4/hadoop-aliyun-2.6.0-cdh5.14.4.jar
    -rw-r--r-- root/root 736658 2018-10-08 18:16 hadoop-oss-cdh-5.14.4/httpclient-4.5.2.jar
    						
  4. 进入 ${CDH_HOME}/lib/hadoop 目录,执行如下命令:
    [root@cdh-master hadoop]# rm -f lib/httpclient-4.2.5.jar
    [root@cdh-master hadoop]# rm -f lib/httpcore-4.2.5.jar
    [root@cdh-master hadoop]# ln -s ../../jars/hadoop-aliyun-2.6.0-cdh5.14.4.jar hadoop-aliyun-2.6.0-cdh5.14.4.jar
    [root@cdh-master hadoop]# ln -s hadoop-aliyun-2.6.0-cdh5.14.4.jar hadoop-aliyun.jar
    [root@cdh-master hadoop]# cd lib
    [root@cdh-master lib]# ln -s ../../../jars/aliyun-java-sdk-core-3.4.0.jar aliyun-java-sdk-core-3.4.0.jar
    [root@cdh-master lib]# ln -s ../../../jars/aliyun-java-sdk-ecs-4.2.0.jar aliyun-java-sdk-ecs-4.2.0.jar
    [root@cdh-master lib]# ln -s ../../../jars/aliyun-java-sdk-ram-3.0.0.jar aliyun-java-sdk-ram-3.0.0.jar
    [root@cdh-master lib]# ln -s ../../../jars/aliyun-java-sdk-sts-3.0.0.jar aliyun-java-sdk-sts-3.0.0.jar
    [root@cdh-master lib]# ln -s ../../../jars/aliyun-sdk-oss-3.4.1.jar aliyun-sdk-oss-3.4.1.jar
    [root@cdh-master lib]# ln -s ../../../jars/httpclient-4.5.2.jar httpclient-4.5.2.jar
    [root@cdh-master lib]# ln -s ../../../jars/httpcore-4.4.4.jar httpcore-4.4.4.jar
    [root@cdh-master lib]# ln -s ../../../jars/jdom-1.1.jar jdom-1.1.jar
  5. 进入 Resurce Manager 部署节点的 ${CDH_HOME}/lib/hadoop-yarn/bin/ 目录,将 yarn 中的CLASSPATH=${CLASSPATH}:$HADOOP_YARN_HOME/${YARN_DIR}/* CLASSPATH=${CLASSPATH}:$HADOOP_YARN_HOME/${YARN_LIB_JARS_DIR}/* 替换为 CLASSPATH=$HADOOP_YARN_HOME/${YARN_DIR}/*:${CLASSPATH}CLASSPATH=$HADOOP_YARN_HOME/${YARN_LIB_JARS_DIR}/*:${CLASSPATH}。
  6. 进入到 Resurce Manager 部署节点的 ${CDH_HOME}/lib/hadoop-yarn/lib 目录,执行如下命令:
    [root@cdh-master lib]# ln -s ../../../jars/httpclient-4.2.5.jar httpclient-4.2.5.jar
    [root@cdh-master lib]# ln -s ../../../jars/httpcore-4.2.5.jar httpcore-4.2.5.jar
  7. 通过集群管理工具 CM 来增加配置。
    若没有 CM 管理的集群,可以修改 core-site.xml。以 CM 为例,需要增加如下配置:
    配置项
    fs.oss.endpoint 填写需要连接的 OSS 的 Endpoint。

    例如:oss-cn-zhangjiakou-internal.aliyuncs.com

    fs.oss.accessKeyId 填写 OSS 的 AccessKeyId。
    fs.oss.accessKeySecret 填写 OSS 的 AccessKeySecret。
    fs.oss.impl Hadoop OSS 文件系统实现类。目前固定为:org.apache.hadoop.fs.aliyun.oss.AliyunOSSFileSystem
    fs.oss.buffer.dir 填写临时文件目录。

    建议值:/tmp/oss

    fs.oss.connection.secure.enabled 是否开启 HTTPS。开启 HTTPS 会影响性能。

    建议值:false

    fs.oss.connection.maximum 与 OSS 的连接数

    建议值:2048

    更多参数解释请参见 Hadoop-Aliyun module

  8. 根据 CM 提示重启集群。
  9. 测试读写 OSS。
    • 测试读:
      hadoop fs -ls oss://${your-bucket-name}/
    • 测试写:
      hadoop fs -mkdir oss://${your-bucket-name}/hadoop-test

      若测试可以读写 OSS,则配置成功;若无法读写 OSS,请检查配置。

步骤二:配置 Impala 对 OSS 的支持

Impala 可以直接查询存储在 HDFS 的数据,在 CDH5 支持 OSS 后,就可以直接查询存储在 OSS 的数据。OSS SDK 要求这两个组件的版本较高,所以需要在所有部署 Impala 的节点执行以下操作:

  1. 进入 ${CDH_HOME}/lib/impala/lib,执行如下命令:
    [root@cdh-master lib]# rm -f httpclient-4.2.5.jar httpcore-4.2.5.jar
    [root@cdh-master lib]# ln -s ../../../jars/httpclient-4.5.2.jar httpclient-4.5.2.jar
    [root@cdh-master lib]# ln -s ../../../jars/httpcore-4.4.4.jar httpcore-4.4.4.jar
    [root@cdh-master lib]# ln -s ../../../jars/hadoop-aliyun-2.6.0-cdh5.14.4.jar hadoop-aliyun.jar
    [root@cdh-master lib]# ln -s ../../../jars/aliyun-java-sdk-core-3.4.0.jar aliyun-java-sdk-core-3.4.0.jar
    [root@cdh-master lib]# ln -s ../../../jars/aliyun-java-sdk-ecs-4.2.0.jar aliyun-java-sdk-ecs-4.2.0.jar
    [root@cdh-master lib]# ln -s ../../../jars/aliyun-java-sdk-ram-3.0.0.jar aliyun-java-sdk-ram-3.0.0.jar
    [root@cdh-master lib]# ln -s ../../../jars/aliyun-java-sdk-sts-3.0.0.jar aliyun-java-sdk-sts-3.0.0.jar
    [root@cdh-master lib]# ln -s ../../../jars/aliyun-sdk-oss-3.4.1.jar aliyun-sdk-oss-3.4.1.jar
    [root@cdh-master lib]# ln -s ../../../jars/jdom-1.1.jar jdom-1.1.jar
  2. 进入到 ${CDH_HOME}/bin 目录,修改 impaladstatestoredcatalogd 三个文件,在文件最后一行 exec 命令前,增加如下内容:
    export CLASSPATH=$CLASSPATH:${IMPALA_HOME}/lib/httpclient-4.5.2.jar:${IMPALA_HOME}/lib/httpcore-4.4.4.jar:${IMPALA_HOME}/lib/hadoop-aliyun.jar:${IMPALA_HOME}/lib/aliyun-java-sdk-core-3.4.0.jar:${IMPALA_HOME}/lib/aliyun-java-sdk-ecs-4.2.0.jar:${IMPALA_HOME}/lib/aliyun-java-sdk-ram-3.0.0.jar:${IMPALA_HOME}/lib/aliyun-java-sdk-sts-3.0.0.jar:${IMPALA_HOME}/lib/aliyun-sdk-oss-3.4.1.jar:${IMPALA_HOME}/lib/jdom-1.1.jar
  3. 重启所有节点的 impala 相关进程,之后 impala 就可以查询 OSS 的数据了。

验证配置

TPC-DS 的 benchmark 有一张表为 call_center,假设存储在 OSS 中。我们可以创建一个外部表指向它,并且查询这张表根据 cc_country 分组分别有多少条记录。
[root@cdh-master ~]# impala-shell -i cdh-slave01:21000
Starting Impala Shell without Kerberos authentication
Connected to cdh-slave01:21000
Server version: impalad version 2.11.0-cdh5.14.4 RELEASE (build20e635646a13347800fad36a7d0b1da25ab32404)
***********************************************************************************
Welcome to the Impala shell.
(Impala Shell v2.11.0-cdh5.14.4 (20e6356) built on Tue Jun 1203:43:08 PDT 2018)

The HISTORY command lists all shell commands in chronological order.
***********************************************************************************
[cdh-slave01:21000] > droptableifexists call_center;
Query: droptableifexists call_center
[cdh-slave01:21000] >
[cdh-slave01:21000] > createexternaltable call_center(
                    >       cc_call_center_sk         bigint
                    > ,     cc_call_center_id         string
                    > ,     cc_rec_start_date        string
                    > ,     cc_rec_end_date          string
                    > ,     cc_closed_date_sk         bigint
                    > ,     cc_open_date_sk           bigint
                    > ,     cc_name                   string
                    > ,     cc_class                  string
                    > ,     cc_employees              int
                    > ,     cc_sq_ft                  int
                    > ,     cc_hours                  string
                    > ,     cc_manager                string
                    > ,     cc_mkt_id                 int
                    > ,     cc_mkt_class              string
                    > ,     cc_mkt_desc               string
                    > ,     cc_market_manager         string
                    > ,     cc_division               int
                    > ,     cc_division_name          string
                    > ,     cc_company                int
                    > ,     cc_company_name           string
                    > ,     cc_street_number          string
                    > ,     cc_street_name            string
                    > ,     cc_street_type            string
                    > ,     cc_suite_number           string
                    > ,     cc_city                   string
                    > ,     cc_county                 string
                    > ,     cc_state                  string
                    > ,     cc_zip                    string
                    > ,     cc_country                string
                    > ,     cc_gmt_offset             double
                    > ,     cc_tax_percentage         double
                    > )
                    > rowformatdelimitedfieldsterminatedby'|'
                    > location 'oss://${your-bucket-name}/call_center';
Query: createexternaltable call_center(
      cc_call_center_sk         bigint
,     cc_call_center_id         string
,     cc_rec_start_date        string
,     cc_rec_end_date          string
,     cc_closed_date_sk         bigint
,     cc_open_date_sk           bigint
,     cc_name                   string
,     cc_class                  string
,     cc_employees              int
,     cc_sq_ft                  int
,     cc_hours                  string
,     cc_manager                string
,     cc_mkt_id                 int
,     cc_mkt_class              string
,     cc_mkt_desc               string
,     cc_market_manager         string
,     cc_division               int
,     cc_division_name          string
,     cc_company                int
,     cc_company_name           string
,     cc_street_number          string
,     cc_street_name            string
,     cc_street_type            string
,     cc_suite_number           string
,     cc_city                   string
,     cc_county                 string
,     cc_state                  string
,     cc_zip                    string
,     cc_country                string
,     cc_gmt_offset             double
,     cc_tax_percentage         double
)
rowformatdelimitedfieldsterminatedby'|'
location 'oss://${your-bucket-name}/call_center'
Fetched 0row(s) in0.07s

[cdh-slave01:21000] > select cc_country, count(*) from call_center groupby cc_country;
Query: select cc_country, count(*) from call_center groupby cc_country
Query submitted at: 2018-10-2816:21:13 (Coordinator: http://cdh-slave01:25000)
Query progress can be monitored at: http://cdh-slave01:25000/query_plan?query_id=fb4e09977145f367:3bdfe4d600000000
+---------------+----------+
| cc_country    | count(*) |
+---------------+----------+
| United States | 30       |
+---------------+----------+
Fetched 1 row(s) in 4.71s

参考文档

关于 Hadoop 更多内容,请参见 Hadoop 支持集成 OSS

您也可以通过阿里云 EMR 访问 OSS。阿里云 EMR 基于开源生态,包括 Hadoop、Spark、Kafka、Flink、Storm 等组件,为您提供集群、作业、数据管理等服务的一站式企业大数据平台,并无缝支持 OSS。阿里云 EMR 与 OSS 紧密结合,针对开源生态访问 OSS,有多项技术优化,详情请参见 EMR 产品介绍