はてなサマーインターン2017の講義とメンターをした話

はてなエンジニア Advent Calendar 2017 - Qiitaの17日目の記事になります。前回はid:dekokunによる Alexa(echo) スキル用AWS Lambda functionをAWS SAMを使ってバババッと立ち上げる - でこてっくろぐ ねおでした。
GitHub - masayoshi634/libipvsgoを元にGeneric NetLinkとIPVSを解説しようと思いましたが、気がついたら当日になっていたので、本日ははてなサマーインターン2017でメンターをしたときの話をしようと思います。

developer.hatenastaff.com

はてなサマーインターン2017では前半の講義パートと後半の実践パートがありました。 私は前半の講義パートのインフラ講義と後半の実践パートの大規模システムコースのメンターを担当しました。
講義の資料作成や大規模システムコースのメンターとして気にかけたことなどを書いてみようと思います。

インフラ講義

技術系の最後の講義として2時間インフラ講義を行いました。 そもそもインフラ講義を2時間してくれっていわれても何話せばいいのかよくわからなかったので色々悩んだのですが、結局インフラ設計の考え方の基礎をお話しました。

最近の学生は本当に技術レベルが高く、例えばテストを書くなどのコードを書く上での常識は比較的よく知っており、実践している学生も多いです。今年のインターン生もレベルが高く、前半パートの課題も動くだけでなくよりキレイな設計になるにはどうするか、といった内容の議論をメンターの方としている場面も見かけました。

一方で、学生は基本的にインフラ技術には詳しくない場合が多いです。なかなか経験することができない、インフラの課題がわからない、勉強すべき箇所がよくわからない(実は私もよくわかっていません)。また、そういった理由から勉強するためにインターンに参加したいという学生さんも多いと思います(社会人も多いと思いますが)。
そこで、インフラ講義ではこれからインフラを勉強する、インフラ技術の話を理解しやすくするために基本的なインフラ設計の考え方を話そうと決めました。 個別のミドルウェアなどは例として名前を出したりすることはしましたが、説明は特にしませんでした。ミドルウェアの仕様とか使い方、利用例はネット上を検索すれば出てくる内容も多いので、考え方などを中心にしたほうがインターンの講義内容としては価値があるだろうと考え、個別のミドルウェア内容は削りました。

大体大きく分けて以下の3部構成で話を作りました。

  1. インフラとは
  2. web,app,dbの3層構成
  3. パフォーマンスの話

インフラとは

まず基本的な話としてインフラという単語は指すものが大きいので注意しましょうみたいな話をしました。 ISP事業者、クラウド事業者、コンテンツプロバイダーがいうインフラはそれぞれが指しているレイヤーが異なることが多いので、話を聞いたりするときはどのレイヤーをインフラと言っているのか意識したほうが話が聞きやすいという感じの話です。 今回の講義ではwebサービスにおけるインフラ(つまりサーバやそれらが通信するためのネットワークの話)を中心としています。 webサービス事業者はサーバを資産として持っていなくてもAWSなどでサービスを提供できたりするのでインフラとはつまりAWS,GCPであるというところもあるよーという話ですね。 あとは、サービスの可用性、継続性、コスト、パフォーマンスとかを気にして設計しましょうという話。 ここだけで3-4時間以上は喋れる気もするけど、いきなり経験ない学生にそんなこといってもという感じもあるのでさらっと流しましたが、インフラはここが最重要ポイント(だと私は考えている)なので、喋る時は強調はしておきました。

web,app,dbの3層構成

web,app,dbに分けた上でさらにbatchとかbackup用のdbとかキャッシュサーバとかくっつけていくと実際動いているサービス構成みたいになるやでーという話をしました。 まぁ伝統の3層構成って感じの話ではあるんですが、それだけだとあんまりおもしろくなかったので、考え方はソフトウェアと同じで全く違う世界が広がっているというわけではないのが伝わるように話しました。3層構成に分けておいたほうがスケールや管理が楽になるといきなり言われてもわからんと思うので、main関数にすべてのコードが書かれている状態を各役割と責任範囲を明確にした上で各クラスに分離したような感じなど例を出すように説明しました。サーバ自体が状態を持ったオブジェクトであるというイメージがつくと、変更時の影響の局所化のためにサーバを分離して管理しようとか、メンテナンスがしやすいように名前を付けたり不要なパッケージは入れないようにしようとか、相互に接続するためのインターフェースは統一されていたほうが良いとか、大きなシステムになれば理解するために相互の関係性をUMLのように可視化したいとか、状態を可能な限り持たせないことでより容易に並列化しようとか、そういったプログラミングと同じ課題がインフラを見た時にも見えてくるんじゃないかなーと思っています。例えば、分散トレーシング、コンテナ技術とかを見た時に解決したい課題が、イメージしやすくなるといいなーなんて考えてたりします。
とは言え、2時間で話すのには限度があるので↑のようなところまで伝わったかはわかりませんが、サーバもどこまで分離するかとか、どう分離しようかみたいな議論は、ディレクトリ構成の分け方、クラス設計などに通じるものがあるというのがなんとなくわかったんじゃないかなーと思います。

