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 エクステンションが含まれています。

Having a Kubernetes Client extension in Quarkus is very useful in order to unlock the power of Kubernetes Operators. Kubernetes Operators are quickly emerging as a new class of Cloud Native applications. These applications essentially watch the Kubernetes API and react to changes on various resources and can be used to manage the lifecycle of all kinds of complex systems like databases, messaging systems and much more. Being able to write such operators in Java with the very low footprint that native images provide is a great match.

設定

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

CLI
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

プロパティーの完全なリストは、 KubernetesClientBuildConfig クラスで確認できます。

オーバーライド

また、このエクステンションでは、アプリケーションコードは、単にそれらのBeanのカスタムバージョンを宣言することで、通常はエクステンションによって提供される io.fabric8.kubernetes.client.Configio.fabric8.kubernetes.client.KubernetesClient のいずれかをオーバーライドすることができます。

この例は、次のスニペットの通りです:

@Singleton
public class KubernetesClientProducer {

    @Produces
    public KubernetesClient kubernetesClient() {
        // here you would create a custom client
        return new DefaultKubernetesClient();
    }
}

テスト

モックの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;

    @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
        mockServer.getClient().pods().create(pod1);
        mockServer.getClient().pods().create(pod2);
    }

    @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>());

Note on using Elliptic Curve keys

Please note that if you would like to use Elliptic Curve keys with Kubernetes Client then adding a BouncyCastle PKIX dependency is required:

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

Note that internally an org.bouncycastle.jce.provider.BouncyCastleProvider provider will be registered if it has not already been registered.

You can have this provider registered as described in the BouncyCastle or BouncyCastle FIPS sections.

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 …​)へのアクセスを提供します。

Note that the configuration properties are shared with the kubernetes-client extension. In particular, they have the same quarkus.kubernetes-client prefix.

以下のコマンドでエクステンションを追加します。

CLI
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

boolean

URL of the Kubernetes API server

Environment variable: QUARKUS_KUBERNETES_CLIENT_MASTER_URL

string

Default namespace to use

Environment variable: QUARKUS_KUBERNETES_CLIENT_NAMESPACE

string

CA certificate file

Environment variable: QUARKUS_KUBERNETES_CLIENT_CA_CERT_FILE

string

CA certificate data

Environment variable: QUARKUS_KUBERNETES_CLIENT_CA_CERT_DATA

string

Client certificate file

Environment variable: QUARKUS_KUBERNETES_CLIENT_CLIENT_CERT_FILE

string

Client certificate data

Environment variable: QUARKUS_KUBERNETES_CLIENT_CLIENT_CERT_DATA

string

Client key file

Environment variable: QUARKUS_KUBERNETES_CLIENT_CLIENT_KEY_FILE

string

Client key data

Environment variable: QUARKUS_KUBERNETES_CLIENT_CLIENT_KEY_DATA

string

Client key algorithm

Environment variable: QUARKUS_KUBERNETES_CLIENT_CLIENT_KEY_ALGO

string

Client key passphrase

Environment variable: QUARKUS_KUBERNETES_CLIENT_CLIENT_KEY_PASSPHRASE

string

Kubernetes auth username

Environment variable: QUARKUS_KUBERNETES_CLIENT_USERNAME

string

Kubernetes auth password

Environment variable: QUARKUS_KUBERNETES_CLIENT_PASSWORD

string

Kubernetes oauth token

Environment variable: QUARKUS_KUBERNETES_CLIENT_TOKEN

string

Watch reconnect interval

Environment variable: QUARKUS_KUBERNETES_CLIENT_WATCH_RECONNECT_INTERVAL

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

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

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

Duration

PT10S

Maximum amount of time in milliseconds to wait for a rollout to be completed

Environment variable: QUARKUS_KUBERNETES_CLIENT_ROLLING_TIMEOUT

Duration

PT15M

HTTP proxy used to access the Kubernetes API server

Environment variable: QUARKUS_KUBERNETES_CLIENT_HTTP_PROXY

string

HTTPS proxy used to access the Kubernetes API server

Environment variable: QUARKUS_KUBERNETES_CLIENT_HTTPS_PROXY

string

Proxy username

Environment variable: QUARKUS_KUBERNETES_CLIENT_PROXY_USERNAME

string

Proxy password

Environment variable: QUARKUS_KUBERNETES_CLIENT_PROXY_PASSWORD

string

IP addresses or hosts to exclude from proxying

Environment variable: QUARKUS_KUBERNETES_CLIENT_NO_PROXY

list of string

Enable the generation of the RBAC manifests.

Environment variable: QUARKUS_KUBERNETES_CLIENT_GENERATE_RBAC

boolean

true

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

期間のフォーマットは標準の java.time.Duration フォーマットを使用します。詳細は Duration#parse() javadoc を参照してください。

数値で始まる期間の値を指定することもできます。この場合、値が数値のみで構成されている場合、コンバーターは値を秒として扱います。そうでない場合は、 PT が暗黙的に値の前に付加され、標準の java.time.Duration 形式が得られます。