The English version of quarkus.io is the official project site. Translated sites are community supported on a best-effort basis.

Kubernetesクライアント

Quarkusには、 Fabric8 Kubernetesクライアント をネイティブモードで使用できるようにする kubernetes-client エクステンションが含まれています。

Kubernetes Operatorのパワーを引き出すためには、QuarkusにKubernetesクライアントエクステンションがあると非常に便利です。Kubernetes Operatorは、クラウドネイティブアプリケーションの新しい種類として急速に台頭してきています。これらのアプリケーションは、基本的にKubernetes APIを監視し、様々なリソースの変更に反応し、データベースやメッセージングシステムなど、あらゆる種類の複雑なシステムのライフサイクルを管理するために使用することができます。ネイティブイメージが提供する非常に低いフットプリントで、このようなOperatorをJavaで書くことができるということは、非常にマッチしています。

設定

Quarkusプロジェクトを設定したら、プロジェクトのベースディレクトリーで次のコマンドを実行して、 kubernetes-client エクステンションをプロジェクトに追加できます。

コマンドラインインタフェース
quarkus extension add kubernetes-client
Maven
./mvnw quarkus:add-extension -Dextensions='kubernetes-client'
Gradle
./gradlew addExtension --extensions='kubernetes-client'

これにより、 pom.xml に以下が追加されます:

pom.xml
<dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-kubernetes-client</artifactId>
</dependency>
build.gradle
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.Configquarkus.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 依存関係を追加する必要があることに注意してください。

pom.xml
<dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-test-kubernetes-client</artifactId>
    <scope>test</scope>
</dependency>
build.gradle
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の依存関係を追加する必要があります:

pom.xml
<dependency>
    <groupId>org.bouncycastle</groupId>
    <artifactId>bcpkix-jdk18on</artifactId>
</dependency>
build.gradle
implementation("org.bouncycastle:bcpkix-jdk18on")

なお、内部的には、 org.bouncycastle.jce.provider.BouncyCastleProvider プロバイダーがまだ登録されていない場合に登録されます。

BouncyCastleまたは BouncyCastle FIPSのセクションで説明したように、このプロバイダーを登録させることができます。

Kubernetes APIへのアクセス

多くの場合、Kubernetes API サーバーにアクセスするには ServiceAccountRoleRoleBinding が必要になります。すべての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
Maven
./mvnw quarkus:add-extension -Dextensions='openshift-client'
Gradle
./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();
    }
}

モックサポートも同様の方法で提供されています。

@QuarkusTestResource(OpenShiftMockServerTestResource.class)
@QuarkusTest
public class OpenShiftClientTest {

    @MockServer
    private OpenShiftMockServer mockServer;
...

または、前のセクションで説明した @WithKubernetesTestServer と同様の @WithOpenShiftTestServer を使用することによって:

@WithOpenShiftTestServer
@QuarkusTest
public class OpenShiftClientTest {

