大家好!我是大聪明-PLUS

与传统的虚拟机或物理服务器相比,容器环境中的 DNS 代表着一种根本不同的范式。容器化技术带来了独特的名称解析挑战,这主要由三个关键因素驱动:隔离性、环境的动态特性以及可扩展性要求。

隔离性意味着每个容器都存在于自己的网络命名空间中,并拥有自己的 DNS 配置,需要特殊的机制来确保连接性。动态性意味着服务会不断被创建和销毁,IP 地址会发生变化,传统的静态 DNS 记录也会失效。扩展性要求每秒处理数千个 DNS 请求,并且不能出现单点故障,这需要分布式容错架构。

与传统环境中从主机继承 DNS 配置不同,容器平台创建了自己的 DNS 生态系统,具有自动服务发现、动态记录更新和复杂的名称解析策略。由于需要同时支持集群内和外部名称解析、确保高负载下的性能以及与现有企业 DNS 基础架构集成,这种复杂性更加复杂。

每个容器平台(Docker、Podman、Kubernetes)都实现了各自的 DNS 架构,并具有特定的特性、优势和缺陷。了解这些差异对于构建可靠且高性能的容器基础设施至关重要。这正是我们将在本文中探讨的内容。

这是探讨域名解析机制和 DNS 操作的系列文章的第四篇。

现在让我们转到容器,我们将逐一研究 Docker、Podman 和 Kubernetes 平台。

Docker:DNS 从简单到复杂的演变

Docker 为每个用户网络使用内置的 DNS 代理,提供自动容器名称解析。此代理运行在 127.0.0.11,主要执行两个功能:解析同一网络内的容器名称,以及将外部请求转发到主机上 daemon.json 或 resolv.conf 中配置的 DNS 服务器。

rootful 模式下的 DNS 架构

在经典的 rootful 模式下,Docker 为容器创建默认的 DNS 配置:


nameserver 127.0.0.11
options ndots:0

Docker DNS代理接受来自容器的请求并按如下方式处理它们:

  • 内部名称:解析 Docker 用户网络内的容器和服务名称

  • 外部名称:将查询转发到守护进程配置或主机 resolv.conf 中指定的 DNS 服务器

  • 范围:适用于所有 Docker 网络类型,包括默认桥接网络,但具有不同的功能:

  • 在用户网络中提供内置容器名称解析

  • 在默认桥接网络中,自动容器名称解析不起作用;只有一种旧机制可用--link,它将条目添加到/etc/hosts

可以在以下位置配置全局 Docker 设置/etc/docker/daemon.json

{
  "dns": ["<dns1>", "<dns2>"],
  "dns-opts": ["use-vc", "rotate"],
  "dns-search": ["example.com"]
}

无根模式的特点

无根 Docker 从根本上改变了网络架构。它不再直接访问主机网络堆栈,而是使用具有隔离网络环境的用户命名空间。主要区别包括:

网络堆栈:使用 slirp4netns 或 RootlessKit 在用户空间模拟网络堆栈。

DNS配置:容器接收DNS服务器10.0.2.3而不是传统的127.0.0.11。

```bash
nameserver 10.0.2.3
```

性能问题:由于数据包转发的开销,无根模式的网络性能明显较差。

源 IP 转发:默认情况下,源 IP 地址无法正确转发,这对于 DNS 或代理等网络服务至关重要。这需要特殊配置:

```bash
[Service]
Environment="DOCKERD_ROOTLESS_ROOTLESSKIT_PORT_DRIVER=slirp4netns"
```

Docker DNS 已知问题

与 systemd-resolved 冲突:自动 127.0.0.53 解析可能会破坏容器中的 DNS。

解决方案:/etc/docker/daemon.json使用显式 DNS 服务器进行配置:

{
  "dns": ["<dns1>", "<dns2>"],
  "dns-opts": [],
  "dns-search": []
}

VPN 问题: DNS 请求可能无法通过 VPN 隧道,从而导致 DNS 泄漏。

解决方案:强制通过 VPN 进行 DNS 路由:


docker run --dns 10.8.0.1 --dns-search vpn.local myimage

{
  "dns": ["10.8.0.1"]  
}

resolv.conf 的过时副本:对主机文件的更改不会影响正在运行的容器,直到它们重新启动。

