(English translation is available here)
ヤフーで Hadoop の運用・開発をしている李 燮鳴です。私たちのチームでは Hadoop 3.2.1 に含まれる Router Based Federation (RBF) で Hadoop のスケーラビリティ問題の解決を試みています。この記事では RBF を導入する背景と Hadoop 3.2.1 と既存の実行系の互換性を紹介します。
背景および目的
Hadoopクラスタ@ヤフー
ヤフーでは、自社が提供している多種多様なサービスのログを分析してサービスの改善に役立てるため、Hadoop クラスタを複数運用しています。ソフトウェアスタックでは、HDFS をストレージシステムとして利用し、MapReduce, Tez, Hive, Pig, Spark などの実行系をリソースマネージャ (YARN) 経由で提供しています。またリソースマネージャを経由しない実行系として Presto も提供しています。
図1. 社内 Hadoop クラスタ構成の一例
ヤフーでは、1000ノードを超える Hadoop クラスタが複数存在します。最大規模のクラスタは1500台以上の DataNode から成り立っています。以前の記事でも紹介したように、HDFS では1つのクラスタで扱えるデータ規模には限界があり、それ以上のデータを格納するためには複数のHDFSクラスタを用意して各クラスタに分割する必要があります。
しかしながら、クラスタを分割してしまうとクライアントから見たときに横断的にデータを活用できなくなり利便性が損なわれるため、複数のクラスタをまとめ、クライアントに1つのネームスペースとして提供する手法が必要とされます。Hadoop において、クラスタをまとめる手法として ViewFS と Router Based Federation (以下RBF) が提供されています。
ViewFS vs. Router Based Federation (RBF)
ViewFS では、クライアント側でマウントテーブルを保存しているのに対して、RBF は StateStore にマウントテーブルを保存しています。
図2は ViewFS のアクセスフローを示したもので、アクセスを行う際クライアントは自分のマウントテーブルを照会し、リクエスト先のディレクトリパスに対応した NameNode(NN) にアクセスします (図2中のⒶ)。そして該当 DataNode(DN) にデータの参照・作成を行います(Ⓑ)。
図2. 社内 Hadoop クラスタ構成の一例
図3は RBF のアクセスを示したもので、クライアント(Client)からリクエストを受け取る(①)と、StateStore のマウントテーブルを参照し(②)、リクエスト先のディレクトリパスに対応したクラスタの NameNode(NN) にルーティングします(③)。クライアントのリクエストは適切な DataNode(DN) にリダイレクトされ、データの参照・作成を行います(④)。
図3. Router Based Federation (RBF) のアクセスフロー
RBF に比べ、ViewFS は追加コンポーネントを必要としないため、簡単な構成となっています。しかし、ViewFS はクライアントにマウントテーブルを持つため、マウントテーブルを変更するたびにクライアントの設定ファイルを更新する必要があります。 私たちが運用するクラスタには1000以上の月間アクティブアカウントが存在し、彼らにマウントテーブルを更新させるのはコストが大きいと考えられます。
一方、RBFでは、StateStore に保存されたマウントテーブルが変更された瞬間、全てのクライアントから最新のマウントテーブルが参照されるようになります。 そのため、私たちのチームでは、RBFを採用しようとしています。
コミュニティ版 HDFS と HDP版 Hadoop の混用
Hortonworks Data Platform (HDP) と CDH は Cloudera 社が提供している Hadoop のディストリビューションです。
私たちのチームでは、近年 HDP を利用して Hadoop を構築しており、現在 HDP 2.6.4 を使用しています。2019年12月時点の最新バージョンである HDP 3.1.4 や CDH 6.3.2 に含まれる HDFS も RBF を公式サポートしていないため、コミュニティ版 HDFS を導入することにしました。
一方、YARN, MapReduce, Hive や Spark のような実行系はバージョンが上がることによる既存クエリに対する影響が大きいため、現段階では HDFS のみをコミュニティ版に変更し、それ以外のコンポーネントは HDP 2.6.4 のものを流用することにしました。本番環境には HDFS 3.3 をデプロイする予定ですが、HDFS 3.3 は現時点ではリリースされていないため、この記事では、最新リリースである HDFS 3.2.1 を利用して分析を行います。
HDP 2.6.4 実行系とコミュニティ版 HDFS の互換性確認
Hadoop は Protocol Buffers を利用して通信のインターフェースを定義しているため、hdfs-client に互換性のない変更がないことを確認すれば、HDP版 Hadoop とコミュニティ版 HDFS の入力フォーマットが変わっていないことが確認できます。
比較対象バージョン:
- Apache Hadoop 3.2.1: https://www.apache.org/dyn/closer.cgi/hadoop/common/hadoop-3.2.1/hadoop-3.2.1-src.tar.gz
- HDP-2.6.4.9: https://github.com/hortonworks/hadoop-release (tag: HDP-2.6.4.9-tag)
比較する Protocol Buffers の定義ファイルの整理
Apache Hadoop 3.2.1 では、hdfs-client の Protocol Buffers の定義ファイルは下記のパスに配置されています:
hadoop-hdfs-project/hadoop-hdfs-client/src/main/proto
ClientDatanodeProtocol.proto
ClientNamenodeProtocol.proto
ReconfigurationProtocol.proto
acl.proto
datatransfer.proto
encryption.proto
erasurecoding.proto
hdfs.proto
inotify.proto
xattr.proto
一方、HDP 2.6.4 では、これらのファイルが下記のパスに配置されています:
hadoop-hdfs-project/hadoop-hdfs/src/main/proto
ClientDatanodeProtocol.proto
ClientNamenodeProtocol.proto
ReconfigurationProtocol.proto
proto/acl.proto
proto/datatransfer.proto
proto/encryption.proto
proto/hdfs.proto
proto/inotify.proto
proto/xattr.proto
互換性の確認
互換性の確認では、変更された Protocol buffers の Message について関連する JIRA や Commit を確認し、影響がないかを確認します。
メッセージの field に変更がある場合は下記の基準で判断します:
- you must not change the tag numbers of any existing fields.
- you must not add or delete any required fields.
- you may delete optional or repeated fields.
- you may add new optional or repeated fields but you must use fresh tag numbers (i.e. tag numbers that were never used in this protocol buffer, not even by deleted fields).
https://developers.google.com/protocol-buffers/docs/javatutorial#extending-a-protocol-buffer
ここでは例としてacl.proto
の差分を詳細に説明:
--- hadoop-hdfs-project/hadoop-hdfs/src/main/proto/acl.proto 2019-10-09 19:26:58.000000000 +0900
+++ /Users/sri/Downloads/hadoop-3.2.1-src/hadoop-hdfs-project/hadoop-hdfs-client/src/main/proto/acl.proto 2019-09-10 23:35:49.000000000 +0900
@@ -21,7 +21,12 @@
option java_generate_equals_and_hash = true;
package hadoop.hdfs;
-import "hdfs.proto";
+/**
+ * File or Directory permision - same spec as posix
+ */
+message FsPermissionProto {
+ required uint32 perm = 1; // Actually a short - only 16bits used
+}
message AclEntryProto {
enum AclEntryScopeProto {
@@ -61,11 +66,6 @@
optional FsPermissionProto permission = 5;
}
-message AclEditLogProto {
- required string src = 1;
- repeated AclEntryProto entries = 2;
-}
-
message ModifyAclEntriesRequestProto {
required string src = 1;
repeated AclEntryProto aclSpec = 2;
import hdfs.proto
の削除について:
- FsPermissionProto が明示的に追加されたため、hdfs.protoを削除しても問題ありません
- 関連JIRA: https://jira.apache.org/jira/browse/HDFS-6984
- 関連Commit: https://github.com/apache/hadoop/commit/12e44e7bdaf53d3720a89d32f0cc2717241bd6b2#diff-c904c24f461666f80be15d52c2c0d0ca
message AclEditLogProto
の削除について:
AclEditLogProto
はeditlog.proto
に移動されているが、移動したあともMessage
の定義が変わっていないため、問題はありません (Related Commitを参照)
- 関連JIRA: https://jira.apache.org/jira/browse/HDFS-8726
- 関連Commit: https://github.com/apache/hadoop/commit/fc6182d5ed92ac70de1f4633edd5265b7be1a8dc#diff-c904c24f461666f80be15d52c2c0d0ca
互換性確認の結果
下記の例外を除いて、HDP 2.6.4 の実行系とコミュニティ版の Hadoop 3.2.1 の HDFS を混用しても、不具合はないと考えられます。
例外:
HDP 2.6.4 の Hadoop から ErasureCoding に関連する機能を使用できない ( HDFS-8854, HDFS-9173, HDFS-10999, HDFS-12218, HDFS-12258, など)
- ErasureCoding については公式ドキュメントを参照:
HDP 2.6.4 の
hdfs
コマンドから下記の機能が利用できません:hdfs dfsadmin -getVolumeReport datanodehost:port
(HDFS-11417)hdfs dfsadmin -upgrade query
(HDFS-13589)hdfs dfsadmin -listOpenFiles
(HDFS-10480)hdfs storagepolicies -satisfyStoragePolicy
(HDFS-10802)hdfs crypto -reencryptZone
(HDFS-10899)
検証環境では HDP 2.6.4 の実行系とコミュニティ版の HDFS 3.2.1 が実際に数カ月間稼働し、古いバージョンのクライアントがいる状況でも HDFS の Protocol Buffers を用いた RPC 通信について互換性に関する問題は発生していません。
まとめ
互換性チェックは Hadoop だと Protocol Buffers の定義ファイル (*.proto) を読む必要があります。
- 今回検証では HDFS のみを異なるバージョンに置き換えたため、hdfs-client のみをチェックしました。
- YARN のバージョンを上げて古いクライアントが混在する場合は yarn-client も確認が必要となります。
バージョンがそろっているのが望ましいが、何らかの事情でそろわない (かつコミュニティがサポートしていると明言していない、コミュニティの言っていることが不安な) 場合は互換性をチェックした方が好ましいです。
互換性がない部分があっても、実際のユースケースで使用していなければ無視できます。
このやりかたは、RPC 通信に Protocol Buffers を使っているミドルウェアなら同じように使用できます。
Compatibility Analysis of Running HDP 2.6.4 Execution Frameworks on HDFS of Apache Hadoop 3.2.1
Background and Motivation
Hadoop Clusters in Yahoo! JAPAN
Yahoo! JAPAN adopted Hadoop as the infrastructure for analyzing logs produced by various services. We employed HDFS as the storage and YARN for managing the resources and orchestrating jobs. On top of that, typical Hadoop execution frameworks (MapReduce, Tez, Hive, Pig, Spark), as well as Presto, are offered for the data scientists inside our company.
Fig 1. A typical configuration of Hadoop Cluster in Yahoo! JAPAN
We are operating multiple Hadoop clusters at 1000-nodes scale. The largest one among those consists of more than 1500 DataNodes (slaves/workers). As you may know, there is a limitation on the amount of data that can be handled by a single Hadoop cluster, exceeding which, the data has to be divided and stored in multiple clusters.
However, running jobs and queries which access data separated on multiple clusters is quite inconvenient. Hence, a method of federating multiple clusters and providing them as a single namespace is preferred in such cases. ViewFS and Router Based Federation (RBF) are the two methods offered by Hadoop for achieving that purpose.
ViewFS vs Router Based Federation (RBF)
When federating multiple clusters with a single virtual namespace, the mount table is required to store the mapping from the original path in each cluster to the new virtual namespace.
In ViewFS, the mount table is stored as a file on the client-side. Whereas in RBF, a dedicated component (StateStore) is employed to hold the mapping information.
The flow of accessing data in ViewFS is shown in Fig 2. The client will refer the mount table stored on its local, and then access corresponding NameNode(NN) (Ⓐ in Fig 2) to acquire the block location. Finally, the client will communicate with DataNode(DN) (Ⓑ in Fig 2) for block access.
Fig 2. Accessing Data in ViewFS
The flow of accessing data in RBF is shown in Fig 3. With RBF, when Router receives a request from the client (① in Fig 3), it will access the StateStore for mount table and figure out the right NameNode to be accessed (② in Fig 3), and then the request will be redirected to the corresponding NameNode(NN) (③ in Fig 3) to acquire the block location, and finally, the client will communicate the DataNode(DN) for block access (④ in Fig 3).
Fig 3. Accessing Data in Router Based Federation (RBF)
When compared with RBF, ViewFS is a much simpler solution since it does not require a dedicated component. However, the maintenance cost is considerably higher because whenever the mapping is updated, the mount tables stored on the clients have to be updated accordingly. Considering that there are 1000+ monthly active accounts in our environment, we have chosen RBF as the federation solution.
Running Execution Frameworks of HDP on Top of Apache Hadoop
Hortonworks Data Platform (HDP) and CDH are Hadoop distributions offered by Cloudera.
We have adopted HDP for constructing Hadoop over the past few years and we are running HDP 2.6.4 right now. Since the latest (as of Dec 2019) HDP 3.1.4 and CDH 6.1.4 do not officially support RBF, we decided to replace the HDFS that comes with HDP 2.6.4 to the HDFS from the Apache community. We plan to deploy Apache Hadoop 3.3 into our production cluster. However, Apache Hadoop 3.2.1 will be used in this article since 3.3 is not yet released.
Updating YARN or other execution frameworks, such as MapReduce, Hive, or Spark, may have a greater impact on existing jobs and queries, therefore, we decided to replace only the HDFS, and stick to the HDP's version for other components.
Compatibility Analysis of Execution Frameworks in HDP 2.6.4 and HDFS of Apache Hadoop 3.2.1
Hadoop is utilizing Protocol Buffers for defining the RPC interface, the compatibility of the HDFS interfaces between HDP 2.6.4 and Apache 3.2.1 can be examined by analyzing the compatibility of Protocol Buffers definition files (*.proto) from hdfs-client of two versions.
The versions used in this article:
- Apache Hadoop 3.2.1: https://www.apache.org/dyn/closer.cgi/hadoop/common/hadoop-3.2.1/hadoop-3.2.1-src.tar.gz
- HDP 2.6.4: https://github.com/hortonworks/hadoop-release (tag: HDP-2.6.4.9-tag)
The Protocol Buffers Definition Files to be Compared
For Apache Hadoop 3.2.1, the Protocol Buffers definition files of hdfs-client are located in the following path:
hadoop-hdfs-project/hadoop-hdfs-client/src/main/proto
ClientDatanodeProtocol.proto
ClientNamenodeProtocol.proto
ReconfigurationProtocol.proto
acl.proto
datatransfer.proto
encryption.proto
erasurecoding.proto
hdfs.proto
inotify.proto
xattr.proto
For HDP 2.6.4, those counterparts are located in the following path:
hadoop-hdfs-project/hadoop-hdfs/src/main/proto
ClientDatanodeProtocol.proto
ClientNamenodeProtocol.proto
ReconfigurationProtocol.proto
proto/acl.proto
proto/datatransfer.proto
proto/encryption.proto
proto/hdfs.proto
proto/inotify.proto
proto/xattr.proto
Compatibility Analysis
The methodology of compatibility analysis is quite straight forward. We take the diff of Protocol Buffers definition files from two versions and check if the modified part is compatible. When messages are deleted or added, we check for the corresponding JIRAs or commits; when fields in a message are deleted, we judge that with the following rules:
- you must not change the tag numbers of any existing fields.
- you must not add or delete any required fields.
- you may delete optional or repeated fields.
- you may add new optional or repeated fields but you must use fresh tag numbers (i.e. tag numbers that were never used in this protocol buffer, not even by deleted fields).
https://developers.google.com/protocol-buffers/docs/javatutorial#extending-a-protocol-buffer
Here, the diff
analysis of acl.proto
is used as an example:
--- hadoop-hdfs-project/hadoop-hdfs/src/main/proto/acl.proto 2019-10-09 19:26:58.000000000 +0900
+++ /Users/sri/Downloads/hadoop-3.2.1-src/hadoop-hdfs-project/hadoop-hdfs-client/src/main/proto/acl.proto 2019-09-10 23:35:49.000000000 +0900
@@ -21,7 +21,12 @@
option java_generate_equals_and_hash = true;
package hadoop.hdfs;
-import "hdfs.proto";
+/**
+ * File or Directory permision - same spec as posix
+ */
+message FsPermissionProto {
+ required uint32 perm = 1; // Actually a short - only 16bits used
+}
message AclEntryProto {
enum AclEntryScopeProto {
@@ -61,11 +66,6 @@
optional FsPermissionProto permission = 5;
}
-message AclEditLogProto {
- required string src = 1;
- repeated AclEntryProto entries = 2;
-}
-
message ModifyAclEntriesRequestProto {
required string src = 1;
repeated AclEntryProto aclSpec = 2;
Deletion ofimport hdfs.proto
:
- FsPermissionProto was added explicitly, so it is safe to not import hdfs.proto
- Related JIRA: https://jira.apache.org/jira/browse/HDFS-6984
- Related Commit: https://github.com/apache/hadoop/commit/12e44e7bdaf53d3720a89d32f0cc2717241bd6b2#diff-c904c24f461666f80be15d52c2c0d0ca
Deletion ofmessage AclEditLogProto
:
- The deletion is safe because AclEditLogProto was moved to editlog.proto, and the definition of that stays unchanged. (Refer to the related commit)
- Related JIRA: https://jira.apache.org/jira/browse/HDFS-8726
- Related Commit: https://github.com/apache/hadoop/commit/fc6182d5ed92ac70de1f4633edd5265b7be1a8dc#diff-c904c24f461666f80be15d52c2c0d0ca
The Result of Compatibility Analysis
Running execution frameworks from HDP 2.6.4 on top of Apache Hadoop HDFS 3.2.1 is considered compatible except for the following exceptions:
Functionalities related to ErasureCoding are not available from HDP 2.6.4 client (HDFS-8854, HDFS-9173, HDFS-10999, HDFS-12218, HDFS-12258, etc.)
- Please refer to the documentation for details.
The following commands are not available from HDP 2.6.4 client
hdfs dfsadmin -getVolumeReport datanodehost:port
(HDFS-11417)hdfs dfsadmin -upgrade query
(HDFS-13589)hdfs dfsadmin -listOpenFiles
(HDFS-10480)hdfs storagepolicies -satisfyStoragePolicy
(HDFS-10802)hdfs crypto -reencryptZone
(HDFS-10899)
We have run a test cluster with real workloads of MapReduce, Hive, and Spark with a mixed version of execution frameworks and HDFS for three months, and no compatibility issues were observed with regard to RPC defined by Protocol Buffers.
Takeaways
- The compatibility analysis of Hadoop can be achieved by checking the compatibility of Protocol Buffers definition files (*.proto)
- We only checked Protocol Buffers definition files from hdfs-client as we only replaced HDFS this time.
- When replacing YARN to a different version, you should also check the compatibility of yarn-client.
- It is always preferable to use components from the same version. You should always do a compatibility check when that is not possible.
- You can safely ignore the incompatibility as long as you do not use the functionality related to that.
- This methodology applies to not only Hadoop but also all the softwares which uses Protocol Buffers to define their RPC interfaces.
こちらの記事のご感想を聞かせください。
- 学びがある
- わかりやすい
- 新しい視点
ご感想ありがとうございました