モノリシックなAPIでのカナリアリリース導入と開発者の認知負荷を減らすためConfigMapを使わない選択をした話

こんにちは、プラットフォームエンジニアリング部門コンテナ基盤グループの岡田です。

当社ではECサイトの裏側で利用されているモノリシックなAPIをコンテナ化し、Elastic Kubernetes Service (EKS) に移行しました。 移行直後は下記のようにトラブルに見舞われましたが、現状安定した運用ができています。

EKSコンテナ移行のトラブル事例:推測するな計測せよ -CoreDNS暴走編- - MonotaRO Tech Blog

EKSコンテナ移行のトラブル事例:FargateにおけるAZ間通信遅延の解消 - MonotaRO Tech Blog

今回はトラブル事例ではなく活用事例になりますが、アプリケーションリリース起因でのトラブル影響を減らすため、コンテナ化したAPIに対してカナリアリリース導入を行いました。そのため、導入に際して生じたConfigやSecret周りの課題とちょっとした工夫及び導入して良かった点についてお話しします。

カナリアリリースに関して、当社では以下のように基本的にArgoCDを用いてKubernetesクラスタへのデプロイを行っている事もあり、Argo Rolloutsを利用して実現しました。

大規模アプリケーション開発運用をマルチテナント方式のGKEクラスタで実現した話 - MonotaRO Tech Blog

Argo Rolloutsについての説明は多くの記事が出ているため、こちらでは割愛させていただきます。

直面した課題

今回対象とするAPIはモノリシックで100本以上のエンドポイントがあり、アプリケーションのConfigはKubernetesのConfigMapを、アプリ用のクレデンシャルはSecretをPodに注入して使う一般的な構成でした。カナリアリリースに関してはエンドポイント毎に流量にばらつきがあるため、2時間程度カナリアで様子を見て自動で展開させる運用を想定していました。

しかし、以下のようにリリース周りでいくつか課題が出てきました。

1.業務や技術に対する理解のばらつき

今回対象とするAPIは様々なチームが機能開発で改修しており、協力会社の方を含め数十人規模のメンバーが触るものです。関わっているプロジェクトや案件によって各チームの開発頻度にはばらつきがあり、業務知識の習得も必要になることからこのAPIの開発プロセスに慣れていないメンバーもいます。さらに当社では全社的なKubernetesへの移行も始まったばかりであるため、開発者はKubernetesにまだ慣れていない状態でした。

2.肥大化したConfigと修正頻度

今回対象とするAPIのConfigは開発ステージング本番用だけでなく社内システム用など検証用の環境以外にも複数存在しており、環境によってリリースタイミングが異なるものもありました。そして、Configは歴史的な経緯により数百行程度の環境設定が存在しているため、機能開発案件やシステムリプレース案件に伴う変更頻度もそれなりに高いという状態でした。

3.Config変更を伴うアプリケーションのリリースフローが複雑

今回対象とするAPIではアプリケーションとマニフェストのリポジトリが分かれており、Config値の修正を伴うようなリリースをする場合はインフラ側でKubernetesのConfigMapを修正し適用 -> アプリケーションをリリースというように順序関係を意識してリリースする必要があります。

また、このAPIに関してはプルリクエスト数がそれなりに多く、休前日を除き毎日リリースが行われています。そのため、リリース作業は自動化され特定時刻に定期実行されています。これによりKubernetesマニフェストのConfigMapやSecretの適用タイミングと自動アプリケーションリリースのスケジュールを意識する必要があるため、開発者にとっては認知負荷が高く障害の原因にもなります。

図.アプリリリース時までのConfig追加漏れでトラブルのケース

さらにConfigMap、Secretは同じKubernetesリソースを注入する構成になっており、安定版もカナリア版も同じ値を参照することになります。そのため、この状態でカナリアリリースを導入した場合、Configの値を削除すると実は安定版のPodからの参照が残っておりアプリケーションエラーが起こるなど依存関係が複雑になり障害が起こりやすくなることが考えられました。

図.Config削除でトラブルが起こるケース

解決策とその結果

これらの課題を解消するために、以下を実施しました。

1.ConfigMapを使わない。

Configとアプリの互換性解消のため、KubernetesのConfigMapリソースは使用せず、Configファイルをアプリ側のリポジトリにもたせてイメージ内に入れ、環境変数で参照するConfigファイルを変えられるようにしました。

