Ep2: 継続的デリバリー - Feature flags, コード変更をデプロイ可能にするもう一つの方法
前のエピソードでは、継続デリバリーの文脈でデプロイ可能とはどういうことかを説明しました:
ただ、コード変更をデプロイ可能にする方法にはほかのやり方があります。Feature flags と呼ばれる優れたテクニックについてお話ししましょう。
アクティベーションなしに新しいコードをデプロイ
多くの人は、コードをデプロイすることと、新しい機能のリリースや振る舞いの変更を同じものと考えてしまいがちです。しかし、デプロイと有効化は同時に起こる必要はありません。以下の様なFeature flags を使うことで、新しいコードをアクティベーションなしにデプロイすることができます:
function main() {
const featureFlags = fetchFeatureFlags();
...
if (featureFlags.enableCoolFeature) {
executeCoolFeature(); // The new code
}
...
}
Feature flag はアプリケーションの実行環境で利用可能な小さい設定です。典型的には上のコードの様に動的に注入されるので、Feature flag の値を変更するのにコードをデプロイする必要がありません。上の様なflag は通常 false がデフォルト値になるので、Feature flag の値を変更するまでは新しいコードは実行されることがないので、このコードは生まれつきデプロイ可能です!
Feature flags はデプロイとリリースを隔離する
運用という観点で、Feature flag はたくさんの利点をもたらしてくれます。いつ新しい機能を有効化するかはデプロイせずに制御できるので、デプロイ自体はリグレッションに耐性があります。どのデプロイも新しい振る舞いを持ち込まないので、理想的にはデプロイ前のコードと同一です。
これは継続的デプロイ、通称(もう一つの)CD を簡単にして、ロールバックがめったに必要なくなります。これは、大規模なコードのアプリケーションにおいては、あなたのコード変更が他のチームの変更とともに、高い確率で問題なく本番環境にデプロイされることを意味します。Feature flags 無しだと、他のチームによって持ち込まれたバグによってあなたの変更が一緒にロールバックされたり、またはその反対が起こりえます。
対照的に、Feature flags は両チームがそれぞれの新しい機能を独立に有効化できるようにしてくれます。もしいずれかのチームが自分の新しい機能による問題に気づいた時には、簡単に自分たちの機能だけを排他的にロールバックすることができます。この隔離は特に大きい組織において非常に有効です。
新しい機能を徐々にリリースすることもできます。例えば、最初に1% のユーザだけ有効化してその挙動を計測することで、正しく動作しているかを検証できます。確認ができたら、100% になるまで毎日少しずつ割合を上げていくことができます。
しかし、Feature flags は銀の弾丸ではありません
CD という意味でFeature flags は完璧なものに見えますが、全ての変更をFeature flags の下でデプロイすることはできません。例えば、依存ライブラリのアップデートはFeature flags の下に隠すのは簡単ではありません。
Feature flags の他の欠点としては、複数のFeature flags の組み合わせがとんでもない数になってしまうことです。理論的には、どの組み合わせも実行時には異なる挙動をする可能性がありますが、全ての組み合わせを検証するのは大変困難です。そのため、既存のFeatuer flags の希少な組み合わせによって引き起こされる、テストでカバーできなかった不可解な挙動に遭遇する可能性があります。
そのため、どの機能をFeature flags の下に置くかは気をつけて選択する必要があり、さらにその利用状況を定期的に監視しておく必要があります。もし、あるFeature flag が長い間全てのユーザで有効化されているなら、そのFeature flag は消しても大丈夫ですし、合わせてもう使われていない古いコードも消すことができます。
最後に、たとえ新機能がFeature flag の下にあっても、インテグレーションテストなどで既知のリグレッションが起こらないことを検証する同じステップを実行する必要があります。例え呼び出さなくても、新しいライブラリを読み込むだけでアプリケーションの挙動が変わることはあります、例えば、関数呼び出しがなくても巨大なオブジェクトをメモリに読み込んでしまうかもしれません。
まとめ
Feature flags は新しいコードを即座にデプロイ可能にする強力なツールです。新しいコードは既存の挙動を変えることなくデプロイ可能で、その後Feature flag を切り替えることで有効化できます。これによって、複数チームの機能リリースを互いに隔離でき、不要なロールバックがめったに起こらなくなります。しかし、それは銀の弾丸ではなく、気をつけて使って、その利用状況を監視し、そしてインテグレーションテストの様な検証ステップは引き続き実行する必要があります。
English version