読者です 読者をやめる 読者になる 読者になる

たごもりすメモ

コードとかその他の話とか。

Hive GenericUDFの挙動がおかしい場合

コンストラクタで初期化処理をやってしまっていないか気をつけよう。

通常 GenericUDF を継承したUDFを実装する場合、初期化処理は initialize メソッド内で行う。コンストラクタで行ってはいけない。それでも古いほうのHiveのバージョンでは動くケースがあったようだが、Hive 0.13で動かなくなっているケースが出て難儀した。
なにしろデータソースによって動いたり動かなかったりする。普通にカラムの入力データを食わせると動かないが、入力データをHiveQLの中で文字列リテラルで与えると動いたりして地獄だった。動かないというのもエラーになるとかじゃなくて、なんかありえない挙動を示す。正規表現マッチのグルーピングが本来の挙動に対してひとつズレた結果が返ってくるとか。

詳しくはそこまで調べてないのであまり書くと嘘になってしまうが、どうもUDFのインスタンスを生成するタイミングと、それを実際に各Task内でinitializeするタイミングが異なるせいではないか、そしてその間に何らかのシリアライズ・デシリアライズが挟まってるのではないか、という感じ。Serializableでない内部状態をコンストラクタ内で作ってしまうと、それが再現できずに(あるいは中途半端に再現されて)以降の処理がおかしいことになる。

ということで、GenericUDFを継承したUDFを作るとき、初期化処理は initialize() メソッド内でやりましょう。

なおUDFを継承したUDFを作るとき(ややこしいな!)は、そのコンストラクタは実際にはGenericUDFのinitialize()から呼ばれるので、使ってよい、ということでした。id:myui さんに教えてもらった。詳しい人がそのへんに座ってるの超便利……!

Hadoop MapReduceのプロファイルをとる

Hadoop MapReduceのジョブは各スレーブノード上で1タスクごとにJVMが1プロセス起動する形で実行される。
で、それらのアプリケーションのプロファイルをとりたい場合、各々のJVMごとにとることになる。これにはhprofを使う。

Apache Hadoop 2.7.0 – MapReduce Tutorial

この記述に従って以下のプロパティをセットする。ジョブ起動時に指定すれば有効にできる。プロファイラのパラメータはデフォルトがあるという話だったけど、やってみたら指定しないとエラーになった。以下の指定は自分が試したとき用にいじってある。

mapreduce.task.profile=true
mapreduce.task.profile.params=-agentlib:hprof=depth=4,interval=100,cutoff=0.001,cpu=samples,heap=sites,force=n,thread=n,verbose=n,file=%s

# MRv1の場合は mapred.task.profile などとする

プロファイラのオプション指定についてはOracle Java SE doucumentを見ればいいのかなと思うけど、なんかいまいち詳しくない。自分が設定する分にはIBMのサイトの日本語解説が役にたった。IBMのやつとOracleので違いがあるかもしれないけど、特に気付かなかった。

HPROF: A Heap/CPU Profiling Tool
IBM Knowledge Center HPROF プロファイラーの使用

このオプションを有効にしてジョブを実行すると、ジョブ終了時(正確にはプロファイラを有効にしたtaskの終了時)に profile.out が生成され、そこにプロファイル結果が出力される。これはJobHistoryServerもしくはJobTrackerのWeb UIから該当のattempt(もしくはtask)を選んで*1、そのログを見れば見られる。いちいちHDFSやローカルファイルシステムに見にいかなくてもいいのは便利。

YARN MRv2での問題

MRv1ならこれだけで一発で結果が得られるんだけど、YARN + MRv2で実行しているとこの結果がちゃんと出てこない。起動時のバナーだけ見られたり、あるいはプロファイル結果の出力が途中でブチ切れた状態になっていたりする。
これはhprofの結果出力がJVMがTERMシグナルを受け取って働く終了処理の中で行われるからだ。んでYARNはTERMを送ったら250msだけ待って終了していないとすぐKILLを送る。ので、プロファイラの結果出力の最中でJVMがKILLられて結果出力がちゃんと得られない、ということになる。

この問題についてはApache JIRAにissueがある。Resolvedになっているが該当バージョンは 2.8.0 だ!

[MAPREDUCE-5465] Tasks are often killed before they exit on their own - ASF JIRA

