目指せNoOps!幸せを呼ぶサーバーレスログ基盤構築への挑戦

目指せNoOps!幸せを呼ぶサーバーレスログ基盤構築への挑戦

こんにちは。HRMOS採用管理事業部のプロダクト開発部でアプリケーションエンジニアをしております、新卒2年目の澤なつみと申します。

普段はScalaで開発をしているのですが、この度先輩とタッグを組み、ログ基盤構築という新しい挑戦をしました。 今回の記事では、ログ基盤の本番運用を目指して試行錯誤した約三ヶ月間の旅の記録をお届けしようと思います。

コトの発端 ~ログってどこからきたの?~

HRMOSの開発者は日々、データ可視化ツールであるkibanaを使ってエラーログの監視をしています。それを配属されてからずっと、当たり前のように利用していた私はふと疑問に思いました。「このアプリケーションログってどこからきたの?」 と。

> 新卒のふとした疑問に爆速で返事をくださるSREの先輩方

その時私は、 ログは鳥が運んでいる ことを知りました。(笑)HRMOSではコンテナ型の仮想環境であるDockerを利用しているのですが、Dockerコンテナから出力されたログはfluentdという鳥によって集約・加工・出力がされていました。

そしてこの時初めて 「幸せを呼ぶログ基盤」 の構想を耳にしました。

> 目指せNoOps!

幸せを呼ぶログ基盤・・・それは、AWSのサービス同士をピタゴラスイッチのようにつなげていくことで サーバーレスなログ基盤 を作り、その結果管理コストが減り開発者が幸せになれる、という構想でした。

また、基盤の拡張性が上がることで、ログ(=ユーザーの行動)データを活用してユーザーにさらなる価値を届けることができます。

つまり、価値を創出できる時間が増え、本当に必要な機能改善ができる、その結果 ユーザーの幸せ にまでつながるということです。私はこの構想を聞き、これは浪漫の原石だと思いました。

そして、黙々とKinesis Data Firehoseというサービスについて調べていたところ、この36件にも及ぶ浪漫スレッドに興味を持ってやってきた大魔王こと大魔王先輩が一緒にインプットを始めてくださいました。ログ基盤についての調査を進めるうちに、先輩のアシストもありどんどん夢が膨らんでいき、気づいた時にはもう既にログ基盤構築への旅が始まっていました。ここまでで二日間の出来事でした。

AWSコンソールも歩き慣れていないくらいの状態からのスタート。旅の指針としてOKRを立て毎週のゴールを設定、詰まったらSREの方々に相談させていただきながら、ロマンドリブンの心で進めていったのでした。

鳥は辛いよ・・・ ~HRMOSのログ基盤について~

まずは、現在のHRMOSのログ基盤についてご紹介します。上記のスレッドで先輩から教えていただいたように、開発者までログを届けるしくみはこのようになっていました。

現在の構成  各環境でfluentdがログを取得し、aggregatorでログを集約、そしてkibana・Slack・S3にアウトプットされます。そうすることで、開発者はSlackの通知をトリガーにkibanaでエラーログの確認をし、ローデータはS3に永久的に保存されるしくみになっています。

しかし、fluentdのメンテナンスは属人化しており、現状のログ基盤には手を加え辛い状態になっていました。そして、fluentdが落ちると集約していたログがすべて失われるリスクも潜んでいました。HRMOSのSREチームはNo Ops!を目指しているため、ログ基盤における運用の辛みを解消したかったのです。

こんなログ基盤を作りたい・・・~妄想の時間~

現状のログ基盤の辛みを解消するにはどうしたらいいのか、ピタゴラスイッチの構想をヒントに考えていきました。ここで大変お世話になったのがsandbox環境。HRMOSではAWSサービスを自由に使える環境が用意されているため(SREのみなさんありがとうございます!)、ログ基盤を試験的に作成しては壊して、を繰り返すことができました。

> 理想の構成について適宜相談、勉強になりすぎる会話

なんせ初めは分からないことだらけだったので、「とにかく小さく作ってみる」という姿勢で進めました。まずはサンプルログを流すために、Akka HTTP(RubyのSinatraのようなイメージ)で簡易サーバを用意。そしてDockerから出力されたログをCloud Watch Logsに送ってみる、Kinesis Data Firehoseにデータを流すとどんな感じなのか見てみる・・・というように、小さく試しては改善を繰り返しました。その結果、以下のような構成が良いだろうという結論になりました。

