使用 Java Kubernetes API 創建、更新和刪除資源
- Docker
- Kubernete
一、簡介
在本教程中,我們將使用其官方 Java API 介紹對 Kubernetes 資源的 CRUD 操作。
我們已經在之前的文章中介紹了此 API 使用的基礎知識,包括基本的項目設置以及我們可以使用它來獲取有關正在運行的集群的信息的各種方法。
一般來說,Kubernetes 部署大多是靜態的。我們創建了一些工件(例如 YAML 文件)來描述我們想要創建的內容並將它們提交到 DevOps 管道。然後我們系統的各個部分保持不變,直到我們添加新組件或升級現有組件。
但是,有些情況下我們需要動態添加資源。常見的一種是運行作業以響應用戶發起的請求。作為響應,應用程序將啟動後台作業來處理報告並使其可用於以後檢索。
這裡的關鍵是,通過使用這些 API,我們可以更好地利用可用的基礎設施,因為我們可以僅在需要時消耗資源,然後再釋放它們。
2. 創建新資源
在這個例子中,我們將在 Kubernetes 集群中創建一個 Job 資源。作業是一種 Kubernetes 工作負載,與其他類型不同,它會一直運行到完成。也就是說,一旦在其 pod 中運行的程序終止,作業本身就會終止。它的 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 對象的方法:
-
new
創建 POJOS 並通過 setter 填充所有必需的屬性 - 使用 fluent API 構建 Java 資源表示
使用哪種方法主要是個人喜好。在這裡,我們將使用 fluent 方法來創建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
資源是Batch API,
一部分,因此我們創建了一個BatchV1Api
實例,我們將使用它來調用集群的 API 服務器。
接下來,我們實例化一個V1JobBuilder
實例,這會引導我們完成填充所有屬性的過程。注意嵌套構建器的使用:要“關閉”嵌套構建器,我們必須調用其endXXX()
方法,這會將我們帶回其父構建器。
或者,也可以使用withXXX
方法直接注入嵌套對象。當我們想要重用一組通用屬性(例如元數據、標籤和註釋)時,這很有用。
最後一步只是調用 API 存根。這將序列化我們的資源對象和 POST 對服務器的請求。正如預期的那樣,API 有同步(上面使用)和異步版本。
返回的對象將包含與創建的作業相關的元數據和狀態字段。 Job
的情況下,我們可以使用它的 status 字段來檢查它何時完成。我們還可以使用我們關於監控資源的文章中介紹的一種技術來接收此通知。
3. 更新現有資源
更新現有資源包括向 Kubernetes API 服務器發送 PATCH 請求,其中包含我們要修改的字段。從 Kubernetes 1.16 版開始,有四種方法可以指定這些字段:
- JSON 補丁 (RFC 6092)
- JSON 合併補丁 (RFC 7396)
- 戰略合併補丁
- 應用 YAML
其中,最後一個是最容易使用的,因為它將所有合併和衝突解決留給服務器:我們所要做的就是發送一個包含我們要修改的字段的 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 表示。然後我們使用這個序列化版本來構造一個V1Patch
對象,用作 PATCH 調用的有效負載。 patch
方法還需要一個額外的參數,我們通知請求中存在的數據類型。在我們的例子中,這是PATCH_FORMAT_APPLY_YAML
,庫將其用作 HTTP 請求中包含Content-Type
傳遞給fieldManager
參數的“baeldung”
值定義了操作資源字段的參與者姓名。當兩個或多個客戶端嘗試修改同一資源時,Kubernetes 在內部使用此值來解決最終衝突。我們還在force
true
,這意味著我們將獲得任何修改字段的所有權。
4. 刪除資源
與之前的操作相比,刪除資源非常簡單:
V1Status response = api.deleteNamespacedJob(
createdJob.getMetadata().getName(),
createdJob.getMetadata().getNamespace(),
null,
null,
null,
null,
null,
null ) ;
在這裡,我們只是使用deleteNamespacedJob
方法使用這種特定類型資源的默認選項刪除作業。如果需要,我們可以使用最後一個參數來控制刪除過程的細節。這採用V1DeleteOptions
對象的形式,我們可以使用它來指定任何依賴資源的寬限期和級聯行為。