# 选项 1:更改主机 DNS 后重启容器

docker restart $(docker ps -q)

# 选项 2:resolv.conf作为卷安装(实时更新)

docker run -v /etc/resolv.conf:/etc/resolv.conf:ro myimage

# 选项 3:使用带有明确服务器的 --dns 标志,或者在 daemon.json 中指定它们

Podman:从 CNI 到现代 Netavark

Podman 代表了容器领域 DNS 架构最具活力的演进,从传统的 CNI 过渡到现代的 Netavark/aardvark-dns 解决方案。这一转变反映了行业整体趋势,即追求更高性能、功能更丰富的 DNS 解决方案。

CNI 架构(传统模式)

在 4.0 版本之前,Podman 使用 CNI(容器网络接口)和 dnsname 插件进行容器名称解析。该架构包括:

  • dnsmasq 作为 DNS 服务器:为每个 CNI 网络创建单独的 dnsmasq 实例

  • 基于文件的记录存储:DNS 记录存储在目录/run/containers/cni/dnsname$XDG_RUNTIME_DIR/containers/cni/dnsname

  • 功能有限:仅支持基本的 A 记录解析,不支持 PTR 和其他记录类型

带有 dnsname 的 CNI 网络配置如下所示:

{
    "cniVersion": "0.4.0",
    "name": "cni-bridge-network",
    "plugins": [
      {
        "type": "bridge",
        "bridge": "cni0"
      },
      {
        "type": "dnsname",
        "domainName": "foobar.com",
        "capabilities": {
            "aliases": true
        }
      }
    ]
}

CNI 方法的主要缺点是 dnsmasq 在高负载下的性能较差、缺乏对现代 DNS 功能的支持、配置和维护的复杂性以及与现代容器编排器的集成有限。

过渡到 Netavark 和 aardvark-dns

从 Podman 4.0 开始,默认使用带有 aardvark-dns DNS 服务器的新 Netavark 网络堆栈。这一革命性的变化带来了诸多改进:

  • Aardvark-dns 作为权威服务器:基于 Rust 的容器 A/AAAA 记录权威 DNS 服务器

  • PTR 记录支持:自动创建反向 DNS 记录以简化诊断

  • 性能提升:与 dnsmasq 相比性能显著提高

  • 更好的 IPv6 支持:特别是在 NAT 和端口转发领域

典型的 Netavark 网络配置:

{
    "name": "mynetwork",
    "id": "3977b0c90383b8460b75547576dba6ebcf67e815f0ed0c4b614af5cb329ebb83",
    "driver": "bridge",
    "network_interface": "podman1",
    "created": "2022-09-06T12:08:12.853219229Z",
    "subnets": [{
        "subnet": "10.89.0.0/24",
        "gateway": "10.89.0.1"
    }],
    "ipv6_enabled": false,
    "internal": false,
    "dns_enabled": true,
    "ipam_options": {
        "driver": "host-local"
    }
}

与 CNI 不同,Netavark 提供与容器运行时的原生集成、创建和删除容器时的自动 DNS 记录管理以及现代监控和调试功能。


podman info --format '{{.Host.NetworkBackend}}'

无根 Podman 中的 DNS

Podman 的无根模式对 DNS 架构提出了特殊要求,因为它缺乏创建成熟桥接网络的权限。 

slirp4netns:传统无根网络

在使用 slirp4netns 的经典无根模式下,Podman 会创建一个隔离的网络环境:


nameserver 10.0.2.3
options edns0 trust-ad
search

slirp4netns 中的 DNS 架构:

• DNS 服务器 10.0.2.3 - 内置 DNS 代理 slirp4netns

• 通过用户模式 ​​NAT 自动转换 DNS 查询

• 具有自己的路由表的独立命名空间

• 可预测但有限的网络配置

slirp4netns 的主要限制:

• 由于缺乏权限,无法充分发挥 Netavark 的潜力

• 向用户空间广播数据包的额外开销

• 解析本地主机名的问题

• 对 IPv6 DNS 查询的支持有限

• 性能明显比本机网络差

Pasta/Passt 革命:新的无根 DNS 标准

从 Podman 5.3 开始,pasta/passt 成为许多发行版中新安装的默认网络后端,取代了 slirp4netns 并从根本上改变了 DNS 的方法。


