見出し画像

REALITYのインフラをIaC化した話

みなさんこんにちは!
REALITYのサーバーチームでエンジニアをしているのぶつねです。新卒で入社からもうすぐ一年経とうとしており、流れる月日の長さがあっという間に感じます。もうすぐ新しい新入社員の方々も入ってくるので2年目としても頑張っていきたいです!

REALITYのインフラについて

さて早速ですが、REALITYではGCP上にインフラを構築しており、さまざまなサービスを用いてアプリが動作しています。各サービスの構築や、スペック調整などはGCPのコンソール上で任意に設定していました。
このような調整でも運用上問題なかったのですが、時折以下のような事象が発生しました。

  • ここのスペックってなんでこの値になっているんだっけ?

  • キャンペーンの負荷に備えたいけど以前のDBスペックってどのくらいに設定してたっけ?

  • なんでこのIPからのアクセスがCloud Armorで許可されているんだっけ?(当時は理由があったはず)

これはなんでこの設定値なのだ?

など、コンソール上で設定できることは直感的に操作でき、ログインさえできれば誰でも操作が可能という便利な反面、誰がどの意図でその設定にしたのかなどの、過去の作業履歴が残らないのがネックとなってしまい、都度有識者に相談という手間が発生していました。
また、コンソール上の作業はどうしてもオペレーターの手作業になるので、誤った設定・人為的ミスなどが発生する可能性が存在します。

そこで去年あたりからREALITYのインフラをIaCで管理しようの動きが始まり、自分もサーバーのキャッチアップ・勉強の一貫として参加しました!

そもそもIaCとは?

そもそもIaC(Infrastructure as Code)とは、字の通りでインフラの構築をコードのように扱うことです。つまりコンソール上で行っていた設定を他のプログラミング言語のようにコードで扱うことを指します。
具体的にはREALTIYではIaCのツールとしてTerraformコードの管理はGithubで行いました。
Terraformの採用背景としては、IaC導入時は PulumiCDK for Terraform
なども候補に上がっていましが、利用例の多さや学習・維持コストの観点で最終的に terraform を採用しました。

対応内容

自分はGCPのサービスであるMemorystore for RedisとCloud Armorの作業を担当しました。REALITYではRedisをキャッシュサーバー・イベント等のランキングのDBとして活用しています。また、Cloud Armorの方は開発環境へのアクセス制限や本番環境でのセキュリティ目的のために活用しています。
今回は一番初めに着手したRedisの対応について話したいと思います。

Memorystore for Redis

Docはこちら
こちらは上記記述のように複数の用途で用いており、設定項目がまちまちになっています。

キャッシュサーバーとして利用しているRedisインスタンスは、同スペックのインスタンスを複数立てており、データを分散させて保存する構成となっているため、以下のように愚直に設定値をコードに記述していくと、スペック調整・設定値の変更をするたびに同様の変更を各フィールドに加えていく必要があります。

例えばtierを変更しようとするとこの場合10, 17, 24行目全てに同じ値を編集する必要があります

これだとせっかくIaC化してコード管理したのに、修正漏れや手間が発生してまいます。コード化の恩恵を最大限使いきれていないです。(余談としてGithub CopilotでRedisのテンプレートを作ってもらったのですが、めっちゃ便利ですね)

このように同等の設定データを扱う場合はTerraformのmodule化を利用すると良さそうです。module化とは複数のリソースをまとめることを指し、この場合、Redisの設定をうまく抽象化し、設定データを使い回すことで、同等の変更を複数加えることなく、設定が行えるようになります。
具体的には以下のようになります。

moduleの定義
module導入前後のbefore/after

コードの説明を簡単にすると一枚目の画像でmoduleを定義しています。
suffix_listで各redisインスタンスのsuffixのリストを格納し、そのリストをfor_eachで回すことでリストのValueを受けれることができます。
クラウド上には全て同設定値、nameのみsuffixが異なるような構成だったのでredis_1~3のインスタンスの設定を行えるようになりました。

この結果、2枚目の画像のようにインスタンスを3つのブロックを構成するのに対して、リソースを使い回し1ブロックで定義することができました。

このように構築することで、例えばインスタンスを1台増やしたい場合はsuffix_listに"4"を追加するとredis_4のような名前のインスタンスが立ち上がるようになったり、35行目のmemory_size_gbを1 => 3への変更を適応させるとredis1~3全てのインスタンスに対してmemory_size_gbが3に設定されます。

困ったとこと・大変だったこと

上記のコードはサンプルとして用意したもので、実際にはもっと設定のフィールドは多かったです。その中でも今後運用上で触ることがなさそうな静的なフィールドはmodule定義時点で静的に設定したり、動的に変更する可能性があるようなフィールドはmoduleの変数として定義して外から変更できるようにしたりなど、各フィールドがどのような設定なのかを全て網羅的に把握するのが大変でした。(コンソール上からどの設定がどの変数に対応しているかなどはなかなかリファレンスもなく、苦労しました。)

また、Cloud Armorの方ではこちらのIssueでも挙げられているように設定値の差分が永遠に出続けてしまうような不具合に直面し解決が大変でした。

最後に

そもそもIaCとは何?って状態からジョインして対応をしていたので、Terraform固有の文法だったり、サーバーの設定値だったりのキャッチアップがかなり大変でした。
しかし、インフラをIaCで管理することで作業をGithubで履歴として扱えたり、レビューをしてもらうことによって限りなくミスを減らせるような体制になったので安心してインフラを触れるようになったと思います!
まだまだ、知らない部分だったり、新規で扱う技術分野だったりが多いと思いますが、2年目も精進していきたいと思います。
今後も新しく触ったことをブログに残していけたらなと思うのでよろしくお願いします!