
---
layout: blog
title: 'Client-Goへのフィーチャーゲートの導入: 柔軟性と管理性を強化するために'
date: 2024-08-12
slug: feature-gates-in-client-go
author: >
 Ben Luddy (Red Hat),
 Lukasz Szaszkiewicz (Red Hat)
translator: >
  [Youmei Masada](https://github.com/youmeim)
---

Kubernetesコンポーネントは _フィーチャーゲート_ というオン/オフのスイッチを使うことで、新機能を追加する際のリスクを管理しています。
_フィーチャーゲート_ の仕組みは、Alpha、Beta、GAといった各ステージを通じて、新機能の継続的な品質認定を可能にします。

kube-controller-managerやkube-schedulerのようなKubernetesコンポーネントは、client-goライブラリを使ってAPIとやりとりします。
Kubernetesエコシステムは、このライブラリをコントローラーやツール、Webhookなどをビルドするために利用しています。
最新のclient-goにはそれ自体にフィーチャーゲート機構があり、開発者やクラスター管理者は新たなクライアントの機能を採用するかどうかを制御することができます。

Kubernetesにおけるフィーチャーゲートについて深く知るには、[フィーチャーゲート](/ja/docs/reference/command-line-tools-reference/feature-gates/)を参照してください。

## 動機

client-goのフィーチャーゲートが登場するまでは、それぞれの機能が独自のやり方で、 利用できる機能とその機能の有効化のための仕組みを区別していました。
client-goの新バージョンにアップデートすることで有効化できる機能もありました。
その他の機能については、利用するプログラムからいつでも設定できる状態にしておく必要がありました。
ごく一部の機能には環境変数を使って実行時に設定可能なものがありました。
kube-apiserverが提供するフィーチャーゲート機能を利用する場合、(設定や機能実装の時期が原因で)そうした機能をサポートしないクライアントサイドのフォールバック機構がしばしば必要になりました。
これらのフォールバック機構で明らかになった問題があれば、問題の影響を緩和するためにclient-goのバージョンを固定したり、ロールバックしたりする必要がありました。

これらのいずれのアプローチも、client-goを利用するいくつかのプログラムに対してのみデフォルトで機能を有効化する場合には、よい効果をもたらすものではありませんでした。

単一のコンポーネントに対して新機能を有効化するだけでも、標準設定の変更が直ちにすべてのKubernetesコンポーネントに伝搬し、影響範囲は甚大なものとなっていました。

## client-goにおけるフィーチャーゲート

こうした課題に対処するため、client-goの個別機能は新しいフィーチャーゲート機構を使うフェーズに移行します。
Kubernetesコンポーネントのフィーチャーゲート使用経験があるなら、開発者やユーザーは誰もが慣れ親しんだやり方で機能を有効化/無効化できるようになります。

client-goの最近のバージョンを使うだけで、client-goを用いてビルドしたソフトウェアを利用する方々にとってはいくつかの利益があります。

* アーリーアダプターはデフォルトでは無効化されているclient-goの機能について、プロセス単位で有効化できます。
* 挙動がおかしな機能については、新たなバイナリをビルドせずに無効化できます。
* client-goのすべての既知のフィーチャーゲートは状態が記録されており、ユーザーは機能の挙動を調査することができます。

client-goを用いてビルドするソフトウェアを開発している方々にとっては、次のような利益があります。

* 環境変数から client-goのフィーチャーゲートのオーバーライドを指定することができます。
  client-goの機能にバグが見つかった場合は、新しいリリースを待たずに機能を無効化できます。
* プログラムのデフォルトの挙動を変更する目的で、開発者は環境変数ベースのオーバーライドを他のソースからの読み込みで置き換えたり、実行時のオーバーライドを完全に無効化したりすることができます。
このカスタマイズ可能な振る舞いは、Kubernetesコンポーネントの既存の`--feature-gates`コマンドラインフラグや機能有効化メトリクス、ロギングを統合するのに利用します。

## client-goのフィーチャーゲートをオーバーライドする

**補足**: ここではclient-goのフィーチャーゲートを実行時に上書きするデフォルトの方法について説明します。
client-goのフィーチャーゲートは、個々のプログラムの開発者がカスタマイズしたり、無効化したりすることができます。
Kubernetesコンポーネントではclient-goフィーチャーゲートの上書きを`--feature-gates`フラグで制御します。

client-goの機能は`KUBE_FEATURE`から始まる名前の環境変数を設定することによって、有効化したり無効化したりすることができます。
例えば、`MyFeature`という名前の機能を有効化するには、次のような環境変数を設定します。

```
 KUBE_FEATURE_MyFeature=true
```

この機能を無効化したいときには、環境変数を`false`に設定します。

```
 KUBE_FEATURE_MyFeature=false
```

**補足**: いくつかのオペレーティングシステムでは、環境変数は大文字小文字が区別されます。
したがって`KUBE_FEATURE_MyFeature`と`KUBE_FEATURE_MYFEATURE`は異なる２つの変数として認識される場合があります。

## client-goのフィーチャーゲートをカスタマイズする

標準のフィーチャーゲート上書き機能である環境変数ベースの仕組みは、Kubernetesエコシステムの多くのプログラムにとって十分なものと言え、特殊なインテグレーションが不要なやり方です。
異なる挙動を必要とするプログラムのために、この仕組みを独自のフィーチャーゲートプロバイダーで置き換えることもできます。
これにより、うまく動かないことが分かっている機能を強制的に無効化したり、フィーチャーゲートを直接外部の設定サービスから読み込んだり、コマンドラインオプションからフィーチャーゲートの上書きを指定したりすることができるようになります。

Kubernetesコンポーネントはclient-goの標準のフィーチャーゲートプロバイダーを、既存のKubernetesフィーチャーゲートプロバイダーに対する接ぎ木(shim)を使って置き換えます。

実用的な理由から、client-goのフィーチャーゲートは他のKubernetesのフィーチャーゲートと同様に取り扱われています。
(`--feature-gates`コマンドラインフラグに落とし込まれた上で、機能有効化メトリクスに登録され、プログラム開始時にログがなされます)。

標準のフィーチャーゲートプロバイダーを置き換えるには、Gatesインターフェースを実装し、パッケージ初期化の際にReplaceFeatureGatesを呼ぶ必要があります。
以下は簡単な例です。


```go
import (
 “k8s.io/client-go/features”
)

type AlwaysEnabledGates struct{}

func (AlwaysEnabledGates) Enabled(features.Feature) bool {
 return true
}

func init() {
 features.ReplaceFeatureGates(AlwaysEnabledGates{})
}
```

定義済みのclient-goの機能の完全な一覧が必要な場合は、Registryインターフェースを実装して`AddFeaturesToExistingFeatureGates`を呼ぶことで取得できます。
完全な例としては[Kubernetesにおける使用方法](https://github.com/kubernetes/kubernetes/blob/64ba17c605a41700f7f4c4e27dca3684b593b2b9/pkg/features/kube_features.go#L990-L997)を参考にしてください。

## まとめ

client-go v1.30のフィーチャーゲートの導入により、client-goの新機能のロールアウトを安全かつ簡単に実施できるようになりました。
ユーザーや開発者はclient-goの新機能を採用するペースを管理できます。

Kubernetes APIの両側にまたがる機能の品質認定に関する共通のメカニズムができたことによって、Kubernetesコントリビューターの作業は効率化されつつあります。

