Akatsuki Hackers Lab | 株式会社アカツキ(Akatsuki Inc.)

Akatsuki Hackers Labは株式会社アカツキが運営しています。

インターンでCloud Runに挑戦した話

エンジニアインターンとして約1ヶ月アカツキで就業したyasuさんの体験記をお届けします。来年4月に入社予定のyasuさんですが、今回の経験で入社までの課題も見えてきた様です。

はじめまして、yasuといいます。
今回私はアカツキで内定者インターンに参加させて頂きました。
期間は1ヶ月ほどでしたが、色々と貴重な経験をさせて頂けたので具体的にどのようなことをしたのか紹介して行きたいと思います。

自己紹介

私は現在、大学で経営工学を学んでいる4年生です。
普段は趣味でGo言語を主に触っています。
Go言語で主にやっている事としては研究室のSlackボット開発や自分用のブログエンジンの開発、ハッカソンなどでネイティブアプリ用のAPIの開発などです。
最近はOSのカーネルやコンパイラなどソフトウェアの中でも低いレイヤーに位置する技術に興味があります。
新しいものが好きです。

きっかけ

きっかけは逆求人イベントでした。
逆求人に参加した際に会社訪問に誘われ、そのまま選考 => 内定 => インターン参加という流れです。
大学3年生のころに一度インターンに参加したことがあり、アカツキの技術に対する挑戦的な姿勢や「なぜ?」を大切にする社風、オフィスの快適さに惹かれてすぐに内定承諾とインターンに参加することを決めました。

何をしたのか?

今回は面接の際にお世話になった坂尾さんの所属するゲームの基盤開発チームでお世話になり以下の3つのタスクをこなしました。

  • 基盤の管理システムのCloud Run移行
  • 基盤の管理システムの操作ログのBigQueryからStackdriver Loggingへの移行
  • アプリケーション側でのIP制限機能の追加

今回利用したCloud Runについて

公式の説明ではRun stateless HTTP containers on a fully managed environment or in your own GKE cluster.と書かれています。
Google Cloud Next ’19で発表されました。
Knativeをベースにしたサービスで、オートスケールの機能やインフラ周りの設定の自動化などが特徴です。
Cloud Run ではContainer Imageさえあれば、その他の設定はほとんど自分でせずにデプロイできます。
公式ではCloud Buildを使ってContainer Imageをビルドしているので今回はCloud Buildも合わせて利用します。

基盤の管理システムのCloud Run移行

今回のインターンの大本のタスクです。
もともとGAE FEで動いていた基盤の管理システムをCloud Runへ移行します。
このタスクをこなすために次のフローを踏みました。

  1. アプリケーションのCloud Runでの動作確認
  2. Cloud Run へCircleCIでデプロイするようにする

アプリケーションのCloud Runでの動作確認

もともとGAE FEを使用していたので既にアプリケーションを動かすためのDockerfileが存在しました。
これをドキュメント通りにCloud Buildでimageをビルドしてgcloud beta run deployをするとすんなりとデプロイ出来ました。

また、GAE FE上でシステムを動かしていた際にはこちらのイメージを使っていたのですが、余計なパッケージを含まないようにDockerオフィシャルのPythonイメージを使うようにDockerfileを修正しました。

Cloud Run へCircleCIでデプロイするようにする

管理システムはCircleCIを使ってデプロイを自動化していたのでCircleCIのconfigファイルを修正する必要がありました。
具体的にはGAE FE向けに書かれていたconfigファイルをCloud Buildを使ってイメージをビルドし、Cloud Run へデプロイするように書き直す必要がありました。
gcloud build submitコマンドでイメージをビルドし、gcloud beta run deployコマンドを使ってCloud Run へデプロイするよう修正しました。

システム操作ログのStackdriver Loggingへの移行

管理システムの監査のための操作ログを、もともとは BigQuery に書き込んでいました。 これを Stackdriver Logging へ移行しました。
このタスクでは次の事を行いました。

  1. Cloud Run 上でStackdriver Logging の構造化ロギングが動くことの確認
  2. ログのデータ構造を定義する
  3. 構造化ログを吐くように操作ログのコードを修正する
  4. ログをRequestログと紐づけて表示できるようにする

Cloud Run 上でStackdriver Logging の構造化ロギングが動くことの確認

Cloud Run では 標準出力・標準エラー出力などにログを書き込むことで、 Stackdriver Logging に自動で集約されます。 またJSON文字列でログを書き込むことで Stackdriver Logging の LogEntry に jsonPayload として格納されます。
これを構造化ログと呼びます。
今回はこちらを使用して操作ログを記録することにしました。
参考 Using simple text vs structured JSON

print('{"sample": "hello"}')

実際に上記のようなJSON文字列でログを標準出力に吐くとLogEntryのjsonPayloadに入り、無事に構造化ロギングが動くことを確認できました。

ログのデータ構造を定義する

操作の際に送信されるパラメーターと送信元と送信者を特定するメタデータをログの構造としてまず定義します。 今回は操作ログなので操作内容と実際に操作しているユーザーのemailなどのメタデータをログのスキーマとして定義しました。

構造化ログを吐くように操作ログのコードを修正する

その定義していた構造通りにJSON文字列をログとして出力します。
今回はFlaskのapp.logger(python標準のloggingライブラリ)を使って標準エラー出力へJSON文字列を吐き出すようにしました。

ログをRequestログと紐づけて表示できるようにする。

