1. 序章

このチュートリアルでは、公式のクライアントライブラリを使用してJavaアプリケーションから KubernetesAPIを使用する方法を示します。

2. なぜKubernetesAPIを使用するのですか?

現在、Kubernetesはコンテナ化されたアプリケーションを管理するためのデファクトスタンダードになったと言っても過言ではありません。 これは、アプリケーションと、ストレージ、シークレット、環境変数などの関連リソースをデプロイ、スケーリング、監視できる豊富なAPIを提供します。 実際、このAPIについて考える1つの方法は、通常のオペレーティングシステムで利用可能なシステムコールの分散アナログです。

ほとんどの場合、アプリケーションはKubernetesで実行されているという事実を無視できます。 これは、ローカルで開発でき、いくつかのコマンドとYAMLの呪文を使用して、わずかな変更を加えるだけで複数のクラウドプロバイダーにすばやくデプロイできるため、良いことです。

ただし、特定の機能を実現するためにKubernetesAPIと通信する必要がある興味深いユースケースがいくつかあります。

  • 外部プログラムを起動してタスクを実行し、後でその完了ステータスを取得します
  • 顧客の要求に応じて、サービスを動的に作成/変更します
  • クラウドプロバイダー間でも、複数のKubernetesクラスター間で実行されるソリューションのカスタムモニタリングダッシュボードを作成します

確かに、これらのユースケースはそれほど一般的ではありませんが、そのAPIのおかげで、非常に簡単に実現できることがわかります。

さらに、Kubernetes APIはオープン仕様であるため、認定された実装を変更せずにコードが実行されることを確信できます

3. ローカル開発環境

アプリケーションの作成に進む前に最初に行う必要があるのは、機能しているKubernetesクラスターにアクセスすることです。これにはパブリッククラウドプロバイダーを使用できますが、ローカル環境では通常、より多くの機能が提供されます。セットアップのすべての側面を制御します。

このタスクに適した軽量のディストリビューションがいくつかあります。

実際のセットアップ手順はこの記事の範囲を超えていますが、どのオプションを選択する場合でも、開発を開始する前にkubectlが正常に動作することを確認してください。

4. Mavenの依存関係

まず、KubernetesJavaAPIの依存関係をプロジェクトのpom.xmlに追加しましょう。

<dependency>
    <groupId>io.kubernetes</groupId>
    <artifactId>client-java</artifactId>
    <version>11.0.0</version>
</dependency>

client-javaの最新バージョンはMavenCentralからダウンロードできます。

5. こんにちは、Kubernetes

それでは、利用可能なノードとそれらに関する情報を一覧表示する、非常に単純なKubernetesアプリケーションを作成しましょう。

このアプリケーションは単純ですが、実行中のクラスターに接続してAPI呼び出しを実行するために実行する必要のある手順を示しています。 実際のアプリケーションで使用するAPIに関係なく、これらの手順は常に同じです。

5.1. ApiClient初期化

ApiClientクラスは、Kubernetes APIサーバーへの呼び出しを実行するためのすべてのロジックが含まれているため、APIで最も重要なクラスの1つです。 このクラスのインスタンスを作成するための推奨される方法は、Configクラスから使用可能な静的メソッドの1つを使用することです。 特に、これを行う最も簡単な方法は、 defaultClient()メソッドを使用することです。

ApiClient client = Config.defaultClient();

このメソッドを使用すると、コードがリモートシナリオとクラスター内シナリオの両方で機能することが保証されます。 また、kubectlユーティリティが構成ファイルを見つけるために使用するのと同じ手順を自動的に実行します。

  • KUBECONFIG環境変数で定義された構成ファイル
  • $ HOME / .kube /configファイル
  • /var/run/secrets/kubernetes.io/serviceaccountの下のサービスアカウントトークン
  • http:// localhost:8080への直接アクセス

3番目のステップは、適切なサービスアカウントが利用可能である限り、アプリをポッドの一部としてクラスター内で実行できるようにするステップです。

また、構成ファイルで複数のコンテキストが定義されている場合、この手順では、 kubectl config set-contextコマンドを使用して定義された「現在の」コンテキストが選択されることに注意してください。

5.2. APIスタブの作成

ApiClient インスタンスを取得したら、それを使用して、使用可能な任意のAPIのスタブを作成できます。 この例では、 CoreV1Api クラスを使用します。このクラスには、使用可能なノードを一覧表示するために必要なメソッドが含まれています。

CoreV1Api api = new CoreV1Api(client);

ここでは、既存のApiClientを使用してAPIスタブを作成しています。