2.8.0 を待っているわけにはいかないので、どうにか設定をいじってattemptのコンテナがKILLられてしまうまで猶予を作ってみる。これは各スレーブノードで設定して NodeManager を再起動する。

  <property>
    <name>yarn.nodemanager.process-kill-wait.ms</name>
    <value>30000</value>
  </property>

  <property>
    <name>yarn.nodemanager.sleep-delay-before-sigkill.ms</name>
    <value>30000</value>
  </property>

ジョブのConfigurationを見てもこの変更が反映されていなくてアレっと思ったが、試してみた限りでは想定通りに動いているようだ。ちゃんとプロファイル結果が最後まで出力されるようになった。
何か副作用があるかどうかというと、もしかして特定の条件で30秒間だけ長く生き残ってしまうattempt containerが出てしまうかもしれないけど……まあ、特に問題でもないでしょう。

めでたしめでたし。

まとめ

Enjoy profiling!

*1:プロファイラが有効になっているものは明らかに実行時間が長くなるからすぐにわかる

"Docker and Fluentd"の話をした

Fluentd meetup と Gophers and Docker-users beer social というのが連続であって、それぞれでほぼ同じ話をした。……んだけど参加者層が違うからまあいいかなと。あと後者は英語だった。いまだに英語でしゃべるのはだいぶ疲れる。

【レポートあり】Fluentd Meetup 2015 夏 - 2015/06/01(月) - dots.[ドッツ]
Gophers & Docker-users Beer Social - Docker Tokyo (Tokyo) - Meetup

資料はこれ。2回目にやるときにFluentd知らない人がけっこういそうだったのでそのあたりを足してあるくらい。

Dockerを使ってアプリケーションをデプロイするときにログの収集に気をつけないといけないんだけど、そもそもその構成を設計するときにどういうパターンが考えられるんだっけとか、それをFluentdでやるとしたらどのような設計を選択できるんだっけとか、そういうことを話題にしている。

そのバリエーションとして、いまpull-reqを出している Fluentd logging driver を使えるようになるといいんだけどね、という話をしていた。あとそろそろ公式の Docker image を作ったらいいのかなあと思ったので、それを出した話も書いてある。

ところで

上述 pull-req はめでたく code review status に進んだので、これと document review が済めばマージされると思う。だいぶ長いことステータスが変わらなかったのが不安でアレだったけど、今ではちょっと安心している。

あと Fluentd meetup の段階では DockerHub でユーザ名がとれてなくてね、という話をしたけど、その後にめでたくユーザ名 tagomoris も organization name fluent も(ついでに fluentd も)とれた。めでたしめでたし。ということでスライド中にURLなどはアップデートしてある。

#norikra meetup 2 をやってきた

atnd.org

いつもながら会場を :DeNA さんに提供していただいて開催できました。本当にありがとうございます。

tagomoris in English — Norikra meetup #2

こっちにも書いたので細かいことは省きますが、今回も100名近く? の人に集まっていただいて、今後の機能どうするかなあとか、実運用こうやってるんだなあとか、一人で開発していると得られない本当に様々なフィードバックをもらえました。ありがとうございます。

自分のスライドはこちらで、最近のアップデートで入った機能などについて話しました。NULLABLEとかは便利だと思いますし、Listener pluginについては簡単なコードで劇的にアーキテクチャが変わる可能性があるので、ぜひ試してみてもらいたいです。

またNorikraは普通に開発を継続していますので、ここが使いづらいとかこの機能が必要だとかあったら、ぜひ issue にお寄せください。みなさんの要望はたぶん一人だけのものではなく、割とみんな欲しいものである可能性が高いです。よろしくおねがいします。

まとめると、今回も楽しかったな!

ソフトウェア技術についてのスライドは英語で書こうぜの話

それだけで潜在読者が軽く10倍以上になるし、自分で英語書く練習にもなるし、1枚のスライドに大量の日本語を書いてしまって見にくくするのも避けられるし、いいことづくめだよ。

まじで。

fluent-plugin-secure-forwardの脆弱性とアップデートのお知らせ

(追記 5/29 13:15)
この更新の際、設定ファイルの shared_key についても変更されることをお勧めします。また変更をいくつか追加した v0.3.2 をリリースしましたので、このバージョンをお使いください。

これは v0.2.x を使用していたときに shared_key_digest を(あるいはshared_keyそのものを)攻撃者に入手されていた場合、認証情報をリプレイ送信されることで攻撃者が input plugin に接続できてしまう可能性があるためです。
深刻度は高くありませんが、念のため shared_key の変更をお勧めします。
また v0.3.2 は認証プロトコルに input plugin から送信するナンスをひとつ増やし、この種の攻撃可能性を排除するための変更を含んでいます。
(追記ここまで)

