使用@kubernetes/client-node对K8s自定义资源进行补丁。

3
我正在使用NodeJS构建基于Istio/K8s的平台,用于控制流量路由。我需要能够以编程方式修改自定义资源,并希望使用@kubernetes/node-client进行操作。在文档和存储库中,我没有找到访问自定义资源的正确API,我是否漏掉了什么?谢谢。

编辑:当使用CustomObjectApi.patchNamespacedCustomObject函数时,我从K8s API收到以下错误:

message: 'the body of the request was in an unknown format - accepted media types include: application/json-patch+json, application/merge-patch+json, application/apply-patch+yaml', reason: 'UnsupportedMediaType', code: 415

我的代码:

const k8sYamls = `${path.resolve(path.dirname(__filename), '..')}/k8sYamls`
const vServiceSpec = read(`${k8sYamls}/${service}/virtual-service.yaml`)
const kc = new k8s.KubeConfig()
kc.loadFromDefault()
const client = kc.makeApiClient(k8s.CustomObjectsApi)
const result = await client.patchNamespacedCustomObject(vServiceSpec.apiVersion.split('/')[0], vServiceSpec.apiVersion.split('/')[1], namespace, 'virtualservices', vServiceSpec.metadata.name, vServiceSpec)

virtual-service.yaml:

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: message-service
spec:
  hosts:
  - message-service
  http:
  - name: 'production'
    route:
    - destination:
        host: message-service
      weight: 100
    retries:
      attempts: 3
      perTryTimeout: 2s
      retryOn: 5xx
5个回答

5

在那个方法中,我使用了错误的类型来表示 body 对象。我成功运行它后,遵循了 这个示例

const patch = [
  {
    "op": "replace",
    "path":"/metadata/labels",
    "value": {
      "foo": "bar"
    }
  }
];
const options = { "headers": { "Content-type": k8s.PatchUtils.PATCH_FORMAT_JSON_PATCH}};
k8sApi.patchNamespacedPod(res.body.items[0].metadata.name, 'default', patch, undefined, undefined, undefined, undefined, options)
  .then(() => { console.log("Patched.")})
  .catch((err) => { console.log("Error: "); console.log(err)});

2

由于已接受的答案编辑队列已满,我将在此提供一个使用patchNamespacedCustomObject的工作示例和更详细的答案:

以下是一些有用的链接:

import * as k8s from "@kubernetes/client-node";
import { CustomObjectsApi, KubeConfig } from "@kubernetes/client-node";

export async function patchCustomResource(newValue: any) {
  const kc: KubeConfig = new k8s.KubeConfig();
  kc.loadFromDefault();
  
  const custObjApi: CustomObjectsApi = kc.makeApiClient(k8s.CustomObjectsApi);
  
  const objectName = 'your-object';
  const options = { "headers": { "Content-type": k8s.PatchUtils.PATCH_FORMAT_JSON_PATCH}};
  const group = 'your-group'; // found in the CRD
  const version = 'v1'; // found in the CRD
  const plural = 'object-plural'; // found in the CRD
  const namespace = `your-namespace`;

  // this will replace the value at `"/spec/path/to/modify"` with the contents of `newValue`
  const patch = [{
    "op": "replace",
    "path":"/spec/path/to/modify", 
    "value": newValue
  }];

  try {
    await custObjApi.patchNamespacedCustomObject(group, version, namespace, plural, objectName, patch, undefined, undefined, undefined, options);
    console.log(`Successfully updated custom resource`);
  } catch (error) {
    const {body} = error;
    console.log(body.message);
  }
}

我建议任何人花时间阅读CustomObjectsAPI文档,以更熟悉可用的方法。文档内容丰富,但至少浏览一下方法名称是值得的。


1
您可以使用customObjectsApipatchClusterCustomObjectpatchNamespacedCustomObject方法,具体取决于所给对象是否有命名空间。

使用CustomObjectApi时,我从K8s API收到以下错误信息:message: '请求的主体格式未知 - 可接受的媒体类型包括:application/json-patch+json、application/merge-patch+json、application/apply-patch+yaml',reason: 'UnsupportedMediaType',code: 415 - undefined
@AleksanderNowak 你能试试用replaceNamespacedCustomObject作为替代方案吗?只是为了看看它是否有效。 - undefined
当然。它给出了另一个错误:virtualservices.networking.istio.io "message-service" 无效:metadata.resourceVersion: 无效的值:0x0:必须为更新指定。上面附上了我的VirtualService规范。 - undefined

0
实际上,Kubernetes API(以及JavaScript客户端API)支持多种补丁格式,包括:
- `application/json-patch+json`(`k8s.PatchUtils.PATCH_FORMAT_JSON_PATCH`) - `application/merge-patch+json`(`k8s.PatchUtils.PATCH_FORMAT_JSON_MERGE_PATCH`) - `application/strategic-merge-patch+json`(`k8s.PatchUtils.PATCH_FORMAT_STRATEGIC_MERGE_PATCH`) - `application/apply-patch+yaml`(`k8s.PatchUtils.PATCH_FORMAT_APPLY_YAML`)
补丁格式的类型决定了在调用相应的“patch”方法时,body参数的预期格式。例如,如果您想要修改命名空间自定义资源的finalizers,您可以使用application/json-patch+json编码提供类似之前示例的body。
// This body is in the format expected by 'application/json-patch+json'
const body = [{
  "op": "replace",
  "path": "/metadata/finalizers",
  "value": updatedFinalizers
}];

// Specify 'application/json-patch+json' content type
const options = { headers: { 'Content-Type': k8s.PatchUtils.PATCH_FORMAT_JSON_PATCH } };

await custObjApi.patchNamespacedCustomObject(group, version, namespace,
  plural, objectName, body, undefined, undefined, undefined, options);

然而,你也可以使用'application/merge-patch+json'选项,并按照以下方式执行相同的更新:
// This body is in the format expected by 'application/merge-patch+json'
const body = {
  metadata: {
    finalizers: updatedFinalizers
  }
};

// Specify 'application/merge-patch+json' content type
const options = { headers: { 'Content-Type': k8s.PatchUtils.PATCH_FORMAT_JSON_MERGE_PATCH } };

await custObjApi.patchNamespacedCustomObject(group, version, namespace,
  plural, objectName, body, undefined, undefined, undefined, options);

-1

在使用@kubernetes/node-client时,我不断地遇到无尽的解析错误,因此选择在我的NodeJS工作节点上安装kubectl并使用shell.js来运行它。

我的结论是,在使用Istio自定义资源时,@kubernetes/node-client存在缺陷,但我不想花时间调试出错的原因。我很快会在他们的存储库中发布Github问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接