DiscoveryClient for Kubernetes
本项目为 发现客户端 提供了针对 Kubernetes 的实现。该客户端可让您通过名称查询 Kubernetes 端点(参见 服务)。服务通常由 Kubernetes API 服务器以一组端点形式暴露,这些端点代表 http 和 https 地址,客户端可在作为 Pod 运行的 Spring Boot 应用程序中访问这些地址。
DiscoveryClient 还可以发现类型为 ExternalName 的服务(参见 外部名称服务)。目前,外部名称服务类型的支持仅在以下属性 spring.cloud.kubernetes.discovery.include-external-name-services 设置为 true 时才可用(默认值为 false)。
我们支持3种类型的发现客户端:
1.
Fabric8 Kubernetes Client
<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.
基于 HTTP 的 DiscoveryClient
<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);
}
}
然后,您只需通过自动装配(autowiring)即可在代码中注入客户端,如下例所示:
@Autowired
private DiscoveryClient discoveryClient;
你应该问自己的第一个问题是在何处查找服务。在 Kubernetes 环境中,这意味着要确定哪个命名空间(或哪些命名空间)。此处有三种选项:
-
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. 这是默认设置,如果您未指定上述任何内容,则使用此设置。它遵循 命名空间解析 中所述的规则。
上述选项对 fabric8 和 k8s 客户端的使用方式与所写完全一致。对于基于 HTTP 的客户端,您需要在 服务器 端启用这些选项。这可以通过在部署镜像到集群时使用的 deployment.yaml 中设置它们来实现,例如通过环境变量(s)进行配置。 |
例如:
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"
一旦命名空间已配置,下一个要回答的问题是要发现哪些服务。可将其视为要应用的筛选器。默认情况下,根本不会应用任何筛选器,并且会发现所有服务。如果需要缩小发现客户端可以找到的内容,那么有两种选项:
-
只选择与某些服务标签匹配的服务。此属性指定为:
0 。它接受一个1 ,并且只有那些具有此类标签(如在服务定义中的2 中所示)的服务才会被考虑在内。 -
另一种选择是使用SpEL 表达式。这由
spring.cloud.kubernetes.discovery.filter属性表示,其值取决于您选择的客户端。如果您使用 fabric8 客户端,则此 SpEL 表达式必须针对io.fabric8.kubernetes.api.model.Service类创建。例如:
spring.cloud.kubernetes.discovery.filter='#root.metadata.namespace matches "^.+A$"'
指示发现客户端仅获取以大写字母A结尾的值为metadata.namespace的服务。
如果你的发现客户端是基于 k8s 原生客户端,则 SpEL 表达式必须基于 io.kubernetes.client.openapi.models.V1Service 类。上面显示的相同过滤器在此处也可以使用。
如果您的发现客户端是基于 http 的,则此 SeEL 表达式必须基于相同的 io.kubernetes.client.openapi.models.V1Service 类,唯一的区别是需要将其设置为部署 yaml 中的环境变量:
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。
0 将返回服务名称,如1 中所示。
| 该方法会返回唯一的服务名称,即使在您为搜索选择的不同命名空间中存在重复项也是如此。 |
getInstances returns a List<ServiceInstance>. Besides the usual fields that a ServiceInstance has, we also add some data, like namespace or pod metadata (more explanation about these will follow in the document). Here is the data that we return at the moment:
-
instanceId- 唯一的服务实例 ID -
serviceId- 服务的名称(与调用getServices时报告的名称相同) -
host- IP of the instance (or name in case of theExternalNametype of service) -
port- 端口号。这需要更多的解释,因为选择端口号有其规则:-
服务未定义端口,将返回 0(零)。
-
service has a single port defined, that one will be returned.
-
如果服务具有标签
0 ,我们将使用标签值中指定名称的端口号。 -
(如果上表中未指定标签,则将使用
spring.cloud.kubernetes.discovery.primary-port-name中指定的端口名来查找端口号。) -
如果两者都不是指定的,我们将使用端口名为
0 或1 计算端口号。 -
作为最后的手段,我们将选择端口列表中的第一个端口。此最终选项可能会导致非确定性行为。
-
-
uri个服务实例 -
schemeeitherhttporhttps(depending on thesecureresult) -
metadataof the service:-
labels(如果通过spring.cloud.kubernetes.discovery.metadata.add-labels=true请求)。 如果设置了spring.cloud.kubernetes.discovery.metadata.labels-prefix,则可以为标签键添加前缀。 -
<代码>0 (如果通过 <代码>1 请求的话)。如果设置了 <代码>2,注释键可以使用它的值进行“前缀”。
-
0(如果通过1)。端口密钥可以带有值的前缀2如果已设置。 -
k8s_namespace,其值为实例所在的命名空间。 -
0表示服务类型,例如1或2
-
-
secure如果发现的端口应该被视为安全的。我们将使用上述概述的相同规则查找端口名称和编号,然后:-
如果此服务在标签
secured中有值为["true", "on", "yes", "1"]的任何值,则将找到的端口视为安全端口。 -
如果未找到此类标签,请搜索名为
secured的注解,并应用上述相同规则。 -
如果此端口号是
spring.cloud.kubernetes.discovery.known-secure-ports的一部分(默认情况下该值包含[443, 8443]),则将端口号视为安全。 -
最后一道防线是查看端口名称是否与
https匹配;如果是,则将该端口视为已加密。
-
-
0 - 命名空间中找到的实例的命名空间。 -
在社会内部质经管理逻理接口关系上,Pods(服务实例)可以配置 标答和注解,正方时,通过 支持此关系,需要通过 和/or 支持,
要发现由 Kubernetes API 服务器标记为“就绪”的服务端点地址,请在application.properties中设置以下属性(默认值:false):
spring.cloud.kubernetes.discovery.include-not-ready-addresses=true
这可能在发现服务用于监视目的时很有用,这将允许检查非就绪服务实例的/health端点。要获取 ServiceInstance以包括ExternalName类型的服务,您需要通过:spring.cloud.kubernetes.discovery.include-external-name-services=true来启用此支持。这样,调用DiscoveryClient::getInstances时也会返回这些服务。可以通过检查ServiceInstance::getMetadata来区分ExternalName和其他类型,查找一个名为type的字段。这将是返回的服务类型: ExternalName/ClusterIP等。如果出于任何原因,您需要关闭 1011 |
spring.main.cloud-platform=NONE
提示:发现客户端的支持是自动的,取决于您在哪里运行应用程序。因此,上述设置可能不需要。
某些Spring Cloud组件使用DiscoveryClient来获取有关本地服务实例的信息。为此,您需要使Kubernetes服务名与spring.application.name属性保持一致。
spring.application.name 对在 Kubernetes 中为应用程序注册的名称没有影响 |
Spring Cloud Kubernetes 还可以监视 Kubernetes 服务目录中的更改,并相应地更新 DiscoveryClient 实现。 要启用此功能,您需要在应用程序中的配置类上添加@EnableScheduling。 所谓“观察”,我们指的是每spring.cloud.kubernetes.discovery.catalog-services-watch-delay毫秒(默认为30000)发布的心跳事件。 对于 http 发现服务器,这必须是在部署 yaml 中设置的环境变量:
containers:
- name: discovery-server
image: springcloud/spring-cloud-kubernetes-discoveryserver:3.0.5-SNAPSHOT
env:
- name: SPRING_CLOUD_KUBERNETES_DISCOVERY_CATALOGSERVICESWATCHDELAY
value: 3000
(心跳事件将包含所有端点的目标引用(以及命名空间)和地址。要查看将返回的确切详细信息,请查看<代码>0。这是实现细节,不应依赖于细节。相反,它们应该通过使用equals方法检查两个连续的心跳之间的差异。我们将负责返回一个符合equals契约的正确实现。端点将按以下方式查询:- <代码>2(通过< code>3 启用))
-
selective namespaces(通过spring.cloud.kubernetes.discovery.namespaces启用),例如: -
one namespace通过 命名空间解析 执行,如果以上两条路径未走。
如果出于某种原因,您需要关闭目录监视程序,那么您需要将spring.cloud.kubernetes.discovery.catalog-services-watch.enabled=false设置。对于http发现服务器,这需要在部署中设置为环境变量,例如: |
SPRING_CLOUD_KUBERNETES_DISCOVERY_CATALOGSERVICESWATCH_ENABLED=FALSE
目录监视功能适用于我们支持的3个发现客户端,但需要注意一些例外情况,特别是对于http客户端。
-
<font color=#0000ff size=5>第一点,该功能默认是禁用的,需要在两个地方进行开启:</font><br />
-
通过部署清单中的环境变量在发现服务器中进行发现,例如:
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" -
在发现客户端中,通过您
application.properties中的某个属性,例如:spring.cloud.kubernetes.http.discovery.catalog.watcher.enabled=true
-
-
第二点是,此功能仅从版本
3.0.6及更高版本开始受支持。 -
因为 HTTP 发现有两个部分:服务器和客户端,我们强烈建议在它们之间对齐版本,否则事情可能不会按预期进行。
-
如果决定禁用catalog watcher,那么在服务器端和客户端都需要禁用它。
从版本 5.0.0 开始,可以缓存发现客户端(我们通过 @Cacheable 注释)的响应。这里有两个需要注意的属性:
spring.cloud.kubernetes.discovery.cacheable.reactive.enabled
和
spring.cloud.kubernetes.discovery.cacheable.blocking.enabled
The first one enables the cacheable reactive client, and the second one, the cacheable blocking client. By default, the non-cacheable discovery clients are created; if you want the cacheable one, you need to toggle one of the above properties. For example:
spring.cloud.kubernetes.discovery.cacheable.reactive.enabled=true
提供您可缓存的响应式发现客户。</br />
默认情况下,我们使用Endpoints(参见kubernetes.io/docs/concepts/services-networking/service/#endpoints)API来获取服务的当前状态。不过,还有一种方法,通过EndpointSlices(kubernetes.io/docs/concepts/services-networking/endpoint-slices/)。可以通过属性启用此支持: spring.cloud.kubernetes.discovery.use-endpoint-slices=true(默认值为false)。当然,你的群集也需要支持它。事实上,如果您启用此属性,但群集不支持它,我们将无法启动应用程序。如果您决定启用此支持,还需要设置适当的Role/ClusterRole。例如:
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"]