内容简介:作者:Kirill Goltsman编辑:小君君(才云)
作者:Kirill Goltsman
编辑:小君君(才云)
众所周知,Kubernetes master 存储了所有 Service 的定义和更新。但是,要与后端 Pod 通信的客户端 Pod(通过 Service 实现负载均衡)也需要知道这些请求会发送到何处。这些 Pod 可以将网络信息存储在容器环境变量中,但从长远来看这是不可行的。如果网络详细信息和一组后端 Pod 在将来发生更改时,客户端 Pod 将无法与它们通信。
今天,我们就来一起看看 Kubernetes DNS 系统是如何解决这个问题的,然后通过一个实际用例加深对该 系统设计原理的理解。
Kube-DNS 和 CoreDNS 是两个已建立的 DNS 解决方案,用于定义 DNS 命名规则。它们还可以将 Pod、DNS 服务解析为其相应的集群 IP。 使用 DNS,Kubernetes 服务可以被 name 引用(该 name 对应于服务管理的任意数量的后端 Pod)。
DNS 的命名方案也遵循了可预测的模式,使各种服务的地址更容易被记住。服务不仅可以通过完全限定域名(FQDN)引用,还可以仅通过服务本身的 name 引用。
通过本文你将了解到:
-
Kubernetes DNS 如何运作;
-
Service DNS 记录;
-
Pod DNS 记录;
-
Pod 的主机名和子域字段;
-
教程: 如何通过 DNS 命名解决服务问题;
-
总结。
Kubernetes DNS 如何运作?
在 Kubernetes 中,你可以设置一个 DNS 系统,其中包含两个受到良好支持的附加组件:CoreDNS 和 Kube-DNS。CoreDNS 是一个较新的附加组件,从 Kubernetes v1.12 开始成为默认的 DNS 服务器。但,某些 Kubernetes 安装程序 工具 仍可将 Kube-DNS 安装为默认 DNS 系统。
这两个附加组件都可以在集群上 调度一个或多个 DNS Pod 以及具有静态 IP 的服务。为了实现互操作性,两者在 metadata.name 字段都被命名为 kube-dns 。当管理员或安装工具配置集群时, kubelet 会将 DNS 功能传递给每个带有 --cluster-dns=<dns-service-ip> 标识的容器。配置 kubelet 时,管理员还可以使用 --cluster-domain=<default-local-domain> 指定本地域名。
目前,Kubernetes DNS 加载项可以支持正向查找(A Record)、端口查找(SRV 记录)、反向 IP 地址查找(PTR 记录)以及一些其他选项。本文将继续讨论,在这些记录类型中 Pod 和 Service 的 Kubernetes 命名方案。
Service DNS 记录
通常,Kubernetes 服务支持 A Record、CNAME 和 SRV 记录。
A Record
A Record 是用于将域或子域指向某个 IP 地址的 DNS 记录的最基本类型。记录包括域名、解析它的 IP 地址和以秒为单位的 TTL。TTL 代表生存时间,是 DNS 记录上的一种到期日期。每个 TTL 都会告诉 DNS 服务器,它应该在其缓存中保留给定记录多长时间。
Kubernetes 为“normal”和“headless”服务分配不同的 A Record name。“headless”服务与“ normal ”服务的不同之处在于它们未分配 ClusterIP 且不执行负载均衡。
“Normal”服务都分配了一个 DNS A Record 作为表单 your-svc.your-namespace.svc.cluster.local 的 name(根域名可以在 kubelet 设置中更改)。此 name 解析为服务的集群 IP。“Headless”服务还为表单 your-svc.your-namespace.svc.cluster.local 的 name 分配一个 DNS A Record。但是,与“normal”服务相反,此 name 解析的是,为服务选择的一组 Pod IP。DNS 不会自动将此设置解析为特定的 IP,因此客户端应该负责好集合中进行的负载均衡或循环选择。
CNAME
CNAME 记录用于将域或子域指向另一个主机名。为此,CNAME 使用现有的 A Record 作为其值。反过来,A Record 会解析为指定的 IP 地址。此外,在 Kubernetes 中,CNAME 记录可用于联合服务的跨集群服务发现。在整个场景中会有一个跨多个 Kubernetes 集群的公共服务。所有 Pod 都可以发现这项服务(无论这些 Pod 在哪个集群上)。这是一种跨集群服务发现方法。
SRV 记录
SRV 记录是通过描述某些服务协议和地址来促进服务发现的。
SRV 记录通常定义一个符号名称和作为域名一部分的传输协议(如,TCP),并定义给定服务的优先级、权重、端口和目标(请参阅下面的示例)。
_sip._tcp.example.com. 3600 IN SRV 10 70 5060 srvrecord.example.com. _sip._tcp.example.com. 3600 IN SRV 10 20 5060 srvrecord2.ex
在上面的示例中, _sip 是服务的符号名称, _tcp 是服务的使用传输协议。记录内容代表的意思是:两个记录都定义了 10 的优先级。另外,第一个记录的权重为 70,第二个记录的权重为 20。优先级和权重通常用于建议指定使用某些服务器。 记录中的最后两个值定义了要连接的端口和主机名,以便与服务通信 。
SRV 记录是为“normal”或“headless”服务的部分指定端口创建的。SRV 记录采用 _my-port-name._my-port-protocol.my-svc.my-namespace.svc.cluster.local 的形式 。对于常规服务,它被解析的端口号和域名是: my-svc.my-namespace.svc.cluster.local 。在 “headless” 服务的情况下,此 name 解析为多个 answer,每个 answer 都支持服务。
每个 answer 都包含 auto-generated-name.my-svc.my-namespace.svc.cluster.local 表单的 Pod 端口号和域名。
Pod DNS 记录
A Record
如果启用了 DNS,Pod 将以 pod-ip-address.my-namespace.pod.cluster.local 的形式被分配为一个 DNS 记录。例如,在 default 命名空间中 IP 为 172.12.3.4 、DNS 名称为 cluster.local 的 Pod 将有一个形式 为 172-12-3-4.default.pod.cluster.local 的条目。
Pod 的主机名和子域字段
Pod 的默认主机名由 Pod 的 metadata.name 值定义。然而,用户可以通过在可选的 hostname 字段中指定一个新值来更改默认主机名。用户还可以在 subdomain 字段中自定义子域名。例如,在命名空间 my-namespace 中,将 hostname 设置为 custom-host ,将 subdomain 设置为 custom-subdomain 的 Pod 将具有完全限定的域名 (FQDN) custom-host.custom-subdomain.my-namespace.svc.cluster.local 。
教程:如何通过 DNS 命名解决服务问题
接下来,本文将演示如何通过 DNS 命名解决服务问题,检查 DNS 解析并在发生 DNS 问题时对其进行调试。要完成下面的示例, 你需要满足以下先决条件:
-
一个正在运行的 Kubernetes 集群;
-
安装与配置 kubectl 命令行工具。
首先,你需要使用三个 Python HTTP 服务器创建一个部署,该服务器会在端口 80 上侦听连接并返回包含 Pod 主机名的自定义问候语。
apiVersion: apps/v1
kind: Deployment
metadata:
name: test-deployment
spec:
replicas: 3
selector:
matchLabels:
app: test-pod
template:
metadata:
labels:
app: test-pod
spec:
containers:
- name: python-http-server
image: python:2.7
command: ["/bin/bash"]
args: ["-c", "echo \" Hello from $(hostname)\" > index.html; python -m SimpleHTTPServer 80"]
ports:
- name: http
containerPort: 80
创建部署:
kubectl create -f deployment.yml deployment.extensions "test-deployment" created
接下来,创建一个服务来发现部署的 Pod 并在它们之间分发客户端请求。以下是分配 ClusterIP 的“normal”服务清单。
kind: Service
apiVersion: v1
metadata:
name: test-service
spec:
selector:
app: test-pod
ports:
- protocol: TCP
port: 4000
targetPort: http
请注意,服务的 spec.selector 字段应该与部署创建的Pod的 spec.template.metadata.labels 相匹配。
kubectl create -f service.yml service "test-service" created
最后,创建一个客户端 Pod,curl 将通过其 name 来提供服务。这样管理员就不需要知道服务端点的 IP,而是依赖于 Kubernetes Pod 的短暂性。
apiVersion: v1
kind: Pod
metadata:
name: client-pod
spec:
containers:
- name: curl
image: appropriate/curl
command: ["/bin/sh"]
args: ["-c","curl test-service:4000 "]
请注意,本实验使用的是服务名称,而不是部署创建的 ClusterIP 或 Pod 的 IP。你可以使用服务的 DNS 名称(“tut-service”),因为本实验设置的 Kubernetes 集群是使用 Kube-DNS 附加组件来监视 Kubernetes API 以获取新服务并为每个服务创建 DNS 记录。如果在集群中启用了 Kube-DNS,则所有 Pod 都可以自动执行服务的名称解析。但是,你也可以继续使用你的服务 ClusterIP。
kubectl create -f client.yml pod "client-pod" created
创建客户端 Pod 后,检查日志。现在,你验证服务的名称已解析为正确的后端 Pod:
上面的响应表明 Kube-DNS 已正确解析服务的 ClusterIP 服务名称,并且服务已成功将客户端请求转发到以循环方式选择的随机后端 Pod。反过来,选定的 Pod 会返回其自定义问候语,你就可以在上面的响应中看到结果。
使用 nslookup 检查 DNS 解析
现在,查找 A Record 定义的 FQDN,验证 DNS 是否正常工作。为此,你需要将 shell 添加到正在运行的 Pod 中,并在其中使用 nslookup 命令。
首先,找到在部署中创建的 Pod:
kubectl get pods -l app=test-pod NAME READY STATUS RESTARTS AGE test-deployment-84dc998fc5-772gj 1/1 Running 0 1m test-deployment-84dc998fc5-fh5pf 1/1 Running 0 1m test-deployment-84dc998fc5-pkmsc 1/1 Running 0 1m
选择其中一个 Pod 并使用下面的命令获取 shell(使用你的唯一 Pod name):
kubectl exec -ti test-deployment-84dc998fc5-772gj -- /bin/bash
下一步,你需要在 BusyBox 包中安装 nslookup 命令:
apt-get update apt-get install busybox
安装 BusyBox 后,请检查服务的 DNS:
busybox nslookup test-service.default.svc.cluster.local Server: 10.96.0.10 Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local Name: test-service.default.svc.cluster.local Address 1: 10.109.90.121 test-service.default.svc.cluster.local
在上面的命令中,本实验使用了服务 A Record 的命名方案。现在,你可以通过验证 DNS 查找 DNS 服务的解析是否为正确的 IP(A Record)。
kubectl describe svc test-service Name: test-service Namespace: default Labels: <none> Annotations: <none> Selector: app=test-pod Type: ClusterIP IP: 10.109.90.121 Port: <unset> 4000/TCP TargetPort: http/TCP Endpoints: 172.17.0.11:80,172.17.0.15:80,172.17.0.19:80 Session Affinity: None Events: <none>
看起来很正确!你可以看到该服务的 ClusterIP 是 10.109.90.121 (与 DNS 查找解析的 IP 相同)。
调试 DNS
如果 nslookup 命令由于某种原因失败,你会有几个调试和故障排除的方案。但是,你应该如何得知 DNS 查找失败呢?如果 DNS 失败,你通常会得到如下响应:
kubectl exec -ti busybox -- nslookup kubernetes.default Server: 10.0.0.10 Address 1: 10.0.0.10 nslookup: can't resolve 'kubernetes.default'
如果出现此错误,你需要做的第一件事是检查 DNS 配置是否正确。
查看容器中的 resolv.conf 文件:
kubectl exec test-deployment-84dc998fc5-772gj cat /etc/resolv.conf
验证是否正确设置了搜索路径和名称服务器,如下例所示(请注意,搜索路径可能因不同的云提供商而异):
nameserver 10.96.0.10 search default.svc.cluster.local svc.cluster.local cluster.local options ndots:5
如果是 /etc/resolve.conf 的所有条目都是正确的,你需要检查 kube-dns / coredns 插件是否已启用。在 Minikube 上,运行:
minikube addons list - addon-manager: enabled - coredns: disabled - dashboard: enabled - default-storageclass: enabled - efk: disabled - freshpod: disabled - heapster: disabled - ingress: disabled - kube-dns: enabled - metrics-server: enabled - registry: disabled - registry-creds: disabled - storage-provisioner: enabled
如你所见,本实验启用了 kube-dns 。如果你的 DNS 加载项未运行,你可以尝试使用以下命令启用它:
minikube addons enable kube-dns kube-dns was successfully enabled
或者,你可以检查 kubedns / coredns Pod 是否正在运行:
kubectl get pods --namespace=kube-system NAME READY STATUS RESTARTS AGE .... kube-dns-86f4d74b45-2qkfd 3/3 Running 232 133d kube-proxy-b2frq 1/1 Running 0 15m ...
如果 Pod 正在运行,则全局 DNS 服务可能存在问题。
检查一下:
$ kubectl get svc --namespace=kube-system NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kube-dns ClusterIP 10.96.0.10 <none> 53/UDP,53
你可能还需要检查是否公开了 DNS 端点:
kubectl get ep kube-dns --namespace=kube-system NAME ENDPOINTS AGE kube-dns 172.17.0.5:53,172.17.0.5:53 133d
这些调试操作通常会指示 DNS 配置的问题,或者它只是向你显示应在集群配置中启用的 DNS 加载项。
总结
总而言之,Kubernetes 通过其内置的 DNS 附件实现高效的服务发现: Kube-DNS 或 CoreDNS。
Kubernetes DNS 系统会将域和子域名分配给 Pod、端口和服务,这使得它们可以被 Kubernetes 集群中的其他组件发现。
基于 DNS 的服务发现是非常强大,因为用户不需要将 IP 和端口等网络参数硬编码到应用程序中。 当服务管理一组 Pod 时,你就可以使用服务的 DNS 轻松访问它们了。
推荐阅读:
在看点一下
写留言
以上所述就是小编给大家介绍的《[译] 深度剖析 K8S DNS 的 Service 与 Pod》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Writing Windows VxDs and Device Drivers, Second Edition
Karen Hazzah / CMP / 1996-01-12 / USD 54.95
Software developer and author Karen Hazzah expands her original treatise on device drivers in the second edition of "Writing Windows VxDs and Device Drivers." The book and companion disk include the a......一起来看看 《Writing Windows VxDs and Device Drivers, Second Edition》 这本书的介绍吧!