nameserver 192.168.1.1    
nameserver <dns1>        
search home.local         
options edns0 trust-ad

Pasta(Pack A Subtle Tap Abstraction)建立在 passt(Plug A Simple Socket Transport)之上,passt 是一种现代网络驱动程序,它为用户模式下的虚拟机和容器提供准原生网络连接,而无需特权。 

与 slirp4netns 的主要区别在于,pasta 默认不使用网络地址转换 (NAT),而是将 IP 地址从主机的主接口复制到容器的命名空间。

转换层架构:Pasta 在虚拟二层网络接口和主机上的原生四层套接字(TCP、UDP、ICMP)之间实现了一个转换层。这从网络角度营造出一种容器化应用程序进程在本地主机上运行的错觉。

内置网络服务:pasta 包括 ARP、DHCP、NDP 和 DHCPv6 的本机实现,为容器提供尽可能接近本机主机配置的网络配置。

架构改进:

  • 使用主机 IP 地址而不是预定义的容器 IP(10.0.2.x)

  • 使用主机的网络接口名称而不是默认名称。tap0

  • 使用主机的网关地址而不是其自己的网关NAT

Pasta 对 DNS 的主要好处:

直接继承 DNS 配置:pasta 将/etc/resolv.conf主机复制到容器中,确保 DNS 配置完全相同。这与使用自身 DNS 代理的 slirp4netns 有着根本的不同。

内置 DNS 服务:pasta 包含其自己的实现:

  • 用于自动 DNS 配置的 DHCP 服务器

  • DNS 转发器,用于高效转发查询

  • 用于解析本地名称的 ARP 解析器

  • 适用于现代双栈环境的 NDP(IPv6)

准原生 DNS 解析: pasta 模拟直接在主机上执行 DNS 查询,消除中间代理层。

Netavark 中的 DNS 管理

Netavark 提供现代 DNS 管理功能,可以通过各种方式与无根网络后端进行交互。

处于 rooted 模式(完整的 Netavark 功能)

podman network create --driver bridge \
  --dns <dns2> \
  --dns <dns1> \
  --dns-search company.local \
  custom-dns-net


podman network update custom-dns-net --dns-add 9.9.9.9
podman network update custom-dns-net --dns-search-add internal.local


nslookup webapp.dns.podman 10.89.0.1
使用 slirp4netns 的无根模式

Slirp4netns 不支持 Netavark 的全部功能。DNS 设置受到限制:

• 无法使用 DNS 设置创建自定义桥接网络

• 由于用户命名空间隔离,Aardvark-dns 不可用

• DNS 配置完全由 slirp4netns 决定


podman run --dns <dns1> --dns-search company.local alpine

在无根模式下使用 pasta/past

Pasta 提供了与 Netavark 的扩展兼容性:

• 通过 Pasta 选项支持自定义 DNS 设置

• 部分支持网络管理命令

• 与主机 DNS 配置自动集成


podman run --network pasta:-a,10.0.2.0,-n,24,-g,10.0.2.2,--dns-forward,10.0.2.3 alpine


podman run --dns <dns2> --dns-search internal.local \
  --network pasta:--map-guest-addr=172.16.1.100 alpine

Podman DNS 已知问题

Aardvark-DNS无法解析名称

中的名称解析失败Podman 4.x с Netavark/aardvark-dns。 

可以通过更新到最新版本并重新配置网络来解决。

容器之间的 DNS 解析延迟过长 

aardvark-dns 1.1.x-1.5.在x 版本中,对等 pod 之间的 DNS 查询会长时间挂起。

在 1.6+ 版本中已修复

rootful模式下DNS解析默认为8.8.8.8

Podman rootful CNI DNS 解析未正确配置默认 DNS 服务器。

https://github.com/containers/podman/issues/10570

已在 GitHub 问题容器/podman#10570 中解决

podman 运行中忽略 DNS 设置在

在 podman run 中指定的 DNS 参数未应用于 Netavark 早期版本中的 /etc/resolv.conf。

https://github.com/containers/netavark/issues/855

在 aardvark-dns 1.6.0+ 和 netavark 1.6.0+ 中修复  

