Fujiwara Tech Conference 2025でfujiwara-wareやecspressoのCI/CDについて話しました&補足など

connpass.com

資料はこちらです。

紹介できなかったところや発表・懇親会中に質問があった内容について補足します。

fujiwara-wareへの貢献

以前にecspresso MeetUpでも紹介しているのでそちらもご確認ください。

speakerdeck.com

個人的に一番好きな貢献はdiffコマンドによるUnified Diff形式の出力で、v1の時はオプションですがv2からはデフォルトで有効にしてもらって自分を含め多くの人が使う機能を用意できたなと思ってます。

github.com

ステージング環境を停止・再開する部分について

再開する際になぜ scale --tasks=1 になってないのかという質問がありました。

これはリポジトリをマスターとして扱いためで、desiredCountも含めコード管理しています。単にdeployコマンドを実行することでdesiredCountが1でない場合や、その他の設定を変更したいときにマージ前のPR上で試してそのままずっと忘れてなんか設定が変だけど?みたいなことを防げます。

ecspressoリポジトリのディレクトリ名規則について

各ECSサービスをサービス名/コンポーネント名/環境名/ という単位で分けてディレクトリを作っています。これらのディレクトリの中でそれぞれecspressoのファイルがあるという感じです。

.
├── blog
│   ├── app
│   │   ├── base
│   │   ├── production
│   │   └── staging
│   └── proxy
│       └── production
└── bookmark
    └── app
        └── production

ここでいうサービス名はECSサービスではなく外部から見たサービスという意味で、コンポーネント名はそのサービスを構成するコンポーネントになっています。

環境名はそのまま本番かステージングかみたいな名前が入り、各環境で共通化したいファイルがあったらbaseディレクトリを別途作ってそれぞれでimportしています。

この命名規則にすることでリポジトリのルートを見るだけでどのサービスがあるかわかり、各サービスにどのコンポーネントがるかわかるようになるという感じです。

ちなみにこれらの名前はECSクラスタやECSサービス名と同じになっている必要はなく、リポジトリ上で管理しやすい名前にしています。

普段の開発の流れとデプロイ対象の特定をまとめるとこんな感じです。

  • アプリケーションリポジトリでmainを変更
    • blog/app/staging 以下のイメージタグファイルを更新&自動マージ
  • アプリケーションリポジトリでリリース作業を開始
    • blog/app/production 以下のイメージタグファイルを更新&手動マージ
  • blog/app/base を何か手動で変更
    • blog/app/stagingblog/app/production もデプロイ対象に

このルールを完全に真似する必要はないですが、何か命名規則を決めることで例えば staging のものだけを対象に実行するみたいなことを入れやすくなります。

jsonnetのimportのルールについて

jsonnetの共通化はいくらでもできてしまいますがこれもルールを設けています。

  • importは各コンポーネントのbaseディレクトリからのみして良い
    • 他の環境からimport禁止
    • 他のコンポーネントやサービスからimport禁止
  • ecspresso.jsonnet のみトップレベルからimportしても良い

例えば blog/proxy/production の設定は blog/proxy/staging からimportすることはしないし別のblog/app/production みたいな別コンポーネントからimportしないようにしています。

これはfluent-bitであったりx-rayであったりのサイドカーでも同様です。

現状はこれらサイドカーの変更頻度も低い他、コンテナ定義ごとにファイルを分けているのあってそこまで手間にはなっていないです。(タグなどの書き換えなどもエディタの検索で十分)

発表でもあったように、多少の手間を許容してとにかく「間違ってデプロイされてしまう/デプロイできてない」みたいな事故をとにかく防ぐ方針でやっています。

ただ今後OTel Collectorなどデフォルトで全サービスに入れたいみたいなことが発生した際に手間ではあるのでそこは課題の一つかなと思います。

解決策としてはトップレベルに common などのディレクトリを作って、そこからimportするみたいな感じになりそうですが、これもまた影響のあるサービスを検出する部分がさらに複雑になってしまうのでその処理も考慮する必要があります。

ecspresso.jsonnet のimport

これに関してはどのECSサービスも同じ設定でECSの設定にもほぼ影響しないのでimportしています。

{
  required_version: '= v' + importstr '.ecspresso-version',
  region: 'ap-northeast-1',
  service_definition: 'service-def.jsonnet',
  task_definition: 'task-def.jsonnet',
  timeout: '15m0s',
  plugins: [{
    name: 'cloudformation'
  }],
}

このファイルをecspresso用リポジトリのトップレベルなどに置いておき、各サービスから参照しています。

local base = import '../../../base-ecspresso.libsonnet';

base {
  cluster: 'blog',
  service: 'app',
}

ecspressoの各設定にはクラスタ名やサービス名を書くだけで済むようになり、他に追加したいものがあればそれだけ書けば良いようになって便利です。

その他感想など

スライドでも軽く話したけど、リリースのフローの作り込みは作り込みが激しいのとpush型が基本になっていて、この辺どうにかできればみたいなのをCNDWでも会話していました。PipeCDのLTを聞いてだいぶ良さそうだったので検討してみたいですね。