fluent-plugin-secure-forward v0.3.0 をリリースしました。これは v0.2.x およびそれ以前の全てのバージョンに存在する脆弱性に対処するためのものです。
古いバージョンはSSLの扱いに問題があり、中間者攻撃が可能な脆弱性がありました。これを利用すると output plugin から送信されるデータの取得および改竄が可能となります。安全な通信を目的とする場合は必ず fluent-plugin-secure-forward を v0.3.0 にアップデートし、サーバ証明書、もしくはプライベートCAを用いるいずれかの方法に設定を変更してください。

なお、いずれの方法でも新しく追加された secure オプションの設定を記述する必要があります。これを含めて設定パラメータに一部互換性がなくなっているため、アップデート時には設定ファイルを更新しなければ Fluentd が起動に失敗することに注意してください。

脆弱性に関して報告をいただいたことがこの修正に直接のきっかけになりました。ありがとうございました。

パブリックCAから発行されたサーバ証明書を用いる

適当なドメインおよびそのドメインFQDNを用いたサーバ証明書を用意できる場合は、それを input plugin で設定して用いることができます。*1
ただしパブリックCAから発行された証明書を用いる場合、output plugin側でFQDNの検証が必要です。これを enable_strict_verification パラメータで有効にしてください。無効では起動できません。

https://github.com/tagomoris/fluent-plugin-secure-forward#using-ssl-certificates-issued-from-trusted-ca

プライベートCA証明書を作成して用いる

サーバ証明書や適当なドメイン名などを設定して用いるのが難しい場合には fluent-plugin-secure-forward 専用のプライベートCA証明書と秘密鍵を作成して用いることができます。v0.3.0 はそのためのユーティリティ secure-forward-ca-generate を同梱しています。
この方法による場合、プライベートCAの証明書および秘密鍵ファイルを input plugin を起動するFluentdのホストに安全な方法でコピーし、またプライベートCAの証明書ファイルを output plugin を起動するFluentdのホストにもコピーする必要があります。

この場合 in_secure_forward v0.3.0 はサーバ証明書を自動生成し、このプライベートCAの証明書および秘密鍵(とそのパスフレーズ)を用いてサーバ証明書に署名します。
また out_secure_forward v0.3.0 はこのプライベートCAによる署名が行われていることをもって証明書検証を行い、SSL通信を有効なものだと判断します。このためプライベートCAの秘密鍵およびパスフレーズが外部に漏れた場合は即座に使用中の証明書と秘密鍵を破棄し、新しいものを生成して入れ替えてください。

https://github.com/tagomoris/fluent-plugin-secure-forward#using-private-ca-file-and-key

セキュアでない方法で通信する

証明書などの設定をいっさい追加しない場合、安全なSSL通信路を確立できません。この場合第三者によりデータの読み取りや改竄が行われる可能性があります。
v0.3.0 およびそれ以降のバージョンでも v0.2.x およびそれ以前と同じ方法で通信を行う方法は存在していますが、使うべきではありません。この方法を有効にする場合は secure false という指定を設定に追加する必要があります。

https://github.com/tagomoris/fluent-plugin-secure-forward#using-insecure-self-signed-certificates

まとめ

fluent-plugin-secure-forward を使っている人は可能な限り迅速に v0.3 にアップデートしてください。設定の変更等が必要です。バグなどについては tagomoris までご連絡ください。よろしくお願いします。

*1:が、この場合に output plugin 側で適切なルート証明書のセットを指定する方法を作り忘れていたことに気付きました。あとで再度アップデートします。

小中規模のIT系企業における技術的選択と雇用戦略に関する雑感

でっかい主語で入ったが、要するに2月にあちこち会社巡りをしたときに感じたことについてつらつら書こう、というのが目的。

特定の会社について書いてもしょうがないので、あれこれ*1回ったうちから少なくとも2〜3ケースで該当するなあ、と思ったことについて書く。特定の1社のみに該当する事項はこのエントリにはひとつも出てきません。
またエントリの主旨からして超上から目線になりますが、どうかご容赦ください。

これから成長が本格化するのでインフラを支えられる人材がほしい

正直に言ってこれが一番多かったパターン。スタートアップ的にサービスを作ってきたがその一方でデプロイや監視などの運用まわりが後手後手になっており、そのあたりを支えられる人物がほしい。