Podman 展现了容器平台中 DNS 架构最活跃的演进,成功实现了从 CNI 到有根模式下的 Netavark 的过渡,并革命性地引入了用于无根容器的 pasta/passt 功能。大多数关键 DNS 问题在最新版本中都已得到解决,这使得 Podman 成为 Docker 在生产部署中极具吸引力的替代方案,具有良好的 DNS 性能和先进的管理功能。

我正在尝试向同事解释为什么 DNS 在他的无根 Podman 容器中不起作用。

我正在尝试向同事解释为什么 DNS 在他的无根 Podman 容器中不起作用。

Kubernetes:企业 DNS 的复杂性

Kubernetes 拥有容器平台中最复杂、功能最丰富的 DNS 架构。其核心组件是 CoreDNS,这是一个模块化 DNS 服务器,负责为域名提供服务*.cluster.local,并将其他请求转发到外部 DNS 服务器。

CoreDNS基本架构

CoreDNS 作为 Deployment 部署在 kube-system 命名空间中,可通过名为 kube-dns 的服务访问:


nameserver 10.96.0.10
search default.svc.cluster.local svc.cluster.local cluster.local
options ndots:5

IP地址10.96.0.10对应kube-dns服务的ClusterIP:

$ kubectl get svc -n kube-system -l k8s-app=kube-dns
NAME       TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)
kube-dns   ClusterIP   10.96.0.10   <none>        53/UDP,53/TCP,9153/TCP

CoreDNS 通过 ConfigMap 和 Corefile(定义 DNS 行为的配置文件)进行配置:

apiVersion: v1
kind: ConfigMap
metadata:
  name: coredns
  namespace: kube-system
data:
  Corefile: |
    .:53 {
        errors
        health {
            lameduck 5s
        }
        ready
        kubernetes cluster.local in-addr.arpa ip6.arpa {
            pods insecure
            fallthrough in-addr.arpa ip6.arpa
            ttl 30
        }
        prometheus :9153
        forward . <dns1> <dns2> {
            except cluster.local in-addr.arpa ip6.arpa
        }
        cache 30
        loop
        reload
        loadbalance
    }

CoreDNS 核心插件:

  • kubernetes:处理 cluster.local 的请求

  • forward:将外部查询转发到上游 DNS

  • 缓存:缓存响应 30 秒

  • health:提供 8080 端口的健康检查

  • prometheus:在端口 9153 上导出指标

Kubernetes 支持多种 DNS 策略来管理 Pod 中的名称解析。策略是一些配置参数,用于确定 Pod 获取名称解析 DNS 设置的位置和方式。这是一项关键设置,会影响 Pod 访问集群服务和外部资源的能力。

  • ClusterFirst(默认):使用集群 DNS(CoreDNS)。

  • ClusterFirstWithHostNet:将集群 DNS 与 hostNetwork 结合起来。

  • 默认:继承主机的 DNS 配置。

  • 无:需要手动 DNS 配置。

具有手动 DNS 配置的 pod 示例dnsPolicy: None

spec:
  dnsPolicy: "None"
  dnsConfig:
    nameservers:
      - <dns1>
      - <dns2>
    searches:
      - ns1.svc.cluster.local
      - my.dns.search.suffix
    options:
      - name: ndots
        value: "2"
      - name: edns0

诊断 Kubernetes 中的 DNS 问题

Kubernetes 提供了专门的 DNS 诊断工具:


kubectl apply -f https://k8s.io/examples/admin/dns/dnsutils.yaml



kubectl exec -i -t dnsutils -- nslookup kubernetes.default




kubectl exec -i -t dnsutils -- nslookup google.com


常见错误、已知问题及解决方案

SERVFAIL:CoreDNS 不可用或过载 - 检查 CoreDNS pod 的状态。


kubectl get pods -n kube-system -l k8s-app=coredns
kubectl get pods -n kube-system -l k8s-app=kube-dns

kubectl get svc -n kube-system -l k8s-app=kube-dns
kubectl get svc -n kube-system -l k8s-app=coredns

kubectl logs -n kube-system -l k8s-app=coredns

NXDOMAIN:DNS 记录不完整或过时 - 检查服务配置。

kubectl get endpoints <service-name> -n <namespace>
kubectl describe service <service-name> -n <namespace>
kubectl get pods -n <namespace> -l <selector-from-service>

