1. 序章

このチュートリアルでは、公式のJavaAPIを使用したKubernetesリソースでのCRUD操作について説明します。

このAPIの基本的な使用法については、基本的なプロジェクトのセットアップさまざまな方法など、実行中のクラスターに関する情報を取得するために使用できる方法など、以前の記事ですでに説明しました。

一般に、Kubernetesのデプロイはほとんど静的です。 いくつかのアーティファクトを作成します(例: YAMLファイル)作成したいものを記述し、DevOpsパイプラインに送信します。 新しいコンポーネントを追加するか、既存のコンポーネントをアップグレードするまで、システムの各部分は同じままです。

ただし、その場でリソースを追加する必要がある場合があります。 一般的なものは、ユーザーが開始した要求に応答してJobsを実行しています。 それに応じて、アプリケーションはバックグラウンドジョブを起動してレポートを処理し、後で取得できるようにします。

ここで重要なのは、これらのAPIを使用することで、必要なときにのみリソースを消費し、後で解放できるため、利用可能なインフラストラクチャをより有効に活用できることです。

2. 新しいリソースの作成

この例では、Kubernetesクラスターにジョブリソースを作成します。 ジョブは、他の種類とは異なり、完了するまで実行される一種のKubernetesワークロードです。 つまり、ポッドで実行されているプログラムが終了すると、ジョブ自体が終了します。 そのYAML表現は、他のリソースと同じです。

apiVersion: batch/v1
kind: Job
metadata:
  namespace: jobs
  name: report-job
  labels:
    app: reports
spec:
  template:
    metadata:
      name: payroll-report
    spec:
      containers:
      - name: main
        image: report-runner
        command:
        - payroll
        args:
        - --date
        - 2021-05-01
      restartPolicy: Never

Kubernetes APIは、同等のJavaオブジェクトを作成するための2つの方法を提供します。

  • new を使用してPOJOSを作成し、セッターを介して必要なすべてのプロパティを入力します
  • 流暢なAPIを使用してJavaリソース表現を構築する

どのアプローチを使用するかは、主に個人的な好みです。 ここでは、流暢なアプローチを使用して V1Job オブジェクトを作成します。これは、構築プロセスが対応するYAMLと非常によく似ているためです。

ApiClient client  = Config.defaultClient();
BatchV1Api api = new BatchV1Api(client);
V1Job body = new V1JobBuilder()
  .withNewMetadata()
    .withNamespace("report-jobs")
    .withName("payroll-report-job")
    .endMetadata()
  .withNewSpec()
    .withNewTemplate()
      .withNewMetadata()
        .addToLabels("name", "payroll-report")
        .endMetadata()
      .editOrNewSpec()
        .addNewContainer()
          .withName("main")
          .withImage("report-runner")
          .addNewCommand("payroll")
          .addNewArg("--date")
          .addNewArg("2021-05-01")
          .endContainer()
        .withRestartPolicy("Never")
        .endSpec()
      .endTemplate()
    .endSpec()
  .build(); 
V1Job createdJob = api.createNamespacedJob("report-jobs", body, null, null, null);

まず、 ApiClient を作成し、次にAPIスタブインスタンスを作成します。 JobリソースはBatchAPI、の一部であるため、 BatchV1Api インスタンスを作成します。これを使用して、クラスターのAPIサーバーを呼び出します。

次に、 V1JobBuilder インスタンスをインスタンス化します。これにより、すべてのプロパティを入力するプロセスが実行されます。  ネストされたビルダーの使用に注意してください。ネストされたビルダーを「閉じる」には、その endXXX()メソッドを呼び出す必要があります。これにより、親ビルダーに戻ります。

または、 withXXX メソッドを使用して、ネストされたオブジェクトを直接挿入することもできます。 これは、メタデータ、ラベル、注釈などの一般的なプロパティのセットを再利用する場合に役立ちます。

最後のステップは、APIスタブの呼び出しです。 これにより、リソースオブジェクトがシリアル化され、リクエストがサーバーにPOSTされます。 予想どおり、APIには同期バージョン(上記で使用)と非同期バージョンがあります。

返されるオブジェクトには、作成されたジョブに関連するメタデータとステータスフィールドが含まれます。 Job の場合、そのステータスフィールドを使用して、いつ終了したかを確認できます。 また、この通知を受信するためのリソースの監視に関する記事で紹介した手法の1つを使用することもできます。

