転生して#hatenaintern2020に参加してきました

あらまし

私、皆さんご存じ梅の仁!
ひょんなことから異世界はてなさんのインターンに応募したら、受かってしまって大わらわ!迫りくるイケメン技術たちに囲まれて密度の濃い1週間を送れと言われて…!?えっ!まさかk8s様まで?!私のエンジニア人生、どうなっちゃうの~~~!?!?!?!*1

TL;DR

  • はてなサマーインターン2020に5日間参加しました
  • k8s/gRPC web/Golangを用いたブログサービスの開発課題を行いました
    • licenseをもっと意識できるブログサービスの提案
    • 安全安心な非同期処理Golang
    • キャッシュ目的でforward Proxyサーバーをk8s上に構築してみました
    • 人の実装を眺めて「賢い!すごい!」と言っていました
    • インターン生の中から技術賞をいただきました。ありがとうございます!

誰お前、なんでお前ここにきたの

京都で最後の大学生生活を送っています、梅の仁です。昨今の情勢で学生ともつかないあいまいな生活を送っていますが、そんな中でも夏休みがやってきます。情報系の学生の夏といえばインターン、ですよね(?)「インターンぐらい行かないといけないかなあ」と思っていた所、はてなさんのインターンを見かけました。

インターン事情などには明るくない私でも、はてなさんのインターンはレベルが高いことをよく聞いていました。過去の参加記などがよくSNSに流れてきて、透明性もありいい印象があります。さらにはてなさんは京都にありますし、「京都n大IT企業」*2の一つといっても過言ではないでしょう。同じ京都に住むこともあり、縁を感じたため、積極的に応募することにしました。

応募/面談/当日まで

  • 5/27 こういうのは勢いが大事なので、思い立ったと同日に応募フォームをちゃっと埋めて応募。応募にあたってdockerを動かそう!みたいな課題があった気がします。
  • 6/5 院試勉強とか研究とかでなんやかんやしてたら面談の連絡
  • 6/11 面談

面談はめちゃくちゃ緊張しました。人事の方やチーフエンジニアの方とオンライン面談をしました。今となっては何を話したかちゃ~んとは覚えてないのですが、事前の課題の話からどんどん技術的な話に話が逸れていっていたような気がします。*3

事前課題pt.2

そこから断絶の時期。途中メールをやり取りして、開催時期が決定したりしましたが、次にはてなさんに意識が戻ってきたのは、そう、夏も暑い8/22のことでした。
事前課題として、インターンで扱うアプリが渡され、動作確認を行うことが課せられました。ここでk8sを使っていることに深く絶望。そうです、「いつかやらなきゃいけないけど逃げ続けていたフレームワーク1位」です。やべえなんもわかんねえ。持ち前の才能でどうにかするしかねえ。あまり予習やコードを眺める時間もなく当日を迎えてしまいました。

1日目:講義

1日目はほぼ講義で埋め尽くされていました。講義のテーマは4つ。

最初の最初の講義はHTTPの歴史やREST APIの話から始まって、「これはまあ大丈夫かな」と思っていたら燦然と登場gRPC。
そうです、「いつかやらなきゃいけないけど逃げ続けていた通信方式1位」です。関連してHTTP2、ProtocolBuffers、も現れてきて2位3位が埋め尽くされました。*4ですが、gRPCの設計方針から、どの専門用語がどのようなシチュエーションで関連づいているのかを分かりやすく解説していただけたため、特に詰まることなく進められました。
続くContainer、「Dockerの導入かな?」と思っていたら、コンテナの仕組みからセキュリティ的な注目する場所など、かなり凝ったことを聞くことができました。個人的には、builderkitの紹介だったり、imageのレイヤー構造を実感できる課題が面白かったですかね。
KubernetesとMicroserviceの講義はもう本当に知らないことが多くて、常に講義にかじりついていました。特に最後の2つはためになる講義でしたし、その後の開発ですぐに使いました。

2-4日目:実装

課題として次のような課題が渡されていました。

  • 基本課題
    • rawなmarkdownを受け取って、htmlを出力するk8sServiceの実装
    • 独自に記法を定め、独自なhtmlを出力するよう改造
    • Linkは埋まっているが、Textが埋まっていない部分に、Link先の<title></title>を埋め込む
  • 発展課題
    • 基本課題において外部URLへのクロールを伴う実装をするが、注意するべきことを考え、安全なクローラーを実装する
    • 大量なリクエストに対して安全
    • リクエスト量という意味で安全
    • robots.txt等を考慮できるという意味で安全

基本課題: 独自記法

ところで皆さん、ライセンスを大切にして過ごしていますでしょうか。世間をにぎわせたCocoaだって、OSSである以上ライセンスがあります。そんな身近なライセンスですが、その事情は複雑極まりなく、世には難しいライセンス*5がたくさんあります。人間の秩序ある知恵の集積と、ライセンスは切って切り離せない存在なのです。

ブログだって知恵の集積の一側面を担います。特に開発者の皆さんは、「技術ブログからソースをコピペするのは、モラル的にも、ライセンス的にも大丈夫なのか」と思うことは多々あるのではないでしょうか。ブログという身近なサービスが、ライセンスしやすく、引用しやすくすることで、開発者以外の方にもライセンスや引用のお作法に慣れ親しんでほしい。そう考えて、「ライセンスと引用がわかりやすいブログサービス」をコンセプトにしました。