响应缓慢:这可能是由于 ndots 问题或 CoreDNS 过载造成的。


kubectl exec dnsutils -- sh -c "time nslookup google.com" 2>&1

kubectl exec dnsutils -- cat /etc/resolv.conf

PodhostNetwork: true使用主机的网络命名空间,这会导致 DNS 问题。

问题在于,由于 pod 使用基于主机的 DNS 配置,因此它无法解析集群服务。

解决方案:使用dnsPolicy: ClusterFirstWithHostNet

spec:
  hostNetwork: true
  dnsPolicy: ClusterFirstWithHostNet

另一种解决方案是使用 iptables 规则来重定向流量:


iptables -t nat -A OUTPUT -p tcp --dport 53 -d external-ip \
    -j DNAT --to-destination cluster-ip:53

Kubernetes DNS 的一个关键问题是 ndots:5 参数,该参数强制解析器首先在集群的内部域中检查不合格的名称(包含少于 5 个点),然后才向外部 DNS 发出请求:


www.google.com.default.svc.cluster.local
www.google.com.svc.cluster.local
www.google.com.cluster.local
www.google.com.  

这会导致多次 DNS 查询和严重的延迟。 

解决方案包括:

使用带点的 FQDN:跳过搜索域。

为各个 pod 设置 ndots:

spec:
  dnsConfig:
    options:
    - name: ndots
      value: "1"

优化 CoreDNS 以提高性能和容错能力

当有大量服务和外部 DNS 请求时,Kubernetes 中的 CoreDNS 通常会成为瓶颈。了解 CoreDNS 配置的复杂性对于维护生产集群的稳定性至关重要。

缓存

默认情况下,缓存插件设置为 30 秒。对于较大的集群,您可以增加 TTL 和缓存大小:

cache {
    success 10000 60   
    denial 10000 15    
}

成功缓存:将其增加到 60-120 秒可减少上游负载 70-80%

拒绝缓存: NXDOMAIN 应该缓存较少的时间(10-15 秒)

预取机制:在TTL到期前自动刷新10%的记录。

转发策略

在forward插件中,可以选择访问上游DNS的策略:

随机——在服务器之间均匀分布请求(改善平衡);

顺序- 始终按照列表顺序查询服务器(默认)。

对于有多个外部DNS的集群,建议使用随机:

forward . <dns1> <dns2> {
    policy random
}
协议优化

prefer_udp 指令可减少大量短请求的开销。

forward . <dns1> <dns2> {
    prefer_udp
    max_concurrent 1000
}

如果存在 UDP 数据包碎片问题(在云和 VPN 中很常见),指定 force_tcp 会很有用。

缩放

CoreDNS 的水平扩展并非可选项,而是生产集群的必需品。典型的 1-2 个副本配置完全无法满足每秒数万次 DNS 查询的负载。每个 CoreDNS 副本在性能下降之前可以处理 5,000-10,000 QPS,而在拥有 100 多个节点和 1,000 多个 Pod 的集群中,峰值负载很容易达到 50,000-100,000 QPS,尤其是在以下情况下:

  • 大规模部署,数百个新 Pod 同时开始解析服务的 DNS 名称

  • 应用程序的滚动更新会导致 DNS 活动暂时出现高峰

  • 基于HPA的自动扩展应用程序

  • 启动突发 - 应用程序在初始化期间发出许多 DNS 请求

CoreDNS副本数量不足会导致:

  • DNS 延迟高(>100ms 而不是 <10ms)

  • 超时和 SERVFAIL 响应

  • CoreDNS pod 上的 CPU 和内存过载

  • 无法找到依赖服务的应用程序级联故障

手动扩展 CoreDNS

增加 CoreDNS 副本数量的最简单方法:将 CoreDNS 副本分布在不同节点上以确保容错能力至关重要。如果所有 CoreDNS 副本都位于单个节点上,则该节点发生故障将导致 DNS 完全中断。


kubectl patch deployment coredns -n kube-system -p '
{
  "spec": {
    "template": {
      "spec": {
        "affinity": {
          "podAntiAffinity": {
            "preferredDuringSchedulingIgnoredDuringExecution": [{
              "weight": 100,
              "podAffinityTerm": {
                "labelSelector": {
                  "matchLabels": {"k8s-app": "kube-dns"}
                },
                "topologyKey": "kubernetes.io/hostname"
              }
            }]
          }
        }
      }
    }
  }
}'