Requestログとの紐づけは次の資料を参考にしました。

https://cloud.google.com/run/docs/logging#correlate-logs

In the Stackdriver logs viewer, logs correlated by the same trace are viewable in "parent-child" format: when you click on the triangle icon at the left of the request log, the container logs related to that request show up nested under the request log.

Container logs are not automatically correlated to request logs unless you use a Stackdriver Logging client library. If you want this correlation without using a client library, use a structured JSON log line that contains a trace field with the content of the incoming X-Cloud-Trace-Context header. Then your logs will be correctly correlated to the request log.

https://cloud.google.com/logging/docs/agent/configuration#special-fields

logging.googleapis.com/trace is stripped from jsonPayload and assigned to the LogEntry trace field. For example, assume the value of logging.googleapis.com/trace is [V]. [V] should be formatted as projects/[PROJECT-ID]/traces/[TRACE-ID], so it can be used by the Logs Viewer and the Trace Viewer to group log entries and display them in line with traces. If autoformat_stackdriver_trace is true and [V] matches the format of ResourceTrace traceId, the LogEntry trace field will have the value projects/[PROJECT-ID]/traces/[V].

飛んでくるRequestからHTTP HeaderにあるX-Cloud-Trace-Contextの値を取ってログとして吐くだけです。

ちなみにX-Cloud-Trace-Context
X-Cloud-Trace-Context: TRACE_ID/SPAN_ID;o=TRACE_TRUE
というフォーマットになっているので
/以下を取り除いてTRACE_IDだけ抽出する必要があります。
このTRACE_IDをログとして吐くJSONのlogging.googleapis.com/traceキーのバリューとして設定します。
そうするとLoggingエージェントが収集し、LogEntryのtraceフィールドに自動的にTRACE_IDを設定してくれます。
これでStackdriver Loggingでリクエストログと紐付き、まとまったログとして見る事ができます。

アプリケーションへのIP制限機能の追加

今回の基盤の管理システムは社内用ツールであるため社外からアクセス出来ないようにする必要がありました。
GAE FEではGAEのfirewallの機能でIP制限をしていたのですがCloud Runでは現時点でそのような機能が提供されていませんでした。
なので、今回はアプリケーションレイヤーでIP制限機能を実装することにしました。

最初は Flask の request.remote_addr の使用を試みてみたのですが、 Cloud Run にデプロイすると、これには Google Frontend の IP アドレスが設定されるということがわかりました。
X-Forwarded-For には Google Frontend がクライアントの IP アドレスを付与してくれていたため、こちらの IP アドレスを使用してアクセス制限機能を実装しました。

Cloud Run を実際に使ってみて

学習コストが低いので初学者でもすぐに始められて良いと感じました。
インフラ周り初心者の私でもすんなりデプロイできたのでの学習コストはかなり低いなと感じました。
また、デプロイをすれば設定など何もすることなくスケーリングなどのサーバー全般の管理をGoogleがやってくれるのでかなり便利だと感じました。

インターンで学んだこと

何をするにも なぜ? そうしたのか深堀ること。

インターン中一番改善しなきゃいけないと思った点はこれです。 どのタスクの際にも技術を理解せずに突き詰められていた事が多かったと思います。 例えばシェルスクリプトでShebangを使っているのにshコマンドを使っていたことがありました。

また、traceの設定の仕方もドキュメントを読めばしっかり書いてあるのに網羅的に読まなかったせいで見落としていたりしていました。 プルリクエストで詰めて頂いたおかげでかなり勉強になったので凄く感謝しています。 理解しないで実装するのは結局はバグや脆弱性を生み出し非効率なので一番自分が成長しなければならない部分だと感じました。

チーム開発でのコミュニケーションの大切さ

普段私はハッカソンや個人開発を主にしていたこともあり一人よがりな開発をしがちです。 そのせいで今回、妙に一人で抱え込んだりして余計に時間をかけたり心配をかけてしまったりしていました。 開発の効率にも関わる問題なので普段からのコミュニケーションも大切にしていきたいなと感じました。

良かったこと

新しい技術に挑戦できた!

他社でのインターンやバイトは自分のできる技術をベースにできることを任されることが多かったです。 しかし今回のインターンではCloud Runという発表されて間もない新しい技術を触らせて頂いた上にインフラ部分の移行を任されるという大きな課題に挑戦できたので他では体験出来ない有意義な経験が出来ました。 プルリクエストのコメントも議論が活発でそこから学べる事も沢山あったので凄く感謝しています。 今までのインターン経験上一番悩んで、一番楽しかった1ヶ月でした。

働きやすい環境が用意されている!

アカツキさんのオフィスではみんなが楽しんで仕事をしている雰囲気があり、オフィスも働きやすい設備(バリスタが常駐してたりとか休憩スペースが用意されてたりとか...etc)が整っていたので非常に働きやすかったです! 私の経験上一番働きやすい環境だと思いました。

最後に

2年前にアカツキでインターンをした際も感じたのですが、アカツキの働きやすさを改めて実感できた1ヶ月だったと思います。 インターン生が行うタスクに関しても他では経験できない裁量が与えられる非常に有意義なものでした。 また、今回のインターンで入社するまでのあと半年で解決すべき私自身の課題も見えてきたので半年後には進化した姿でまた戻ってこれるように精進したいです。 今回色々と見て頂いた坂尾さん、田中さん本当に感謝しています。

長々と書いてしまいましたが最後までお付き合い頂きありがとうございました!