その導入として、「ライセンスバッジのSnippet」を下図のように用意しました。

f:id:featveir:20200911171057p:plain

独自記法としてのSnippet

バッジをクリックすればライセンス条項に移動する安心仕様。これをいろんなところに張り付ければ、ブログのソースごとにライセンスを変えることだって可能なわけです。
この記法をyuin/goldmarkのextensionとして実装しました。ついでにmarkdownの記法とかもこのライブラリを使って導入。
このgoldmarkですが、最初はかなりとっつきにくさを感じたものの、非常によくできたライブラリでした。いやぁ勉強になりました。

…と、志は高く、まだまだ実装したい内容はいっぱいあった*6*7*8*9のですが、他の課題との兼ね合いもあり時間の都合で断念。まだまだ掘り下げることのできるテーマだったかなあと思っています。

基本/発展課題: クローラーの設計

クローラーとしてfetcherサービスをk8sに作ることにしました。実装言語はGolangです。前述した記法変換を行うサービスがrendererで、こいつが対象のASTNodeを拾い集め、urlの配列をgRPCを通して投げ、fetcherがtitleの配列を返す形になっています。

f:id:featveir:20200911175114p:plain

fetcherサービスの概要*10

このままだと、ユーザーの入力、しかも入力しやすいテキスト入力の形で、大量の外部リクエストが発生してしまいます。相手にとっても自分にとってもものすごく迷惑なので、fetcherのForwardProxyサーバーとしてsquidを構成し、キャッシュヒットを起こさせることでリクエスト数を減らす作戦をとることにしました。

f:id:featveir:20200911174941p:plain

Forward Proxyの概要

紆余曲折波乱万丈がありながらも、Proxyサーバーが構成できるようになったところで、今度は「サイトによってキャッシュしたりしなかったりする」現象に見舞われました。ところでこの図を見てください。

f:id:featveir:20200911181042p:plain

MITM

聡明な皆さんならお気づきでしょう、そうです、中間者攻撃(Man In The Middle attack)の形をしていますね。つまり、httpsの内容をキャッシュすることはできず、httpの内容はキャッシュできていたことが原因でした。これに対する解決方法は、Squidに証明書を当てることでSSLBumpを行い、SSLの内容を復号化しないといけません。本来はfetcherがクライアントで、外部URLがサーバーなのですからこれは完全に中間者攻撃の様相を呈しています。このhttpsの時代に、httpsのポリシーを守ろうとするなら、ラフなプロキシキャッシュサーバーは難しいんだなあ、と知見を得ました。結局、今回の課題の範囲ではhttpsのキャッシュはあきらめることにしています。

アプリレイヤーでのキャッシュを実装するか、nginxなどで流量制限を書けることで実現すればよかったかなあ、うーん。

その他

フロントに関してはラフな実装を渡されていたため、bootstrapを用いてビューを整えたりもしました。

f:id:featveir:20200911182158p:plain

before

f:id:featveir:20200911182258p:plain

after

終えてみて

ごめん、明日のISUCON*11には行けません。 いま、はてなさんの送別会にいます。 この国を南北に縦断するwebアプリを私は作っています。 本当は、あの頃*12が恋しいけれど......。 でも、今はもう少しだけ知らないふりをします。 私の作るこのwebアプリも、きっといつか、誰かの青春を乗せるから。 - 大成建設さんのCMのパロ

何言ってんだこいつって感じですけど、燃え尽きました。非常に疲れました。その分得られたことは多かったです。

  • Golangの(特にテストの)お作法、Golangに限らないテスト設計方法
  • k8s, gRPC等の技術になじみを持つことができた
  • メンターさんとのペアプロ経験
  • 同じ課題に対して人々のアプローチが違って面白い
  • はてなさんへの印象が良くなった :+1:

成果発表の後面談、そしてこのブログを執筆しているので疲労困憊、曖昧模糊、満身創痍です。本当はもうちょっと書きたいけど疲れた。そのうち追記します。それでも充実した5日間を過ごすことができました。メンター、同じインターン生の皆さんへの感謝の念をもってこのエントリを終わりにさせていただきます。長文、駄文、末筆ながら、読了ありがとうございました。

追記

0911 19:20に、インターン生の中から技術賞をいただきました。ありがとうございます!

 

*1:どうしてイケメンで書いたのかはわかりません。謎です。

*2:n=いくつかは読者の想像にお任せします

*3:なんかjwtの会話をした気がするんだけど、面談で何話してんだ俺。

*4:protoBufは通信方式ではないですけど勢いです

*5:https://www.zen-lang.org/ja-JP/blog/2020-08-20/

*6:コピーした時に引用日時がclipboardに入るとか

*7:引用日時用のsnippetとか

*8:ライセンスを見てコピペを防ぐとか

*9:最後まで見てくれてありがとう!

*10:Pod同士が通信してるのはおかしいんですけどね

*11:インターン終了が0911、ISUCON10が0912だった。

*12:ISUCON9にも出ました。