在 Kubernetess 中使用 DNS 和 Headless Service 发现运行中的 Pod

在 Kubernetess 中使用 DNS 和 Headless Service 发现运行中的 Pod_第1张图片

什么是 Headless Service?


部署 Service时,可以设置三种不同的 ServiceTypes 以指定所需的 Service 类型:

  • ClusterIP:仅在集群内部 ip 地址上公开 Service,这也是默认的 ServiceType

  • NodePort:允许通过节点上的静态端口公开 Service。

  • LoadBalancer:允许使用云提供商的外部负载均衡器公开 Service 。

为避免请求在单个 IP 地址后面进行负载均衡,当不需要单个 IP 地址时,我们可以通过指定 Cluster IP(spec.clusterIP)的值为 "None" 来创建 Headless Service。Kubernetes 不会为该 Service 分配任何 IP 地址。这种 Service 就称为 Headless Services。

 

 

DNS 解析和 Headless Service


部署 Service 时,Kubernetes 会为其分配一个 DNS 名称。集群中的其他组件可以使用此名称与 DNS 和上游 Pod 通信。DNS 名称遵循以下命名约定:

图片

在 IP 地址上使用可读名称后,其他组件就不需要分配给 Service 实际 IP 地址。

使用正确的 Pod 选择(selector)配置 Headless Service 时,Kubernetes 将为上游选定的 Pod 创建正确端点记录和 DNS 配置。

对于将连接到 Headless Service 的每个已连接 Pod,也会配置 A 或 AAAA 记录。这样就可以对 Headless Service 执行 DNS 查询,以解析所连接 Pod 的所有 IP 地址。

如何实践?


假设存在以下问题:Kubernetes 集群中运行着一组有状态的三个 MongoDB Pod。这三个 Pod 共同构成一个 MongoDB 副本集,这是一个高度可用的数据集。

在 Kubernetess 中使用 DNS 和 Headless Service 发现运行中的 Pod_第2张图片

为了能够将控制台应用程序连接到 MongoDB 副本集,我们使用 MongoDB C# 驱动程序,同时需要显式定义三个 Pod 的地址。

我们用 Headless Service 解决这个问题。假定 MongoDb Pod 都带有 app=mongodb 标签,该标签可以在 Headless Service 中用于选择 Pod。

我们定义的 Headless Service 资源如下所示:

在 Kubernetess 中使用 DNS 和 Headless Service 发现运行中的 Pod_第3张图片

通过将 clusterIp 设置为 "none",我们告诉 Kubernetes 将此 Service 视为 Headless Service。由于我们定义了名称和命名空间,因此可以推断出 DNS 名称。我们在集群内部使用 mongodb-headless-service.infrastructure.svc.cluster.local 或 mongodb-headless-service.infrastructure 作为地址与 Service 进行通信。

接下来让我们来执行 DNS 查询,以检索连接 Pod 的 IP 地址。Dns.GetHostAddresses 方法位于 System.Net 命名空间中,可帮助我们执行该 DNS 查询并返回 IP 地址数组。它需要一个主机名或 IP 地址。最后,我们可以使用 MongoDB 创建连接字符串(connection string)。

代码如下:

在 Kubernetess 中使用 DNS 和 Headless Service 发现运行中的 Pod_第4张图片

通过该解决方案,我们可以动态创建连接字符串,其主要优点是,在必须扩展数据库集群时,我们不必手动更改连接字符串。

注意:MongoDB 确实通过 DNS 实现了类似的服务发现过程,只需定义 Headless Service 的 DNS 名称即可,这样我们就不必自己生成连接字符串。

Headless Service


service 有一个特别的形态就是 Headless Service。service 创建的时候可以指定 clusterIP:None,告诉 K8s 说我不需要 clusterIP(就是刚才所说的集群里面的一个虚拟 IP),然后 K8s 就不会分配给这个 service 一个虚拟 IP 地址,它没有虚拟 IP 地址怎么做到负载均衡以及统一的访问入口呢?

它是这样来操作的:pod 可以直接通过 service_name 用 DNS 的方式解析到所有后端 pod 的 IP 地址,通过 DNS 的 A 记录的方式会解析到所有后端的 Pod 的地址,由客户端选择一个后端的 IP 地址,这个 A 记录会随着 pod 的生命周期变化,返回的 A 记录列表也发生变化,这样就要求客户端应用要从 A 记录把所有 DNS 返回到 A 记录的列表里面 IP 地址中,客户端自己去选择一个合适的地址去访问 pod。

在 Kubernetess 中使用 DNS 和 Headless Service 发现运行中的 Pod_第5张图片

你可能感兴趣的:(Kubernetes,Service,kubernetes)