所属していないクラスタに対してDispCpやhdfs dfsを使う場合のTips

f:id:yassan0627:20201211005710p:plain この記事は Distributed computing (Apache Spark, Hadoop, Kafka, ...) Advent Calendar 2020 の11日目の記事です。

qiita.com

クラスタ間でHDFSファイルを移動したいというのは割とよくある話です。 そこでHDFSファイルを大量に移動する際は、DistCpを使うことになります。

ただ、移動元も移動先にも所属していないクライアントから通常DistCpは使えません(クラスタの設定情報がないので)。

設定をどうにかして渡せば、多分出来るだろうなぁと思いつつも「まぁ移動先のクラスタクライアントにSSHしたらいいか。」で後回しにしてましたが、自分のPCからDocker使ってやりたいなぁって事で調べました。

DistCpそのものについては、以下の最高の記事があるのでそこを参照下さい。 shiumachi.hatenablog.com

前提

以下のCloudera Enterpriseが対象です。

所属していないクラスタに対してDispCpを実施したい場合

例:クラスタAのクライアントから、クラスタB(source)→クラスタC(target)に対してDistCpを実行したい

# クライアント
$ hadoop version
Hadoop 2.6.0-cdh5.15.0
Subversion http://github.com/cloudera/hadoop -r e3cb23a1cb2b89d074171b44e71f207c3d6ffa50
Compiled by jenkins on 2018-05-24T11:19Z
Compiled with protoc 2.5.0
From source with checksum 2efeda2e2d6b27ecf59ab56fffd9881
This command was run using /usr/lib/hadoop/hadoop-common-2.6.0-cdh5.15.0.jar

# Source
$ hadoop version
Hadoop 2.6.0-cdh5.14.0
Subversion http://github.com/cloudera/hadoop -r 9b197d35839383c798c618ba917ccaa196a17699
Compiled by jenkins on 2018-01-06T21:38Z
Compiled with protoc 2.5.0
From source with checksum f4ddee45985a34faa91db2aad8731f
This command was run using /opt/cloudera/parcels/CDH-5.14.0-1.cdh5.14.0.p0.24/jars/hadoop-common-2.6.0-cdh5.14.0.jar

# Target
$ hadoop version
Hadoop 3.0.0-cdh6.3.2
Source code repository http://github.com/cloudera/hadoop -r 9aff20de3b5ecccf3c19d57f71b214fb4d37ee89
Compiled by jenkins on 2019-11-08T13:49Z
Compiled with protoc 2.5.0
From source with checksum f539c87da37534aad732f2a7ddcc59
This command was run using /opt/cloudera/parcels/CDH-6.3.2-1.cdh6.3.2.p0.1605554/jars/hadoop-common-3.0.0-cdh6.3.2.jar

以下のコマンドを使う

ソースとターゲットのHadoopのメジャーバージョンが変わらない場合

hadoop --config <target_conf_dir> distcp [DistCpオプション郡] \
   hdfs://<source_nameservice>/<source_hdfs_path> \
   hdfs://<target_nameservice>/<target_hdfs_path> 

ソースとターゲットのHadoopのメジャーバージョンが異なる場合

hadoop --config <target_conf_dir> distcp [DistCpオプション郡] \
   webhdfs://<source_nameservice>/<source_hdfs_path> \
   hdfs://<target_nameservice>/<target_hdfs_path> 
パラメータ 説明 今回(クラスタB→クラスタC)の場合
[DistCpオプション郡] -overwrite、 -pbなどのdistcpのオプション (必要に応じて指定)
--config target_conf_dir target側クラスタhdfs-site.xml があるディレクトリへのフルパス
<target directory> が自分のクラスタ内なら不要
/etc/hadoop/conf.claster-c/
(予めクラスタCのクライアント設定を入れておく)
<source_nameservice> 以下のいずれか
* source側サービス名
* source側のNNのFQDN:NN のポート番号
cluster-b
cluster-b-namenode.example.com:50070
<target_nameservice> 以下のいずれか
* target側サービス名
* target側のNNのFQDN:NNのポート番号
cluster-c
cluster-c-namenode.example.com:50070

※NN=NameNode
※サービス名=hdfs-site.xmlのプロパティdfs.nameservicesの値

今回(クラスタB→クラスタC)の場合の具体例

$ sudo -u user1 hadoop --config /etc/hadoop/conf.claster-c/ distcp -overwrite -pb \
     hdfs://cluster-b/hoge_db/hoge_table/dt=20201210/ \
     hdfs://cluster-c/hoge_db/hoge_table/dt=20201210/

$ sudo -u user1 hadoop --config /etc/hadoop/conf.claster-c/ distcp -overwrite -pb \
     hdfs://cluster-b/hoge_db/hoge_table/dt=20201210/ \
     webhdfs://cluster-c/hoge_db/hoge_table/dt=20201210/

注意点

hadoopコマンドを実行したユーザが、DistCpでターゲット側に生成されるファイルの所有権になるので注意

所属していないクラスタに対してhdfs dfsを使いたい場合

DistCpの場合とほぼ同じ。

クラスタAのクライアントから、クラスタCを参照したい場合は以下の様にする。

hdfs --config /etc/hadoop/conf.claster-c/ dfs -ls \
   hdfs://cluster-c/hoge_db/hoge_table/dt=20201210/

/etc/hadoop/conf.claster-c/クラスタCの core-site.xml が必要

さいごに

以上が出来るだろうなぁって放置してたTipsでした。

つまり、これを使えば、手元のPCからDocker使って、hadoophdfsコマンドを使ってリモートのクラスタの操作を行うことが出来ます。 今回の話は私が探した範囲では、ドキュメントには明示的に書いて無くて、CLIのヘルプにconfのオプションがあるくらいでそこから推測出来る程度の情報しか探せなかった。

# hadoop --help
Usage: hadoop [OPTIONS] SUBCOMMAND [SUBCOMMAND OPTIONS]
 or    hadoop [OPTIONS] CLASSNAME [CLASSNAME OPTIONS]
  where CLASSNAME is a user-provided Java class

  OPTIONS is none or any of:

--config dir                     Hadoop config directory
 :

# hdfs --help
Usage: hdfs [OPTIONS] SUBCOMMAND [SUBCOMMAND OPTIONS]

  OPTIONS is none or any of:

--buildpaths                       attempt to add class files from build tree
--config dir                       Hadoop config directory
 :

以上、小ネタでした。