Closed19

Goで書いたAPIにOpenFeatureを入れたい

お窓お窓

まだフィーチャーフラグがなく、メンテナンス? ガハハ無言でコンテナシャットダウンだ、というフラグのフの字も無いGo net/http製のAPIに OpenFeature(Go Feature Flag)を導入して、簡単に設定を切り替えできる基盤を用意したいというスクラップです。

お窓お窓

元ネタは半年以上前にはてなブックマークで話題になっていたこの記事です。
今使っているAPIでは OpenAPI / OpenTelemtryを既に導入しているので、もっとOpenなものを入れて、色々楽に設定できるようにしようってのがモチベーションです。

https://future-architect.github.io/articles/20230621a/

お窓お窓

目標は WebUIから 特定のAPIを一瞬でメンテナンスモードと切り替えできるようにすること。(キルスイッチ的なもの)

不正アクセスされたら即死なので、WebUIを使うのは、直感的にセキュリティ上よろしくない気がしますが個人開発・ほぼ個人利用のAPIで使っているので別にいいかなと...

お窓お窓

フィーチャーフラグとは

機能の有効無効を切り替えするフラグ的なやつのこと。バグが見つかってヤバいとなったときに、サーバー自体を止めずに、フラグの変更だけで特定のエンドポイントを無効化するというのが主なユースケースだと思う。

OpenFeatureとは

フィーチャーフラグの標準規格、ベンダーに依存しないので、好きなベンダーを選んで、そこの値をフィーチャーフラグとして扱ったりできるらしい。

(下記から非常に大雑把に抜粋)

https://openfeature.dev/docs/reference/intro/

https://future-architect.github.io/articles/20230621a/

お窓お窓

フラグを受け取る側(client)に使うもの

github.com/thomaspoignant/go-feature-flag
https://gofeatureflag.org/
前例があることから、というよりたぶんこれ以外になさそう?

フラグを提供する側(provider)に使うもの

flagsmith
https://github.com/Flagsmith/flagsmith/

feature flag provider saasと検索して一番上でおすすめされていたもの。
コード内を openfeature と検索したところ go用のproviderライブラリが提供されていたので、使えそうと判断。SaaSでもオンプレでも行けるので、とりあえずこれを試す。

https://github.com/Flagsmith/flagsmith/blob/84d912d25ba924f22562245765bcad1316860a93/docs/docs/advanced-use/openfeature.md

お窓お窓

https://www.flagsmith.com/pricing

SaaSとしてのサイトを見ると無料プランがあったので無料枠を試そうと思う。
無料枠では 1ヶ月あたり 50000回という呼び出し回数制限があるので、
1日あたり 1612回 / 1時間あたり 67回 / 1分あたり1.7回 までのリクエストに制限する。

お窓お窓

FlagSmithのアカウントを作り チュートリアルにしたがってフラグを定義してみた。

どうやらFlagSmithのフラグは 特定の条件のユーザーにだけ 機能を提供する、のようなトラフィックのN%だけ有効にするみたいな カナリアリリース等のユースケースを想定していそう。今回はAPIサーバーの設定変更にだけ使うので、その機能は無視する。(どのみち無料枠では呼び出し回数枠を使い切ってしまう

お窓お窓

(本筋から脱線だが) 色々連携して、フラグの変更ログを送ったりできるらしい。Discordに送りたかったのだけど、このSlack連携はSlack認証だったためDiscordのSlack互換Webhookは使えなかった、残念。

お窓お窓

実装を始めようと思ったが用語に混乱したのでまとめる

OpenFeatureとは

前述の通り標準規格

GoFeatureFlagとは

OpenFeatureを実装するGoライブラリ。GoOpenFeatureでだけ使えるファイルフォーマット等のエコシステムがある。便利でこの仕様をGoだけに限定するのはクローズドだということで、GoFeatureFlag RelayProxyを経由して、色々な言語に対応するライブラリが派生している。(Goでの実装以外は、OpenFeature.dev で書かれている純粋なOpenFeatureの公式ライブラリとは別物になっている...)

GoFeatureFlagのドキュメントで言うProviders

単に提供しているSDKバインディング一覧を指す。(どういう意図でProviderなんだろう...?)
現状サーバー側Go/Java/node/Python/.NETクライアント側Kotlin/JavaScriptに対応している。

https://gofeatureflag.org/docs/openfeature_sdk/sdk

GoFeatureFlagのドキュメントで言うRelayProxy

フィーチャーフラグの値の提供元は複数のSaaSやファイルにまたがる可能性があるので、それらを一元的に管理できたらいいよねということでできた GoOpenFeatureで使えるバックエンドAPI。使わずに、プロバイダー情報を直接値を読み出す箇所にハードコードすることもできるが、このAPIを経由することが推奨されている。

https://gofeatureflag.org/docs/relay_proxy

OpenFeatureの言うProviders

フィーチャーフラグの値を保存しておりOpenFeature規格で提供してくれるライブラリ一覧

https://openfeature.dev/ecosystem?instant_search[refinementList][type][0]=Provider

お窓お窓

https://gofeatureflag.org/docs/relay_proxy/configure_relay_proxy

GoFeatureFlagでRelayProxyが推奨されているので、今回はGoFeatureFlag+go-feature-flag relay proxy+FlagSmithにしてみる。RelayProxyそれ自体のサポートは S3/Github/Gitlab/File/HTTP/GoogleStorage/KubernetesConfigMap
と個人的に見慣れない顔ぶれだが、HTTPで FlagSmithのAPI `を叩いて値を持ってくることができるようなのでそれを使おうと思う。

FlagSmithはOpenFeature向けのGoバインディングAPI仕様(GET /api/v1/flags/を見る限り、元あったAPIを後付けでOpenFeature対応にしているので、Relayproxyでは使えないようだった。

お窓お窓

DevCycleを試してみた。
このサービスでは Variablesを定義してそれを束ねるFeatureを定義し、Feature単位でどのフラグに何を指定するかを選び、どんなユーザーにその値を提供するかを選べるらしい。

  • メリット
    • たぶん対象ユーザーグループの設定が細かくできそう
    • たぶん前評判によればAPIレスポンスが早い
  • デメリット
    • フラグを変える画面の導線が遠い
    • ダッシュボードの遷移がなぜかかなり重い

今回の自分の用途はサーバーサイドの機能切り替えのみで、カナリアリリースやA/Bテストをするつもりがサラサラ無い。なので、トップページ開いたら即フラグ切替画面が出てくれるシンプルさを持つFlagSmithの方にしようと思う。

お窓お窓

GoFeatureFlag != OpenFeatureなので GoFeatureFlagを使わなくとも github.com/open-feature/go-sdk/openfeatureさえあれば、OpenFeatureフォーマットの値は取れそう? GoFeatureFlagの役割がやや分かりづらい。ラッピングしてキャッシュとか取ってる?

お窓お窓

SaaS群は OpenFeatureには対応していても GoFeatureFlagには対応していない気がする...
GoFeatureFlagを使わずSDKだけ使ったほうが早いのでは...?

お窓お窓

EdgeProxyを設定するのが面倒なので、OSS版のFlagSmithのサーバーを立てて自前で動かすことにする。こちらなら呼び出し回数制限を無視できる。

お窓お窓

結局 FlagSmith(セルフホスト) とopen-feature/go-sdk だけを使い、GoFeatureFlagを使わずになんとかした。若干レスポンスが遅くなるので、キャッシュ機構を入れた。これでいい感じになったので、とりあえずこれでクローズ。(別途Qiitaに記事を書きます。)

このスクラップは2024/01/31にクローズされました