minikube ingress-dns 插件实战:用集群内 DNS 终结/etc/hosts污染问题
【免费下载链接】minikubeRun Kubernetes locally项目地址: https://gitcode.com/gh_mirrors/mi/minikube
本文以 minikube 的ingress-dnsaddon 为对象,讲解如何在不修改宿主机/etc/hosts的情况下,让myservice.test这类本地域名直接解析到minikube ip,从而用 Ingress 替代 NodePort 和minikube tunnel访问本地服务。读完本文,你将掌握ingress-dns的工作原理、完整的安装与宿主机 DNS 配置步骤(覆盖 Linux 的 resolvconf / NetworkManager / systemd-resolved、macOS、Windows 三大平台)、集群内 CoreDNS 转发配置,以及一套可复现的端到端验证方法。
为什么需要 ingress-dns:/etc/hosts污染问题
在本地使用 minikube 时,访问服务的常规手段有两种:minikube tunnel和 NodePort。NodePort 在很多场景下够用,但当你希望用 Ingress 测试某些特性(比如基于 Host 头路由、TLS 终结、灰度发布)时,就必须让 Ingress 控制器能够工作。Ingress 控制器的核心依赖是DNS——你配置的myservice.test这类本地域名必须能解析到minikube ip。
传统做法是手动为每个服务在宿主机/etc/hosts中追加一条记录。这会带来一系列问题:
- 每新增、删除、重命名一个服务,都需要人工维护
/etc/hosts; - 即便用脚本自动化,配置也被分散存储在宿主机操作系统里,而不是保存在集群中,无法随集群一起版本化管理;
- 条目会持续累积、腐化,形成"
/etc/hosts污染"。
解决方案:运行在集群内的 DNS 服务
ingress-dnsaddon 的思路是:把 DNS 服务本身跑进 Kubernetes 集群里。启用后你只需要做两件事:
- 安装(启用)该 addon;
- 把
minikube ip配置为宿主机的一个 DNS 服务器。
此后每次 DNS 查询到来时,该服务都会向 Kubernetes API Server(master service)发起一次调用,获取集群中全部 Ingress 的列表;如果查询的域名与某个 Ingress rule 的 host 匹配,就返回minikube ip作为解析结果。
以minikube ip为192.168.99.169、集群内配置了myservice.test的 Ingress 规则为例,宿主机上的查询结果如下:
#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从源码看 addon 的构成
仓库中该 addon 的部署模板位于 deploy/addons/ingress-dns/ingress-dns-pod.yaml.tmpl,由 5 个 Kubernetes 对象组成,可以清晰地看到它的权限模型与运行方式:
- ServiceAccount
minikube-ingress-dns(kube-system 命名空间):Pod 以专用服务账户运行; - ClusterRole
minikube-ingress-dns:授予对""、extensions、networking.k8s.io三个 API 组中ingresses资源的get、list、watch权限——这正是"查询集群内全部 Ingress"所需的最小权限集; - ClusterRoleBinding:把上述角色绑定到服务账户;
- Pod
kube-ingress-dns-minikube:这是核心,注意它的spec.hostNetwork: true,意味着 DNS Pod 直接共享节点网络栈,并通过containerPort: 53 / hostPort: 53 / protocol: UDP将 DNS 端口暴露出来;容器镜像由模板变量{{.CustomRegistries.IngressDNS | default .ImageRepository | default .Registries.IngressDNS }}{{.Images.IngressDNS}}决定,即支持通过自定义镜像仓库覆盖; - ConfigMap
minikube-ingress-dns:目前包含一个配置项dns-nodata-delay-ms: "20",用于控制无匹配记录(NODATA)时的应答延迟。
从 pkg/minikube/assets/addons.go 可以看到该 addon 在 minikube 中的注册定义:默认镜像为kicbase/minikube-ingress-dns:0.0.4(带 sha256 摘要),并绑定了官方文档地址。另外,pkg/addons/addons.go 中的supportLegacyIngress逻辑专门处理了兼容性问题:当 Kubernetes 版本< 1.19.0时,ingress与ingress-dns两个 addon 会替换为兼容旧版本的镜像(ingress-dns 使用cryptexlabs/minikube-ingress-dns:0.3.0),从而保证在旧集群上仍可工作。
安装步骤
第 1 步:启动 minikube
minikube start第 2 步:启用 addon
注意需要同时启用ingress与ingress-dns两个 addon——前者提供 Ingress 控制器,后者提供 DNS 解析:
minikube addons enable ingress minikube addons enable ingress-dns第 3 步:把minikube ip配置为宿主机 DNS 服务器
首先用minikube ip拿到节点 IP(下文所有示例中的192.168.99.169都替换为该命令的实际输出),然后按你的操作系统选择对应配置。
Linux:先确认 DNS 管理方式
查看/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管理。
Linux + resolvconf
更新/etc/resolvconf/resolv.conf.d/base,写入以下内容(192.168.99.169替换为minikube ip的输出):
search test nameserver 192.168.99.169 timeout 5如果系统使用systemctl:
sudo resolvconf -u systemctl disable --now resolvconf.service如果系统不使用systemctl,则需要采用该系统对应的 resolvconf 刷新方式(原文档中该分支尚待补充具体命令)。
Linux + NetworkManager(dnsmasq)
NetworkManager 自带集成的缓存 DNS 服务器dnsmasq插件,可以按域名配置独立的 nameserver。编辑/etc/NetworkManager/NetworkManager.conf,启用 dnsmasq:
[main] dns=dnsmasq然后配置 dnsmasq 处理以.test结尾的域名:
sudo mkdir -p /etc/NetworkManager/dnsmasq.d/ echo "server=/test/$(minikube ip)" | sudo tee /etc/NetworkManager/dnsmasq.d/minikube.conf重启 NetworkManager:
systemctl restart NetworkManager.service最后确认/etc/resolv.conf中只有一个 nameserver:
cat /etc/resolv.conf | grep nameserver nameserver 127.0.0.1Linux + systemd-resolved
创建 drop-in 配置并重启 systemd-resolved:
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这里Domains=~test的含义是:仅当查询域名以test结尾(波浪号前缀表示"路由到该 DNS")时才使用 minikube 的 DNS,其余域名仍走系统原有解析,从而避免影响正常上网。
macOS
创建文件/etc/resolver/minikube-test,写入:
domain test nameserver 192.168.99.169 search_order 1 timeout 5192.168.99.169替换为你的minikube ip。如果你有多个 minikube IP(例如多个集群/多节点),必须为每个 IP 分别配置一个文件。注意:该 resolver 文件的port字段在 macOS 上不生效,与文档描述不符,请勿依赖。
Windows
以管理员身份打开 PowerShell 并执行:
Add-DnsClientNrptRule -Namespace ".test" -NameServers "$(minikube ip)"NRPT(Name Resolution Policy Table)规则用于按命名空间指定解析服务器。当minikube ip变化时,可先移除旧规则再新建,一条命令完成:
Get-DnsClientNrptRule | Where-Object {$_.Namespace -eq '.test'} | Remove-DnsClientNrptRule -Force; Add-DnsClientNrptRule -Namespace ".test" -NameServers "$(minikube ip)"第 4 步(可选):让集群内部也能解析本地域名
有时你希望集群内的其他应用(微服务、API、测试)也能通过 Ingress 的本地域名互相访问,此时需要让集群内的 CoreDNS 把test域的查询转发给 ingress-dns。
编辑 CoreDNS 配置:
kubectl edit configmap coredns -n kube-system在 Corefile 中追加一个针对本地域的 server block(192.168.99.169替换为minikube ip):
test:53 { errors cache 30 forward . 192.168.99.169 }最终的 ConfigMap 大致如下(省略号部分为原有默认内容):
apiVersion: v1 data: Corefile: | .:53 { errors health { lameduck 5s } ... } test:53 { errors cache 30 forward . 192.168.99.169 } kind: ConfigMap metadata: ...其中cache 30表示对该域的解析结果缓存 30 秒,forward . 192.168.99.169表示把test域的所有查询转发到 minikube 的 DNS 服务。
验证测试
仓库自带了完整的测试样例,位于 deploy/addons/ingress-dns/example/example.yaml。该清单包含 5 个对象:
- Deployment
hello-world-app:使用docker.io/kicbase/echo-server:1.0镜像,容器端口 8080; - Ingress
example-ingress(kube-system):ingressClassName: nginx,包含hello-john.test与hello-jane.test两个 host 规则,路径/(pathType: Prefix),后端指向 servicehello-world-app的 80 端口; - Service
hello-world-app(kube-system):type: ExternalName,externalName 指向hello-world-app.default.svc.cluster.local,用于跨命名空间转发; - Service
hello-world-app(default):type: NodePort,端口 80 → targetPort 8080,selector 匹配app: hello-world-app。
第 1 步:部署测试 Ingress
kubectl apply -f https://raw.githubusercontent.com/kubernetes/minikube/master/deploy/addons/ingress-dns/example/example.yaml注意:该示例 Ingress 使用了
networking.k8s.io/v1API,最低要求 Kubernetes 1.19。上文提到的 pkg/addons/addons.go 中的supportLegacyIngress正是为< 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预期结果(两域名均解析到minikube ip):
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 msPING 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第 4 步:通过 Ingress 访问示例服务
curl http://hello-john.test curl http://hello-jane.test预期结果(echo-server 返回):
Hello, world! Version: 1.0.0 Hostname: hello-world-app-557ff7dbd8-64mtv已知问题与注意事项
.localhost总是解析到回环地址
.localhost在多数系统上会被强制解析为回环地址(127.0.0.1),因此不能用于minikube ip。请改用.test、.example或.invalid这类本地测试保留域。
.local是保留 TLD
不要使用.local作为域名后缀——它是 mDNS(多播 DNS)和 bind9 的保留 TLD,会与局域网内的 mDNS 解析冲突。
macOS:mDNS 重载
每次在/etc/resolver中创建或修改文件后,可能需要重载 macOS 的 mDNS resolver 才能生效:
- Big Sur 之前的 macOS,使用以下传统命令:
sudo launchctl unload -w /System/Library/LaunchDaemons/com.apple.mDNSResponder.plist sudo launchctl load -w /System/Library/LaunchDaemons/com.apple.mDNSResponder.plist- 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时自动停止。
也就是说,目前宿主机侧(尤其是 macOS)的 resolver 文件仍需手动维护。
附:addon 使用的镜像
| Image | Source | Owner |
|---|---|---|
| ingress-nginx | kubernetes/ingress-nginx | Kubernetes ingress-nginx |
| minikube-ingress-dns | cryptexlabs/public/development/minikube-ingress-dns | Cryptex Labs |
其中minikube-ingress-dns是 ingress-dns addon 的核心实现(DNS 服务器 + Kubernetes Ingress 查询逻辑),minikube 侧通过 pkg/minikube/assets/addons.go 中的默认镜像kicbase/minikube-ingress-dns:0.0.4引用它;在 Kubernetes< 1.19的旧集群中则自动降级为cryptexlabs/minikube-ingress-dns:0.3.0(见 pkg/addons/addons.go)。
小结
ingress-dns把"本地域名 → minikube IP"的映射从宿主机/etc/hosts迁移到了集群内的 DNS 服务,天然解决了手动维护、配置分散的问题,让基于 Ingress 的本地开发体验与生产环境保持一致。核心使用链路可以概括为:启用ingress+ingress-dnsaddon → 把minikube ip配成宿主机 DNS(或 CoreDNS 转发)→ 部署带 host 规则的 Ingress → 用本地域名直接访问。在动手之前,请记住两条铁律:优先使用.test等保留域而非.localhost/.local,并确保宿主机 DNS 配置方式与你的系统(resolvconf / NetworkManager / systemd-resolved / macOS resolver / Windows NRPT)匹配。
【免费下载链接】minikubeRun Kubernetes locally项目地址: https://gitcode.com/gh_mirrors/mi/minikube
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考