服务发现是容器环境的核心功能,本文将详解Rancher 2.0中的服务发现功能,展示如何将Rancher 1.6功能集映射到最新2.x版本,如何通过Kubernetes DNS功能在Rancher 2.0中支持等效的服务发现。玩转Rancher 2.0中的服务发现在此一举。
对于所有基于容器的环境而言,服务发现都是不可或缺的核心功能之一。使用容器打包和启动应用程序之后,下一步就是使其可以被环境或外部世界中的其他应用程序容器发现。
在本文中,我们将详解Rancher 2.0中服务发现功能,并向你展示如何将Rancher 1.6功能集映射到最新版本。
Rancher 1.6中的服务发现
Rancher 1.6在Cattle环境中提供服务发现。Rancher自己的DNS微服务提供了内部DNS功能。
Rancher的内部DNS提供以下主要功能:
- 堆栈内和跨堆栈的服务发现
堆栈中的所有服务都可以通过<service_name> 和<service_name>.<stack_name>跨堆栈解析。
- 容器发现
所有容器都通过他们的名字全局解析。
- 创建服务别名
为服务添加别名,并使用别名链接到其他服务。
- 发现外部服务
指向使用外部IP或域名部署在Rancher之外的服务。
Rancher 2.0中的服务发现
Rancher 2.0使用原生的Kubernetes DNS支持为Kubernetes工作负载和pod提供等效的服务发现。Cattle用户将能够在不丢失任何功能的情况下复制Rancher 2.0中的所有服务发现功能。
与Rancher 1.6 DNS微服务类似,Kubernetes在集群内调度DNS pod和服务,并配置kubelet以将所有DNS查找路由到此DNS服务。Rancher 2.0的Kubernetes集群将skyDNS部署为Kubernetes DNS服务,这是默认Kube-DNS实现的一种风格。
服务解析
Rancher 1.6服务映射到某种类型的Kubernetes工作负载,您可以在此了解一个有关流行类型工作负载的简短摘要:
Kubernetes工作负载是指定为工作负载启动的pod的部署规则的对象。工作负载对象本身无法通过DNS解析为Kubernetes集群中的其他对象。要查找和访问工作负载,需要为工作负载创建Kubernetes服务。以下是Kubernetes服务的一些细节:
在Kubernetes中创建的任何服务都会获得DNS名称。为服务创建的DNS A记录的格式为 <service_name>.<namespace_name>.svc.cluster.local。服务的DNS名称解析为服务的集群IP。集群IP是分配给服务的内部IP,可在集群内解析。
在Kubernetes命名空间内,服务可以使用<service_name> 直接解析,命名空间外部的服务则可以使用<service_name>.<namespace_name>直接解析。这类似于Rancher 1.6中堆栈内以及跨堆栈的服务发现。
因此,要查找和访问应用程序工作负载,需要创建一个获取DNS记录的服务。
Rancher通过使用您在UI中选择的服务端口和服务类型自动创建服务以及工作负载,同时部署与工作负载名称相同的工作负载和服务名称,从而简化了此过程。如果没有暴露端口,则使用端口42。这种做法使得工作负载可以通过名称在命名空间内和跨命名空间发现。
例如,如下所示,我使用Rancher 2.0 UI在两个名称空间中部署了几个类型为Deployment的工作负载。
我可以在Cluster> Project> Service Discovery选项卡下看到Rancher为工作负载自动创建的相应DNS记录。
如下所示,工作负载可供命名空间内和跨命名空间的任何其他工作负载访问。
Pod解析
在Kubernetes集群中运行的各个pod也会分配一个DNS记录,其格式为 <pod_ip_address>.<namespace_name>.pod.cluster.local。例如,某pod的IP为10.42.2.7,它在命名空间default 中,DNS名称为 cluster.local,则它的entry为10-42-2-7.default.pod.cluster.local。
如果是在pod规范中设置,也可以使用hostname和subdomain字段解析Pod。相关内容可以参考Kubernetes文档:
为工作负载和外部服务创建别名
就像您可以为Rancher 1.6服务创建别名一样,您也可以使用Rancher 2.0对Kubernetes工作负载执行相同的操作。同样,您也可以使用Rancher 2.0中的主机名或IP地址创建指向外部运行服务的DNS记录。这些DNS记录是Kubernetes服务对象。
使用2.0 UI,导航到Cluster> Project视图,然后选择Service Discovery选项卡。此处,为您的工作负载创建的所有现有DNS记录都将列在每个命名空间下。
单击“Add Record ”以创建新的DNS记录,并查看链接到外部服务所支持的各种选项,或为另一个工作负载/ DNS记录/pod组创建别名。
需要注意的一点是,在创建DNS记录的这些选项中,Kubernetes本身支持以下选项:
-
指向外部主机名
-
指向一组与选择器匹配的pod
其余功能由Rancher利用Kubernetes实现:
-
指向外部IP地址
-
为另一个DNS记录创建别名
-
指向另一个工作负载
从Docker Compose到Kubernetes YAML
现在让我们看看如果我们想要使用Compose文件将应用程序从1.6迁移到2.0而不是通过2.0 UI部署它,我们需要怎么做。
上文中介绍过,当我们使用Rancher 2.0 UI部署工作负载时,Rancher会在内部为服务发现创建必要的Kubernetes ClusterIP服务。但是,如果您是通过Rancher CLI或Kubectl客户端部署工作负载,那么您应该如何确保完成相同的服务发现行为?
通过Compose在命名空间内和跨命名空间进行服务发现
让我们从以下docker-compose.yml文件开始,该文件显示了堆栈中的两个服务(foo和bar)。在Cattle堆栈中,这两个服务可以使用其服务名称相互访问。
那么,如果我们将这两个服务迁移到Rancher 2.0中的命名空间,会发生什么?
我们可以使用Kompose工具将此docker-compose.yml文件从Rancher 1.6转换为Kubernetes YAML,然后使用Rancher CLI在Kubernetes集群中部署该应用程序。
现在,此转换会生成* -deployment.yaml文件,使用Rancher CLI部署它们会在命名空间内创建相应的工作负载。
这些工作负载可以在命名空间内相互访问吗?我们可以使用Rancher 2.0 UI执行工作负载foo的shell,然后看看ping另一个工作负载bar是否有效。
没有!原因是我们只创建了Deployment类型的工作负载对象。为了使这些工作负载可被发现,它们每个都需要一个指向它们的ClusterIP类型的服务,该服务将被分配一个DNS记录。用于此类服务的Kubernetes YAML应如下所示。
请注意,ports是必填字段。因此,我们需要为其提供一些端口号,如此处所示的42。
通过CLI部署此服务后,服务foo可以成功ping到服务bar了!
因此,如果您使用Compose-to-Kubernetes-YAML路由将1.6服务迁移到Rancher 2.0,请确保您还为工作负载部署了相应的ClusterIP服务。相同的解决方案也适用于工作负载的跨命名空间引用。
Compose的链接/外部链接
如果您是Cattle用户,您一定知道在Rancher 1.6中,您可以创建指向其他服务的服务链接/别名,并在您的应用程序中使用该别名来发现该链接的目标服务。
例如下面的应用程序,其中Web服务使用别名mongo链接到数据库服务。
使用Kompose,将此Compose文件转换为Kubernetes YAML生成相应的部署和服务YAML规范。如果您在docker-compose.yml中的服务公开端口,Kompose默认会生成Kubernetes ClusterIP服务YAML规范。
使用Rancher CLI部署这些工具会生成必要的工作负载。
但是此处缺少了服务链接mongo,因为Kompose转换不支持docker-compose.yml文件中的链接。如此一来,工作负载web出现了错误,其pod继续重新启动,无法解析到数据库服务的mongo链接。
我们如何修复破坏的DNS链接?解决方案是创建另一个ClusterIP服务规范,并将其名称设置为docker-compose中链接的别名。
部署此服务会创建必要的DNS记录,并创建链接mongo,从而使web工作负载可用。
下图显示的就是web工作负载启动的pod已进入Running状态。
未来从SkyDNS过渡到CoreDNS
从Rancher v2.0.7开始,Rancher部署了由Kubernetes版本1.10.x支持的skyDNS。在Kubernetes 1.11及更高版本中,CoreDNS可以作为DNS提供程序安装。我们也正在评估CoreDNS,它将在Rancher的未来版本中作为skyDNS的替代品。
结 语
本文介绍了如何通过Kubernetes DNS功能在Rancher 2.0中支持等效的服务发现。在后续文章中,我们将分享Rancher 2.0支持的负载均衡功能以及与Rancher 1.6相比存在的限制。