引数なしのコンストラクターも利用できることに注意してください。ただし、一般的には、使用を控える必要があります not を使用する理由は、内部的には、 Configuration.setDefaultApiClient()を介して事前に設定する必要があるグローバルApiClientを使用するという事実です。 これにより、スタブを使用する前にこのメソッドを呼び出す誰かに暗黙の依存関係が作成され、ランタイムエラーやメンテナンスの問題が発生する可能性があります。

より良いアプローチは、依存性注入フレームワークを使用してこの初期配線を行い、必要な場所に結果のスタブを注入することです。

5.3. KubernetesAPIの呼び出し

最後に、使用可能なノードを返す実際のAPI呼び出しに取り掛かりましょう。 CoreApiV1 スタブにはこれを正確に実行するメソッドがあるため、これは簡単になります。

V1NodeList nodeList = api.listNode(null, null, null, null, null, null, null, null, 10, false);
nodeList.getItems()
  .stream()
  .forEach((node) -> System.out.println(node));

この例では、オプションであるため、メソッドのほとんどのパラメーターにnullを渡します。最後の2つのパラメーターは、呼び出しタイムアウトとを指定するため、すべてのlistXXX呼び出しに関連します。これがWatch呼び出しであるかどうか。 メソッドのシグネチャをチェックすると、残りの引数が明らかになります。

public V1NodeList listNode(
  String pretty,
  Boolean allowWatchBookmarks,
  String _continue,
  String fieldSelector,
  String labelSelector,
  Integer limit,
  String resourceVersion,
  String resourceVersionMatch,
  Integer timeoutSeconds,
  Boolean watch) {
    // ... method implementation
}

この簡単な紹介では、ページング、監視、およびフィルターの引数を無視します。 この場合の戻り値は、返されたドキュメントのJava表現を持つPOJOです。 このAPI呼び出しの場合、ドキュメントには V1Node オブジェクトのリストと、各ノードに関するいくつかの情報が含まれています。 このコードによってコンソールで生成される典型的な出力は次のとおりです。

class V1Node {
    metadata: class V1ObjectMeta {
        labels: {
            beta.kubernetes.io/arch=amd64,
            beta.kubernetes.io/instance-type=k3s,
            // ... other labels omitted
        }
        name: rancher-template
        resourceVersion: 29218
        selfLink: null
        uid: ac21e09b-e3be-49c3-9e3a-a9567b5c2836
    }
    // ... many fields omitted
    status: class V1NodeStatus {
        addresses: [class V1NodeAddress {
            address: 192.168.71.134
            type: InternalIP
        }, class V1NodeAddress {
            address: rancher-template
            type: Hostname
        }]
        allocatable: {
            cpu=Quantity{number=1, format=DECIMAL_SI},
            ephemeral-storage=Quantity{number=18945365592, format=DECIMAL_SI},
            hugepages-1Gi=Quantity{number=0, format=DECIMAL_SI},
            hugepages-2Mi=Quantity{number=0, format=DECIMAL_SI},
            memory=Quantity{number=8340054016, format=BINARY_SI}, 
            pods=Quantity{number=110, format=DECIMAL_SI}
        }
        capacity: {
            cpu=Quantity{number=1, format=DECIMAL_SI},
            ephemeral-storage=Quantity{number=19942490112, format=BINARY_SI}, 
            hugepages-1Gi=Quantity{number=0, format=DECIMAL_SI}, 
            hugepages-2Mi=Quantity{number=0, format=DECIMAL_SI}, 
            memory=Quantity{number=8340054016, format=BINARY_SI}, 
            pods=Quantity{number=110, format=DECIMAL_SI}}
        conditions: [
            // ... node conditions omitted
        ]
        nodeInfo: class V1NodeSystemInfo {
            architecture: amd64
            kernelVersion: 4.15.0-135-generic
            kubeProxyVersion: v1.20.2+k3s1
            kubeletVersion: v1.20.2+k3s1
            operatingSystem: linux
            osImage: Ubuntu 18.04.5 LTS
            // ... more fields omitted
        }
    }
}

ご覧のとおり、利用できる情報はかなりたくさんあります。 比較のために、これはデフォルト設定での同等のkubectl出力です。

root@rancher-template:~# kubectl get nodes
NAME               STATUS   ROLES                  AGE   VERSION
rancher-template   Ready    control-plane,master   24h   v1.20.2+k3s1

6. 結論

この記事では、Java用のKubernetesAPIの簡単な紹介を紹介しました。 今後の記事では、このAPIをさらに深く掘り下げ、その追加機能のいくつかを探求します。

  • 利用可能なAPI呼び出しバリアントの違いを説明する
  • Watchを使用してクラスターイベントをリアルタイムで監視する
  • ページングを使用して、クラスターから大量のデータを効率的に取得する方法

いつものように、例の完全なソースコードはGitHubにあります。