适用于 Kubernetes 的 DiscoveryClient
该项目提供了 Discovery Client for Kubernetes 的实现。
此客户端允许您按名称查询 Kubernetes 终端节点(请参阅服务)。
服务通常由 Kubernetes API 服务器作为表示和寻址的端点集合公开,并且客户端可以
从作为 Pod 运行的 Spring Boot 应用程序访问。http
https
DiscoveryClient 还可以找到 类型的服务(参见 ExternalName 服务)。目前,仅当以下属性设置为 (默认情况下) 时,外部名称支持类型的服务才可用。ExternalName
spring.cloud.kubernetes.discovery.include-external-name-services
true
false
我们支持 3 种类型的发现客户端:
1.
Fabric8 Kubernetes 客户端
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-kubernetes-fabric8</artifactId>
</dependency>
2.
Kubernetes Java 客户端
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-kubernetes-client</artifactId>
</dependency>
3.
基于 HTTPDiscoveryClient
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-kubernetes-discoveryclient</artifactId>
</dependency>
spring-cloud-starter-kubernetes-discoveryclient 旨在与 Spring Cloud Kubernetes DiscoveryServer 一起使用。 |
要启用加载 ,请添加到相应的配置或应用程序类,如下例所示:DiscoveryClient
@EnableDiscoveryClient
@SpringBootApplication
@EnableDiscoveryClient
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
然后,您只需通过自动装配客户端即可将其注入代码中,如下例所示:
@Autowired
private DiscoveryClient discoveryClient;
您应该问自己的第一个问题是应该在哪里发现服务。在 kubernetes 世界中,这意味着什么命名空间。这里有 3 个选项:DiscoveryClient
-
selective namespaces
.例如:
spring.cloud.kubernetes.discovery.namespaces[0]=ns1
spring.cloud.kubernetes.discovery.namespaces[1]=ns2
此类配置使发现客户端仅搜索两个命名空间和 中的服务。ns1
ns2
-
all-namespaces
.
spring.cloud.kubernetes.discovery.all-namespaces=true
虽然存在这样的选项,但这可能会给 kube-api 和你的应用程序带来负担。很少需要这样的设置。
-
one namespace
.如果未指定上述任何一项,则这是默认设置。它适用于 Namespace Resolution 中概述的规则。
以上选项的工作方式与为 fabric8 和 k8s 客户端编写的完全一样。对于基于 HTTP 的客户端,您需要在服务器上启用这些选项。这可以通过使用 env 变量将它们设置为 used 来实现,以便在集群中部署镜像。deployment.yaml |
例如:
containers:
- name: discovery-server
image: springcloud/spring-cloud-kubernetes-discoveryserver:3.0.5-SNAPSHOT
env:
- name: SPRING_CLOUD_KUBERNETES_DISCOVERY_NAMESPACES_0
value: "namespace-a"
配置命名空间后,下一个要回答的问题是要发现哪些服务。将其视为要应用的过滤器。默认情况下,根本不应用筛选,并且会发现所有服务。如果需要缩小发现客户端可以查找的范围,则有两个选项:
-
仅接受与特定服务标签匹配的服务。此属性由 : 指定。它接受 a,并且仅考虑具有此类标签的服务(如服务定义中所示)。
spring.cloud.kubernetes.discovery.service-labels
Map
metadata.labels
-
另一种选择是使用 SpEL 表达式。这由属性表示,其值取决于您选择的客户端。如果使用 fabric8 客户端,则必须针对类创建此 SPEL 表达式。一个这样的例子可能是:
spring.cloud.kubernetes.discovery.filter
io.fabric8.kubernetes.api.model.Service
spring.cloud.kubernetes.discovery.filter='#root.metadata.namespace matches "^.+A$"'
它告诉 Discovery Client 仅获取 that 以大写结尾的服务。metadata.namespace
A
如果您的发现客户端基于 k8s-native 客户端,则 SPEL 表达式必须基于类。上面显示的相同过滤器在这里也有效。io.kubernetes.client.openapi.models.V1Service
如果您的发现客户端是基于 http 的客户端,则 SeEL 表达式必须基于相同的类,唯一的区别是这需要在部署 yaml 中设置为 env 变量:io.kubernetes.client.openapi.models.V1Service
containers: - name: discovery-server image: springcloud/spring-cloud-kubernetes-discoveryserver:3.0.5-SNAPSHOT env: - name: SPRING_CLOUD_KUBERNETES_DISCOVERY_FILTER value: '#root.metadata.namespace matches "^.+A$"'
现在是时候考虑 discovery client 应该返回什么了。通常,有两种方法具有: 和 。DiscoveryClient
getServices
getInstances
getServices
将返回服务名称,如 .metadata.name
此方法将返回唯一的服务名称,即使不同命名空间(您为搜索选择)之间存在重复项。 |
getInstances
返回 .除了 a 通常具有的字段外,我们还添加了一些数据,例如 namespace 或 pod 元数据(有关这些的更多解释将在文档中提供)。以下是我们目前返回的数据:List<ServiceInstance>
ServiceInstance
-
instanceId
- 服务实例的唯一 ID -
serviceId
- 服务的名称(与调用getServices
) -
host
- 实例的 IP(如果是服务类型,则为名称)ExternalName
-
port
- 实例的端口号。这需要更多的解释,因为选择端口号有其规则:-
service 未定义端口,则返回 0(零)。
-
service 定义了一个端口,该端口将被返回。
-
如果服务有 标签 ,我们将使用具有标签值中指定的名称的端口号。
primary-port-name
-
如果上述标签不存在,那么我们将使用 中指定的端口名称来查找端口号。
spring.cloud.kubernetes.discovery.primary-port-name
-
如果以上均未指定,我们将使用名为 或 的端口来计算端口号。
https
http
-
作为最后的手段,我们将选择端口列表中的第一个端口。最后一个选项可能会导致非确定性行为。
-
-
uri
服务实例的 -
scheme
要么 or (取决于结果)http
https
secure
-
metadata
的服务范围:-
labels
(如果通过以下方式请求)。标签键可以 “prefixed” with value of (如果已设置)。spring.cloud.kubernetes.discovery.metadata.add-labels=true
spring.cloud.kubernetes.discovery.metadata.labels-prefix
-
annotations
(如果通过以下方式请求)。如果设置了 Commentss 键,则可以以 的值 “prefixed” 。spring.cloud.kubernetes.discovery.metadata.add-annotations=true
spring.cloud.kubernetes.discovery.metadata.annotations-prefix
-
ports
(如果通过以下方式请求)。如果设置了 Port 键,则可以以 value of 作为“前缀”。spring.cloud.kubernetes.discovery.metadata.add-ports=true
spring.cloud.kubernetes.discovery.metadata.ports-prefix
-
k8s_namespace
替换为 instance 所在的命名空间的值。 -
type
,其中包含 Service 类型,例如ClusterIP
ExternalName
-
-
secure
如果发现的端口应被视为安全端口。我们将使用上面概述的相同规则来查找端口名称和编号,然后:-
如果此服务具有使用任何值 : 调用的标签,则将找到的端口视为安全端口。
secured
["true", "on", "yes", "1"]
-
如果未找到此类标签,请搜索名为 并应用相同的上述规则的注释。
secured
-
如果此端口号是 (默认情况下此值保持) 的一部分,请将端口号视为 secured。
spring.cloud.kubernetes.discovery.known-secure-ports
[443, 8443]
-
最后的手段是查看 port name 是否匹配;如果确实,则将此端口视为安全端口。
https
-
-
namespace
- 找到的实例的命名空间。 -
pod-metadata
服务实例 (pod) 的标签和注解,采用 .此支持需要通过 and/或Map<String, Map<String, String>>
spring.cloud.kubernetes.discovery.metadata.add-pod-labels=true
spring.cloud.kubernetes.discovery.metadata.add-pod-annotaations=true
要发现未被 kubernetes api 服务器标记为 “ready” 的服务端点地址,您可以在 (default: false) 中设置以下属性:application.properties
spring.cloud.kubernetes.discovery.include-not-ready-addresses=true
这在发现用于监控目的的服务时可能很有用,并且将启用检查未就绪服务实例的终端节点。
如果要获取 也包括 services 类型的列表,则需要通过以下方式启用该支持: 。因此,在调用时,也会返回这些值。您可以通过检查和查找名为 .这将是返回的服务类型:/ 等。
如果出于任何原因需要禁用 ,则可以在 中设置以下属性:/health ServiceInstance ExternalName spring.cloud.kubernetes.discovery.include-external-name-services=true DiscoveryClient::getInstances ExternalName ServiceInstance::getMetadata type ExternalName ClusterIP DiscoveryClient application.properties |
spring.main.cloud-platform=NONE
请注意,对 discovery client 的支持是自动的,具体取决于您运行应用程序的位置。因此,可能不需要上述设置。
某些 Spring Cloud 组件使用 for 来获取有关本地服务实例的信息。为
要正常工作,您需要将 Kubernetes 服务名称与属性保持一致。DiscoveryClient
spring.application.name
spring.application.name 只要在 Kubernetes 中为应用程序注册的名称,则没有影响 |
Spring Cloud Kubernetes 还可以监视 Kubernetes 服务目录的更改,并相应地更新实现。为了启用此功能,您需要在应用程序中添加 configuration 类。“watch”是指每毫秒发布一次心跳事件(默认情况下为 )。对于 http 发现服务器,这必须是在部署 yaml 中设置的环境变量:DiscoveryClient
@EnableScheduling
spring.cloud.kubernetes.discovery.catalog-services-watch-delay
30000
containers: - name: discovery-server image: springcloud/spring-cloud-kubernetes-discoveryserver:3.0.5-SNAPSHOT env: - name: SPRING_CLOUD_KUBERNETES_DISCOVERY_CATALOGSERVICESWATCHDELAY value: 3000
heartbeat 事件将包含目标引用(及其所有端点地址的命名空间
(有关将退回的内容的确切详细信息,您可以查看内部)。这是一个实现细节,以及 heartbeat 事件的侦听器
不应依赖细节。相反,他们应该通过 method 查看两个后续心跳之间是否存在差异。我们将注意返回符合 equals 协定的正确实现。
将在以下任一位置查询端点:
- (通过KubernetesCatalogWatch
equals
all-namespaces
spring.cloud.kubernetes.discovery.all-namespaces=true
)
-
selective namespaces
(启用方式),例如:spring.cloud.kubernetes.discovery.namespaces
-
one namespace
通过 Namespace Resolution 如果未采用上述两条路径。
如果出于任何原因,您想要禁用 catalog watcher,则需要设置 。对于 http 发现服务器,这需要是在部署中设置的环境变量,例如:spring.cloud.kubernetes.discovery.catalog-services-watch.enabled=false |
SPRING_CLOUD_KUBERNETES_DISCOVERY_CATALOGSERVICESWATCH_ENABLED=FALSE
catalog watch 的功能适用于我们支持的所有 3 个发现客户端,但在使用 http 客户端时需要注意一些注意事项。
-
首先是此功能默认处于禁用状态,需要在两个地方启用:
-
在 Discovery Server 中,通过部署清单中的环境变量,例如:
containers: - name: discovery-server image: springcloud/spring-cloud-kubernetes-discoveryserver:3.0.5-SNAPSHOT env: - name: SPRING_CLOUD_KUBERNETES_HTTP_DISCOVERY_CATALOG_WATCHER_ENABLED value: "TRUE"
-
在 Discovery Client 中,通过您的属性,例如:
application.properties
spring.cloud.kubernetes.http.discovery.catalog.watcher.enabled=true
-
-
第二点是,这只支持 从 version 及以上版本开始。
3.0.6
-
由于 http 发现有两个组件:服务器和客户端,我们强烈建议在它们之间对齐版本,否则可能无法工作。
-
如果您决定禁用 catalog watcher,则需要在 server 和 client 中禁用它。
默认情况下,我们使用 (参见 kubernetes.io/docs/concepts/services-networking/service/#endpoints) API 来了解服务的当前状态。不过还有另一种方法,通过 (kubernetes.io/docs/concepts/services-networking/endpoint-slices/)。可以通过 property 启用此类支持: (默认情况下为 )。当然,您的集群也必须支持它。事实上,如果您启用了此属性,但您的集群不支持它,我们将无法启动应用程序。如果您决定启用此类支持,则还需要适当的 Role/ClusterRole 设置。例如:Endpoints
EndpointSlices
spring.cloud.kubernetes.discovery.use-endpoint-slices=true
false
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: default
name: namespace-reader
rules:
- apiGroups: ["discovery.k8s.io"]
resources: ["endpointslices"]
verbs: ["get", "list", "watch"]