扩展时,配置 PodDisruptionBudget 至关重要,以防止一次删除太多 CoreDNS 副本。

NodeLocal DNSCache:一种现代解决方案

NodeLocal DNSCache 代表了 Kubernetes 中 DNS 优化的一种现代方法。它是一个 DaemonSet,在每个集群节点上运行 DNS 缓存。

NodeLocal DNSCache 的优点:

  • 减少平均 DNS 解析时间(Pod 访问同一节点上的本地缓存,而不是通过 kube-dns 服务)

  • 消除 DNS 连接的 conntrack 记录(直接访问本地缓存可避免 iptables DNAT 规则和连接跟踪)

  • 直接访问 Cloud DNS,绕过 kube-dns 进行外部请求(这减少了中央 CoreDNS 上的负载并改善了延迟。)

  • 自动继承存根域和上游名称服务器

架构:pod 访问同一节点上的 DNS 缓存,避免 iptables DNAT 规则和连接跟踪。

NodeLocal DNSCache配置:

apiVersion: v1
kind: ConfigMap
metadata:
  name: node-local-dns
  namespace: kube-system
data:
  Corefile: |
    cluster.local:53 {
        errors
        cache {
            success 9984 30
            denial 9984 5
        }
        reload
        loop
        bind 169.254.20.25 10.96.0.10
        forward . __PILLAR__CLUSTER__DNS__ {
            force_tcp
        }
        prometheus :9253
        health 169.254.20.25:8080
    }

NodeLocal DNSCache 在每个节点上运行一个专用的链路本地 IP 地址 169.254.20.25。Pod 会自动配置为使用此地址作为主域名服务器。

针对企业环境进行定制

企业环境对 DNS 基础架构有着特定的要求:与现有名称解析系统集成、内部区域和外部区域的分离、符合安全策略以及合规性要求。CoreDNS 通过存根域、水平分割 DNS、网络策略和加密 DNS 提供了灵活的机制来实现这些要求。

CoreDNS 支持灵活配置上游服务器和存根域,以便与企业 DNS 基础设施集成:


consul.local:53 {
    errors
    cache 30
    forward . 10.150.0.1
}


forward . 172.16.0.1  

分割水平 DNS:对内部和外部查询有不同的响应:


internal.company.com:53 {
    hosts {
        192.168.1.10 api.internal.company.com
        fallthrough
    }
    forward . 192.168.1.1  
}

external.company.com:53 {
    hosts {
        203.0.113.10 api.external.company.com
        fallthrough
    }
    forward . <dns1>     
}

限制对 DNS 服务器的访问:使用网络策略。

Kubernetes 网络策略通过限制哪些 pod 可以发出 DNS 请求以及 CoreDNS 可以从哪里接收请求,实现了对 CoreDNS 的细粒度访问控制。

保护 CoreDNS 的基本 NetworkPolicy 示例:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
meta
  name: coredns-network-policy
  namespace: kube-system
spec:
  podSelector:
    matchLabels:
      k8s-app: kube-dns
  policyTypes:
  - Ingress
  ingress:
  
  - from:
    - namespaceSelector: {}
    ports:
    - protocol: UDP
      port: 53
    - protocol: TCP
      port: 53
 
  - from:
    - namespaceSelector: {}
    ports:
    - protocol: TCP
      port: 8080  # health
    - protocol: TCP
      port: 8181  # ready
  
  - from:
    - namespaceSelector:
        matchLabels:
          name: monitoring
    ports:
    - protocol: TCP
      port: 9153

DNS 监控和日志记录

有效的 CoreDNS 监控对于确保整个 Kubernetes 集群的稳定性至关重要。当服务无法相互发现时,DNS 问题可能会导致连锁故障,因此监控系统是防范严重事件的第一道防线。

CoreDNS提供了丰富的监控功能:

Prometheus 指标:每个 CoreDNS pod 的端口 9153 上可用。

关键指标包括:

- DNS响应时间

- 成功请求的百分比

- 缓存命中率

- 上游请求数量

记录查询:

log向 Corefile添加插件以进行详细日志记录:

Corefile: |
  .:53 {
      log  
      errors
      
  }

