2

我有一个项目想用 Operator 更新 Pod 的 DNS 配置,

get dns message
get matched pod
modify:
    pod.Spec.DNSConfig = CRD_SPEC
    pod.Spec.DNSPolicy = corev1.DNSNone
client.Update(ctx,&pod)

但是当我实现它时,我得到了以下错误:

 ERROR   controller-runtime.manager.controller.dnsinjection      Reconciler error        {"reconciler group": "xxxx", "reconciler kind": "xxxxx", "name": "dnsinjection", "namespace": "default", "error": "Pod \"busybox\" is invalid: spec: Forbidden: pod updates may not change fields other than `spec.containers[*].image`, `spec.initContainers[*].image`, `spec.activeDeadlineSeconds` or `spec.tolerations` (only additions to existing tolerations)\n  core.PodSpec{\n  \t... // 21 identical fields\n  \tPriority:         &0,\n  \tPreemptionPolicy: nil,\n  \tDNSConfig: &core.PodDNSConfig{\n  \t\tNameservers: []string{\n  \t\t\t\"1.2.3.4\",\n- \t\t\t\"0.0.0.0\",\n  \t\t},\n  \t\tSearches: []string{\"ns1.svc.cluster-domain.example\", \"my.dns.search.suffix\"},\n  \t\tOptions:  []core.PodDNSConfigOption{{Name: \"ndots\", Value: &\"2\"}, {Name: \"edns0\"}},\n  \t},\n  \tReadinessGates:   nil,\n  \tRuntimeClassName: nil,\n  \t... // 3 identical fields\n  }\n"}

DNSConfigDNSPoicy字段在源码中没有声明不能更新,那为什么更新失败呢?

我在使用kubect edit pod busyboxandkubectl apply -f modifyed_pod.yml(add DNSConfig)命令时遇到了同样的错误。

如果您能告诉我如何解决它,我将不胜感激。

4

2 回答 2

1

就像消息说您无法更新 pod: 的 DNS 配置一样Forbidden: pod updates may not change fields other than spec.containers[*].image, spec.initContainers[*].image

如果要将 DNS 配置注入所有 pod,则需要在创建 pod 之前添加配置。研究 MutatingAdmissionWebhook作为一种方法。

于 2021-11-01T14:40:52.183 回答
1

正如消息所说,Kubernetes不支持直接更新大多数 pod 的字段

Kubernetes 不会阻止您直接管理 Pod。可以就地更新正在运行的 Pod 的某些字段。但是,Pod 更新操作类似于 patch, 并且 replace 有一些限制:

  • 大多数关于 Pod 的元数据都是不可变的。例如,您不能更改 namespacenameuidcreationTimestamp 字段;该 generation 领域是独一无二的。它只接受增加字段当前值的更新。
  • 如果 metadata.deletionTimestamp 设置了,则不能将新条目添加到 metadata.finalizers 列表中。
  • Pod 更新可能不会更改除 spec.containers[*].image、 或 spec.initContainers[*].image之外 的字段。对于 ,您只能添加新条目。spec.activeDeadlineSecondsspec.tolerationsspec.tolerations

这是为什么?

Kubernetes 中的 Pod被设计为相对短暂的、一次性的实体

您很少会直接在 Kubernetes 中创建单独的 Pod,即使是单例 Pod。这是因为 Pod 被设计为相对短暂的、一次性的实体。当一个 Pod 被创建(由您直接创建,或由控制器间接创建)时,新的 Pod 被安排在集群中的节点上运行。Pod 将一直保留在该节点上,直到 Pod 完成执行、删除 Pod 对象、因缺乏资源而驱逐Pod 或节点失败。

Kubernetes 假设要管理 pod 和进行任何更新,您应该使用工作负载资源而不是直接创建 pod:

Pod 通常不是直接创建的,而是使用工作负载资源创建的。有关 如何将 Pod 用于工作负载资源的更多信息,请参阅使用 Pod 。以下是管理一个或多个 Pod 的工作负载资源的一些示例:

您可以轻松更新工作负载资源定义中的大多数字段,并且它将正常工作。请记住,它不会编辑任何现有的 Pod -它会删除当前运行的具有旧配置的 Pod 并启动新的 Pod - Kubernetes 将确保此过程顺利进行

修改 pod 模板或切换到新的 pod 模板对已经存在的 Pod 没有直接影响。如果您更改工作负载资源的 Pod 模板,该资源需要创建使用更新模板的替换 Pod。

例如,StatefulSet 控制器确保正在运行的 Pod 与每个 StatefulSet 对象的当前 pod 模板匹配。如果您编辑 StatefulSet 以更改其 pod 模板,则 StatefulSet 开始根据更新的模板创建新的 Pod。最终,所有旧 Pod 都被新 Pod 替换,更新完成。

每个工作负载资源都实现了自己的规则来处理对 Pod 模板的更改。如果您想详细了解 StatefulSet,请阅读 StatefulSet 基础教程中的更新策略

因此,基于以上所有信息,我建议切换到工作负载资源,例如部署

Deployment为PodReplicaSet提供 声明式更新 。

例如 - 现在我有以下定义的 pod:

apiVersion: v1
kind: Pod
metadata:
  name: busybox
  namespace: default
spec:
  containers:
  - image: busybox:1.28
    command:
      - sleep
      - "9999999"
    imagePullPolicy: IfNotPresent
    name: busybox
  restartPolicy: Always
  hostNetwork: true
  dnsPolicy: ClusterFirstWithHostNet

当我尝试运行kubectl edit pod busybox命令进行更改时dnsPolicy,我遇到了与您相同的错误。但是,如果我更改为具有相同 pod 定义的部署:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: busybox-deployment
  labels:
    app: busybox
spec:
  replicas: 1
  selector:
    matchLabels:
      app: busybox
  template:
    metadata:
      labels:
        app: busybox
    spec:
      containers:
      - image: busybox:1.28
        command:
        - sleep
        - "9999999"
        imagePullPolicy: IfNotPresent
        name: busybox
      restartPolicy: Always
      hostNetwork: true
      dnsPolicy: ClusterFirstWithHostNet

然后,如果我运行kubectl edit deploy busybox-deployment并更改dnsPolicy字段,我将获得一个具有新配置的新 pod(旧 pod 将被自动删除)。

请记住,如果您想坚持直接定义 pod,您可以随时删除 pod 并在尝试时应用一个新的、修改过的 yaml ( kubectl delete pod {your-pod-name} && kubectl apply -f {modified.yaml})。它会正常工作。

还要检查:

于 2021-11-02T12:23:54.090 回答