Ingress DNS

为您的 minikube 服务器上运行的 Ingress 控制器提供的 DNS 服务

概述

问题

在本地运行 minikube 时,您可能希望在 Ingress 控制器上运行您的服务,这样您就不必使用 minikube tunnel 或 NodePorts 来访问您的服务。虽然在许多情况下 NodePort 可能会很好,但 Ingress 是测试某些功能所必需的。Ingress 控制器非常棒,因为您可以在类似 Helm Chart 的东西中定义整个架构,并且您的所有服务都将可用。

但是,对于 minikube 来说,还有一个额外的挑战。您的 Ingress 控制器依赖于 DNS,因此像 myservice.test 这样的本地 DNS 名称必须解析为您的 minikube ip。真正实现此目的的唯一方法是在您的 /etc/hosts 文件中为每个服务添加一个条目。由于显而易见的原因,这会变得很混乱。对于您正在运行的每个服务,并且每个服务都有自己的 DNS 条目,您都需要手动配置它。即使您对其进行自动化,也需要依赖主机操作系统来存储配置,而不是将其存储在您的集群中。更糟糕的是,这些配置必须随着服务的添加、删除和重命名而不断维护和更新。我称之为 /etc/hosts 污染问题。

解决方案

如果您可以神奇地访问本地服务而无需编辑您的 /etc/hosts 文件会怎样? 好吧,现在你可以了。ingress-dns 插件充当在您的 Kubernetes 集群内运行的 DNS 服务。您所要做的就是安装该服务并将 minikube ip 作为 DNS 服务器添加到您的主机上。每次查询 DNS 服务时,都会向 Kubernetes 主服务发出 API 调用,以获取所有 Ingress 的列表。如果找到与名称匹配的项,则会返回与 minikube ip 匹配的 IP 地址。例如,如果 minikube ip192.168.99.169,并且在集群中配置了 myservice.test 的 Ingress 规则,则来自主机的 DNS 查询将产生

#bash:~$ nslookup myservice.test $(minikube ip)
Server:		192.168.99.169
Address:	192.168.99.169#53

Non-authoritative answer:
Name:	myservice.test $(minikube ip)
Address: 192.168.99.169

安装

1启动 minikube

minikube start

2启用插件

minikube addons enable ingress
minikube addons enable ingress-dns

3添加 `minikube ip` 作为 DNS 服务器

在 Linux 上,您应该确定您的域名解析器配置,并相应地更新其配置。为此,请查看 /etc/resolv.conf 的第一行

  • 如果它提到 resolvconf,则解析很可能由 resolvconf 处理,
  • 如果是 # Generated by NetworkManager,则解析由 NetworkManager 处理,
  • 如果类似于 # This is /run/systemd/resolve/stub-resolv.conf managed by man:systemd-resolved(8),则解析由 systemd-resolved 处理。

启动 minikube,并应用以下与您的系统配置匹配的配置。

使用 resolvconf 的 Linux OS

更新文件 /etc/resolvconf/resolv.conf.d/base 以包含以下内容。

search test
nameserver 192.168.99.169
timeout 5

192.168.99.169 替换为 minikube ip 的输出。

如果您的 Linux OS 使用 systemctl,请运行以下命令。

sudo resolvconf -u
systemctl disable --now resolvconf.service

如果您的 Linux OS 不使用 systemctl,请运行以下命令。

# TODO add supporting docs for Linux OS that do not use `systemctl`

请参阅 https://linux.die.net/man/5/resolver

使用 NetworkManager 的 Linux OS

NetworkManager 可以运行集成的缓存 DNS 服务器 - dnsmasq 插件,并且可以配置为对每个域使用单独的名称服务器。

编辑 /etc/NetworkManager/NetworkManager.conf 并通过添加以下内容来启用 dns=dnsmasq

[main]
dns=dnsmasq

另请参阅 NetworkManager.conf 中的 dns=

配置 dnsmasq 以处理以 .test 结尾的域名

sudo mkdir -p /etc/NetworkManager/dnsmasq.d/
echo "server=/test/$(minikube ip)" | sudo tee /etc/NetworkManager/dnsmasq.d/minikube.conf

重启 Network Manager

systemctl restart NetworkManager.service

确保您的 /etc/resolv.conf 仅包含单个名称服务器

cat /etc/resolv.conf | grep nameserver
nameserver 127.0.0.1

使用 systemd-resolved 的 Linux OS

运行以下命令为 .test 域添加 minikube DNS

