内容简介:作者: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》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
REST实战
Jim Webber、Savas Parastatidis、Ian Robinson / 李锟、俞黎敏、马钧、崔毅 / 东南大学出版社 / 2011-10 / 78.00元
为何典型的企业项目无法像你为web所开发的项目那样运行得如此平滑?对于建造分布式和企业级的应用来说,rest架构风格真的提供了一个可行的替代选择吗? 在这本富有洞察力的书中,三位soa专家对于rest进行了讲求实际的解释,并且通过将web的指导原理应用到普通的企业计算问题中,向你展示了如何开发简单的、优雅的分布式超媒体系统。你将会学习到很多技术,并且随着一家典型的公司从最初的小企业逐渐成长为......一起来看看 《REST实战》 这本书的介绍吧!
RGB CMYK 转换工具
RGB CMYK 互转工具
HEX HSV 转换工具
HEX HSV 互换工具