Apache Hadoop — 1つのPodにHDFSとYARNを立てて運用する
1 バイトのファイルが 30MB のクォータに阻まれる理由を再現する
目標
ディレクトリに名前クォータとスペースクォータをかけ、名前クォータがディレクトリ自身まで数えることと、スペースクォータがブロックサイズ×レプリケーション係数の分だけ事前に予約することを、拒否メッセージで確認します。ブロックサイズを減らして同じファイルを入れ、クォータが移動(mv)までブロックすることも見ます。
なぜ重要なのか
複数のチームが1つのHDFSを共有すると、あるチームのミス(無限にファイルを作るジョブ、小さなファイル数百万個)が、NameNodeのヒープとディスクを、全員のものから奪います。クォータは、その被害を1つのディレクトリに閉じ込める仕組みです。名前クォータはファイルとディレクトリの数を、スペースクォータはレプリカを含むバイト数を制限します。 スペースクォータには、落とし穴が1つあります。ファイルを書き始めるとき、NameNodeはまだ何バイト書くかを知らないので、ブロック1つを丸ごと(ブロックサイズ×レプリケーション係数)予約します。そのため、残りのクォータが128MBより小さければ、1バイトのファイルも入れません。書き込みが終われば実際のサイズに調整されますが、始めることさえできなければ意味がありません。本番での「クォータが残っているのに、なぜ書けないのか」という問い合わせの大半は、これです。 クォータは、新しい名前ができるすべての操作にかかります。別のディレクトリから移動してくることも、そのディレクトリから見れば新しい名前です。
ステップ
- /quota/team-aをHDFSに作成し、名前クォータ10をかけてください(
hdfs dfsadmin -setQuota)。 - 小さなローカルファイルを1つずつteam-aにアップロードして、拒否されるまで埋め、拒否された
putのエラー出力を、/root/hdp/quota/quota_err.txtに保存してください。 - /quota/team-bを作成し、スペースクォータ30MBをかけてください(
hdfs dfsadmin -setSpaceQuota 30m)。 - /root/hdp/quota/one.txt(1バイトのローカルファイル)を作成し、/quota/team-b/one.txtにアップロードしてみて、エラー出力を、/root/hdp/quota/space_err.txtに保存してください。
- 同じファイルを、ブロックサイズ1MiB(
-D dfs.blocksize=1048576)で、/quota/team-b/one-1m.txtにアップロードしてください。 hdfs dfs -count -q -v /quota/team-a /quota/team-bの出力を、/root/hdp/quota/count.txtに保存してください。- /quota/stagingを作成し、ファイル1つ(/quota/staging/f.txt)をアップロードしたあと、それをteam-aに
-mvしてみて、エラー出力を、/root/hdp/quota/mv_err.txtに保存してください。 - /root/hdp/quota/report.mdに、
## 이름 쿼터・## 공간 쿼터・## 쿼터가 막는 것の3つの節を書いてください(見出しは韓国語で、順に「名前クォータ」「スペースクォータ」「クォータが防ぐもの」を意味します)。最初の節にteam-aに実際に入ったファイル数を、2つ目の節に予約しようとしたバイト数(134217728)を入れてください。
参考
- クォータをかけるのは管理者コマンド(
hdfs dfsadmin)で、スーパーユーザーしかできません。このPodではrootです。 - スペースクォータの単位はバイトで、
30m・1gのような接尾辞が使えます。レプリカも数えます。レプリケーション係数3なら、1MBのファイルが3MBを使います。 -count -qの列: QUOTA・REM_QUOTA・SPACE_QUOTA・REM_SPACE_QUOTA・DIR_COUNT・FILE_COUNT・CONTENT_SIZE・PATHNAME。- よくあるミスは、名前クォータ10ならファイル10個が入ると思い込むことと、スペースクォータの残りの量だけを見て書けると判断することです。
- 公式ドキュメント: HDFS Quotas Guide・HDFS Commands — dfsadmin・FileSystem Shell — count・WebHDFS — Get Content Summary
名前クォータをかける
/quota/team-aをHDFSに作成し、hdfs dfsadmin -setQuota 10 /quota/team-aで名前クォータ10をかけてください。
名前クォータは、そのディレクトリの下(自身を含む)のファイルとディレクトリの数の上限です。かかった値は、hdfs dfs -count -qの最初の列で見ます。
10なのに、いくつ入るのか
小さなローカルファイルを複数作成し、1つずつhdfs dfs -putでアップロードしていってください(アップロード先: /quota/team-a/)。拒否されたputのエラー出力(標準エラー出力)を、/root/hdp/quota/quota_err.txtに保存してください。
ディレクトリ自身も、名前1つとして数えます。そのため、ファイルはクォータより1つ少なく入ります。拒否メッセージには、クォータと「入れようとしたあとの個数」が一緒に出力されます。
スペースクォータをかける
/quota/team-bをHDFSに作成し、hdfs dfsadmin -setSpaceQuota 30m /quota/team-bでスペースクォータ30MBをかけてください。
30mは、30×1024×1024バイトです。スペースクォータは、レプリカまで数えた実際のディスク使用量の上限です。
1バイトがブロックされる
/root/hdp/quota/one.txt(1バイトのローカルファイル)を作成し(printf x > /root/hdp/quota/one.txt)、hdfs dfs -putで、/quota/team-b/one.txtにアップロードしてみてください。エラー出力を、/root/hdp/quota/space_err.txtに保存してください。
書き込みを始める瞬間、NameNodeはブロック1つ(ブロックサイズ×レプリケーション係数)を予約します。デフォルトのブロックサイズ128MBは、30MBのクォータより大きいです。メッセージの2つの数値、つまりクォータと必要だった容量を比べてみてください。
ブロックを小さくすると入る
/root/hdp/quota/one.txt(先ほどと同じファイル)を、hdfs dfs -D dfs.blocksize=1048576 -putで、/quota/team-b/one-1m.txtにアップロードしてください。
ブロックサイズが1MiBなら、予約も1MiBです。書き込みが終わると、使用量は実際のサイズ(1バイト×レプリケーション係数)に調整されます。-count -qのREM_SPACE_QUOTAがどれだけ減ったかを見てください。
count -qで2つのクォータを読む
hdfs dfs -count -q -v /quota/team-a /quota/team-bの出力を、/root/hdp/quota/count.txtに保存してください。
クォータがない列は、none/infと出力されます。team-aはREM_QUOTAが0で、team-bは容量がほとんどそのまま残っています。拒否は「残りの量」ではなく、「予約する量」が原因でした。
移動もクォータに引っかかる
/quota/stagingをHDFSに作成してファイル1つを、/quota/staging/f.txtとしてアップロードしたあと、hdfs dfs -mv /quota/staging/f.txt /quota/team-a/を実行してみて、エラー出力を、/root/hdp/quota/mv_err.txtに保存してください。
移動はバイトを動かしませんが、team-aから見れば名前が1つ増えます。そのため、名前クォータが拒否し、ファイルはstagingにそのまま残ります。
クォータの問い合わせに答えられるように
/root/hdp/quota/report.mdに、## 이름 쿼터・## 공간 쿼터・## 쿼터가 막는 것の3つの節を書いてください(見出しは韓国語で、順に「名前クォータ」「スペースクォータ」「クォータが防ぐもの」を意味します)。最初の節にteam-aに実際に入ったファイル数を、2つ目の節にステップ4で予約しようとしたバイト数を、数値で入れてください。
「クォータ10なのに、なぜ9個しか入らないのですか」「30MBが残っているのに、なぜ1バイトも書けないのですか」という問い合わせに答えるつもりで書いてください。