パフォーマンスの話

ここは少し具体的な技術の話をしています。今まではフワッとした話だったのでちょっとおもしろ要素として入れています。まぁ2時間もフワッとした話しても飽きてしまうかもなーとおもったのでマルチプロセス、マルチスレッド、イベントなどの話や、DBのシャーディングなどのお話をちょろっといれてフィニッシュという感じです。
今回はここはそこまで重視して話していない(面白いところではあるけど)ので気になる人はこの後一緒に話しましょうぐらいで締めました

大規模システムコース

はてなのサーバ・ネットワーク基盤技術を探究するインターンの紹介 - Hatena Developer Blog *1に書いてあるとおり、大規模システムコースの課題はいくつかテーマを用意しておき、実際に配属されるインターン生の特性を見ながらインターン生と相談して実際に行うテーマを決定しました。今回のテーマは"次世代監視技術への挑戦"という感じでした。具体的な内容はインターン生がまとめてくれたブログをご覧ください。 developer.hatenastaff.com

内容の決定はid:y_uukiと案を出しつついくつかの候補をインターン生に示し、一番興味がありそうなのをやってもらう感じにしました。
案ではいくつかあってredis4.0などのミドルウェア検証から今回採用した次世代技術への挑戦みたいな研究に近い内容までありました。
インターン生に最高の夏だった、成長したと思ってもらうことが我々メンターの目標なので大規模システムコースのテーマの決定はなかなか大変です。2週間(10営業日)で実サービスのインフラ環境を触ったことないインターン生が、インフラ技術で内外に反響がある成果を出すというのは難しいものです。
大規模システムコースは他のサービスに紐付いたコースとは異なり、実サービスの機能開発という感じでは無いため、比較的自由にテーマを決定することができる反面、実際のユーザからのフィードバックなどがもらいにくいため、成功体験が得られにくいというデメリットがあります。今までの大規模システムコースも成果としては出ているものの、フィードバックが社内からしか得られにくいという点がありました。
また、サービスに関係したインフラ改善(例えばMySQLのバージョンを上げましたとか、パフォーマンス改善とか)はタイミングが合えばインターン生にも可能な範囲でユーザからのフィードバックがもらえるものがあるのですが、10日で出来るのかというのと果たしてそれが"大規模"であるかという問題点があります。
今回採用した次世代監視技術への挑戦では、現在の課題とそれに対する私とid:y_uukiが考える解決案のイメージを伝え、それをインターン生が自分たちで理解した上で自ら実装を提案し、それらの成果をOSSや技術ブログとして外部に公開するという研究に近い課題の出し方にしました。このテーマになった理由はインターン生が選んだというのもありますが、インターン生の基礎力が十分であると判断できたという点と他のテーマより圧倒的に楽しそうだったからです。
今回来てくれたインターン生2人(id:makenowjust, id:t-k3ntaroo)は、自ら調べ考え考察する技術、研究に必要な基礎力が十分に備わっていました。また、彼らなら我々が考えた解決案以上のものを提案し、共に議論が出来る実力が十分にあるのでやっている我々も楽しいものになると思ったからです。

実際にテーマが決まってからは、私が主にメンターを努め2人の進捗を見守りつつ議論に参加するという感じでした。
メンターをやる上で気を付けた点は以下の2点です

  1. メンター側から意見を出しすぎず、インターン生との議論に一人のエンジニアとして参加する
  2. こまめに進捗確認と議論をする

