此项目提供了 Discovery Client for Kubernetes 的实现。 此客户端允许您按名称查询 Kubernetes 端点(请参阅服务)。 Kubernetes API 服务器通常将服务公开为表示和寻址的终结点的集合,客户端可以 从作为 pod 运行的 Spring Boot 应用程序进行访问。httphttpsSpring中文文档

DiscoveryClient 还可以查找类型的服务(请参阅 ExternalName 服务)。目前,仅当以下属性设置为(默认情况下)时,外部名称支持类型的服务才可用。ExternalNamespring.cloud.kubernetes.discovery.include-external-name-servicestruefalseSpring中文文档

我们支持 3 种类型的发现客户端:Spring中文文档

Fabric8 Kubernetes 客户端Spring中文文档

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-kubernetes-fabric8</artifactId>
</dependency>

Kubernetes Java 客户端Spring中文文档

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-kubernetes-client</artifactId>
</dependency>

基于 HTTPDiscoveryClientSpring中文文档

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-kubernetes-discoveryclient</artifactId>
</dependency>
spring-cloud-starter-kubernetes-discoveryclient旨在与 Spring Cloud Kubernetes DiscoveryServer 一起使用。
spring-cloud-starter-kubernetes-discoveryclient旨在与 Spring Cloud Kubernetes DiscoveryServer 一起使用。

要启用加载 ,请添加到相应的配置或应用程序类中,如以下示例所示:DiscoveryClient@EnableDiscoveryClientSpring中文文档

@SpringBootApplication
@EnableDiscoveryClient
public class Application {
  public static void main(String[] args) {
    SpringApplication.run(Application.class, args);
  }
}

然后,只需通过自动连线即可将客户端注入代码中,如以下示例所示:Spring中文文档

@Autowired
private DiscoveryClient discoveryClient;

您应该问自己的第一个问题是应该在哪里发现服务。在 kubernetes 世界中,这意味着什么命名空间。这里有 3 个选项:DiscoveryClientSpring中文文档

spring.cloud.kubernetes.discovery.namespaces[0]=ns1
spring.cloud.kubernetes.discovery.namespaces[1]=ns2

这样的配置使得发现客户端只搜索两个命名空间中的服务,并且 .ns1ns2Spring中文文档

spring.cloud.kubernetes.discovery.all-namespaces=true

虽然存在这样的选项,但这可能会给 kube-api 和您的应用程序带来负担。很少需要这样的设置。Spring中文文档

上述选项的工作方式与为 fabric8 和 k8s 客户端编写的完全相同。对于基于 HTTP 的客户端,您需要在服务器上启用这些选项。这可以通过使用 env 变量将它们设置为用于在集群中部署映像来实现。deployment.yaml
上述选项的工作方式与为 fabric8 和 k8s 客户端编写的完全相同。对于基于 HTTP 的客户端,您需要在服务器上启用这些选项。这可以通过使用 env 变量将它们设置为用于在集群中部署映像来实现。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"

配置命名空间后,下一个要回答的问题是要发现哪些服务。把它看作是要应用什么过滤器。默认情况下,根本不应用任何筛选,并且会发现所有服务。如果需要缩小发现客户端可以找到的范围,则有两个选项:Spring中文文档

  • 仅接受与某些服务标签匹配的服务。此属性由以下选项指定: 。它接受一个,并且只有那些具有此类标签的服务(如服务定义中所示)才会被考虑在内。spring.cloud.kubernetes.discovery.service-labelsMapmetadata.labelsSpring中文文档

  • 另一种选择是使用 SpEL 表达式。这由属性表示,其值取决于您选择的客户端。如果使用 fabric8 客户端,则必须针对类创建此 SpEL 表达式。一个这样的例子可以是:spring.cloud.kubernetes.discovery.filterio.fabric8.kubernetes.api.model.ServiceSpring中文文档

spring.cloud.kubernetes.discovery.filter='#root.metadata.namespace matches "^.+A$"'

它告诉发现客户端只获取以大写结尾的服务。metadata.namespaceASpring中文文档

如果发现客户端基于 k8s 本机客户端,则 SpEL 表达式必须基于类。上面显示的相同过滤器在这里也有效。io.kubernetes.client.openapi.models.V1ServiceSpring中文文档

如果发现客户端是基于 http 的客户端,则 SeEL 表达式必须基于同一类,唯一的区别是需要将其设置为部署 yaml 中的 env 变量:io.kubernetes.client.openapi.models.V1ServiceSpring中文文档

      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$"'

现在是时候考虑应该返回哪个发现客户端了。通常,有两种方法具有:和 .DiscoveryClientgetServicesgetInstancesSpring中文文档

