本文介绍了 Kubernetes 中的 DNS 分配方式

概述


Kubernetes 集群中运行了一组 DNS Pod,配置了对应的 Service,并由 kubelete 将 DNS Service 的 IP 地址配置到节点上的容器中以便解析 DNS names。

集群中的每一个 Service(包括 DNS 服务本身)都将被分配一个 DNS name。默认情况下,客户端 Pod 的 DNS 搜索列表包括 Pod 所在的名称空间以及集群的默认域。例如:

假设名称空间 bar 中有一个 Service 名为 foo:

  • 名称空间 bar 中的 Pod 可以通过 nslookup foo 查找到该 Service
  • 名称空间 quux 中的 Pod 可以通过 nslookup foo.bar 查找到该 Service

本文后面的章节详细介绍了支持的 DNS 记录类型及格式。如果有任何其他类型的格式凑巧可以使用,这仅仅是实现上的细节,并且可能在将来的版本中失效。参考此文档可以查看最新的规范 Kubernetes DNS-Based Service Discovery(opens new window)

Services


A 记录

  • Service(headless Service 除外)将被分配一个 DNS A 记录,格式为 my-svc.my-namespace.svc.cluster-domain.example。该 DNS 记录解析到 Service 的 ClusterIP。
  • Headless Service(没有 ClusterIP)也将被分配一个 DNS A 记录,格式为 my-svc.my-namespace.svc.cluster-domain.example。该 DNS 记录解析到 Service 所选中的一组 Pod 的 IP 地址的集合。调用者应该使用该 IP 地址集合,或者按照轮询(round-robin)的方式从集合中选择一个 IP 地址使用。

    SRV 记录

    Service(含 headless Service)的命名端口(有 name 的端口)将被分配一个 SRV 记录,其格式为 _my-port-name._my-port-protocol.my-svc.my-namespace.svc.cluster-domain.example:

  • 对于一个普通 Service(非 headless Service),该 SRV 记录解析到其端口号和域名 my-svc.my-namespace.svc.cluster-domain.example

  • 对于一个 Headless Service,该 SRV 记录解析到多个结果:每一个结果都对应该 Service 的一个后端 Pod,包含其端口号和 Pod 的域名 auto-generated-pod-name.my-svc.my-namespace.svc.cluster-domain.example

    Pods


Pod 的 hostname / subdomain

Kubernetes 在创建 Pod 时,将 Pod 定义中的 metadata.name 的值作为 Pod 实例的 hostname。

Pod 定义中有一个可选字段 spec.hostname 可用来直接指定 Pod 的 hostname。例如,某 Pod 的 spec.hostname 字段被设置为 my-host,则该 Pod 创建后 hostname 将被设为 my-host

Pod 定义中还有一个可选字段 spec.subdomain 可用来指定 Pod 的 subdomain。例如,名称空间 my-namespace 中,某 Pod 的 hostname 为 foo,并且 subdomain 为 bar,则该 Pod 的完整域名(FQDN)为 foo.bar.my-namespace.svc.cluster-domain.example。
例子:

  1. apiVersion: v1
  2. kind: Service
  3. metadata:
  4. name: default-subdomain
  5. spec:
  6. selector:
  7. name: busybox
  8. clusterIP: None
  9. ports:
  10. - name: foo # Actually, no port is needed.
  11. port: 1234
  12. targetPort: 1234
  13. ---
  14. apiVersion: v1
  15. kind: Pod
  16. metadata:
  17. name: busybox1
  18. labels:
  19. name: busybox
  20. spec:
  21. hostname: busybox-1
  22. subdomain: default-subdomain
  23. containers:
  24. - image: busybox:1.28
  25. command:
  26. - sleep
  27. - "3600"
  28. name: busybox
  29. ---
  30. apiVersion: v1
  31. kind: Pod
  32. metadata:
  33. name: busybox2
  34. labels:
  35. name: busybox
  36. spec:
  37. hostname: busybox-2
  38. subdomain: default-subdomain
  39. containers:
  40. - image: busybox:1.28
  41. command:
  42. - sleep
  43. - "3600"
  44. name: busybox

如果 Pod 所在名称空间中存在一个 headless Service,其名称与 Pod 的 subdomain 相同,则集群的 KubeDNS 服务器仍将为 Pod 的完整域名(FQDN)返回一个 A 记录。例如,假设一个 Pod 的 hostname 为 busybox-1 且其 subdomain 为 default-subdomain,同名称空间下有一个 headless Service 的名字为 default-subdomain,此时,该 Pod 的完整域名(FQDN)为 busybox-1.default-subdomain.my-namespace.svc.cluster-domain.example。DNS 服务将其解析到一个 A 记录,指向 Pod 的 IP 地址。上面 yaml 文件中的 Pod busybox1 和 busybox2 都将有各自的 A 记录

