【问题标题】:How to update DNS configuration of K8S Pod如何更新 K8S Pod 的 DNS 配置
【发布时间】:2021-11-03 17:24:43
【问题描述】:

我有一个项目想用 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 busyboxkubectl apply -f modifyed_pod.yml(add DNSConfig) 命令出现同样的错误。

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

【问题讨论】:

  • 您使用的是哪个 Kubernetes 版本?
  • @MikolajS。版本是 1.18

标签: kubernetes kubernetes-operator kubernetes-dns


【解决方案1】:

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

如果您想将 DNS 配置注入所有 pod,您需要在创建 pod 之前添加配置。研究 MutatingAdmissionWebhook 作为解决此问题的方法。

【讨论】:

    【解决方案2】:

    正如消息所说,Kubernetes does not support updating most pod's fields directly

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

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

    为什么会这样?

    Kubernetes 中的 Pod are designed as relatively ephemeral, disposable entities:

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

    Kubernetes assumes that for managing pods and doing any updates you should use workload resources 而不是直接创建 pod:

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

    您可以轻松更新工作负载资源定义中的大多数字段,并且它会正常工作。请记住,它不会编辑任何现有的 pod - it will delete the currently running pods with old configuration and start the new ones - Kubernetes will make sure that this process goes smoothly

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

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

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

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

    DeploymentPodsReplicaSets 提供声明式更新。

    例如 - 现在我有以下定义的 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})。它会正常工作。

    同时检查:

    【讨论】:

    • 谢谢你的回答,但是对于项目,我不知道要操作哪个workload,所以我可能看不到对应的资源,以及Pod的创建和销毁可能会导致service failure。 Lukas Eichler 的MutatingAdmissionWebhook 方案似乎更能满足我的需求。我试试看
    猜你喜欢
    • 1970-01-01
    • 2020-09-24
    • 2018-05-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-13
    • 2020-11-16
    • 1970-01-01
    相关资源
    最近更新 更多