こんにちは!SUZURI事業部エンジニアのyukunです。
SUZURIでは1年前からRails アプリケーションに機能フラグサービスのUnleashを導入して活用しています。今までに30回以上のリリースやオペレーションに機能フラグを使ってきました。 そこで、この記事では私たちのサービスでの活用事例と共にUnleashの機能の一部を紹介します。
Unleashについて
Unleashはオープンソースで開発されている機能フラグ(Feature Flag)サービスです。コードの中にフラグを実装しておくと、そのフラグを外部のWeb管理画面から有効、無効に切り替えることができます。 機能フラグを使うことで新機能を任意のタイミングでリリースしたり、問題が起きた時に直ぐその機能を無効にできるので、コード変更による障害を最小限に留めて迅速にリリースサイクルを回すことができます。
Unleashと制御対象のアプリケーションはAPIで通信していますが、さまざまな言語向けにSDKが用意されているため導入は容易です。SUZURIではRailsにRuby SDKのGemをインストールして使っています。
Railsの場合、Unleash Clientをinitializersで設定しておくことで、Model, View, Controllerといった多くの箇所で次のように呼び出すことができます。このコードではUnleashに設定した NewFeature
というフラグが有効の時に条件式がtrue
になります。このようにフラグで制御したい箇所に実装を行います。@unleash_context
については御述します。
if UNLEASH.is_enabled? "NewFeature", @unleash_context
puts "Flagが有効の時に実行される処理"
end
参考: Ruby | Unleash
ペパボではいまのところ、無料のOSSプランを使用しています。これは社内の共通基盤としてセルフホストしているものです。いっぽうで、Unleashには、このほかにも、より高機能かつマネージドに提供されるProプランや、Enterpriseプランといった上位プランもあります。
機能と活用事例
それでは実際に活用している場面と機能を紹介します。
Releaseフラグとして
私たちのチームでは機能ごとにmainブランチから機能ブランチを切って、レビュー後にマージするといったGitHub Flowで開発をしています。Git-flowに比べてブランチ構造やリリースがシンプルで現在のチームにも合っていますが、大きな機能を開発する時には、PRが大きくなってしまったり、リリース日までマージできないといった状況が発生していました。 そこで新機能の箇所にフラグを実装することで、機能の一部を開発したブランチをmainにマージしやすくなりました。 もちろん本番環境にデプロイしてもUnleashで制御されているので、その機能は有効になりません。
Kill Switchとして
多くのWebアプリケーションでは外部の決済サービスや連携APIを使っているかと思います。 そして外部サービスに障害が起きたり、メンテナンス時に、Webアプリケーションが障害や不具合に巻き込まれる場合があります。 こうした機能にUnleashで無効にするフラグを実装しておけば、問題が起きた時に直ぐにメンテナンスモードに切り替えることができるのでユーザへの悪影響を少なくできます。
また、実施時間が決まっている予定メンテナンスの場合でも、コードに変更を加えずにフラグの切り替えだけで済むので運用が楽になります。 さらに、重い処理にもBusyModeのようなフラグを実装しておくと、アクセス集中時に高負荷になった時に直ぐにその機能を無効にできるのでインシデント時の対応が早く出来るようになりました。
Activation Strategiesの活用
Unleashのフラグは有効/無効の2択ではなく、さらに細かく有効の状態を制御できます。 例えばWebアプリケーション上のユーザIDやユーザ名、ユーザのIPアドレスなどで有効にする対象を絞り込むことができるのです。
中でもこのユーザ識別情報を元に、パーセント指定で有効状態を指定できる段階的ロールアウト(Gradual rollout)という機能が便利です。 パフォーマンスに悪影響を与えそうな新機能を問題がないことを確認しながら少しずつ有効の割合を上げていくカナリアリリースという方法がUnleashを使うと簡単に行うことができます。
また、SUZURIでは動的画像合成サーバを運用しており、そこへリクエストする画像サイズを上げるという仕様変更がありました。その際に、段階的リリースを行うことで一気に仕様変更を反映せずに、少しずつ新しい画像サイズのリクエストをしそれらをCDNにキャッシュさせることで画像合成サーバの負荷を抑えながら仕様変更をすることができました。
この機能を使うためにはいくつかのユーザ情報をUnleashに送る必要があり、その情報をcontextというプロパティでフラグを呼び出す際にUnleash Clientに渡す必要があります。この実装がうまくいっていないと、Activation Strategiesを設定しても無効状態のままになってしまいます。これについては次に説明します。
ContextとCustom Propertiesの活用
Unleash Clientに渡すcontextプロパティの変数は多くの箇所から使いたいため、Railsの場合ApplicationController
のbefore_action
でセットするようにしています。簡易的なコードを以下に示します。
remote_address
やuser_id
, user_name
はデフォルトでUnleashが対応しているcontextの情報ですが、properties
には任意でカスタム情報を追加できます。
参考: Strategy Constraints | Unleash
class ApplicationController < ActionController::Base
before_action :set_unleash_context
def set_unleash_context
@unleash_context =
Unleash::Context.new(
remote_address: request.remote_ip,
user_id: current_user&.id,
user_name: current_user&.name,
properties: { user_role: current_user&.role } # Unleashに送りたいカスタム情報を追加する
)
end
end
このカスタムプロパティがとても便利な機能で、私たちは管理者やカスタマーサポートなどが判別できるユーザの権限情報をセットしています。
そしてUnleashから管理者だけや一部のユーザロールだけに、フラグを有効にして検証し、その後に全ユーザに公開するというようなリリースフローを簡単に行えます。 また、段階的リリースの際の際に管理者は有効な割合に関わらず全員有効にするといった複合的な条件を設定することもできます。
ちなみに、こうした本番環境で開発者やテストユーザだけに機能を有効にして試すことをダークカナリアリリースと呼ぶそうです。
おまけ: Slack連携
Unleashのフラグ変更は本番環境の挙動に影響を与えるものなので、一人で行う際にもチームに共有しておくとより安心です。 そこで、UnleashのAddonにあるSlack連携を使うと、フラグ変更やその内容を特定のチャンネルに投稿することができます。 通知内容はいろいろ選べます。試したうえで、最終的にはフラグの有効/無効の2つだけを通知するようにしました。
他にもTeamsやWebhook、DatadogのAddonがあるようです。
終わりに
Unleashという機能フラグサービスの機能とその活用場面がお分かりいただけましたでしょうか?
最後に注意点ですが、機能フラグは実装と手間が少しだけ増えるので、全ての新機能リリースで活用しているわけではありません。本番環境でしか検証ができないときや、この記事で紹介したようなフラグを使うメリットがあるときにだけ活用しています。
また、フラグが増えすぎて有効にするフラグのセットや順序を考慮しないといけなくなるような共依存ができてしまうと思わぬインシデントにつながる可能性もあります。 使いすぎない、共依存しない、不要になったら直ぐに消す、ということを心掛けて運用しています。
他にも便利な機能がたくさんあるのでぜひ公式サイトもご覧ください!!