1つ目の"メンター側から意見を出しすぎず、インターン生との議論に一人のエンジニアとして参加する"のは可能な限り自分たちの手法を提案してほしいからです。私はインターン生を学生ではなく一人のエンジニアとして扱っていますが、インターン生側は私が意見してしまうと「実際に働いているエンジニアが言うのだからそうなのだ」と思ってしまう可能性があるからです。あくまで1つの意見などを出しますが、インターン生で考えた実装を成果としてもらうことで、成功体験を掴んでほしいと思っていました。「これはメンターから言われたものを実装したものではなく、自分たちが考えた実装なのだ」そういうものにして欲しいのです。
2つ目の"こまめに進捗確認と議論をする"のは別にインターンに限ったことではないですが、特に「普段一緒に開発しないメンバーと共に10日間で新しい技術に挑戦し、ブログとOSSとして公開する」ということをやり遂げる必要があるので、方向性が間違ったまま1日立つとそれを修正するだけで2日程度無駄にする可能性があります。なので出勤後,昼食後,退勤前の3回進捗と方向性の確認、困っていることと課題と感じていること、それに対する解決案を確認していました。短い時間で目的を達成するのには、Bestな選択をし続けるのは難しくても最低限Betterな選択をしていかなければなりません。本質で無いことに躓いていたり、熱中するあまり本来とは違うものを実装していないか注意する必要があります。

私もメンターをしたことがないので実際のところはよくわかっていませんが、上記の2点のみを注意してやったところ10日間でインターン成果をブログとして公開し、OSSとしてgithubリポジトリを公開するところまで行けました。まぁインターン生が優秀すぎたので特に上の2点を重視しなくても成功していた可能性が高いのですが、1に関しては意識しておいてよかったなーと思うことが多かったです。
実は始める段階では可視化までは行けないだろうと思っていたので、特に何も考えずgraphvizあたりで可視化するんだろうなーみたいに考えていたのですが、「見にくいのでneo4jで試してみました」と持ってきたのでびっくりしました。
上記リンクの成果を読んでもらえるとわかるかと思いますが、実装段階でいくつもの課題が出てきてそれぞれに議論を行っています。dockerでテストしてたらARPテーブル溢れてきたみたいな話から、接続の関係性のデータ保持は誰が担当するのか、クラスタを形成する時のnetstat情報はLISTEN側(サーバ側)からjoinするのかクライアント側からするのか、Gossipプロトコルを使うのは妥当か、Gossipプロトコルの通信量は問題ないか、ヘルスチェック監視に利用するものはpingでいいのか、UDPで問題ないのか、agent自体のCPU負荷はどうなのか、などなど紹介しきれていない議論もたくさんしました。
議論ではネットワークなどインターン生にとって前提知識が薄いものに関しては積極的に意見を出しつつ、それ以外のものに関してはあがってくる提案手法などに対して意見を出したりしていました。最初はConsul聞いたことはあるという程度の知識だったインターン生が、1週間も立たずにGossipプロトコルの挙動やネットワーク帯域や通信頻度への言及などの議論が出来るようになったのは、単純に使うのではなく、特性を考え活用するという過程を踏んでいるからだと思います。彼らからあがってくる報告や課題は私自身も「なるほどなー確かに実用を考えると気になる点だなー」と気付かされることが多く、もしかしたら私のほうが楽しんでいたかもしれません。

講義とメンターをしてみた感想

インフラ講義の資料作成では、実際に自分がインフラを学んできた過程、思考、知識の整理ができたので良かったかなーと思います。インフラなどにかかわらず人にものを教えることの最大のメリットですね。 ただ結局整理した結果良くわかっていないことも多いし、インフラ知識は体系だったものはあんまりなく結局個人の経験から得たものが多いのかなという印象があります。また、個人の経験では体系だった教科書を作ることは難しく、多くの経験者たちと議論をする必要がありそうです。そういったこともありWebSystemArchitecture研究会を発足し、広く議論することでより体系だったインフラ講義などを提供できるようになるかなとも思っています。

websystemarchitecture.hatenablog.jp

メンターは課題の設計から議論を考えるとかなり労力を使うなーという感じです。インフラは特に適当にやるのは簡単だけど、実力がつくインターンをするのは、会社としては工数をしっかりかけないと提供は難しそうです。逆に言えば学生はメンターがしっかりインフラのインターン内容を考えてくれそうなところに参加すれば、(学べるレイヤーの違いはあれど)しっかり実力や考え方を身に着けてインターンを終える可能性が高い(時間を無駄にした感が少ない)インターンを選ぶことが出来るんではないでしょうか?
来年のインターン担当かどうかはまだわかりませんが、担当になるとしたらより体系的な講義と課題にできたら良いなと思っていますので、もし本記事を読んで興味が出てきた学生がいればぜひ応募していただけたらと思います。

*1:ちなみにここに書いてある"昨年入社した新卒のエンジニアに、はてなインターンに応募しようと思ったが選考に通らないと思って応募しなかった人"は私のことである