所以,我试图让我的kube集群从内部运行的注册表中拉出来。我有kube dns设置,我有一个注册表部署和服务运行。我可以通过节点上的host命令解析服务内部名称。我在docker守护进程中添加了--dns
标志,其中包含kube dns服务的地址。我的kubelet运行时--cluster-dns
标志也设置为相同的地址。然而,当我尝试使用此注册表创建一个pod时,这就是我得到的。
Failed to pull image "kube-registry.kube-system.svc.cluster.local/myuser/myimage": rpc error: code = Unknown desc = Error response from daemon: Get https://kube-registry.kube-system.svc.cluster.local/v1/_ping: dial tcp: lookup kube-registry.kube-system.svc.cluster.local: no such host
不知何故,即使将kube dns地址明确地提供给dockerd和kubelet,由于名称解析,从注册表服务中提取图像也会失败。我错过了什么?
答案 0 :(得分:1)
问题:“我正在尝试从内部运行的注册表中拉取我的 kube-cluster。” (请注意,我打算编辑您的问题标题以稍微澄清/使其更易于搜索)
简短回答:你不能*
*细致入微的回答:从技术上讲,通过黑客攻击和对 Kubernetes 基础知识的深入了解是可能的。您可能希望避免这样做,除非您有很好的理由,并且完全理解我对基本问题和解决方法的解释,因为这是一个高级用例,需要调试才能使其工作。这很复杂且细微到足以使逐步指导变得困难,但我可以让您对您遇到的基本问题有一个可靠的了解,这些问题使这个具有挑战性,以及有关如何完成您正在尝试的工作的高级概述指南无论如何。
为什么不能/遇到的基本问题:
在 Kubernetes 领域,通常存在 3 个网络:Internet、LAN 和内部集群网络。
(更深入的资源:https://oteemo.com/kubernetes-networking-and-services-101/)
并且这 3 个网络都有自己的 DNS / 有 3 层 DNS。
这是您遇到的问题:
您可以采取的解决方法选项/技巧和细微差别,以强制您尝试执行的操作:
选项 1。)(我不建议这样做,有额外困难的鸡和蛋问题,仅供参考)
托管一个额外的 coredns 实例作为面向 LAN 的实例 Kubernetes 上的 DNS,将注册中心和第二个 coredns 实例暴露给 LAN 通过显式 NodePorts(使用静态服务清单,因此 他们会提出可预测的/静态的 NodePorts,而不是随机的 NodePorts 在 30000 - 32768 范围内)所以它们可以从 LAN(我建议在这里使用 LB 上的 NodePorts 作为一种更少的依赖/事物 这可能会出错)。让 coredns 的第二个实例使用您的 LAN 路由器/局域网 DNS,因为它是上游 DNS 服务器。重新配置操作系统以使用 面向 coredns 的 LAN,因为它是 DNS 服务器。
选项 2.) 更合理以及 trow 的作用:
什么是特罗: https://thenewstack.io/trow-a-container-registry-to-run-inside-a-kubernetes-cluster/
证明他们使用了 /etc/hosts 方法 https://github.com/ContainerSolutions/trow/blob/main/QUICK-INSTALL.md
支付 12 美元购买 some-dns-name.tld
使用 Cert Manager Kubernetes Operator 或 Cert Bot 独立 docker 容器 + 证明您拥有域,以从 Lets Encrypt Free 获取 https://registry.some-dns-name.tld HTTPS 证书。并配置您的内部集群托管注册表以使用此 HTTPS 证书。
使用 NodePort 服务将集群中托管的注册表暴露给 LAN,该服务具有基于明确固定的约定的端口号,例如 32443
为什么是 NodePort 而不是 LB? 在这种情况下,NP 优于 LB 有 3 个原因:
1.) 服务类型 LB 的实现不同 在部署环境和 Kubernetes 分发之间,同时键入 NodePort 是通用的。
2.) 如果 LB 发生变化,您必须更新每个节点的 /etc/host 文件指向“LB_IP registry.some-dns-name.tld”,你必须 知道 LB IP,这并不总是事先知道/这意味着你会 必须遵循一些操作顺序。如果您使用服务类型 NodePort 您可以将 localhost IP 条目添加到每个节点的 /etc/host, 所以它看起来像“127.0.0.1 registry.some-dns-name.tld”,很好 已知可重用并简化操作顺序。
3.) 如果您需要更改集群的托管位置,您可以 可以安排它,以便您可以在 1 个集中位置进行更改 即使在您无法访问或控制 LAN DNS 的情况下。 您可以制作指向静态定义的 IP 或外部的服务 名称(可能存在于集群之外)。并拥有 NodePort 服务指向静态定义的服务。
将“127.0.0.1 registry.some-dns-name.tld”添加到集群中每个节点的/etc/hosts。
将您的 yaml 清单设置为从 registry.some-dns-name.tls 中提取,或配置 containerd/cri-o 的注册表镜像功能以将 registry.some-dns-name.tld:32443 映射到任何条目被镜像到您的本地注册表。
还有两个可解决的鸡和蛋问题需要处理。第一个鸡蛋问题是 Kubernetes 和注册中心都可能需要访问容器镜像才能做到这一点。
答案 1 :(得分:0)
另一种解决方案是将kube-dns IP添加到resolv.conf
:
echo "nameserver $(kubectl -n kube-system get svc kube-dns -o jsonpath='{.spec.clusterIP}')" >> /etc/resolv.conf
CoreDNS服务以static IP公开,因此无需保持更新。
我可以确认它可以在Ubunutu 18.04上运行,尽管resolv.conf
是由systemd-resolved
生成的。不需要其他DNS配置。仅FQDN提供的服务:
root@dev:~# nslookup harbor.default.svc.cluster.local
;; Got SERVFAIL reply from 127.0.0.53, trying next server
Server: 10.96.0.10
Address: 10.96.0.10#53
Name: harbor.default.svc.cluster.local
Address: 10.109.118.191
;; Got SERVFAIL reply from 127.0.0.53, trying next server