話としてはわかるのだが、気になったのは、これを聞くとき、詳しい内容を突っ込んでみると、どうも実際にはそう困ってはいない、というケースがほとんどだったように思えたことだ。単に人数が足りないとか優先順位が低いとかで後回しになっており、しかもそれがその時点では特段大きな問題になっていない。そのあたりについて質問してみても技術的なポイントが出てくるわけではない。

だったら問題になるまで放置しておけば? というのはまあ乱暴なんだけど、そうおかしくもない話だと思う。運用を先回りしてやれるのは、サービスが安定して相応の会社規模があるところだけに許される特権だと思っている。
会社/サービスが成長曲線の途中にあるなら、技術的問題が明確に指摘できないようなことにこだわるべきではない。サービスのことだけ考えよう。

これから成長が本格化するのでデータ分析基盤を作れる人材がほしい

これも多かった。これはもうこちらに書く機会があったので書いてしまったが、自分で作ってはいけない。使いましょう。

データ分析基盤を作ることそのものがサービスの根幹である場合を除いて*2、データ分析基盤がサービスにかかわってくるとき、焦点となるのはデータそのものか、ロジカルな分析手法にあるのであって、基盤そのものが競争力の源泉となるケースはほとんど存在しないはず。そして「これから成長が本格化する」という段階であれば、競争力の中核でないようなことに無駄な力を割くべきではない。

もうちょっと言うと、Hadoopやら何やらの環境は、作れば作れる。そこまではそう難しくない。しかし運用するのは非常に面倒で、基盤を作ってから2年も経つとあれこれ綻びが出始める。
新しい機能が欲しくてアップデートしたくなるが、分散処理ソフトウェア基盤のアップグレードというのは非常に面倒な仕事だ*3。特に業務がデータ分析に多大に依存しており、処理を止められないケースで困難が増大する。

反面、ざっと業界を見渡して、データの分散処理基盤をトータルに設計・構築・運用できる人の数はきわめて少ない。安定的に採用するのは不可能と言ってもよいくらいに少ない。
外部サービスの採用がコスト的に見合わないようなごく一部の大企業などでない限り、まずサービスの利用を最優先に考えるべきだ。作ってはいけない。

100%自己資本で経営しておりVCにわずらわされず仕事できる

経営の人がこれを言うとき、すごく得意そうに言われるのだが、自分には正直どうでもよい。誰の言うことが元になっていようが、経営方針は経営方針である。特に変わりはない。

というより、拡大志向は無いのかな、ということが気になる。がつんとサービスを大きくする、と言う一方で自己資本にこだわる旨のお話をされると、どっち、という感じ。あまりベンチャー的ノリを感じなくなるのは確かだと思う。新卒を雇って20年働いてもらうためにはいいのかもしれない。

高度な技術で日本の広告事業を支配する

それができたらGunosyやSmartNewsが既に日本を支配しているのでは。というかGoogleか。
いやもちろん個々の主張があるのだろうけど、技術的なアプローチに特殊な点が見えない状況でそのように主張するより、何がどうなっているから確実に勝てる、という差別化を先に済ませたほうがよいように見える。

あれとこれとそれをやりたいが、できる人がいない

御社に必要なのは共同経営者CTOか、あるいは何人もの技術顧問ではありませんか?

この点については、もっと技術顧問みたいな働きかたをする人が増えればいいのかなと思うことは多かった。フルタイムで関わるまでは必要なさそうに見えるが、もっと多くの働きかたや技術的視点を(おそらくはパートタイムで)必要としているように見える、という会社はたぶん思っていたより多い。

まとめ

最後だいぶ雑になったが、だいたいこんな感じ。こういった状況を俯瞰している人ってどこかにいるのかなあ。いるんだろうな。

(追記) 技術の話をしよう

大事なことを書くのを忘れていた。

中途で技術者を採用しようというとき、たぶん一番良いのは、技術の話をすることだと思う。何が技術的な差別化ポイントであり、本質的な技術的困難は何であり、今もっとも深刻な技術的課題は何か。
自分は技術的なチャレンジのあるところで働きたいし、おそらくカンファレンスなどの空気を見ていても、技術的なチャレンジのあるところに人の興味は引きつけられる。

だから、技術的困難な点として何があるか、という話をしよう。自分もそのような話がしたい。

*1:だいたい40社前後

*2:なおそのようなケースは話した中にはTreasure Dataしかありませんでした

*3:最近はCloudera ManagerやApache Ambariのおかげで多少は楽になっているかもしれないが。