备注

  • A 记录不是根据 Pod name 创建的,而是根据 hostname 创建的。如果一个 Pod 没有 hostname 只有 subdomain,则 Kubernetes 将只为其 headless Service 创建一个 A 记录 default-subdomain.my-namespace.svc.cluster-domain.example,该记录指向 Pod 的 IP 地址。
  • Pod 必须达到就绪状态才可以拥有 A 记录,除非 Service 的字段 spec.publishNotReadyAddresses 被设置为 True

Pod 的 DNS Policy

可以为每一个 Pod 设置其自己的 DNS Policy。Kubernetes 通过 Pod 定义中的 spec.dnsPolicy 字段设置 DNS Policy,可选的值有:

  • Default: Pod 从其所在的节点继承域名解析配置。更多细节请参考 Customizing DNS Service(opens new window)
  • ClusterFirst:任何与集群域名后缀(例如 www.kubernetes.io)不匹配的 DNS 查询,都将被转发到 Pod 所在节点的上游 DNS 服务。集群管理员可能配置了额外的 stub-domain 及上游 DNS 服务,更多细节请参考 Customizing DNS Service(opens new window)
  • ClusterFirstWithHostNet: 对于运行在节点网络上的 Pod,其 dnsPolicy 必须指定为 ClusterFirstWithHostNet
  • None: 允许 Pod 忽略 Kubernetes 环境中的 DNS 设置。此时,该 Pod 的 DNS 的所有设置必须通过 spce.dnsConfig 指定。 参考 Pod 的 DNS 配置


dnsPolicy的默认值 “Default” 并非是默认的 DNS Policy。如果 spec.dnsPolicy 字段未指定,则 “ClusterFirst” 将被默认使用

下面的例子中的 Pod,其 DNS Policy 必须设置为 “ClusterFirstWithHostNet”,因为它的 hostNetwork 字段为 true

  1. apiVersion: v1
  2. kind: Pod
  3. metadata:
  4. name: busybox
  5. namespace: default
  6. spec:
  7. containers:
  8. - image: busybox:1.28
  9. command:
  10. - sleep
  11. - "3600"
  12. imagePullPolicy: IfNotPresent
  13. name: busybox
  14. restartPolicy: Always
  15. hostNetwork: true
  16. dnsPolicy: ClusterFirstWithHostNet

Pod 的 DNS 配置 Kuboard v1.0.8.3

Kuboard v1.0.8.3 开始,支持 Pod 的 dnsConfig 字段。配置界面在 工作负载编辑器 —> 容器组的更多设定

在 Kubernetes 中,您可以直接配置 Pod 的 DNS 设置。

Pod 定义中的 spec.dnsConfig 是可选字段,且可以与任何类型的 spec.dnsPolicy 配合使用。如果 spec.dnsPolicy 被设置为 “None”,则 spec.dnsConfig 必须被指定。

spec.dnsConfig 中有如下字段可以配置:

  • nameservers: Pod 的 DNS Server IP 地址列表。最多可以执行 3 个 IP 地址。当 spec.dnsPolicy 为 “None”,至少需要指定一个 IP 地址,其他情况下该字段是可选的。DNS Server 的 IP 地址列表将会与 DNS Policy 所产生的 DNS Server 地址列表合并(重复的条目被去除)。
  • searches:Pod 中执行域名查询时搜索域的列表。该字段是可选的。如果指定了该字段,则指定的搜索域列表将与 DNS Policy 所产生的搜索域列表合并(重复的条目被去除)。合并后的列表最多不超过 6 个域。
  • options:可选数组,其中每个元素由 name 字段(必填)和 value 字段(选填)组成。该列表中的内容将与 DNS Policy 所产生的 DNS 选项合并(重复的条目被去除) ```yaml apiVersion: v1 kind: Pod metadata: namespace: default name: dns-example spec: containers:
    • name: test image: nginx dnsPolicy: “None” dnsConfig: nameservers:
      • 1.2.3.4 searches:
      • ns1.svc.cluster-domain.example
      • my.dns.search.suffix options:
      • name: ndots value: “2”
      • name: edns0
  1. 上述 Pod 创建后,容器 test etc/resolv.conf 文件如下所示(从 spec.dnsConfig 的配置产生),执行命令 kubectl exec -it dns-example -- cat /etc/resolv.conf 可查看该文件内容:
  2. ```bash
  3. nameserver 1.2.3.4
  4. search ns1.svc.cluster-domain.example my.dns.search.suffix
  5. options ndots:2 edns0

如果集群使用的是 IPv6,执行命令 kubectl exec -it dns-example — cat /etc/resolv.conf 的输出结果如下所示:

  1. nameserver fd00:79:30::a
  2. search default.svc.cluster-domain.example svc.cluster-domain.example cluster-domain.example
  3. options ndots:5

版本兼容性

Pod 定义中的 spec.dnsConfig 和 spec.dnsPolicy=None 的兼容性如下:

Kubernetes 版本号 支持情况
1.14 Stable
1.10 Beta(默认启用)
1.9 Alpha