理想の構成図

ECS のDockerコンテナから出力されたログは、task definitionの設定によって CloudWatchLogs にログを流し込むことができます。そして、ストリーミングデータを提供するフルマネージド型サービスである Kinesis Data Firehose にログを集約。fluentdのaggregatorで行っていたログの集約は、ここで肩代わりされます。その後、図の通り S3→Lambda→S3 を通り、後半では拡張性を高めるファンアウトパターンにするために SNS を経由。最後に Lambda でS3からログデータを取得し解凍、Elasticsearchやslackに送り、開発者がログを確認できるしくみです。

このログ基盤になると何が嬉しいかというと、まずはやはりフルマネージドなので管理コストが下がること。私の大好きなSREチームの方々が笑顔になってくれるなら・・・やるしかないですね。SREチームドリブン&ロマンドリブン!

実際に新しいログ基盤を作成

さて、理想の構成が決まったので、あとは実際に各環境でピタゴラスイッチログ基盤を作成していきました。我々はアプリケーション開発が主業務のため、お互いの業務の合間をぬってペアプロを中心に進めました。

そしてここからは、効率的に作業を進めるために以下のような戦略に切り替えました。

戦略

ここまではsandbox環境だったこともありAWSコンソール上でまごころをこめて一つ一つリソースを作成(調査中はすぐ壊したり修正できたりしたので良かった)していましたが、AWS CLI・Terraformを駆使して進めることにしました。

AWS CLIで環境構築

まず、各リソースにおける細かい設定を見直しながら、AWS CLIを利用してsandbox環境にリソースを作成。GUIでの作業だと作業ログを残すことが難しいですが、 AWS CLIコマンドを打ってインプットとアウトプットを記録 しておくことで、後のTerraformのコーディングに役立てようと考えました。

AWS CLIコマンド例

$ aws s3api create-bucket --bucket pitagora-bucket --region ap-northeast-1
{ "Location": "/pitagora-bucket" }

ピタゴラスイッチの過程で、どうしてもロジックを挟む必要がある部分はlambdaで処理をしました。Kinesis Data Firehoseから配信されたJsonが複数個連結されていたためそのままパースできず、その処理は結構苦しみました。ですが、大魔王先輩の大いなる問題解決力のおかげでクリアでき、コトの発端から一ヶ月もしないうちに、sandbox環境にログ基盤を完成させることができました。

Terraformで検証環境に再現

HRMOSではインフラの環境構築にTerraformを利用しています。インフラ環境のバージョン管理ができ、同じ環境を何度でも再現できるのでとても便利です。 今回のログ基盤の旅でも検証環境においてはTerraformを利用しました。実際に先ほどの作業ログを参考にしてコーディングを進め、スムーズにログ基盤の再現をすることができました。

Terraformソースコード例

resource "aws_s3_bucket" "pitagora-bucket" {
  bucket = "pitagora-bucket"
  acl    = "private"
  region = "ap-northeast-1"
}

[余談]楽しくデバッグできるコマンド作成

また、「デバッグ時にAWSコンソールを歩き回って疲れちゃう」件、シェルを書いて解決しました。AWS CLIの出力結果をいい感じに加工するシェルスクリプトです。(大魔王先輩からの無茶振りでしたが、シェル初心者につき基本から教えてくださいました・・・。シェル最高。)例えば今回だと、Cloud Watch LogsやS3に期待したデータが存在するか確認するようなコマンドを作成。AWSコンソール上を歩き回る工数を減らし、作成したリソースの稼働確認作業を楽しくできるようにしました。

自作コマンド

それからはすっかりシェルのトリコになり、日々のノンコア作業を見つけてはシェルを書いて生産性をあげることが趣味になりました。インフラ(に限らずだと思いますが)エンジニアの当たり前の思考回路を身につけられた良い機会になりました。

HRMOSのアプリケーションログを新しいログ基盤に・・・!

無事に検証環境にログ基盤が作成できたので、最後にHRMOSのログ出力先をfluentdからCloud Watch Logsに切り替えることで、新しいログ基盤に流し込むという作業に着手しました。実はこちらは第二回SRE合宿(後日記事になりますので乞うご期待)に参加させていただき、開発者が検証環境を利用していない休日中にデプロイすることで動作確認をしました。

初日、まずはリスクの少ないカナリア環境(こちらもSREの方々、素晴らしい環境を用意してくださりありがとうございます!本当にすごい。)にデプロイして問題が起きないかを確認。その後、検証環境にデプロイしました。しかし、こちらはなかなか最後までログが流れず苦戦しました・・・。

ログがこない!ピタゴラスイッチのどこかに問題がある!となった時に、問題の切り分けが必要になってきますが、ピタゴラスイッチが長いほど原因の特定が大変なんですね・・・。事前に先人の経験談を耳に挟んでおり出来るだけシンプルにはしていましたが、ピタゴラスイッチはなるべく短く構成することが肝ということを改めて実感しました。

最終的に、HRMOSのログをElasticSearchまで到達させることはできたのですが、一定の確率でログが一部欠損してしまうという課題が残りました。調査をした結果以下のような結果が得られました。

  • Cloud Watch Logsにはすべてのデータが流れている
  • S3バケットをみると一部欠損していることがある

→ Kinesis Data Firehoseのバッファサイズとバッファ間隔の指定が適切でないと予想

調査結果元に、 Kinesis Data Firehoseの設定 を見直して後日デプロイリベンジをしようと思っています。(合宿で完成できず本当に悔しい・・・まだまだインフラ修行が必要でした。)

検証環境で安定運用が確認できたら、Terraformによって本番環境に全く同じ環境を再現し、晴れて憧れのサーバーレスログ基盤本番運用にたどり着けます。今回のSRE合宿では悔しい思いをしましたが、改めてインフラを支える難しさや、その面白さを実感することが出来ました。

これからのログ基盤

ログ基盤自体は形になりましたが、開発者・ユーザーに幸せを運べるようになるまでもう少しクリアすべき課題が残っています。

  • 安定性の確保・保証
    • 100%ログを落とさずにすばやく運べていること、またその安定状態を常に確認できること
  • 現在のログ基盤との共存
    • 初めは安全のために共存して運用できること

そして、なんといってもその先にはさらなる野望があります。この拡張性の高い新しい基盤の上で、さらなる挑戦がしたいです。

ビッククエリ

ログはユーザーの行動や気持ちを表してくれます。それによって、私たち開発者は次の機能開発・改善を決めることができます。すなわち、ログはユーザーとプロダクトを繋ぐ架け橋。そんなログを目一杯活用して、ユーザーへの価値提供の最大化を図りたいと思っています。具体的にはGCPの BigQueryBigQueryML を上手く利用して、面白いことをしたいなと目論んでいます。 (絶賛インプット中。何かアドバイスがあればご教授いただきたい・・・!)

まとめ

今回アプリケーションエンジニア二人で進めたこのプロジェクト。自分たちにとって全く新しい挑戦でしたが、HRMOSの基盤に深く潜ることで新しい発見がたくさんあり、インフラの面白さ・辛み、どちらも体感することができました。開発者とユーザーに幸せを運べるフェーズにいけるまで、引き続きログ基盤の挑戦を続けようと思います。(続編が書けるように頑張ります。)

また、課題解決に繋がることであれば「やってみたい!」と思ったことをメンバーと挑戦してみることは、組織全体としてもとても意味があることだと思っています。先輩方のスキルを盗んで、普段の業務に活かすことができますし、自分の興味の幅が自然と広がります。「やってみたい!」を聞いてくれるところがBizreachプロダクト組織のとても良いところ。そんな環境を駆使して、まだまだいろんな分野で修行を積み、ログ基盤プロジェクトで組織に貢献できるよう引き続きロマンドリブンで精進して参ります!最後まで読んでいただきありがとうございました。

記事に登場する人のコメント:

大魔王先輩: 最初はエンジニアの先輩として、先導をしようというマインドでしたが、気づいたら澤さんがTerraformに詳しくなっていたりシェル芸人化してしまっていたり、負けるものか!と追いかけたり追いこされたり姿が、SREの方から「歯車が噛み合っていないようで噛み合っているコンビだ」と言う表現を頂いて非常に嬉しかったです。成長し続ける若い姿を見て刺激を受けないエンジニアはいないでしょう。