2025年のお仕事をまとめてみた。
プラットフォームの機能拡充
KEDA による外部メトリクスや時間帯のスケーリング
通知や集計といった重い処理を非同期ジョブで処理しているが、worker pod のスケーリングが難しいという課題があった。例えば、非同期ジョブがない場合は pod が暇になってしまうが、スパイクした場合は瞬く間に pod が足りなくなってしまう。通知や集計処理などの遅れはユーザー体験に直結するため、なるべく早く完了することが望ましい。非同期ジョブは主に SQS や Redis を経由して処理されている。これまで HPA から Datadog のメトリクスを参照するスケーリングが導入されていたが、どうしても数分の遅延が発生するという問題を抱えていた。
そこで、KEDA で SQS や Redis のメトリクスを直接参照するスケーリングを導入した。KEDA の導入は、非同期ジョブの課題を持っているサービスオーナーと Kubernetes のプラットフォームを提供している SRE で横断的なチームを作り、週2回30分枠のモブプロで進めた。非同期ジョブで要求されるユーザー体験によってスケーリングのパラメーターは異なる。例えば、多少レスポンスが悪くても問題ないジョブの場合は worker pod を0台までスケールインできる。しかし、スパイクに耐えられるようにするには min replicas を上げておくことが望ましい。そのような塩梅を判断するにはサービスオーナーの高い解像度が不可欠である。
また、ピークタイムに Pod を増やす仕組みを KEDA に移行した。これまでは GitHub Actions で HPA の min replicas にパッチを適用するという複雑な仕組みが導入されていたが、KEDA では時間帯と最低台数を宣言的に定義できるようになった。プラットフォームのセルフサービス化という意味でも大きな改善であった。
Self-hosted Renovate への移行とサービスオーナーによる分割統治
現職では大規模な monorepo を運用している。これまで Mend-hosted Renovate が導入されていたが、2025年の春ぐらいからリソース不足による失敗が目立つようになった。Renovate が途中で異常終了した場合、Renovate は PR を rebase するため、日中帯に GitHub Actions が詰まるという問題が常態化していた。この機会に GitHub Actions で Renovate を運用する構成に移行することにした。
移行にあたっては、以下のような課題も解決することを目指した。
- 長年に渡り、さまざまなサービスオーナーによって設定ファイルの継ぎ足しが繰り返されていた
- 横断的な設定とマイクロサービス固有の設定が複雑に入り組んでおり、最終的な結果を読み解くのが困難であった
- 歴史的経緯から Dependabot と Renovate が併用されていたが、一部は重複していた
まずは、一部のマイクロサービスだけ Renovate の設定ファイルを切り出して、Self-hosted Renovate の検証を進めた。Self-hosted Renovate が安定的に稼働するようになってからは、チームごとに設定ファイルの切り出しを進めた。人間が大量の設定を読み書きすると疲れてしまうので、claude-code-action を利用して設定を切り出した。Dependabot の設定はすべて Renovate に移行して、セキュリティに関する機能のみ利用する方針に転換した。
GPU 実行環境の整備
プロダクトでの AI 利用が広がり、ローカル GPU を利用したいユースケースが出てきた。これまで Kubernetes クラスターでは GPU を利用したことがなかったため、クラスターに nvidia-device-plugin を導入したり、GPU アプリケーション向けに NodePool を用意するといった対応を進めた。
claude-code-action を monorepo に導入する
現職では言語やフレームワークの多様性があるため、AI のコーディングエージェントが高い生産性を発揮するためには開発環境が重要となる。AI にまともな開発環境を与えないと、まるでメモ帳でコードを書いている現場のようになってしまう。claude-code-action の導入にあたっては以下のような工夫を施した。
- Issue や Pull Request のラベルから開発対象のサービスを判断し、必要な開発環境をセットアップする。例えば、Ruby のサービスが選択されている場合は setup-ruby を実行し、TypeScript のサービスが選択されている場合は setup-node を実行するといった感じである。これにより、AI が必要に応じて linter やテストなどを実行できるようになる。
- テストが通ることなどの受け入れ条件はサービスによって異なるため、サービスごとのディレクトリで AGENTS.md を整備している。
- Terraform のリポジトリでは、AI が terraform plan などを実行できるように実行環境を整備した。AI がクラウドを操作できるようになるため、実行可能なコマンドや読み取り可能なリソースを絞るといったガードレールが重要になる。
- Kubernetes のマニフェストを修正する場合は推奨ルールや受け入れ条件を明確にする。これはまだ改善の余地があると考えている。
指標による継続的な改善
Coverband による Ruby アプリケーションのカバレッジ可視化
現職では Coverband が導入されており、実行時のカバレッジ情報をもとにデッドコードを安全に削除できるようになっている。以下の課題があった。
- マイクロサービスごとに Coverband を設定していたため、誤って外部に公開してしまうとセキュリティ事故になるリスクがあった
- 複数のマイクロサービスで利用している内部 Gem のカバレッジを参照できない
このような課題の解決をモブプロで進めた。Coverband に詳しい同僚がリードを務めて、モブチームで交代でコードを書きながら探索を進めた。
まずは、カバレッジの記録と参照を分離した。具体的には、各マイクロサービスの Coverband でカバレッジを記録し、社内向けの Coverband でカバレッジを参照する構成に見直した。
また、Coverband で内部 Gem のカバレッジも取得できるように改善した。Coverband は Gem のカバレッジを除外する前提で設計されているため、やむを得ずモンキーパッチで内部 Gem も記録できるように対応した。
SLO による OOM killed イベントの継続的なモニタリング
Kubernetes クラスターを構成する重要なコンポーネントがメモリ不足で動かなくなり、本番サービスに影響するインシデントが発生した。再発防止として、重要なコンポーネントについては OOM killed のイベントを Datadog の time-slice SLO でモニタリングするようにした。これにより、例えば uptime が 99.9% を下回ったら memory request を増やすといったアクションを取りやすくなった。
一定のエラーを許容する場合、エラーをそのままアラート通知すると割れ窓になってしまうことが多い。そのような場合は SLO が向いているのではないかと考えている。
その他
- Pod 単位のインフラコストの可視化
- trace-workflows-action による GitHub Actions のリードタイムの可視化
プラットフォームの信頼性の改善やトイルの削減
Argo CD Application の削減による安定性改善
現職では、Pull Request ごとにマイクロサービス一式のプレビュー環境がデプロイされる仕組みを整備している。Pull Request で変更されていないマイクロサービスについては Service リソースを経由して別環境にリクエストがプロキシされるようになっている。これまでマイクロサービスごとに Argo CD Application を作成していたが、マイクロサービスの増加とともに Argo CD の負荷が問題となった。そこで、Service リソースを集約させることで Application を大きく削減した。
具体的には、App of Apps パターンの構成を以下のようにしている。
- Pull Request のプレビュー環境の Application
- Pull Request で変更されていないマイクロサービスの Service リソース
- Pull Request で変更されているマイクロサービスの Application
- マイクロサービスのリソース群 (Deployment など)
厳密には、Pull Request で変更されたマイクロサービスにリクエストを送信するマイクロサービスも Deployment などを配置している。例えば、サービス間通信が A→B→C の場合、Pull Request で C が変更された場合に前段からの通信を受け取るには A と B の Pod が必要になるためである。これについては今後改善の余地があるかもしれない。