7

我正在尝试让我的 kubernetes 集群从在其内部运行的容器注册表服务中提取。我有 kube dns 设置,我有一个注册表部署和服务正在运行。我可以通过节点上的主机命令解析服务内部名称。我已经--dns使用 kube dns 服务的地址向 docker daemon 添加了标志。我也让 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,由于名称解析,从注册表服务中提取图像也会失败。我错过了什么?

4

2 回答 2

3

问题:“我正试图让我的 kube-cluster 从一个在其内部运行的注册表中拉取。” (请注意,我打算编辑您的问题的标题以稍微澄清/使其更易于搜索)

简短的回答:你不能*
*细致入微的回答:从技术上讲,通过 hack 和对 Kubernetes 基础知识的深刻理解是可能的。您可能希望避免这样做,除非您有充分的理由,并且完全理解我对基本问题和解决方法的解释,因为这是一个高级用例,需要调试才能使其正常工作。这很复杂且细致入微,足以使逐步的指导变得困难,但我可以为您提供一个坚实的概念,让您了解您遇到的使这个具有挑战性的基本问题,以及有关如何实现您想要的目标的高级概述指导无论如何做。

为什么不能/您遇到的根本问题:
在 Kubernetes 领域中,往往存在 3 个网络:Internet、LAN 和内部集群网络。
(更深入的资源:https ://oteemo.com/kubernetes-networking-and-services-101/ )而且
这 3 个网络都有自己的 DNS / 有 3 层 DNS。

  • 互联网 DNS:8.8.8.8、1.1.1.1、9.9.9.9(google、cloudflare、quad9 或路由器配置指向的任何公共互联网 DNS。)
  • LAN DNS:192.168.1.1(LAN DNS 托管在您的路由器上)
  • CoreDNS:10.43.0.10(内部集群网络CIDR范围的第10个IP)

这是您遇到的问题:

  • pod 可以解析托管在这 3 个 DNS 级别中的任何一个上的 DNS 条目。
  • 托管 Kubernetes 集群的操作系统只能解析托管在 LAN DNS 或 Internet DNS 上的 DNS 条目。(操作系统的范围不包括对 CoreDNS/Inner Cluster Network 存在的可见性。)
  • kubelet + docker/containerd/cri-o/other 运行时,负责从注册表中提取图像,这些图像以 systemd 服务的形式存在于操作系统级别,因此不具有内部集群 DNS 名称的范围。这就是为什么你试图做的事情失败了。

您可以采取的解决方法选项/技巧和细微差别来强制您尝试执行的操作:

选项1。)(我不建议这样做,有额外的困难鸡肉和鸡蛋问题,仅供参考)

在 Kubernetes 上托管一个额外的 coredns 实例作为面向 LAN 的 DNS 实例,通过显式 NodePorts 将注册表和第二个 coredns 实例暴露给 LAN(使用静态服务清单,因此它们将提出可预测/静态 NodePorts,而不是随机 NodePorts在 30000 - 32768 的范围内),因此它们可以从 LAN 路由(我建议 NodePorts over LB 在这里作为一种较少的依赖项/可能出错的事情)。让 coredns 的第二个实例使用您的 LAN 路由器/LAN DNS 作为上游 DNS 服务器。重新配置操作系统以使用面向 LAN 的 coredns 作为其 DNS 服务器。

选项 2.) 更合理以及 trow 的作用:

  1. 为 some-dns-name.tld 支付 12 美元

  2. 使用 Cert Manager Kubernetes Operator 或 Cert Bot 独立 docker 容器 + 证明您拥有该域以从 Lets Encrypt Free获取https://registry.some-dns-name.tld HTTPS 证书。并配置您的内部集群托管注册表以使用此 HTTPS 证书。

  3. 使用具有明确固定的基于约定的端口号(如 32443)的 NodePort 服务将托管在集群中的注册表公开到 LAN

为什么选择 NodePort 而不是 LB? 在这种情况下,NP 优于 LB 的原因有 3 个:

  • 1.) 服务类型 LB 的实现在 Deployment Environment 和 Kubernetes Distribution 之间有所不同,而 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.) 如果您需要更改集群的托管位置,您可以安排它,以便即使在您无法访问或控制 LAN DNS 的情况下,您也可以在 1 个集中位置进行更改。您可以制作指向静态定义的 IP 或外部名称(可能存在于集群外部)的服务。并让 NodePort 服务指向静态定义的服务。

  1. 将“127.0.0.1 registry.some-dns-name.tld”添加到集群中每个节点的/etc/hosts。

  2. 将您的 yaml 清单设置为从 registry.some-dns-name.tls 中提取,或配置 containerd/cri-o 的注册表镜像功能以将 registry.some-dns-name.tld:32443 映射到本地注册表上正在镜像的任何条目.

  3. 还有两个可解决的鸡和蛋问题需要处理。第一个鸡蛋问题是 Kubernetes 和注册中心都可能需要访问容器镜像才能做到这一点。

  • 如果您可以访问 Internet,并且您的内部注册表仅用于缓存目的,那么这可能没什么大不了的。
  • 如果您没有互联网访问权限,则需要 .tar 压缩您的 kube 发行版和注册表所需的图像,并将它们“预加载”到 docker/containerd/cri-o 期望的位置。
  • 如果您没有互联网访问权限,您也可以选择另一个 /etc/hosts 条目或 LAN DNS 条目,用于非 HA 临时基于 docker compose 的注册表,用于初始引导或托管在集群外部。
  1. 第二个鸡蛋问题是托管在您的集群上的注册表需要某种方式来植入图像。
  • 如果互联网访问应该很容易弄清楚和编写脚本
  • 如果无法访问 Internet,您可能需要提出某种 DR 解决方案来备份和恢复注册表后端持久存储。
  • 如果没有 Internet 访问权限,您也可以使用“临时传输注册表”来进行播种。基本上做这个 docker compose 来启动具有文件系统支持的非 HA 注册表:2 映像,使用skopeo播种,压缩文件系统支持,并将其导入另一台计算机,恢复文件系统支持,重新加载非 HA 注册表: 2 从预填充的文件系统支持,然后使用 skopeo 从您的“临时传输注册表”复制到您在集群中托管的注册表。
于 2021-06-16T13:02:53.163 回答
1

另一种解决方案是将 kube-dns IP 添加到resolv.conf

echo "nameserver $(kubectl -n kube-system get svc kube-dns -o jsonpath='{.spec.clusterIP}')" >> /etc/resolv.conf

CoreDNS 服务使用静态 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
于 2018-11-28T15:42:11.257 回答