Hadoop3.1.1でs3a://ファイルシステムを利用する場合の環境構築をしてみる
今日はHadoopのファイルシステム(特に、s3を利用するもの)についてすこしおさらいしてから表題の環境構築をしてみます。
Hadoopのファイルシステム
Hadoopは抽象化されたファイルシステムの概念を持っていて、その実装に
- HDFS
- Hadoop上で利用される分散ファイルシステム。ファイルの内容をブロック単位で管理するので、クラスタ上の全ノードより大きいサイズのファイルもファイルの一部をブロック単位で各ノードに配置するため、ギガバイト、テラバイト、ペタバイトのような巨大なファイルも扱える
- Local
- ローカルのファイルシステム
など、さまざまなストレージをバックエンドとした実装があり、今日扱うS3をバックエンドとするファイルシステムもこの中に含まれます。
ただ、Hadoopで扱えるファイルシステムのうち、S3をバックエンドとするものにはいくつか種類があり、ややこしいので動かすための設定を見ていく前にかんたんに整理しておきます。
Hadoopのs3をバックエンドとしたファイルシステム
詳しい歴史的経緯はこちらのドキュメントの冒頭やこちらの記事が参考になりますが、Hadoopのs3用のファイルシステムを表にすると以下のようになります。
ファイルシステムのURIスキーマ*1 | 備考 |
---|---|
s3 | 最初に作成されたs3をバックエンドとするファイルシステム。このファイルシステムで作成されたファイルはHadoopのs3ファイルシステムを通してしか読み書きできなかった。現在はもうApacheによる開発は終了しており、ソースコードにも含まれていない。下の方で述べるEMRのs3ファイルシステムとは別物。 |
s3n | 上述のs3ファイルシステムの問題点を解決し、アプリケーションのコードとHadoopの間でS3のオブジェクトを共用できるようにしたもの。Hadoopの2.x系で利用することができた |
s3a | s3nより、より大きいファイルをより高いパフォーマンスで扱えることを目的に開発された第三世代。改善内容は、たとえば、部分的なシークの追加など。Hadoop 3.x系で利用できる |
s3(Amazon版) | s3nが開発されている頃からAmazonが独自にEMR用に改良したファイルシステム。現在s3のファイルシステムで開発されているものはこちらであり、Hadoopコミュニティが開発していたs3ファイルシステムとは別物 |
それでは、今日はs3aプロトコルを利用する場合の環境構築をしていきます。
Hadoopでs3a://ファイルシステムをPseudo-Distributed Modeで動かしてみる場合の環境構築について
s3にHadoop用のファイルを置くバケットを作成
なお、バケットには管理者のみがアクセスできるようにします。
バケットを作成したら、テスト用のCSVもアップロードしておきます。
そのCSVの中身は以下です。
dog dog dog cat cat dog dog cat
Hadoopの設定
Hadoopの認証情報とファイルシステムの実装クラスを設定する
次にHadoop側の設定をしていきます。まず、 core-site.xml
の変更内容ですが以下になります。
<!-- etc/hadoop/core-site.xml --> <property> <name>fs.s3a.access.key</name> <value>MY_ACCESS_KEY</value> </property> <property> <name>fs.s3a.secret.key</name> <value>MY_SECRET_KEY</value> </property>
etc/hadoop/core-site.xml
の変更はずいぶん少ないですが、これは今回s3a系のファイルシステムを利用する際の設定のうち、
- s3aファイルシステムを実装しているクラス(
fs.s3a.impl
) - s3aファイルシステムを利用する場合に認証のために利用するクラス(
fs.s3a.aws.credentials.provider
)
についてHadoopのデフォルトの設定を利用しているためです。
まず、Hadoopのデフォルトの設定については、 https://hadoop.apache.org/docs/r3.1.1/hadoop-project-dist/hadoop-common/core-default.xml に記載されていて、fs.s3a.impl
の値は org.apache.hadoop.fs.s3a.S3AFileSystem
になっています。
また、 fs.s3a.aws.credentials.provider
の値の設定に関しては https://hadoop.apache.org/docs/r3.1.1/hadoop-project-dist/hadoop-common/core-default.xml にも記載されていますが、s3のファイルシステムの設定について説明しているHadoop-AWS module: Integration with Amazon Web Servicesのページの方がわかりやすいです。
Hadoop-AWS module: Integration with Amazon Web Servicesによると、s3a://ファイルシステムを利用する場合、
- 認証方法の指定は credential provider クラスの指定という形で行い、複数指定することもできる
- 特に認証方法を指定しない場合、デフォルトで指定されている認証方法が用いられる
- デフォルトで指定されている credential provider は以下の順で試される
org.apache.hadoop.fs.s3a.BasicAWSCredentialsProvider
...core-site.xml
に記載したfs.s3a.access.key
とfs.s3a.secret.key
を利用して認証を行うcom.amazonaws.auth.EnvironmentVariableCredentialsProvider
... 環境変数AWS_ACCESS_KEY_ID
,AWS_SECRET_ACCESS_KEY
を利用com.amazonaws.auth.InstanceProfileCredentialsProvider
... EC2のインスタンスプロファイルの認証情報を利用
- デフォルトで指定されている credential provider は以下の順で試される
となっています。
そして、今回はデフォルトの認証方法のうち、org.apache.hadoop.fs.s3a.BasicAWSCredentialsProvider
を利用する前提の設定となっているので、 core-site.xml
に fs.s3a.access.key
と fs.s3a.secret.key
だけ記載しています。
HadoopからAWSを利用するためのクラスのパスをクラスパスに追加
hadoop
から s3
を利用するためには $HADOOP_HOME/share/hadoop/tools/lib/
以下にある hadoop-aws-3.1.1.jar
が必要なので、 etc/hadoop/hadoop-env.sh
に以下を追記します。
# etc/hadoop/hadoop-env.sh export HADOOP_CLASSPATH=$HADOOP_CLASSPATH:$HADOOP_HOME/share/hadoop/tools/lib/*
その他
また、 s3a://
プロトコルを利用することとは関係ないですが、以下の設定もしていました。
<!-- etc/hadoop/hdfs-site.xml --> <!-- 今回もおためしなのでレプリケーションは作りません --> <configuration> <property> <name>dfs.replication</name> <value>1</value> </property> </configuration>
コマンドを実行してみる
$ $HADOOP_HOME/bin/hadoop jar share/hadoop/mapreduce/hadoop-mapreduce-examples-3.1.1.jar wordcount s3a://woshidan-hadoop-test/word_count_test.csv wordcount-output-s3 $ $HADOOP_HOME/bin/hdfs dfs -cat wordcount-output-s3/* cat 3 dog 5
よさそうです。
トラブルシューティング
bin/hadoop fs -ls s3a://bucket_name を実行したら ls: `s3a://bucket_name': No such file or directory というエラーメッセージが返ってきた
https://hortonworks.github.io/hdp-aws/s3-s3aclient/index.html のコマンドを眺めていたら s3a://bucket_name/
のように末尾に /
が必要なようでした。
[ec2-user@ip-172-31-16-244 hadoop]$ bin/hadoop fs -ls s3a://woshidan-hadoop-test 2018-09-20 23:14:46,289 INFO impl.MetricsConfig: loaded properties from hadoop-metrics2.properties 2018-09-20 23:14:46,384 INFO impl.MetricsSystemImpl: Scheduled Metric snapshot period at 10 second(s). 2018-09-20 23:14:46,384 INFO impl.MetricsSystemImpl: s3a-file-system metrics system started 2018-09-20 23:14:48,278 INFO Configuration.deprecation: fs.s3a.server-side-encryption-key is deprecated. Instead, use fs.s3a.server-side-encryption.key ls: `s3a://woshidan-hadoop-test': No such file or directory 2018-09-20 23:14:48,543 INFO impl.MetricsSystemImpl: Stopping s3a-file-system metrics system... 2018-09-20 23:14:48,544 INFO impl.MetricsSystemImpl: s3a-file-system metrics system stopped. 2018-09-20 23:14:48,544 INFO impl.MetricsSystemImpl: s3a-file-system metrics system shutdown complete. [ec2-user@ip-172-31-16-244 hadoop]$ bin/hadoop fs -ls s3a://woshidan-hadoop-test/ 2018-09-20 23:20:24,680 INFO impl.MetricsConfig: loaded properties from hadoop-metrics2.properties 2018-09-20 23:20:24,798 INFO impl.MetricsSystemImpl: Scheduled Metric snapshot period at 10 second(s). 2018-09-20 23:20:24,798 INFO impl.MetricsSystemImpl: s3a-file-system metrics system started 2018-09-20 23:20:26,691 INFO Configuration.deprecation: fs.s3a.server-side-encryption-key is deprecated. Instead, use fs.s3a.server-side-encryption.key Found 1 items -rw-rw-rw- 1 ec2-user ec2-user 31 2018-09-19 23:26 s3a://woshidan-hadoop-test/word_count_test.csv 2018-09-20 23:20:26,924 INFO impl.MetricsSystemImpl: Stopping s3a-file-system metrics system... 2018-09-20 23:20:26,925 INFO impl.MetricsSystemImpl: s3a-file-system metrics system stopped. 2018-09-20 23:20:26,925 INFO impl.MetricsSystemImpl: s3a-file-system metrics system shutdown complete.
org.apache.hadoop.fs.s3a.BasicAWSCredentialsProvider を fs.s3a.aws.credentials.provider に指定して fs -ls
したらエラーになった
[ec2-user@ip-172-31-16-244 hadoop]$ bin/hadoop fs -ls s3a://woshidan-hadoop-test 2018-09-20 23:05:52,547 INFO impl.MetricsConfig: loaded properties from hadoop-metrics2.properties 2018-09-20 23:05:52,670 INFO impl.MetricsSystemImpl: Scheduled Metric snapshot period at 10 second(s). 2018-09-20 23:05:52,670 INFO impl.MetricsSystemImpl: s3a-file-system metrics system started ls: org.apache.hadoop.fs.s3a.BasicAWSCredentialsProvider constructor exception. A class specified in fs.s3a.aws.credentials.provider must provide a public constructor accepting Configuration, or a public factory method named getInstance that accepts no arguments, or a public default constructor.
fs.s3a.aws.credentials.provider
に指定できる credential provider
のクラスは
org.apache.hadoop.conf.Configuration
のインスタンスを引数にとるpublicコンストラクタを持つ- 何も引数を取らないgetInstance()メソッドを持つ
- publicなデフォルトコンストラクタを持つ
という条件を満たす必要があります。
たとえば、他の credential provider
のクラスを見てみると TemporaryAWSCredentialsProvider
では
public TemporaryAWSCredentialsProvider(Configuration conf) { this(null, conf); }
のように、 Configuration
のインスタンスを引数にとるpublicコンストラクタを持っており、 AnonymousAWSCredentialsProvider
では
public class AnonymousAWSCredentialsProvider implements AWSCredentialsProvider { public static final String NAME = "org.apache.hadoop.fs.s3a.AnonymousAWSCredentialsProvider"; public AWSCredentials getCredentials() { return new AnonymousAWSCredentials(); } public void refresh() {} @Override public String toString() { return getClass().getSimpleName(); }
コンストラクタが宣言されていないので、publicなデフォルトコンストラクタを使えます。一方、 BasicAWSCredentialsProvider
クラスは
public BasicAWSCredentialsProvider(String accessKey, String secretKey) { this.accessKey = accessKey; this.secretKey = secretKey; }
のようにコンストラクタが定義されていますが、これは fs.s3a.aws.credentials.provider
に指定できる credential provider
のクラスの条件
org.apache.hadoop.conf.Configuration
のインスタンスを引数にとるpublicコンストラクタを持つ- 何も引数を取らないgetInstance()メソッドを持つ
- publicなデフォルトコンストラクタを持つ
を満たしていないので、Basic
と接頭辞がついているので試しに使ってみたい感じなのですが、 fs.s3a.aws.credentials.provider
に指定することはできません。ですが、 fs.s3a.aws.credentials.provider
に何も指定しなければ、デフォルトで利用されるため、今回はそうしています。
現場からは以上です。