getServices将返回服务名称,如 .metadata.nameSpring中文文档

此方法将返回唯一的服务名称,即使不同命名空间(您为搜索选择的命名空间)之间存在重复项。
此方法将返回唯一的服务名称,即使不同命名空间(您为搜索选择的命名空间)之间存在重复项。

getInstances返回一个 .除了 a 的常用字段外,我们还添加了一些数据,例如命名空间或 pod 元数据(有关这些字段的更多解释将在文档中发布)。以下是我们目前返回的数据:List<ServiceInstance>ServiceInstanceSpring中文文档

  1. instanceId- 服务实例的唯一 IDSpring中文文档

  2. serviceId- 服务的名称(与调用报告的名称相同getServices)Spring中文文档

  3. host- 实例的 IP(或服务类型的名称)ExternalNameSpring中文文档

  4. port- 实例的端口号。这需要更多的解释,因为选择端口号有其规则:Spring中文文档

    1. 服务未定义端口,将返回 0(零)。Spring中文文档

    2. 服务定义了一个端口,该端口将被返回。Spring中文文档

    3. 如果服务具有标签,我们将使用具有标签值中指定名称的端口号。primary-port-nameSpring中文文档

    4. 如果上面的标签不存在,那么我们将使用中指定的端口名称来查找端口号。spring.cloud.kubernetes.discovery.primary-port-nameSpring中文文档

    5. 如果以上均未指定,我们将使用名为 or 的端口来计算端口号。httpshttpSpring中文文档

    6. 作为最后的手段,我们将选择港口列表中的第一个港口。最后一种选择可能会导致非确定性行为。Spring中文文档

  5. uri服务实例的Spring中文文档

  6. scheme或(取决于结果)httphttpssecureSpring中文文档

  7. metadata服务:Spring中文文档

    1. labels(如果通过 )请求。如果设置了标签键,则可以使用值“前缀”。spring.cloud.kubernetes.discovery.metadata.add-labels=truespring.cloud.kubernetes.discovery.metadata.labels-prefixSpring中文文档

    2. annotations(如果通过 )请求。注释键可以“前缀”为值(如果已设置)。spring.cloud.kubernetes.discovery.metadata.add-annotations=truespring.cloud.kubernetes.discovery.metadata.annotations-prefixSpring中文文档

    3. ports(如果通过 )请求。端口键可以“前缀”为值(如果已设置)。spring.cloud.kubernetes.discovery.metadata.add-ports=truespring.cloud.kubernetes.discovery.metadata.ports-prefixSpring中文文档

    4. k8s_namespace替换为 instance 所在的命名空间的值。Spring中文文档

    5. type保存服务类型,例如ClusterIPExternalNameSpring中文文档

  8. secure如果发现的端口应被视为安全端口。我们将使用上面概述的相同规则来查找端口名称和编号,然后:Spring中文文档

    1. 如果此服务具有使用任何值 : 调用的标签,则将找到的端口视为安全端口。secured["true", "on", "yes", "1"]Spring中文文档

    2. 如果未找到此类标签,请搜索名为的注释并应用相同的上述规则。securedSpring中文文档

    3. 如果此端口号是 的一部分(默认情况下此值保持不变),则将端口号视为安全端口号。spring.cloud.kubernetes.discovery.known-secure-ports[443, 8443]Spring中文文档

    4. 最后的手段是查看端口名称是否匹配;如果它确实将此端口视为安全端口。httpsSpring中文文档

  9. namespace- 找到的实例的命名空间。Spring中文文档

  10. pod-metadata服务实例 (Pod) 的标签和注释,格式为 。此支持需要通过和/或Map<String, Map<String, String>>spring.cloud.kubernetes.discovery.metadata.add-pod-labels=truespring.cloud.kubernetes.discovery.metadata.add-pod-annotaations=trueSpring中文文档

若要发现未被 kubernetes API 服务器标记为“就绪”的服务终结点地址,可以在 (default: false) 中设置以下属性:application.propertiesSpring中文文档