健康检查和自动恢复

CoreDNS 提供两个端点用于健康检查:

健康终点(/health:8080


livenessProbe:
  httpGet:
    path: /ready
    port: 8181
    scheme: HTTP
  initialDelaySeconds: 30
  periodSeconds: 10
  timeoutSeconds: 5
  failureThreshold: 5

就绪端点(/ready:8181


readinessProbe:
  httpGet:
    path: /health
    port: 8080
    scheme: HTTP
  initialDelaySeconds: 10
  periodSeconds: 10
  timeoutSeconds: 5
  successThreshold: 1
  failureThreshold: 3

与云平台集成

生产环境中的 Kubernetes DNS 架构很少孤立存在。它与云 DNS 服务、自动化记录管理系统和服务网格解决方案集成,构建了一个全面的生态系统,确保 DNS 管理的高可用性、安全性和自动化。

Cloud DNS 集成

使用云提供商提供的托管 DNS 服务。Google Cloud DNS、Amazon Route 53 和 Azure DNS 为外部查询提供了高可用性和可扩展性的解决方案。

外部 DNS

外部 DNS 可根据 Kubernetes 资源自动创建和更新 DNS 记录,将 Kubernetes 中的 DNS 管理提升到新的水平。这消除了手动 DNS 管理的需要,并确保集群状态与外部 DNS 提供商完全同步。

架构和工作原理

外部 DNS 充当控制器:

  • 监控 Kubernetes 资源(Service、Ingress)

  • 从资源中提取 DNS 注释

  • 通过 API 与外部 DNS 提供商同步记录

  • 发生变更时保持记录最新

服务网格集成

Istio 使用 Envoy 代理拦截所有流量,包括 DNS 请求。在此架构中,DNS 成为服务网格控制平面的一部分。

Istio DNS 架构

  • Sidecar Envoy 拦截来自应用程序的 DNS 请求

  • Pilot 通过 xDS API 提供服务注册中心

  • Envoy 中的 DNS 代理根据 Istio 服务注册表解析名称

  • 外部域名仍然通过 CoreDNS 解析。

实用建议和结论

平台推荐

如果您使用 Docker,请注意 rootful 和 rootless 模式之间的区别。 

在 rootful 模式下 

  • 监控DNS代理127.0.0.11的稳定性

  • 在 daemon.json 中配置备用 DNS 服务器

  • 使用 systemd-resolved 时,创建一个符号链接来/run/systemd/resolve/resolv.conf代替stub-resolver

在无根模式下 

  • 请注意 slirp4netns 造成的性能限制

  • 请注意,DNS 服务器 10.0.2.3 是独立网络堆栈的一部分

如果你正在切换到现代 Podman

  • 从 CNI 迁移到 Netavark/aardvark-dns 以获得更好的性能。 

  • 通过 使用动态 DNS 管理功能podman network update。 

在无根模式下 

  • 请考虑 slirp4netns 的限制

  • 请记住,Podman 5.3+ 默认使用 pasta,但如果您在使用 pasta 时遇到问题,可以通过以下方式切换回 slirp4netnscontainers.conf

如果你使用 Kubernetes

  • 请务必考虑实施 NodeLocal DNSCache 以减少延迟。 

  • 针对发出大量外部请求的应用程序优化 ndots。 

  • 为具有 hostNetwork 的 pod 配置正确的 dnsPolicy。 

  • 监控 CoreDNS 性能并规划扩展

结论

容器环境中的 DNS 是一种多层架构,不同平台之间存在显著差异。Docker 内置 DNS 代理,使用起来非常方便,但在无根模式下需要特别注意。Podman 展示了从传统 CNI 到现代 Netavark(带有 aardvark-dns)的快速演进,并带来了更佳的性能和功能。Kubernetes 通过 CoreDNS 提供了最复杂、最强大的 DNS 系统,但需要深入了解配置和优化。

容器 DNS 架构是一个快速发展的领域,其性能、安全性和功能都在不断改进。了解每个平台的具体特性并应用现代最佳实践,可以确保为容器化应用程序提供可靠且可扩展的 DNS 基础架构。投资合适的 DNS 架构能够提升应用程序性能、降低运营成本并提升整体系统可靠性,从而带来丰厚的回报。

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