Kubernetes 网络权威指南:基础、原理与实践

Kubernetes Master 存储了所有 Service 的定义和更新。但是,要与后端 Pod 通信的客户端 Pod 在使用 Service 实现负载均衡时也需要知道这些请求会发送到何处。这些 Pod 可以将网络信息存储在容器环境变量中,但从长远来看这是不可行的。(Pod 如果在 service 之前创建就不行了)。

Kubernetes DNS 系统可以解决这个问题。在一个 Kubernetes 集群中, DNS服务是非必需的,因此无论是 Kube-dns 还是 CoreDNS,通常以插件(add-on)的方式安装,作为运行在集群上的应用。如果涉及服务发现和域名访问,那么 Kubernetes 的 DNS 服务又是必不可少的。

1、DNS 服务基本框架

具体到 Kubernetes DNS 服务的功能,它是用来解析 Kubernetes 集群内的 Pod 和 Service 域名的,而且一般情况下只供集群内的容器使用,不给外人使用。

Kubernetes 的 DNS 应用部署好后,会对外暴露一个服务,集群内的容器通过访问该服务的 Cluster IP+53 端口获得域名解析服务,而这个 Service 的 Cluster IP 一般情况下都是固定的。

一般应用程序是无须感知 DNS 服务器的 IP 地址的,以 Linux 系统为例,容器内进程想要获得域名解析服务,只需把 DNS Server 写入 /etc/resolv.conf 文件。刷新 /etc/resolv.conf 配置这个动作是 Kubelet 完成的。

当 Kubernetes 的 DNS Service Cluster IP 分配后,系统(一般是指安装程序)会给 Kubelet 配置--cluster-dns=<dns service ip>启动参数, DNS Service 的 IP 地址将在用户容器启动时传递,并写入每个容器的 /etc/resolv.conf 文件。

2、域名解析基本原理

Kubernetes DNS 的命名方案也遵循可预测的模式,使各种服务的地址 更容易被记住。服务不仅可以通过完全限定域名(FQDN)引用,还可以仅通过服务本身的 name 引用。目前, Kubernetes DNS 加载项支持正向查找(A Record)、端口查找(SRV记录)、反向IP地址查找(PTR记录)及其他功能。

对于Service,Kubernetes DNS 服务器会生成三类 DNS 记录,分别是A 记录、SRV 记录和 CNAME 记录。

2.1、A 记录

A记录(A Record)是用于将域名指向某个 IP 地址的DNS记录的最基本类型。记录包括域名、解析它的 IP 地址和以秒为单位的 TTL。TTL 代表生存时间,是 DNS 记录上的一种到期日期。每个 TTL 都会告诉 DNS 服务器,它应该在其缓存中保留给定记录多长时间。

普通 Service 的 A 记录的映射关系是:

{service name}.{service namespace}.svc.{domain} -> cluster IP

每个部分字段的含义是:

  • service_name:Service 名

  • namespace:Service 所在 namespace

  • domain:提供的域名后缀,是 Kubelet 通过 --cluster-domain 配置的, 比如默认的 cluster.local。

在 Pod 中可以通过域名{ service name}.{service namespace}.svc. {domain}访问任何服务,也可以使用缩写{ service name}.{service namespace}直接访问。如果 Pod 和Service 在同一个 namespace 中,那么甚至可以直接使用{service name}访问。

headless Service 的 A 记录的映射关系是:

{service name}.{service namespace}.svc.{domain} -> 后端 Pod IP 列表

一旦启用了 DNS,Pod 将被分配一个 DNS A 记录,格式如下所示:

{pod-ip}.{pod namespace}.pod.{domain} -> Pod IP 

其中 pod-ip 为 Pod 的 IP 地址用-符号隔开,例如 Pod IP 是1.2.3.4,上面的{ pod-ip }即 1-2-3-4 ,因此对应的域名就是 1-2-34.default.pod.cluster.local。Pod 的 A 记录其实没什么用,都知道 Pod IP了, 还用查DNS吗?所以这也是一个即将废弃的特性。

2.2、SRV 记录

SRV 记录(Service Record)是一种特殊的 DNS 记录类型,用于指定某个服务的主机名和端口号。SRV 记录允许客户端在访问服务时,不仅能获取服务的主机名,还能获得服务运行的端口号。它通常用于基于域名的服务发现和负载均衡。

SRV 记录的格式如下:

_service._protocol.name TTL class SRV priority weight port target
_sip._udp.example.com. 86400 IN SRV 10 60 5060 sipserver1.example.com.

在上面的示例中, sip 是服务的符号名称udp 是服务的使用传输协 议。10是优先级,60是权重,优先级和权重通常用于建议指定使用某些服务器。记录中的最后两个值定义了要连接的端口和主机名, 以便与服务通信。
Kubernetes DNS 的 SRV 记录是按照一个约定俗成的规定实现了对服务 端口的查询:

_{port name}._{port protocol}.{service name}.{service namespace}.svc.cluster.local -> Service Port

在 Kubernetes 中,SRV 记录可以用于发现服务的名称和端口。例如,如果有一个名为 my-service 的服务在 default 命名空间中运行,客户端可以通过 SRV 记录找到该服务,并确定其运行的端口。

示例命令

可以通过以下命令查找 Kubernetes 中的 SRV 记录:

dig SRV _http._tcp.my-service.default.svc.cluster.local

这将返回 my-service 服务的主机名和端口号,供客户端进行访问。

2.3、CNAME记录

CNAME 记录用于将域名指向另一个主机名。为此, CNAME使用现有的A记录作为其值。此外, 在 Kubernetes 中,CNAME记录可用于联合服务的跨集群服务发现。在整个场景中会有一个跨多个 Kubernetes 集群的公共服务。所有 Pod 都可以发现这项服务(无论这些 Pod 在哪个集群上)。这是一种跨集群服务发现方法。