Kubernetesクライアント
Quarkusには、 Fabric8 Kubernetesクライアント をネイティブモードで使用できるようにする kubernetes-client
エクステンションが含まれています。
Kubernetes Operatorのパワーを引き出すためには、QuarkusにKubernetesクライアントエクステンションがあると非常に便利です。Kubernetes Operatorは、クラウドネイティブアプリケーションの新しい種類として急速に台頭してきています。これらのアプリケーションは、基本的にKubernetes APIを監視し、様々なリソースの変更に反応し、データベースやメッセージングシステムなど、あらゆる種類の複雑なシステムのライフサイクルを管理するために使用することができます。ネイティブイメージが提供する非常に低いフットプリントで、このようなOperatorをJavaで書くことができるということは、非常にマッチしています。
設定
Quarkusプロジェクトを設定したら、プロジェクトのベースディレクトリーで次のコマンドを実行して、 kubernetes-client
エクステンションをプロジェクトに追加できます。
quarkus extension add kubernetes-client
./mvnw quarkus:add-extension -Dextensions='kubernetes-client'
./gradlew addExtension --extensions='kubernetes-client'
これにより、 pom.xml
に以下が追加されます:
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-kubernetes-client</artifactId>
</dependency>
implementation("io.quarkus:quarkus-kubernetes-client")
使用方法
Quarkusは、よく知られたCDIメソッドを使用してアプリケーションコードに注入できる KubernetesClient
タイプのBeanを設定します。このクライアントは、以下の例にあるように、さまざまなプロパティーを使用して設定することができます。
quarkus.kubernetes-client.trust-certs=false
quarkus.kubernetes-client.namespace=default
なお、プロパティの全リストは、 設定リファレンスのDev Servicesセクション にあります。
devモードやテスト実行時には、 Dev Services for Kubernetes が自動的にKubernetes APIサーバーを起動します。
カスタマイズとオーバーライド
Quarkusは、CDI Beanとして提供されるKubernetes Clientに影響を与えるための複数の統合ポイントを提供します。
Kubernetes クライアント設定のカスタマイズ
最初の統合ポイントは、 io.quarkus.kubernetes.client.KubernetesConfigCustomizer
インターフェイスの使用です。このようなBeanが存在する場合、Quarkusが作成した io.fabric8.kubernetes.client.Config
( quarkus.kubernetes-client.*
のプロパティを考慮します)を任意にカスタマイズすることができます。
あるいは,アプリケーションコードは,単にそれらのBeanのカスタムバージョンを宣言することによって,(通常エクステンションによって提供される) io.fabric8.kubernetes.client.Config
,あるいは io.fabric8.kubernetes.client.KubernetesClient
Beanをオーバーライドすることもできます。
この例は、次のスニペットの通りです:
@Singleton
public class KubernetesClientProducer {
@Produces
public KubernetesClient kubernetesClient() {
// here you would create a custom client
return new DefaultKubernetesClient();
}
}
KubernetesクライアントObjectMapperのカスタマイズ
Fabric8 Kubernetes Clientは、Kubernetesリソースのシリアライズとデシリアライズのために独自の ObjectMapper
インスタンスを使用します。このマッパーは、 KubernetesClient
Beanに注入された KubernetesSerialization
インスタンスを通してクライアントに提供されます。
何らかの理由で、このエクステンションによって提供され、Kubernetes Clientによって使用されるデフォルトの ObjectMapper
Beanをカスタマイズする必要がある場合は、 KubernetesClientObjectMapperCustomizer
インターフェイスを実装するBeanを宣言することでカスタマイズできます。
次のコード・スニペットには、 ObjectMapper
ロケールを設定する KubernetesClientObjectMapperCustomizer
の例が含まれています:
@Singleton
public static class Customizer implements KubernetesClientObjectMapperCustomizer {
@Override
public void customize(ObjectMapper objectMapper) {
objectMapper.setLocale(Locale.ROOT);
}
}
さらに、エクステンションが自動的に作成する Kubernetes Client が使用するデフォルトの ObjectMapper
Bean を置き換える必要がある場合は、 @KubernetesClientObjectMapper
型の Bean を宣言することで置き換えることができます。次のコードスニペットは、このBeanを宣言する方法を示しています:
@Singleton
public class KubernetesObjectMapperProducer {
@KubernetesClientObjectMapper
@Singleton
@Produces
public ObjectMapper kubernetesClientObjectMapper() {
return new ObjectMapper();
}
}
静的な io.fabric8.kubernetes.client.utils.Serialization utils クラスは非推奨であり、使用すべきではありません。 Serialization.jsonMapper() へのアクセスは @KubernetesClientObjectMapperCustomizer` で宣言された Bean を使用することで置き換える必要があります。
|
テスト
モックのKubernetes APIに対するテストを非常に簡単にするために、Quarkusでは、Kubernetes APIサーバーのモックを自動的に起動し、Kubernetesクライアントがそのモックを使用するように設定するために必要な適切な環境変数を設定する KubernetesMockServerTestResource
を提供しています。テストは、 @MockServer
アノテーションを使用して、特定のテストに必要な方法でモックを注入し、設定することができます。
このようにRESTエンドポイントが定義されているとします。
@Path("/pod")
public class Pods {
private final KubernetesClient kubernetesClient;
public Pods(KubernetesClient kubernetesClient) {
this.kubernetesClient = kubernetesClient;
}
@GET
@Path("/{namespace}")
public List<Pod> pods(String namespace) {
return kubernetesClient.pods().inNamespace(namespace).list().getItems();
}
}
このエンドポイントのテストは次のように簡単に書けます。
// you can even configure aspects like crud, https and port on this annotation
@WithKubernetesTestServer
@QuarkusTest
public class KubernetesClientTest {
@KubernetesTestServer
KubernetesServer mockServer;
@Inject
KubernetesClient client;
@BeforeEach
public void before() {
final Pod pod1 = new PodBuilder().withNewMetadata().withName("pod1").withNamespace("test").and().build();
final Pod pod2 = new PodBuilder().withNewMetadata().withName("pod2").withNamespace("test").and().build();
// Set up Kubernetes so that our "pretend" pods are created
client.pods().resource(pod1).create();
client.pods().resource(pod2).create();
}
@Test
public void testInteractionWithAPIServer() {
RestAssured.when().get("/pod/test").then()
.body("size()", is(2));
}
}
これらの機能を利用するには、例えば次のように quarkus-test-kubernetes-client
依存関係を追加する必要があることに注意してください。
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-test-kubernetes-client</artifactId>
<scope>test</scope>
</dependency>
testImplementation("io.quarkus:quarkus-test-kubernetes-client")
デフォルトでは、モックサーバはCRUDモードになっているので、アプリケーションがステートを取得する前に、クライアントを使ってステートを構築する必要がありますが、非CRUDモードに設定して、KubernetesへのすべてのHTTPリクエストをモックすることもできます。
// you can even configure aspects like crud, https and port on this annotation
@WithKubernetesTestServer(crud = false)
@QuarkusTest
public class KubernetesClientTest {
@KubernetesTestServer
KubernetesServer mockServer;
@BeforeEach
public void before() {
final Pod pod1 = new PodBuilder().withNewMetadata().withName("pod1").withNamespace("test").and().build();
final Pod pod2 = new PodBuilder().withNewMetadata().withName("pod2").withNamespace("test").and().build();
// Mock any HTTP request to Kubernetes pods so that our pods are returned
mockServer.expect().get().withPath("/api/v1/namespaces/test/pods")
.andReturn(200,
new PodListBuilder().withNewMetadata().withResourceVersion("1").endMetadata().withItems(pod1, pod2)
.build())
.always();
}
@Test
public void testInteractionWithAPIServer() {
RestAssured.when().get("/pod/test").then()
.body("size()", is(2));
}
}
また、 @WithKubernetesTestServer
アノテーションの setup
属性を使用して、 KubernetesServer
インスタンスを設定するクラスを提供することもできます。
@WithKubernetesTestServer(setup = MyTest.Setup.class)
@QuarkusTest
public class MyTest {
public static class Setup implements Consumer<KubernetesServer> {
@Override
public void accept(KubernetesServer server) {
server.expect().get().withPath("/api/v1/namespaces/test/pods")
.andReturn(200, new PodList()).always();
}
}
// tests
}
または、 `KubernetesServerTestResource`クラスの拡張を作成して、 ` @ QuarkusTest`が有効なすべてのテストクラスが `QuarkusTestResource`アノテーションを介して同じモックサーバーセットアップを共有するようにすることもできます。
public class CustomKubernetesMockServerTestResource extends KubernetesServerTestResource {
@Override
protected void configureServer() {
super.configureServer();
server.expect().get().withPath("/api/v1/namespaces/test/pods")
.andReturn(200, new PodList()).always();
}
}
そして、これを次のように他のテストクラスで使用します。
@QuarkusTestResource(CustomKubernetesMockServerTestResource.class)
@QuarkusTest
public class KubernetesClientTest {
//tests will now use the configured server...
}
ジェネリック型の実装または拡張に関する注意
GraalVMによって課せられた制限のため、アプリケーションがネイティブモードで動作することを意図している場合、 クライアントによって提供されるジェネリック型を実装または拡張する際には特別な注意が必要です。基本的に、 Watcher
、 ` ResourceHandler`、 CustomResource`などのジェネリッククラスのすべての実装または拡張は、クラス定義時に関連するKubernetesモデルクラス(または、 ` CustomResource
の場合は通常のJavaタイプ)を指定する必要があります。 よく理解するために、例えばKubernetesの Pod`リソースへの変更を監視するとします。 ネイティブでの動作が保証されているこのような `Watcher
を作成するには、いくつかの方法があります。
client.pods().watch(new Watcher<Pod>() {
@Override
public void eventReceived(Action action, Pod pod) {
// do something
}
@Override
public void onClose(KubernetesClientException e) {
// do something
}
});
または
public class PodResourceWatcher implements Watcher<Pod> {
@Override
public void eventReceived(Action action, Pod pod) {
// do something
}
@Override
public void onClose(KubernetesClientException e) {
// do something
}
}
...
client.pods().watch(new PodResourceWatcher());
以下の例のようにクラス階層を介してジェネリック型を定義した場合も、正しく動作することに注目してください。
public abstract class MyWatcher<S> implements Watcher<S> {
}
...
client.pods().watch(new MyWatcher<Pod>() {
@Override
public void eventReceived(Action action, Pod pod) {
// do something
}
});
以下の例では、クラスやメソッドの定義を見てウォッチャーのジェネリック型を判断できないため、Quarkusはリフレクション登録が必要なKubernetesモデルクラスを適切に判断できないため、ネイティブモードでは動作 しません 。 |
public class ResourceWatcher<T extends HasMetadata> implements Watcher<T> {
@Override
public void eventReceived(Action action, T resource) {
// do something
}
@Override
public void onClose(KubernetesClientException e) {
// do something
}
}
client.pods().watch(new ResourceWatcher<Pod>());
楕円曲線鍵使用時の注意点
なお、Kubernetes Clientで楕円曲線鍵を使用したい場合は、BouncyCastle PKIXの依存関係を追加する必要があります:
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-jdk18on</artifactId>
</dependency>
implementation("org.bouncycastle:bcpkix-jdk18on")
なお、内部的には、 org.bouncycastle.jce.provider.BouncyCastleProvider
プロバイダーがまだ登録されていない場合に登録されます。
BouncyCastleまたは BouncyCastle FIPSのセクションで説明したように、このプロバイダーを登録させることができます。
Kubernetes APIへのアクセス
多くの場合、Kubernetes API サーバーにアクセスするには ServiceAccount
、 Role
、 RoleBinding
が必要になります。すべてのPodをリスト可能な例は以下のようになります。
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: <applicationName>
namespace: <namespace>
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: <applicationName>
namespace: <namespace>
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: <applicationName>
namespace: <namespace>
roleRef:
kind: Role
name: <applicationName>
apiGroup: rbac.authorization.k8s.io
subjects:
- kind: ServiceAccount
name: <applicationName>
namespace: <namespace>
<applicationName>
と <namespace>
は値に置き換えてください。 PodのService Accountの設定 を参照して、詳細な情報を入手してください。
OpenShiftクライアント
対象となるKubernetesクラスターがOpenShiftクラスターであれば、同様の方法で、 openshift-client
エクステンションを利用してアクセスすることが可能です。これは専用の fabric8 openshift クライアントを利用し、 OpenShift
固有のオブジェクト(例: Route
, ProjectRequest
, BuildConfig
…)へのアクセスを提供します。
設定プロパティーは kubernetes-client
エクステンションと共有されていることに注意してください。特に、これらは同じ quarkus.kubernetes-client
プレフィックスを持っています。
以下のコマンドでエクステンションを追加します。
quarkus extension add openshift-client
./mvnw quarkus:add-extension -Dextensions='openshift-client'
./gradlew addExtension --extensions='openshift-client'
openshift-client
エクステンションは kubernetes-client
エクステンションに依存していることに注意してください。
クライアントを使用するには、 KubernetesClient
の代わりに OpenShiftClient
を注入します。
@Inject
private OpenShiftClient openshiftClient;
デフォルトの OpenShiftClient
を上書きする必要がある場合は、次のようなプロデューサーを提供してください。
@Singleton
public class OpenShiftClientProducer {
@Produces
public OpenShiftClient openshiftClient() {
// here you would create a custom client
return new DefaultOpenShiftClient();
}
}
前節で説明した @WithKubernetesTestServer
を使用することで、同様の方法でモック・サポートも提供されます:
@WithKubernetesTestServer
@QuarkusTest
public class OpenShiftClientTest {
@KubernetesTestServer
KubernetesServer mockServer;
@Inject
OpenShiftClient client;
@Test
public void testInteractionWithAPIServer() {
RestAssured.when().get("/route/test").then()
.body("size()", is(2));
}
}
この機能を使うには、 quarkus-test-kubernetes-client
への依存関係を追加する必要があります:
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-test-kubernetes-client</artifactId>
<scope>test</scope>
</dependency>
testImplementation("io.quarkus:quarkus-test-kubernetes-client")
設定リファレンス
ビルド時に固定される設定プロパティ - 他のすべての設定プロパティは実行時にオーバーライド可能
Configuration property |
型 |
デフォルト |
---|---|---|
Whether the client should trust a self-signed certificate if so presented by the API server Environment variable: Show more |
boolean |
|
URL of the Kubernetes API server Environment variable: Show more |
string |
|
Default namespace to use Environment variable: Show more |
string |
|
CA certificate file Environment variable: Show more |
string |
|
CA certificate data Environment variable: Show more |
string |
|
Client certificate file Environment variable: Show more |
string |
|
Client certificate data Environment variable: Show more |
string |
|
Client key file Environment variable: Show more |
string |
|
Client key data Environment variable: Show more |
string |
|
Client key algorithm Environment variable: Show more |
string |
|
Client key passphrase Environment variable: Show more |
string |
|
Kubernetes auth username Environment variable: Show more |
string |
|
Kubernetes auth password Environment variable: Show more |
string |
|
Kubernetes oauth token Environment variable: Show more |
string |
|
Watch reconnect interval Environment variable: Show more |
||
Maximum reconnect attempts in case of watch failure By default there is no limit to the number of reconnect attempts Environment variable: Show more |
int |
|
Maximum amount of time to wait for a connection with the API server to be established Environment variable: Show more |
||
Maximum amount of time to wait for a request to the API server to be completed Environment variable: Show more |
||
Maximum number of retry attempts for API requests that fail with an HTTP code of >= 500 Environment variable: Show more |
int |
|
Time interval between retry attempts for API requests that fail with an HTTP code of >= 500 Environment variable: Show more |
||
HTTP proxy used to access the Kubernetes API server Environment variable: Show more |
string |
|
HTTPS proxy used to access the Kubernetes API server Environment variable: Show more |
string |
|
Proxy username Environment variable: Show more |
string |
|
Proxy password Environment variable: Show more |
string |
|
IP addresses or hosts to exclude from proxying Environment variable: Show more |
list of string |
|
Enable the generation of the RBAC manifests. If enabled and no other role binding are provided using the properties Environment variable: Show more |
boolean |
|
型 |
デフォルト |
|
If Dev Services for Kubernetes should be used. (default to true) If this is true and kubernetes client is not configured then a kubernetes cluster will be started and will be used. Environment variable: Show more |
boolean |
|
The kubernetes api server version to use. If not set, Dev Services for Kubernetes will use the latest supported version of the given flavor. see https://github.com/dajudge/kindcontainer/blob/master/k8s-versions.json Environment variable: Show more |
string |
|
The flavor to use (kind, k3s or api-only). If not set, Dev Services for Kubernetes will set it to: api-only. Environment variable: Show more |
|
|
By default, if a kubeconfig is found, Dev Services for Kubernetes will not start. Set this to true to override the kubeconfig config. Environment variable: Show more |
boolean |
|
Indicates if the Kubernetes cluster managed by Quarkus Dev Services is shared. When shared, Quarkus looks for running containers using label-based service discovery. If a matching container is found, it is used, and so a second one is not started. Otherwise, Dev Services for Kubernetes starts a new container. The discovery uses the Container sharing is only used in dev mode. Environment variable: Show more |
boolean |
|
The value of the This property is used when you need multiple shared Kubernetes clusters. Environment variable: Show more |
string |
|
Environment variables that are passed to the container. Environment variable: Show more |
Map<String,String> |
期間フォーマットについて
期間の値を書くには、標準の 数字で始まる簡略化した書式を使うこともできます:
その他の場合は、簡略化されたフォーマットが解析のために
|