我們介紹了透過 Ingress NGINX Controller、Argo Rollouts 實現 Pod 維度的部署策略,但若要長時間運行運行新舊版本的 Pod,需佔用多一倍的運算資源。
另外再微服務架構中,也會面對一些挑戰,例如:A服務與B服務有 API 依賴性,當 A 服務走新版本邏輯程時,必須與 B 服務中的新版本邏輯,反之都需要走舊版本邏輯。
這時候我們能透過 Feature Toggle,實現代碼維度的部署策略,達成靈活、快速地發布新功能且盡可能的降低風險。
Feature Toggle 是一種設計模式,讓開發團隊可以在不影響系統的情況下,靈活地控制新功能的開啟或關閉,在功能完成前不對使用者開放。當功能準備就緒時,開發團隊只需開啟開關即可立即發布新功能,而無需重新部署。
這是一個最簡單的 Feature Toggle 代碼範例
fun doSomething(){
// 當 Feature Toggle 為 True 時,使用新邏輯,反之使用舊邏輯
if( featureIsEnabled("use-new-feature") ){
return doSomethingWithNewLogic();
}else{
return doSomethingWithOldLogic();
}
}
此範例中,featureIsEnabled(String)
這個函數作為 Toggle Router,負責管理功能的啟用/關閉,而 Toggle Router 的實現方式將直接影響 Feature Toggle 是否好用與可靠。
今天,將使用 Flipt 作為 Toggle Router 的實現,來介紹 Feature Toggle 的使用方式。
Flipt 是一個 Open soruce 的 Feature Toggle 平台,提供以下功能
Flags:FlagsFlipt 中的功能開關,用於控制應用程式中功能的啟用與禁用。分為兩種類型:
true
或 false
,適用於簡單的功能開關。dark
、light
、auto
),適用於多種狀態的功能,例如調整 UI 的主題色。Segments:根據特定條件(如地區或用戶類型)對用戶進行分群,以便對不同群體應用不同的功能標籤。
Rules / Rollouts:定義哪些用戶群(Segments)符合某 Flag 的條件,並根據條件或百分比分發不同的結果,例如,30% 的用戶使用 dark
色系。
Evaluation:Flipt 會根據 Evaluation 請求來決定是否啟用某個 Flag,Evaluation 請求中包含以下資訊。
Entity Id
:通常是能識別用戶的唯一值,如 userId、email,Entity Id
將作為百分比發佈演算法計算的參數。Context
:通常用來攜帶與用戶身份無關,提供資訊來識別用戶屬於什麼 Segments,如:用戶地區資訊。生產環境部署時,僅將新功能僅開放給屬於內部人員的帳號,當內部人員驗證新功能正確時,再開放給外部使用者。
圖檔來自 Integration of both Canary Deployment and feature flagging design patterns simplified
典型的金絲雀部署,由小量開放新版本功能,確認功能穩定在逐漸放大比例
圖檔來自 Feature Toggle Makes Development Faster and Safer @ TECHPULSE 2023
類似金絲雀部署,但通常是為了商業目的,例如:分析新/舊版本的訂單轉換率較高 或 用戶停留時間更長。
圖檔來自 The role of feature flags in A/B testing
透過 Flipt,我們就不需要部署多個版本的 Deployment,只需要在應用程序中向 Flipt server 發出 Evaluation 請求,應用程序依照 Evaluation 的回應執行對應的代碼。
當有多組服務要同時應用同一個版本時,只要使用同樣的資訊向 Flipt 發出 Evaluation 請求都能得到相同的回應值 (假設 Segments、Rules / Rollouts 都未改變),能完美解決服務依賴的版本控制難題。
能使用 Helm 輕鬆的安裝到 Kubernetes 中
# add the Flipt Helm repository
helm repo add flipt https://helm.flipt.io
# create namespace
kubectl create ns flipt
# install
helm install flipt flipt/flipt --namespace=flipt
能看到 namespace:flipt
中有 flipt 的 Pod 在運行。
kubectl get pod -n flipt
# Output
NAME READY STATUS RESTARTS AGE
flipt-6c487dc75f-h9xg8 1/1 Running 0 3m57s
我們來配置一個依據 用戶地區 決定功能開關的 Feature toggle
將 flipt UI 轉發到 http://localhost:8080
,方便配置
kubectl port-forward services/flipt 8080:8080
用瀏覽器開啟 http://localhost:8080
Asia-User
Asia-User
String
region
==
Asia
Demo-Feature-Toggle
Demo-Feature-Toggle
Boolean
Segment
Asia-User
True
能透過 Flipt UI 直接測試 Flag
Demo-Feature-Toggle
{"region": "Asia"}
{
"enabled": true,
"reason": "MATCH_EVALUATION_REASON",
"requestId": "fbad0ce1-447f-4ef0-af46-73bab293ed5b",
"requestDurationMillis": 2.39275,
"timestamp": "2024-10-02T16:16:40.784382764Z",
"flagKey": "Demo-Feature-Toggle"
}
其中 enabled
欄位代表了 Boolean Flag 中的配置
反之,region
為空或其他值時,enabled
欄位會返回 false
import io.flipt.api.FliptClient;
import io.flipt.api.evaluation.models.*;
public class Main {
public static void main(String[] args) {
FliptClient fliptClient = FliptClient.builder().url("YOU_FLIPT_SERVER_URL").build();
Map<String, String> context = new HashMap<>();
context.put("region", "Asia");
EvaluationRequest variantEvaluationRequest =
EvaluationRequest.builder()
.namespaceKey("default")
.flagKey("Demo-Feature-Toggle")
.entityId("userId")
.context(context)
.build();
BooleanEvaluationResponse booleanEvaluationResponse = fliptClient.evaluation().evaluateBoolean(variantEvaluationRequest);
// 依據 Flipt Evaluation Response 值判斷使用新/舊版邏輯
if(booleanEvaluationResponse.isEnabled()){
return doSomethingWithNewLogic();
}else{
return doSomethingWithOldLogic();
}
}
}
只要應用程序將實際的用戶地區填入 context
中,使用 Evaluation 時,Flipt 就會依據該 Flag 的 Segments 與 Rules / Rollouts 運算出對應的值,讓應用程序使用。
對 Canary 發布有興趣的讀者,能自行嘗試配置 Rollouts 的 Type 為 Threshold
或調整其他條件看看。
今天介紹了如何利用 Feature Toggle 結合 Flipt 來靈活管理功能發布。相比傳統的金絲雀部署,Feature Toggle 專注於代碼層面的功能控制,讓開發團隊能快速啟用或禁用功能,無需重新部署。Flipt 提供高效的 API、簡單的 UI 介面,以及多種語言 SDK,讓配置更加靈活。無論是 Beta 測試、金絲雀發布,還是 A/B 測試,Flipt 都能幫助開發團隊更好地管理和驗證新功能的運行,提升部署效率與穩定性。