見出し画像

Effective Deployment

こんにちは!SREの岩崎です。最近の趣味は採用活動です。今回はデプロイを改善した話について書きたいと思います。

サービスの成長とデプロイ速度

一般的にサービスが成長するにつれて関わる人間の数も増えていきます。人数が少ないうちは多少デプロイに時間がかかってもそれほど問題にならなかったものが、人数が増えてくれば致命的な問題になりかねません。

CAMPFIREも数ヶ月前まさにその状態でした。去年の8月にシステムをリプレイスした際の開発者は7人でしたが、今年の春には17人にまで膨れ上がっていました。この17人全員がフルタイムというわけではないのですが、アプリケーションに関わる人数増えるにつれてデプロイ問題が表面化していきました。

CAMPFIREのデプロイ方法

CAMPFIREのインフラはAWSを利用しており、本番サーバはECSで運用しています。デプロイはCIからDockerイメージをビルドしてプッシュ、ECSへローリングデプロイを行うという構成になっています。CIから継続的にデプロイできること、コンテナ化されており堅牢なシステムになっている点は良いのですが、その反面CIで色々やりすぎていてデプロイに時間がかかるという問題がありました。

また、デプロイフローとして前段にstaging環境が存在しており、デプロイ時は最初にstaging環境にデプロイしてからproduciton環境にデプロイするという流れになっています。これはどのサービスでも同じだと思うのですが、上記のようにCIに時間がかかっているため、staging→productionと時間がかかる作業が二度繰り返される問題がありました。さらに当時のstaging環境ではテストも走っており、このテストにもかなり時間がかかるという問題がありました。

デプロイ改善

当初はstagingのデプロイに約30分、productionのデプロイにも約30分かかっており合計約1時間のデプロイ時間となっていましたが、以下のような施策を行うことで結果的にデプロイ時間を半分以下にすることができました。

・ECSの最小ヘルス率を調整

ECSには最小ヘルス率というパラメーターがあり、デプロイ時に何台残した状態にするかを設定することができます。例えば、CAMPFIREの場合平常時のEC2の数は5台なので、最小ヘルス率が80だと常に4台は残して一台ずつロードバランサーから外してデプロイするという挙動になります。ここを80から60に下げることで一度にデプロイ可能な台数を増やしました。

また、この時に単純に数値を下げるだけだとデプロイ時の負荷が上がってしまうため、合わせてキャッシュ化するなど少ない数のインスタンスでも処理が重くならないようにしました。

・スタンバイインスタンスを追加

元々の構成だとバックエンドのEC2 * 5台に対して5つのタスクを立ち上げていましたが、EC2のみ6台に増やしました。これによりリソースに余裕ができ、一度にデプロイ可能な台数を増やすことができました。

一見このスタンバイインスタンスはデプロイ時にしか役に立たないように見えますが、CAMPFIREではバッチ処理も同じEC2のリソースで行なっているため十分合理性があります。

・テストの並列化

CircleCIでは以下のように parallelism を指定できるため、これを使って処理を並列化しました。また、時間がかかるシステムスペックは別jobとして切り出しました。

test:
  <<: *test_config

  parallelism: 2

  steps:
    - checkout

・sasscの導入

sass-rails からsassc-rails に置き換えることでデプロイ時のコンパイルを高速化しました。結構速くなりました。

・運用ルールを整備

実はこれが一番書きたかったことなのですが、運用ルールを整備することで大幅にデプロイを楽にすることができました。具体的にはチームで話し合って以下のようなルールを決めました。

- デプロイがぶつからないようにデプロイ時はSlackで声を掛け合う

人数が増えたことでデプロイが頻繁にぶつかるようになり、場合によっては重要なデプロイが後回しになっていたため、より積極的に声を掛け合うようにしました。コミュニケーションが活発になったことで、まとめてデプロイできるものはまとめてデプロイする、影響がありそうな変更はお互いに連絡しあうなどの文化が生まれました。

- productionブランチをマージできる人数を増やした

これまで限られた人間しかproductionへのリリース権限がなかったのですが、リリースできる人間を大幅に増やしました。これにより特定の人間がボトルネックになることがなくなりデプロイがスムーズになりました。

- テストは基本的にトピックブランチのみ必須とし、事前にテストが通っていればデプロイ時はテストを通さなくてもOKとした

最終的にstagingデプロイ時のテストを必須から外しました。理由は、masterブランチにマージする際にテストは通っているはずなので、デプロイ時に二重にテストをする必要性は低いと考えたからです。もちろん、ケースによってはその限りではありません。SREは可用性100%を目指す活動ではないので、このようにバランスを見てチャレンジする選択肢は常にあり得ます。

私は何回もテストをするのは、ある意味でチームメンバーを信用していないからだと思います。手元でテストが通っていることが信用できないので、デプロイフローに組み込む形で強制的に信頼性を担保する。人を信頼せず、自動化で解決するのはエンジニアとして正しい姿勢ですが、お互いを信頼できる最強のチームが行う「運用」が「仕組み」を上回ることもあります。

DevOpsというと継続的デプロイなど技術的な側面が話題になることが多いですが、同様に良い組織であることも大切です。Effective DevOpsを読むとそれがよくわかります。

システムにはそれを生み出した組織の構造が反映されるというのがコンウェイの法則ですが、ちょっと拡大して解釈すれば、良い組織が生み出すシステムが最強といえるかもしれません。

最後に

このようなデプロイ改善が実り、CAMPFIREの先月のデプロイ数は過去最高になりました。同時にデプロイ時間も過去最速となっています。また、素晴らしいことにエラー数も過去最小に近い数値でした。

しかし、これ以上人数が増えればデプロイ改善だけでは限界があります。マイクロサービス化など別の施策が必要になるでしょう。実は今そちらも行なっているところです。

CAMPFIREでは現在私たちと一緒に働いてくれるSREを募集中です!興味を持たれた方はお気軽にご連絡ください。




この記事が気に入ったらサポートをしてみませんか?