sudo mkdir -p /etc/systemd/resolved.conf.d
sudo tee /etc/systemd/resolved.conf.d/minikube.conf << EOF
[Resolve]
DNS=$(minikube ip)
Domains=~test
EOF
sudo systemctl restart systemd-resolved

/etc/resolver/minikube-test 中创建一个文件,包含以下内容。

domain test
nameserver 192.168.99.169
search_order 1
timeout 5

192.168.99.169 替换为您的 minikube ip

如果您有多个 minikube IP,则必须为每个 IP 配置一个文件。

请参阅 https://www.unix.com/man-page/opendarwin/5/resolver/

请注意,port 功能无法按文档所述工作。

以管理员身份打开 Powershell 并执行以下操作。

Add-DnsClientNrptRule -Namespace ".test" -NameServers "$(minikube ip)"

以下操作将在创建新规则之前删除任何匹配的规则。这对于更新 minikube ip 非常有用。

Get-DnsClientNrptRule | Where-Object {$_.Namespace -eq '.test'} | Remove-DnsClientNrptRule -Force; Add-DnsClientNrptRule -Namespace ".test" -NameServers "$(minikube ip)"

4(可选)配置集群内 DNS 服务器以解析集群内的本地 DNS 名称

有时,通过 Ingress 及其本地 DNS 名称(微服务/API/测试)访问集群内的其他应用程序很有用。在这种情况下,集群内 DNS 服务器 - CoreDNS 应该使用 ingress-dns 插件来解析本地 DNS 名称。

编辑您的 CoreDNS 配置

kubectl edit configmap coredns -n kube-system

并为您的本地域添加块

    test:53 {
            errors
            cache 30
            forward . 192.168.99.169
    }

192.168.99.169 替换为您的 minikube ip

最终的 ConfigMap 应如下所示

apiVersion: v1
data:
  Corefile: |
    .:53 {
        errors
        health {
           lameduck 5s
        }    
...
    }
    test:53 {
            errors
            cache 30
            forward . 192.168.99.169
    }
kind: ConfigMap
metadata:
...

请参阅 https://kubernetes.ac.cn/docs/tasks/administer-cluster/dns-custom-nameservers/

测试

1添加测试 Ingress

kubectl apply -f https://raw.githubusercontent.com/kubernetes/minikube/master/deploy/addons/ingress-dns/example/example.yaml

注意:示例 Ingress 的最低 Kubernetes 版本为 1.19

2确认 DNS 查询正在返回 A 记录

nslookup hello-john.test $(minikube ip)
nslookup hello-jane.test $(minikube ip)

3确认域名在主机操作系统上解析

ping hello-john.test
ping hello-jane.test

预期结果

PING hello-john.test (192.168.99.169): 56 data bytes
64 bytes from 192.168.99.169: icmp_seq=0 ttl=64 time=0.361 ms
PING hello-jane.test (192.168.99.169): 56 data bytes
64 bytes from 192.168.99.169: icmp_seq=0 ttl=64 time=0.262 ms

4Curl 示例服务器

curl http://hello-john.test
curl http://hello-jane.test

预期结果

Hello, world!
Version: 1.0.0
Hostname: hello-world-app-557ff7dbd8-64mtv
Hello, world!
Version: 1.0.0
Hostname: hello-world-app-557ff7dbd8-64mtv

已知问题

.localhost 始终解析为回环地址

.localhost 通常会解析为回环地址(请参阅 RFC 2606RFC 6761),因此它不能用于 minikube ip。请改用 .test、.example 或 .invalid

.local 是保留的 TLD

请勿使用 .local,因为它是 mDNS 和 bind9 DNS 服务器的保留 TLD

Mac OS

mDNS 重新加载

每次在 /etc/resolver 中创建文件或对文件进行更改时,您可能需要运行以下命令来重新加载 Mac OS mDNS 解析器。

sudo launchctl unload -w /System/Library/LaunchDaemons/com.apple.mDNSResponder.plist
sudo launchctl load -w /System/Library/LaunchDaemons/com.apple.mDNSResponder.plist

待办事项

  • 添加一个在主机操作系统上运行的服务,该服务将自动更新 /etc/resolver 中的文件
  • 在运行 minikube addons enable ingress-dns 时启动此服务,并在运行 minikube addons disable ingress-dns 时停止该服务

贡献者

此插件中使用的镜像

镜像 来源 所有者
ingress-nginx ingress-nginx Kubernetes ingress-nginx
minikube-ingress-dns minikube-ingress-dns Cryptex 实验室