3. 既存のリソースの更新

既存のリソースの更新は、変更するフィールドを含むPATCHリクエストをKubernetesAPIサーバーに送信することで構成されます。 Kubernetesバージョン1.16以降、これらのフィールドを指定する方法は4つあります。

  • JSONパッチ(RFC 6092)
  • JSONマージパッチ(RFC 7396)
  • 戦略的マージパッチ
  • YAMLを適用する

これらのうち、最後の1つは、すべてのマージと競合解決をサーバーに任せるため、最も簡単に使用できます。必要なのは、変更するフィールドを含むYAMLドキュメントを送信することだけです。

残念ながら、Java APIには、この部分的なYAMLドキュメントを作成する簡単な方法がありません。 代わりに、 PatchUtil ヘルパークラスを使用して、生のYAMLまたはJSON文字列を送信する必要があります。 ただし、ApiClientオブジェクトから利用できる組み込みのJSONシリアライザーを使用して取得できます。

V1Job patchedJob = new V1JobBuilder(createdJob)
  .withNewMetadata()
    .withName(createdJob.getMetadata().getName())
    .withNamespace(createdJob.getMetadata().getNamespace())
    .endMetadata()
  .editSpec()
    .withParallelism(2)
  .endSpec()
  .build();

String patchedJobJSON = client.getJSON().serialize(patchedJob);

PatchUtils.patch(
  V1Job.class, 
  () -> api.patchNamespacedJobCall(
    createdJob.getMetadata().getName(), 
    createdJob.getMetadata().getNamespace(), 
    new V1Patch(patchedJobJSON), 
    null, 
    null, 
    "baeldung", 
    true, 
    null),
  V1Patch.PATCH_FORMAT_APPLY_YAML,
  api.getApiClient());

ここでは、 createNamespacedJob()から返されたオブジェクトをテンプレートとして使用し、そこからパッチを適用したバージョンを作成します。 この場合、 parallelism の値を1から2に増やし、他のすべてのフィールドは変更しません。 ここで重要な点は、変更されたリソースを構築するときに、 withNewMetadata()。  これにより、リソースの作成後に取得した返されたオブジェクトに存在する管理フィールドを含むオブジェクトを作成しないようになります。 管理対象フィールドの詳細とKubernetesでの使用方法については、ドキュメントを参照してください。

変更されたフィールドを使用してオブジェクトを作成したら、serializeメソッドを使用してオブジェクトをJSON表現に変換します。 次に、このシリアル化されたバージョンを使用して、PATCH呼び出しのペイロードとして使用されるV1Patchオブジェクトを構築します。 patch メソッドは、リクエストに存在するデータの種類を通知する追加の引数も取ります。 この場合、これは PATCH_FORMAT_APPLY_YAML であり、ライブラリはこれをHTTPリクエストに含まれるContent-Typeヘッダーとして使用します。

fieldManager パラメーターに渡される“ baeldung” 値は、リソースのフィールドを操作しているアクター名を定義します。 Kubernetesはこの値を内部的に使用して、2つ以上のクライアントが同じリソースを変更しようとした場合の最終的な競合を解決します。 また、forceパラメーターにtrueを渡します。これは、変更されたフィールドの所有権を取得することを意味します。

4. リソースの削除

以前の操作と比較すると、リソースの削除は非常に簡単です。

V1Status response = api.deleteNamespacedJob(
  createdJob.getMetadata().getName(), 
  createdJob.getMetadata().getNamespace(), 
  null, 
  null, 
  null, 
  null, 
  null, 
  null ) ;

ここでは、 deleteNamespacedJob メソッドを使用して、この特定の種類のリソースのデフォルトオプションを使用してジョブを削除しています。 必要に応じて、最後のパラメーターを使用して、削除プロセスの詳細を制御できます。 これはV1DeleteOptionsオブジェクトの形式を取り、これを使用して、依存するリソースの猶予期間とカスケード動作を指定できます。

5. 結論

この記事では、JavaKubernetesAPIライブラリを使用してKubernetesリソースを操作する方法について説明しました。 いつものように、例の完全なソースコードはGitHubにあります。