0

我对 Kubernetes 比较陌生,并且我的大学课程有一个项目,在裸机上构建一个 Kubernetes 集群。

为此,我建立了一个 PoC 环境,6 台机器(其中 3 台是一个节点上的 KVM 机器)中的所有管理都由 MAAS 完成,即 DHCP,而 DNS 由那台机器管理。我有一个 DNS 区域委派给 MAAS DNS 服务器 k8s.example.com,所有机器都在其中。整个网络在它自己的 VLan 10.0.10.0/24 中,其中 metallb IPRange 从 DHCP 中保留。这是一张图片来说明简单的集群:

k8s概述

软件方面,所有主机都使用 ubuntu 20.04,我使用 kubespray 部署所有内容,即 kubernetes、metallb 和 nginx-ingress-controller。我对 kubespray 的对应值是:

dashboard_enabled: false
ingress_nginx_enabled: true
ingress_nginx_host_network: true

kube_proxy_strict_arp: true

metallb_enabled: true
metallb_speaker_enabled: true
metallb_ip_range:
  - "10.0.10.100-10.0.10.120"

kubeconfig_localhost: true

我的问题是,我无法将 DNS 从集群中移到 Internet 上工作。我为 nginx-Ingress 外部 ip 设置了 *.k8s.example.com 的通配符 A 记录,这对于可以从外部访问的每个 pod 都很好。问题是,集群内的每个容器都无法再访问互联网。每个请求都通过入口路由。这意味着如果我尝试访问www.google.net,它会尝试访问www.google.net.k8s.example.com,这是有道理的。删除通配符 A 记录后,只有每个 .com 域都可以正常访问(例如www.google.com )。集群内的所有 pod 相互访问都没有问题。

我看到了几种配置可能性,在这些地方进行调整是有意义的,但 2 周后,我真的更喜欢基于最佳实践且做得正确的解决方案。

我真的很想能够使用通配符 A 记录,但我担心这可能是不可能的。

我希望我提供了所需的所有信息,以便为您提供足够的概述以了解我的问题。

编辑:我使用了标准的 kubespray DNS 配置,因为我被告知它就足够了:

DNS configuration.
# Kubernetes cluster name, also will be used as DNS domain
cluster_name: cluster.local
# Subdomains of DNS domain to be resolved via /etc/resolv.conf for hostnet pods
ndots: 2
# Can be coredns, coredns_dual, manual or none
dns_mode: coredns
# Set manual server if using a custom cluster DNS server
# manual_dns_server: 10.x.x.x
# Enable nodelocal dns cache
enable_nodelocaldns: true
nodelocaldns_ip: 169.254.25.10
nodelocaldns_health_port: 9254
# nodelocaldns_external_zones:
# - zones:
#   - example.com
#   - example.io:1053
#   nameservers:
#   - 1.1.1.1
#   - 2.2.2.2
#   cache: 5
# - zones:
#   - https://mycompany.local:4453
#   nameservers:
#   - 192.168.0.53
#   cache: 0
# Enable k8s_external plugin for CoreDNS
enable_coredns_k8s_external: false
coredns_k8s_external_zone: k8s_external.local
# Enable endpoint_pod_names option for kubernetes plugin
enable_coredns_k8s_endpoint_pod_names: false

# Can be docker_dns, host_resolvconf or none
resolvconf_mode: docker_dns
# Deploy netchecker app to verify DNS resolve as an HTTP service
deploy_netchecker: false
# Ip address of the kubernetes skydns service
skydns_server: "{{ kube_service_addresses|ipaddr('net')|ipaddr(3)|ipaddr('address') }}"
skydns_server_secondary: "{{ kube_service_addresses|ipaddr('net')|ipaddr(4)|ipaddr('address') }}"
dns_domain: "{{ cluster_name }}"

我注意到的是,pod 的 etc resolv.conf 看起来像这样:

/ $ cat /etc/resolv.conf 
nameserver 169.254.25.10
search flux-system.svc.cluster.local svc.cluster.local cluster.local k8s.example.com maas
options ndots:5

例如在由 MAAS 管理的节点上,它是:

# This file is managed by man:systemd-resolved(8). Do not edit.
#
# This is a dynamic resolv.conf file for connecting local clients to the
# internal DNS stub resolver of systemd-resolved. This file lists all
# configured search domains.
#
# Run "resolvectl status" to see details about the uplink DNS servers
# currently in use.
#
# Third party programs must not access this file directly, but only through the
# symlink at /etc/resolv.conf. To manage man:resolv.conf(5) in a different way,
# replace this symlink by a static file or a different symlink.
#
# See man:systemd-resolved.service(8) for details about the supported modes of
# operation for /etc/resolv.conf.

nameserver 127.0.0.53
options edns0 trust-ad
search k8s.example.com maas
4

1 回答 1

1

正如评论中所讨论的,问题在于您的 Kubernetes 节点上的 resolv.conf,以及您使用通配符记录这一事实,该记录与该 resolv.confsearch条目中的名称之一匹配。

您可能从节点或 Pod 调用的任何名称都将首先被搜索为${input}.${search-entry},而只有在与您的连接没有返回某些记录时${input}才会被查询。search在域搜索列表中有通配符记录将导致任何名称解析为该记录。

假设在这种情况下,k8s.example.com记录是由 MAAS 推送的,并且我们不能真正持久地删除它,下一个最佳解决方案是使用另一个名称为您的 Ingress 服务 - 子域或不相关的东西。通常,更改 DHCP 服务器中的选项就足够了——或者可以说更好:不要使用 DHCP 托管 Kubernetes 节点。

于 2021-07-01T11:07:16.043 回答