Ingress DNS
在您的 minikube 服务器上运行的 Ingress 控制器的 DNS 服务
概述
问题
在本地运行 minikube 时,您可能希望在 ingress 控制器上运行服务,这样就不必使用 minikube tunnel 或 NodePort 来访问服务。虽然 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 master service 发出 API 调用,以获取所有 ingress 的列表。如果找到了与该名称匹配的项,则返回一个包含与 minikube ip 匹配的 IP 地址的响应。例如,如果 minikube ip 为 192.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.cn/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/测试)访问集群内部的其他应用程序很有用。在这种情况下,ingress-dns 插件应由集群内 DNS 服务器 - CoreDNS 用于解析本地 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 2606 和 RFC 6761),因此不能用于 minikube ip。请改用 .test、.example 或 .invalid
.local 是保留 TLD
请勿使用 .local,因为它是 mDNS 和 bind9 DNS 服务器的保留 TLD
Mac OS
mDNS 重新加载
每次在 /etc/resolver 中创建文件或对文件进行更改时,您可能需要运行以下命令来重新加载 Mac OS mDNS 解析器。对于 Big Sur 之前的 macOS 版本,您可以使用以下旧命令重新加载 mDNS 解析器
sudo launchctl unload -w /System/Library/LaunchDaemons/com.apple.mDNSResponder.plist
sudo launchctl load -w /System/Library/LaunchDaemons/com.apple.mDNSResponder.plist
但是,如果您使用的是较新的 macOS 版本(Big Sur 及更高版本),运行旧命令可能会导致以下错误
Load failed: 5: Input/output error
Try running `launchctl bootstrap` as root for richer errors.
在这种情况下,建议的方法是改用以下命令
sudo launchctl enable system/com.apple.mDNSResponder.reloaded
sudo launchctl disable system/com.apple.mDNSResponder.reloaded
待办事项
- 添加一个在主机操作系统上运行的服务,该服务将自动更新
/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 Labs |