    @OpenShiftTestServer
    private OpenShiftServer mockOpenShiftServer;
...

この機能を使用するには、 quarkus-test-openshift-client に依存関係を追加する必要があります。

pom.xml
<dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-test-openshift-client</artifactId>
    <scope>test</scope>
</dependency>
build.gradle
testImplementation("io.quarkus:quarkus-test-openshift-client")

設定リファレンス

ビルド時に固定される構成プロパティ - 他のすべての構成プロパティは実行時にオーバーライド可能

Configuration property

デフォルト

Whether the client should trust a self-signed certificate if so presented by the API server

Environment variable: QUARKUS_KUBERNETES_CLIENT_TRUST_CERTS

Show more

boolean

URL of the Kubernetes API server

Environment variable: QUARKUS_KUBERNETES_CLIENT_API_SERVER_URL

Show more

string

Default namespace to use

Environment variable: QUARKUS_KUBERNETES_CLIENT_NAMESPACE

Show more

string

CA certificate file

Environment variable: QUARKUS_KUBERNETES_CLIENT_CA_CERT_FILE

Show more

string

CA certificate data

Environment variable: QUARKUS_KUBERNETES_CLIENT_CA_CERT_DATA

Show more

string

Client certificate file

Environment variable: QUARKUS_KUBERNETES_CLIENT_CLIENT_CERT_FILE

Show more

string

Client certificate data

Environment variable: QUARKUS_KUBERNETES_CLIENT_CLIENT_CERT_DATA

Show more

string

Client key file

Environment variable: QUARKUS_KUBERNETES_CLIENT_CLIENT_KEY_FILE

Show more

string

Client key data

Environment variable: QUARKUS_KUBERNETES_CLIENT_CLIENT_KEY_DATA

Show more

string

Client key algorithm

Environment variable: QUARKUS_KUBERNETES_CLIENT_CLIENT_KEY_ALGO

Show more

string

Client key passphrase

Environment variable: QUARKUS_KUBERNETES_CLIENT_CLIENT_KEY_PASSPHRASE

Show more

string

Kubernetes auth username

Environment variable: QUARKUS_KUBERNETES_CLIENT_USERNAME

Show more

string

Kubernetes auth password

Environment variable: QUARKUS_KUBERNETES_CLIENT_PASSWORD

Show more

string

Kubernetes oauth token

Environment variable: QUARKUS_KUBERNETES_CLIENT_TOKEN

Show more

string

Watch reconnect interval

Environment variable: QUARKUS_KUBERNETES_CLIENT_WATCH_RECONNECT_INTERVAL

Show more

Duration

PT1S

Maximum reconnect attempts in case of watch failure By default there is no limit to the number of reconnect attempts

Environment variable: QUARKUS_KUBERNETES_CLIENT_WATCH_RECONNECT_LIMIT

Show more

int

-1

Maximum amount of time to wait for a connection with the API server to be established

Environment variable: QUARKUS_KUBERNETES_CLIENT_CONNECTION_TIMEOUT

Show more

Duration

PT10S

Maximum amount of time to wait for a request to the API server to be completed

Environment variable: QUARKUS_KUBERNETES_CLIENT_REQUEST_TIMEOUT

Show more

Duration

PT10S

Maximum number of retry attempts for API requests that fail with an HTTP code of >= 500

Environment variable: QUARKUS_KUBERNETES_CLIENT_REQUEST_RETRY_BACKOFF_LIMIT

Show more

int

0

Time interval between retry attempts for API requests that fail with an HTTP code of >= 500

Environment variable: QUARKUS_KUBERNETES_CLIENT_REQUEST_RETRY_BACKOFF_INTERVAL

Show more

Duration

PT1S

HTTP proxy used to access the Kubernetes API server

Environment variable: QUARKUS_KUBERNETES_CLIENT_HTTP_PROXY

Show more

string

HTTPS proxy used to access the Kubernetes API server

Environment variable: QUARKUS_KUBERNETES_CLIENT_HTTPS_PROXY

Show more

string

Proxy username

Environment variable: QUARKUS_KUBERNETES_CLIENT_PROXY_USERNAME

Show more

string

Proxy password

Environment variable: QUARKUS_KUBERNETES_CLIENT_PROXY_PASSWORD

Show more

string

IP addresses or hosts to exclude from proxying

Environment variable: QUARKUS_KUBERNETES_CLIENT_NO_PROXY

Show more

list of string

Enable the generation of the RBAC manifests. If enabled and no other role binding are provided using the properties quarkus.kubernetes.rbac., it will generate a default role binding using the role "view" and the application service account.

Environment variable: QUARKUS_KUBERNETES_CLIENT_GENERATE_RBAC

Show more

boolean

true

Dev Services

デフォルト

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: QUARKUS_KUBERNETES_CLIENT_DEVSERVICES_ENABLED

Show more

boolean

true

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: QUARKUS_KUBERNETES_CLIENT_DEVSERVICES_API_VERSION

Show more

string

The flavor to use (kind, k3s or api-only). Default to api-only.

Environment variable: QUARKUS_KUBERNETES_CLIENT_DEVSERVICES_FLAVOR

Show more

kind, k3s, api-only

api-only

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: QUARKUS_KUBERNETES_CLIENT_DEVSERVICES_OVERRIDE_KUBECONFIG

Show more

boolean

false

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 quarkus-dev-service-kubernetes label. The value is configured using the service-name property.

Container sharing is only used in dev mode.

Environment variable: QUARKUS_KUBERNETES_CLIENT_DEVSERVICES_SHARED

Show more

boolean

true

The value of the quarkus-dev-service-kubernetes label attached to the started container. This property is used when shared is set to true. In this case, before starting a container, Dev Services for Kubernetes looks for a container with the quarkus-dev-service-kubernetes label set to the configured value. If found, it will use this container instead of starting a new one. Otherwise, it starts a new container with the quarkus-dev-service-kubernetes label set to the specified value.

This property is used when you need multiple shared Kubernetes clusters.

Environment variable: QUARKUS_KUBERNETES_CLIENT_DEVSERVICES_SERVICE_NAME

Show more

string

kubernetes

Environment variables that are passed to the container.

Environment variable: QUARKUS_KUBERNETES_CLIENT_DEVSERVICES_CONTAINER_ENV

Show more

Map<String,String>

期間フォーマットについて

To write duration values, use the standard java.time.Duration format. See the Duration#parse() Java API documentation for more information.

数字で始まる簡略化した書式を使うこともできます:

  • 数値のみの場合は、秒単位の時間を表します。

  • 数値の後に ms が続く場合は、ミリ秒単位の時間を表します。

その他の場合は、簡略化されたフォーマットが解析のために java.time.Duration フォーマットに変換されます:

  • 数値の後に hms が続く場合は、その前に PT が付けられます。

  • 数値の後に d が続く場合は、その前に P が付けられます。

関連コンテンツ