spring.cloud.kubernetes.discovery.include-not-ready-addresses=true
这在发现用于监视目的的服务时可能很有用,并且可以检查未就绪服务实例的终结点。 如果要获取 的列表也包括类型服务,则需要通过以下方式启用该支持: 。因此,在调用时,这些也将返回。您可以通过检查和查找名为 的字段来区分任何其他类型。这将是返回的服务类型:/等。 如果出于任何原因需要禁用 ,可以在 中设置以下属性:/healthServiceInstanceExternalNamespring.cloud.kubernetes.discovery.include-external-name-services=trueDiscoveryClient::getInstancesExternalNameServiceInstance::getMetadatatypeExternalNameClusterIPDiscoveryClientapplication.properties
这在发现用于监视目的的服务时可能很有用,并且可以检查未就绪服务实例的终结点。 如果要获取 的列表也包括类型服务,则需要通过以下方式启用该支持: 。因此,在调用时,这些也将返回。您可以通过检查和查找名为 的字段来区分任何其他类型。这将是返回的服务类型:/等。 如果出于任何原因需要禁用 ,可以在 中设置以下属性:/healthServiceInstanceExternalNamespring.cloud.kubernetes.discovery.include-external-name-services=trueDiscoveryClient::getInstancesExternalNameServiceInstance::getMetadatatypeExternalNameClusterIPDiscoveryClientapplication.properties
spring.main.cloud-platform=NONE

请注意,发现客户端的支持是自动的,具体取决于运行应用程序的位置。因此,可能不需要上述设置。Spring中文文档

某些 Spring Cloud 组件使用 来获取有关本地服务实例的信息。为 为此,您需要将 Kubernetes 服务名称与属性对齐。DiscoveryClientspring.application.nameSpring中文文档

spring.application.name对于在 Kubernetes 中为应用程序注册的名称而言,它不起作用
spring.application.name对于在 Kubernetes 中为应用程序注册的名称而言,它不起作用

Spring Cloud Kubernetes 还可以查看 Kubernetes 服务目录的更改,并相应地更新实现。为了启用此功能,您需要在应用程序中添加一个配置类。通过“监视”,我们的意思是我们将每毫秒发布一次心跳事件(默认为 )。对于 http 发现服务器,这必须是在部署 yaml 中设置的环境变量:DiscoveryClient@EnableSchedulingspring.cloud.kubernetes.discovery.catalog-services-watch-delay30000Spring中文文档

      containers:
        - name: discovery-server
          image: springcloud/spring-cloud-kubernetes-discoveryserver:3.0.5-SNAPSHOT
          env:
            - name: SPRING_CLOUD_KUBERNETES_DISCOVERY_CATALOGSERVICESWATCHDELAY
              value: 3000

检测信号事件将包含目标引用(及其所有终结点地址的命名空间) (有关将返回的确切详细信息,您可以查看内部)。这是一个实现细节,以及检测信号事件的侦听器 不应该依赖细节。相反,他们应该通过方法查看两个后续心跳之间是否存在差异。我们将注意返回符合等价合约的正确实现。 终结点将在以下任一位置进行查询: - (通过KubernetesCatalogWatchequalsall-namespacesspring.cloud.kubernetes.discovery.all-namespaces=true)Spring中文文档

如果出于任何原因想要禁用目录观察程序,则需要设置 .对于 http 发现服务器,这需要是在部署中设置的环境变量,例如:spring.cloud.kubernetes.discovery.catalog-services-watch.enabled=false
如果出于任何原因想要禁用目录观察程序,则需要设置 .对于 http 发现服务器,这需要是在部署中设置的环境变量,例如:spring.cloud.kubernetes.discovery.catalog-services-watch.enabled=false
SPRING_CLOUD_KUBERNETES_DISCOVERY_CATALOGSERVICESWATCH_ENABLED=FALSE

目录监视的功能适用于我们支持的所有 3 个发现客户端,但在使用 http 客户端时需要注意一些注意事项。Spring中文文档

  • 首先是此功能默认处于禁用状态,需要在两个地方启用:Spring中文文档

    • 在 Discovery Server 中,通过部署清单中的环境变量,例如:Spring中文文档

      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"
    • 在发现客户端中,通过 ur 中的属性,例如:application.propertiesSpring中文文档

      spring.cloud.kubernetes.http.discovery.catalog.watcher.enabled=true
  • 第二点是,这仅支持从版本及更高版本开始。3.0.6Spring中文文档

  • 由于 http 发现有两个组件:服务器和客户端,我们强烈建议在它们之间对齐版本,否则可能无法正常工作。Spring中文文档

  • 如果决定禁用目录观察程序,则需要在服务器和客户端中禁用它。Spring中文文档

默认情况下,我们使用(见 kubernetes.io/docs/concepts/services-networking/service/#endpoints)API 来查找服务的当前状态。不过还有另一种方法,通过(kubernetes.io/docs/concepts/services-networking/endpoint-slices/)。可以通过以下属性启用此类支持:(默认为 )。当然,您的集群也必须支持它。事实上,如果您启用了此属性,但您的集群不支持它,我们将无法启动应用程序。如果决定启用此类支持,则还需要正确的 Role/ClusterRole 设置。例如:EndpointsEndpointSlicesspring.cloud.kubernetes.discovery.use-endpoint-slices=truefalseSpring中文文档

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"]