简体   繁体   English

如何更新 K8S Pod 的 DNS 配置

[英]How to update DNS configuration of K8S Pod

I had a project that wanted to update the DNS configuration of Pod with Operator,我有一个项目想用 Operator 更新 Pod 的 DNS 配置,

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

but when I implemented it, I got the following error但是当我实现它时,出现以下错误

 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"}

DNSConfig and DNSPoicy fields are not declared to be unable to be updated in the source code, so why did the update fail?源代码中没有声明DNSConfig和DNSPoicy字段无法更新,那么为什么更新失败呢?

I got the same error with kubect edit pod busybox and kubectl apply -f modifyed_pod.yml(add DNSConfig) command我在使用kubect edit pod busyboxkubectl apply -f modifyed_pod.yml(add DNSConfig)命令时遇到了同样的错误

I would appreciate it if you could tell me how to solve it.如果您能告诉我如何解决它,我将不胜感激。

As the message says, Kubernetes does not support updating most pod's fields directly :正如消息所说,Kubernetes 不支持直接更新大多数 pod 的字段

Kubernetes doesn't prevent you from managing Pods directly. Kubernetes 不会阻止您直接管理 Pod。 It is possible to update some fields of a running Pod, in place.可以就地更新正在运行的 Pod 的某些字段。 However, Pod update operations like patch , and replace have some limitations:但是,诸如patchreplace类的 Pod 更新操作有一些限制:

  • Most of the metadata about a Pod is immutable.大多数关于 Pod 的元数据是不可变的。 For example, you cannot change the namespace , name , uid , or creationTimestamp fields;例如,您不能更改namespacenameuidcreationTimestamp字段; the generation field is unique. generation字段是唯一的。 It only accepts updates that increment the field's current value.它只接受增加字段当前值的更新。
  • If the metadata.deletionTimestamp is set, no new entry can be added to the metadata.finalizers list.如果设置了metadata.deletionTimestamp ,则不能将新条目添加到metadata.finalizers列表中。
  • Pod updates may not change fields other than spec.containers[*].image , spec.initContainers[*].image , spec.activeDeadlineSeconds or spec.tolerations . Pod 更新不能更改除spec.containers[*].imagespec.initContainers[*].imagespec.activeDeadlineSecondsspec.tolerations For spec.tolerations , you can only add new entries.对于spec.tolerations ,您只能添加新条目。

Why is that?这是为什么?

Pods in Kubernetes are designed as relatively ephemeral, disposable entities : Kubernetes 中的 Pod 被设计为相对短暂的、一次性的实体

You'll rarely create individual Pods directly in Kubernetes—even singleton Pods.您很少会直接在 Kubernetes 中创建单独的 Pod——即使是单例 Pod。 This is because Pods are designed as relatively ephemeral, disposable entities.这是因为 Pod 被设计为相对短暂的、一次性的实体。 When a Pod gets created (directly by you, or indirectly by a controller ), the new Pod is scheduled to run on a Node in your cluster.当 Pod 被创建时(直接由您创建,或由控制器间接创建),新 Pod 将被安排在集群中的节点上运行。 The Pod remains on that node until the Pod finishes execution, the Pod object is deleted, the Pod is evicted for lack of resources, or the node fails. Pod 将保留在该节点上,直到 Pod 完成执行、删除 Pod 对象、由于缺乏资源而驱逐Pod 或节点失败。

Kubernetes assumes that for managing pods and doing any updates you should use a workload resources instead of creating pods directly: Kubernetes 假设为了管理 Pod 和执行任何更新,您应该使用工作负载资源而不是直接创建 Pod:

Pods are generally not created directly and are created using workload resources. Pod 通常不是直接创建的,而是使用工作负载资源创建的。 See Working with Pods for more information on how Pods are used with workload resources.有关如何将 Pod 与工作负载资源一起使用的更多信息,请参阅使用 Pod Here are some examples of workload resources that manage one or more Pods:以下是管理一个或多个 Pod 的工作负载资源的一些示例:

You can easily update most fields in workload resources definition and it will work properly.您可以轻松更新工作负载资源定义中的大多数字段,它会正常工作。 Keep in mind that it won't edit any existing pods - 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——Kubernetes 将确保此过程顺利进行

Modifying the pod template or switching to a new pod template has no direct effect on the Pods that already exist.修改 Pod 模板或切换到新的 Pod 模板对已经存在的 Pod 没有直接影响。 If you change the pod template for a workload resource, that resource needs to create replacement Pods that use the updated template.如果您更改工作负载资源的 Pod 模板,则该资源需要创建使用更新模板的替换 Pod。

For example, the StatefulSet controller ensures that the running Pods match the current pod template for each StatefulSet object.例如,StatefulSet 控制器确保正在运行的 Pod 与每个 StatefulSet 对象的当前 Pod 模板匹配。 If you edit the StatefulSet to change its pod template, the StatefulSet starts to create new Pods based on the updated template.如果您编辑 StatefulSet 以更改其 pod 模板,StatefulSet 将开始基于更新的模板创建新的 Pod。 Eventually, all of the old Pods are replaced with new Pods, and the update is complete.最终,所有旧 Pod 都替换为新 Pod,更新完成。

Each workload resource implements its own rules for handling changes to the Pod template.每个工作负载资源都实现自己的规则来处理对 Pod 模板的更改。 If you want to read more about StatefulSet specifically, read Update strategy in the StatefulSet Basics tutorial.如果您想详细了解 StatefulSet,请阅读 StatefulSet 基础教程中的更新策略

So based on all above information I'd suggest to switch to workload resource, for example deployment :因此,基于以上所有信息,我建议切换到工作负载资源,例如部署

A Deployment provides declarative updates for Pods and ReplicaSets . DeploymentPodsReplicaSets提供声明性更新。

For example - right now I have pod with below definition:例如 - 现在我有以下定义的 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

When I try to run kubectl edit pod busybox command to change dnsPolicy I have the same error as you.当我尝试运行kubectl edit pod busybox命令来更改dnsPolicydnsPolicy了与您相同的错误。 However, If I changed to deployment with the same pod definition:但是,如果我更改为具有相同 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

Then if I run kubectl edit deploy busybox-deployment and change dnsPolicy field I will get a new pod with new configuration (the old pod will be automatically deleted).然后,如果我运行kubectl edit deploy busybox-deployment并更改dnsPolicy字段,我将获得一个具有新配置的新 pod(旧 pod 将被自动删除)。

Keep in mind, if you want to stick with direct pod definition, you can always just delete pod and apply a new, modified yaml as you tried ( kubectl delete pod {your-pod-name} && kubectl apply -f {modified.yaml} ).请记住,如果您想坚持使用直接 pod 定义,您可以随时删除 pod 并在尝试时应用一个新的、修改过的 yaml( kubectl delete pod {your-pod-name} && kubectl apply -f {modified.yaml} )。 It will work properly.它会正常工作。

Also check:还要检查:

Like the message says you cannot update a DNS config of a pod: Forbidden: pod updates may not change fields other than spec.containers[*].image, spec.initContainers[*].image .就像消息说您无法更新 pod 的 DNS 配置: Forbidden: pod updates may not change fields other than spec.containers[*].image, spec.initContainers[*].image

If you want to inject a DNS config into all pods you need to add the configuration before the pod is created.如果要将 DNS 配置注入所有 Pod,则需要在创建 Pod 之前添加配置。 Look into MutatingAdmissionWebhook as an approach for this.MutatingAdmissionWebhook视为解决此问题的一种方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM