Slide 1

Slide 1 text

Open Feature面白いぞ Jagu'e'r Cloud Native ハイブリッド Meetup# 17 株式会社スリーシェイク 佐藤慧太 Copyright © 3-shake, Inc. All Rights Reserved.

Slide 2

Slide 2 text

自己紹介 佐藤 慧太@SatohJohn ● 2012/4 フリュー株式会社 入社 ToC 向けのアプリケーション開発を 10年ほど経験 リードエンジニアとして 0からサービスを 設計開発運用を経験 ● 2023/1 株式会社スリーシェイク 入社 SRE として労苦 を減らす仕事に従事 Google Cloud Partner Top Engineer ’24、’25 生成 AI とかやってます

Slide 3

Slide 3 text

What’s Open Feature 01 Copyright © 3-shake, Inc. All Rights Reserved.

Slide 4

Slide 4 text

そもそも Feature Flag について 1. Trunk ベース開発など高速なリリースにおける痛みを和らげる a. AB テスト、カナリアテストのように切り替える b. kill スイッチのように特定の機能を無効化する c. チェックができておらずマージできない など 2. Permission のようなパラメータ管理 https://speakerdeck.com/biwashi/cloudnative-days-summer-2024-declarative-aggregated-management-of -feature-flags-using-openfeature-and-auto-generation OpenFeatureと自動生成を活用したフィーチャーフラグの宣言的集約管理

Slide 5

Slide 5 text

Open Feature について 1. ベンダー中立性 a. Provider で抽象化(ConfigCat、など) 2. Feature Flag について標準化 a. Spec をまとめて新しい Provider の作成に役立てる 3. 様々な言語での実装 https://openfeature.dev/

Slide 6

Slide 6 text

HotoUse(Flag Evaluation) 1. Flagd Provider 2. Node.js services: server: build: ./app environment: NODE_ENV: production FLAGD_HOST: flagd PORT: 3333 ports: - 3333:3333 flagd: image: ghcr.io/open-feature/flagd:latest volumes: - type: bind source: ./flagd/flags.flagd.json target: /etc/flagd/flags.flagd.json ports: - 8013:8013 command: ["start", "--uri", "file:/etc/flagd/flags.flagd.json"]

Slide 7

Slide 7 text

HotoUse(Flag Evaluation) 1. Flagd Provider 2. Node.js { "flags": { "welcome-message": { "variants": { "on": true, "off": false }, "state": "ENABLED", "defaultVariant": "on" } } } ● Flagd がファイルを watch し続けているのでdefault value を変更すると アプリケーションでも変更が伝わる ● Variants に無いものを設定するとエラーになるがアプリケーション側では 前回の値になっている ● このあたりのエラー状態については、 https://openfeature.dev/specification/sections/events#requirement-535 https://flagd.dev/reference/monitoring/

Slide 8

Slide 8 text

HotoUse(Flag Evaluation) 1. Flagd Provider 2. Node.js import express from "express"; import Router from "express-promise-router"; import { OpenFeature } from "@openfeature/server-sdk"; import { FlagdProvider } from "@openfeature/flagd-provider"; OpenFeature.setProvider(new FlagdProvider({ host: process.env.FLAGD_HOST || "localhost" })); const client = OpenFeature.getClient(); const app = express(); const routes = Router(); app.use((_, res, next) => { res.setHeader("content-type", "text/plain"); next(); }, routes); routes.get("/", async (_, res) => { const showWelcomeMessage = await client.getBooleanValue( "welcome-message", false ); if (showWelcomeMessage) { res.send("Express + TypeScript + OpenFeature Server"); } else { res.send("Express + TypeScript Server"); } }); const port = process.env.PORT || 3333; app.listen(port, () => { console.log(`Server running at http://localhost:${port}`); }); https://openfeature.dev/specification/sections/flag-eval uation/

Slide 9

Slide 9 text

HotoUse(GKE) apiVersion: core.openfeature.dev/v1beta1 kind: FeatureFlag metadata: name: flags labels: app: open-feature spec: flagSpec: flags: welcome-message: state: ENABLED variants: 'on': true 'off': false defaultVariant: 'off' --- # Feature flag source custom resource, configuring flagd to source flags from FeatureFlag CRDs apiVersion: core.openfeature.dev/v1beta1 kind: FeatureFlagSource metadata: name: flag-sources labels: app: open-feature spec: sources: - source: flags provider: kubernetes 1. GKE 2. K8s operator

Slide 10

Slide 10 text

HotoUse(GKE) # Deployment of a app using our custom resources apiVersion: apps/v1 kind: Deployment metadata: name: open-feature-deployment labels: app: open-feature spec: replicas: 1 selector: matchLabels: app: open-feature template: metadata: labels: app: open-feature annotations: openfeature.dev/enabled: 'true' openfeature.dev/featureflagsource: 'flag-sources' spec: containers: 1. GKE 2. K8s operator

Slide 11

Slide 11 text

HotoUse(Tracking) 1. Devcycle (Flagd では未実装っぽい) 2. Node.js const devcycleClient = initializeDevCycle("id") OpenFeature.setProviderAndWait(await devcycleClient.getOpenFeatureProvider()); client.track("welcomemessage_trackingid", context); https://openfeature.dev/specification/sections/flag-eval uation/

Slide 12

Slide 12 text

Provider の自作 ● Providerの 仕様 にしたがって メソッドを記載していくと 作れる ● Firebase Remote Config 周りで挑戦してみても 良いかもしれない https://openfeature.dev/specification/ class MyProvider implements Provider { readonly hooks: Hook[] = [new MyProviderHook()]; void initialize(EvaluationContext initialContext) { /* A hypothetical initialization function: make an initial call doing some bulk initial evaluation, start a worker to do periodic updates */ this.flagCache = this.restClient.bulkEvaluate(initialContext); this.startPolling(); } getProviderHooks(): Hook[] { return [new MyProviderHook()]; } void dispose() { // close connections, terminate threads or timers, etc... } /** * Record a tracking event. */ void track(String trackingEventName, EvaluationContext context, TrackingEventDetails details): void; }

Slide 13

Slide 13 text

まとめ 1. Feature Flag を使っているプロジェクトであれば使っていくのは良さそう a. いろんなプロジェクトがあって困るみたいなときに良さそう b. ちょっと Provider 作れないかなーという感じ 2. Tracking がサポートされている Provider が少ないので作って! 作るかー!

Slide 14

Slide 14 text

Thank you Copyright © 3-shake, Inc. All Rights Reserved.