Fabric8io K8s java 客户端是否支持使用 YAML 片段的 patch() 或 rollingupdate()?

Does Fabric8io K8s java client support patch() or rollingupdate() using YAML snippets?

我正在尝试通过将部署片段作为输入来对 k8s 应用程序的 patching/rolling 升级进行编程。我使用 patch() 方法将代码片段应用到现有部署中,作为滚动更新的一部分,使用 fabric8io's k8s client APIS.. Fabric8.io kubernetes-client 版本 4.10.1 我还使用了 kubernetes-api 3.0.12.

中的一些 loadYaml 辅助方法

这是我的示例片段 - adminpatch.yaml 文件:

    kind: Deployment   
    spec:
      strategy:
        type: RollingUpdate
        rollingUpdate:
          maxSurge: 1
          maxUnavailable: 0     
      template:
        spec:
          containers:
            - name: ${PATCH_IMAGE_NAME}
              image: ${PATCH_IMAGE_URL}
              imagePullPolicy: Always

我将上面的文件内容(替换了所有占位符)作为字符串发送到 patchDeployment() 方法。 这是我对 fabric8 patch() 方法的调用:

     public static String patchDeployment(String deploymentName, String namespace, String deploymentYaml) {
    try {
    Deployment deploymentSnippet = (Deployment) getK8sObject(deploymentYaml);
    if(deploymentSnippet instanceof Deployment) {
            logger.debug("Valid deployment object.");
    Deployment deployment = getK8sClient().apps().deployments().inNamespace(namespace).withName(deploymentName)
        .rolling().patch(deploymentSnippet);
    System.out.println(deployment.toString());
    return getLastConfig(deployment.getMetadata(), deployment);
    }
    } catch (Exception Ex) {
      Ex.printStackTrace();
    }
      return "Failed";
  }

它抛出以下异常:

> io.fabric8.kubernetes.client.KubernetesClientException: Failure
> executing: PATCH at:
> https://10.44.4.126:6443/apis/apps/v1/namespaces/default/deployments/patch-demo.
> Message: Deployment.apps "patch-demo" is invalid: spec.selector:
> Invalid value:
> v1.LabelSelector{MatchLabels:map[string]string{"app":"nginx",
> "deployment":"3470574ffdbd6e88d426a77dd951ed45"},
> MatchExpressions:[]v1.LabelSelectorRequirement(nil)}: field is
> immutable. Received status: Status(apiVersion=v1, code=422,
> details=StatusDetails(causes=[StatusCause(field=spec.selector,
> message=Invalid value:
> v1.LabelSelector{MatchLabels:map[string]string{"app":"nginx",
> "deployment":"3470574ffdbd6e88d426a77dd951ed45"},
> MatchExpressions:[]v1.LabelSelectorRequirement(nil)}: field is
> immutable, reason=FieldValueInvalid, additionalProperties={})],
> group=apps, kind=Deployment, name=patch-demo, retryAfterSeconds=null,
> uid=null, additionalProperties={}), kind=Status,
> message=Deployment.apps "patch-demo" is invalid: spec.selector:
> Invalid value:
> v1.LabelSelector{MatchLabels:map[string]string{"app":"nginx",
> "deployment":"3470574ffdbd6e88d426a77dd951ed45"},
> MatchExpressions:[]v1.LabelSelectorRequirement(nil)}: field is
> immutable, metadata=ListMeta(_continue=null, remainingItemCount=null,
> resourceVersion=null, selfLink=null, additionalProperties={}),
> reason=Invalid, status=Failure, additionalProperties={}).

我还用 kubectl patch deployment <DEPLOYMENT_NAME> -n <MY_NAMESPACE> --patch "$(cat adminpatch.yaml) 尝试了原始代码段(带有标签和选择器),这很好地应用了相同的代码段。

我无法获得有关 fabric8io k8s 客户端补丁 () java API 的大量文档。任何帮助将不胜感激。

这是 Fabric8io rolling API 中的相关错误:https://github.com/fabric8io/kubernetes-client/issues/1868

截至目前,我发现使用 fabri8io APIs 实现修补的一种方法是:

  1. 获取运行部署对象
  2. add/replace 个容器和新容器
  3. 使用createOrReplace()API重新部署部署对象

但是可以理解,您的补丁可能不仅仅是对容器领域的更新。在那种情况下,处理每个可编辑字段会变得混乱。

我继续使用官方 K8s 客户端的 patchNamespacedDeployment() API 来实现补丁。 https://github.com/kubernetes-client/java/blob/356109457499862a581a951a710cd808d0b9c622/examples/src/main/java/io/kubernetes/client/examples/PatchExample.java

随着 Fabric8 Kubernetes Client 的最新改进,除了使用旧答案中提到的 createOrReplace() 之外,您还可以通过 patch()rolling() API 来完成。

使用 patch() 调用修补 JSON/Yaml 字符串:

根据最新版本 v5.4.0,Fabric8 Kubernetes Client 支持通过原始字符串打补丁。它可以是 YAML 或 JSON,请参阅 PatchTest.java。下面是一个使用原始 JSON 字符串更新 Deployment 图像的示例:

try (KubernetesClient kubernetesClient = new DefaultKubernetesClient()) {
  kubernetesClient.apps().deployments()
    .inNamespace(deployment.getMetadata().getNamespace())
    .withName(deployment.getMetadata().getName())
    .patch("{\"spec\":{\"template\":{\"spec\":{\"containers\":[{\"name\":\"patch-demo-ctr-2\",\"image\":\"redis\"}]}}}}");
}

滚动更新以更改容器映像:

但是,如果您只想进行滚动更新;您可能想改用 rolling() API。这是更新现有 Deployment 图像的样子:

try (KubernetesClient client = new DefaultKubernetesClient()) {
    // ... Create Deployment 

    // Update Deployment for a single container Deployment
    client.apps().deployments()
            .inNamespace(namespace)
            .withName(deployment.getMetadata().getName())
            .rolling()
            .updateImage("gcr.io/google-samples/hello-app:2.0");
}

滚动更新以更改多容器部署中的多个图像:

如果你想用多个容器更新 Deployment。您需要改用 updateImage(Map<String, String>) 方法。这是它的用法示例:

try (KubernetesClient client = new DefaultKubernetesClient()) {
    Map<String, String> containerToImageMap = new HashMap<>();
    containerToImageMap.put("nginx", "stable-perl");
    containerToImageMap.put("hello", "hello-world:linux");
    client.apps().deployments()
            .inNamespace(namespace)
            .withName("multi-container-deploy")
            .rolling()
            .updateImage(containerToImageMap);
}

滚动更新重启现有部署

如果您需要重新启动现有部署,您可以使用 rolling().restart() DSL 方法,如下所示:

try (KubernetesClient client = new DefaultKubernetesClient()) {
    client.apps().deployments()
            .inNamespace(namespace)
            .withName(deployment.getMetadata().getName())
            .rolling()
            .restart();
}