- name: CONFIG_YAML_PATH
  value: "/app/config/stg/XXX-config.yaml"

これにより開発者はアプリとconfigの互換性を意識せず、自動化されたアプリケーションのリリースフローでconfigの修正とカナリアリリースができるようになり、Config値変更によるリスクを低減できました。

図.Configをイメージ内で持つ図

(今回は自動リリースされている事やアプリと組織の特性上configMapGeneratorもしくは同等の仕組みを利用しませんでしたが、マイクロサービスに分割されており、Kubernetesに関する習熟度が高いメンバーのみで開発しているような環境であれば十分リスクを低減できると思います。)

2.Secretはimmutableにする。

Secret変更時に関しては変更のたびにKubernetesのSecretリソース自体を新規作成する事でSecret変更もカナリアリリースされるようにしました。

以下のようにKubernetesのリソース名にversionのsuffixをつけて実現しています。(Helmでの例)

Deployment
- name: XXX-secret
  secret:
    secretName: XXX-secret-{{ $.Values.secret.version | trunc 8 }}

(前提としてArgo Rolloutsを利用した場合、Deploymentの変更全てがカナリアになるため一部のPodのみに新しい設定が反映されるようになります。そのため上記のようにDeploymentの設定でPodに注入するSecretリソースを変更するとカナリア用の一部のPodのみ新しいSecretを参照するようになります。)

また、古いSecretについてはStable版のPodが参照するため消さないようにしています。 古くて不要なSecretリソースが残ってしまうデメリットはありますが、動作中のPodと新たに作成するカナリア版Podが参照するリソースを分け、Secret変更による影響範囲を新しいPodのみに限定しました。

図.Secret変更時は毎回新規作成し、トラブルを軽減

これにより、Secretが更新できていない状態でアプリケーションリリースが行われたり、安定版のPodから参照されているSecretの値に意図せぬ変更が入ってしまうことでアプリケーションエラーが発生してしまうリスクを低減できました。

その他よかった点

カナリアリリース導入により影響範囲を絞った状態でエラーに気づけるようになりました。また、Argo Rolloutsでcanary用のラベルを付与することで、Datadog APMにてカナリア中にパフォーマンスを確認できるようにもなりました。一部のチームでは大きめの改修の際に実際に活用していただけました。

図.Slackでの会話抜粋

またArgo RolloutsではPythonのバージョンアップやサイドカーの更新でも活用できました。

副次的にですが運用に関してもよかった点がありました。

弊社はメインの顧客層がB2Bのため、トラフィックが業務時間内に偏っています。そのため、定時付近にリリースしてエラーがあれば戻すといった運用になっていましたが、カナリアリリースで影響範囲を減らした状態であれば定時内リリースしやすいため、定時後に本APIのリリース関連トラブルが発生して担当者が残業するといったケースも減らせました。

課題と心残り

今回はArgo Rolloutsを使ったカナリアリリースの導入、ConfigとSecretの管理方法の改善を行いました。これによりConfig/Secret周辺のトラブルやアプリケーションエラーが起こった場合の影響範囲を抑えることができました。また、開発者の視点からもリリースプロセスがシンプルになりました。(当初は考えられていませんでしたが、そのまま肥大化したConfigmapを利用していたらローカル開発環境周りも大変になりそうでした。)

一方で不要なリソースが残ってしまうことや新しいConfigファイル作成のために、イメージを作り直す必要があるケースもあることなどがデメリットとして挙げられます。

また、当社では以下記事で紹介されているようにアプリケーションをSLOベースでシステムを運用しているため、エラーバジェットの消費度合いによって自動的にロールバックさせていくなどの活用を検討していました。しかし、現状ではArgo Rollouts単体ではCloud LoggingやCloud Monitoringとの連携ができず未実現のままです。今後はこうしたモニタリング周りの改善にも取り組んでいきたいと考えています。

SRE導入: システムを安定させる4000万円の魔法の壺 - MonotaRO Tech Blog

最後に

私たちは現在、複数のアプリケーションのコンテナ化及びマイクロサービス化などを通じてシステムのモダナイゼーションを進めています。特にコンテナ基盤グループではKubernetesへの移行やKubernetes周りのエコシステムを利用した高効率な運用を目指して日々奮闘中なので、これらの取り組みに興味がある方はぜひカジュアル面談にお越しください!

ソフトウェアエンジニア (コンテナ基盤) | 株式会社MonotaRO