对于最新稳定版本,请使用Spring Cloud Kubernetes 5.0.0spring-doc.cadn.net.cn

Kubernetes Discovery 客户端

该项目为 Kubernetes 提供了 Discovery 客户端的实现。 这个客户端允许你按名称查询Kubernetes端点(见服务)。 Kubernetes API 服务器通常以端点集合的形式将服务暴露为httphttps地址,以及客户端可以 通过以 pod 形式运行的 Spring Boot 应用程序访问。spring-doc.cadn.net.cn

DiscoveryClient 还可以找到各类服务外部名称(参见 ExternalName 服务)目前,外部名称支持服务仅在满足以下属性的情况下提供Spring.cloud.kubernetes.discovery.include-external-name-services设置为true(确实如此false默认情况下)。spring-doc.cadn.net.cn

我们支持三种类型的发现客户端:spring-doc.cadn.net.cn

Fabric8 Kubernetes 客户端spring-doc.cadn.net.cn

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

Kubernetes Java 客户端spring-doc.cadn.net.cn

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

基于HTTP的发现客户端spring-doc.cadn.net.cn

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-kubernetes-discoveryclient</artifactId>
</dependency>
Spring-cloud-starter-kubernetes-discoveryclient设计用于与 Spring Cloud Kubernetes DiscoveryServer 配合使用。

为了实现发现客户端@EnableDiscoveryClient到相应的配置或应用类,如下示例所示:spring-doc.cadn.net.cn

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

然后你只需自动接线客户端,就能在代码中注入客户端,如下示例所示:spring-doc.cadn.net.cn

@Autowired
private DiscoveryClient discoveryClient;

你首先应该问自己的问题是,哪里发现客户端应该是发现服务的。在 Kubernetes 世界中,这意味着命名空间。这里有三种选择:spring-doc.cadn.net.cn

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

这种配置使得发现客户端只能在两个命名空间中搜索服务NS1NS2.spring-doc.cadn.net.cn

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

虽然有这样的选项,但这对 kube-api 和你的应用都是一种负担。需要这样的环境是很少见的。spring-doc.cadn.net.cn

上述选项对 fabric8 和 k8s 客户端完全符合设计。对于基于HTTP的客户端,你需要在服务器上启用这些选项。这可以通过放置它们来实现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-doc.cadn.net.cn

  • 只接受符合特定服务标签的服务。该性质由以下方式指定:Spring.cloud.kubernetes.discovery.service-labels.它接受地图并且只有那些带有此类标签的服务(如Metadata.labels在服务定义中)将被考虑。spring-doc.cadn.net.cn

  • 另一种选择是使用SpEL表达式。这表示为Spring.cloud.kubernetes.discovery.filter房产及其价值取决于你选择的客户。如果你使用 fabric8 客户端,必须针对 创建这个 SpEL 表达式io.fabric8.kubernetes.api.model.Service类。其中一个例子可能是:spring-doc.cadn.net.cn

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

这告诉发现客户端只获得具有Metadata.namespace结尾为大写一个.spring-doc.cadn.net.cn

如果你的发现客户端基于k8s原生客户端,那么SpEL表达式必须基于io.kubernetes.client.openapi.models.V1Service类。上面展示的同样滤镜在这里也能用。spring-doc.cadn.net.cn

如果你的发现客户端是基于 http 的,那么 SeEL 表达式也必须基于同样的 HTTPio.kubernetes.client.openapi.models.V1Service唯一的区别是需要在部署 yaml 中将 env 变量设置为:spring-doc.cadn.net.cn

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

现在是时候考虑应该回传哪个发现客户端了。一般来说,有两种方法发现客户端拥有:getServicesgetInstances.spring-doc.cadn.net.cn

getServices将返回服务名称,如metadata.name.spring-doc.cadn.net.cn

这种方法会返回唯一的服务名称,即使你选择的不同命名空间中有重复的服务名称。

getInstances返回 aList<ServiceInstance>.除了通常的场外ServiceInstance我们也会添加一些数据,比如命名空间或播客元数据(关于这些的详细解释将在文档中详细说明)。以下是我们目前返回的数据:spring-doc.cadn.net.cn

  1. 实例ID- 服务实例的唯一IDspring-doc.cadn.net.cn

  2. 服务ID- 服务名称(与呼叫报告的名称相同getServices)spring-doc.cadn.net.cn

  3. 主机- 实例的IP(或在外部名称服务类型)spring-doc.cadn.net.cn

  4. 端口- 实例的端口号。这需要更多解释,因为选择端口号有其规则:spring-doc.cadn.net.cn

    1. 服务没有定义端口,返回0(0)。spring-doc.cadn.net.cn

    2. 服务中只定义了一个端口,那个端口会被返回。spring-doc.cadn.net.cn

    3. 如果服务有标签主端口名我们会使用标签值中指定名称的端口号。spring-doc.cadn.net.cn

    4. 如果没有上述标签,则使用指定在Spring.cloud.kubernetes.discovery.primary-port-name去找端口号。spring-doc.cadn.net.cn

    5. 如果上述都未指定,我们将使用名为httpshttp计算端口号。spring-doc.cadn.net.cn

    6. 最后的选择是选择端口列表中的第一个。最后一种方式可能导致非确定性行为。spring-doc.cadn.net.cn

  5. 乌里服务实例的spring-doc.cadn.net.cn

  6. 方案httphttps(视具体情况而定安全结果)spring-doc.cadn.net.cn

  7. 元数据关于该服务:spring-doc.cadn.net.cn

    1. 标签(如请求通过Spring.cloud.kubernetes.discovery.metadata.add-labels=true).标签键可以“前缀”为Spring.cloud.kubernetes.discovery.metadata.labels-prefix如果它已经设定好了。spring-doc.cadn.net.cn

    2. 附注(如请求通过Spring.cloud.kubernetes.discovery.metadata.add-annotations=true).注释键可以“前缀”为Spring.cloud.kubernetes.discovery.metadata.annotations-prefix如果它已经设定好了。spring-doc.cadn.net.cn

    3. 端口(如请求通过Spring.cloud.kubernetes.discovery.metadata.add-ports=true).端口键可以“前缀”为Spring.cloud.kubernetes.discovery.metadata.ports-prefix如果它已经设定好了。spring-doc.cadn.net.cn

    4. k8s_namespace其中为实例所在命名空间的值。spring-doc.cadn.net.cn

    5. 类型例如,保持服务类型ClusterIP外部名称spring-doc.cadn.net.cn

  8. 安全如果发现的端口应被视为安全。我们将使用上述相同的规则来查找端口名和号码,然后:spring-doc.cadn.net.cn

    1. 如果这项服务有一个标签叫做担保其中任一值为:[“true”、“on”、“yes”、“1”]然后将发现的端口视为安全。spring-doc.cadn.net.cn

    2. 如果找不到这样的标签,可以搜索一个名为担保并应用上述相同的规则。spring-doc.cadn.net.cn

    3. 如果这个端口号是Spring.cloud.kubernetes.discovery.known-secure-ports(默认情况下,该值成立[443, 8443]),将端口号视为安全。spring-doc.cadn.net.cn

    4. 最后的办法是看看端口名是否匹配https;如果它真的把这个端口当作安全。spring-doc.cadn.net.cn

  9. Namespace- 找到实例的命名空间。spring-doc.cadn.net.cn

  10. 播客元数据服务实例(pod)的标签和注释,形式为映射<字符串,映射,<字符串,字符串>>.这种支持需要通过以下方式实现Spring.cloud.kubernetes.discovery.metadata.add-pod-labels=true和/或Spring.cloud.kubernetes.discovery.metadata.add-pod-annotaations=truespring-doc.cadn.net.cn


要发现kubernetes api服务器未标记为“准备好”的服务端点地址,可以在application.properties(默认:错误):spring-doc.cadn.net.cn

spring.cloud.kubernetes.discovery.include-not-ready-addresses=true
这在寻找用于监控的服务时可能非常有用,并能实现对/健康尚未准备好服务实例的端点。 如果你想获得名单ServiceInstance还包括外部名称类型服务,你需要通过以下方式启用该支持:Spring.cloud.Kubernetes.discovery.include-external-name-services=true.因此,当呼叫时DiscoveryClient::getInstances这些也会被归还。你可以区分外部名称以及通过检查的其他类型ServiceInstance::getMetadata并查找一个名为类型.这将是退回的服务类型:外部名称/ClusterIP等。 如果你因任何原因需要禁用发现客户端,你可以将以下性质设在application.properties:
spring.main.cloud-platform=NONE

注意,发现客户端的支持是自动的,具体取决于你在哪里运行应用。所以上述设置可能不需要。spring-doc.cadn.net.cn

一些 Spring Cloud 组件使用发现客户端以获取关于本地服务实例的信息。为 要实现这个功能,你需要将 Kubernetes 服务名称与spring.application.name财产。spring-doc.cadn.net.cn

spring.application.name对于Kubernetes中注册的应用名称没有影响

Spring Cloud Kubernetes 还可以监控 Kubernetes 服务目录的变更并更新发现客户端相应地实施。要启用此功能,你需要添加以下内容@EnableScheduling在你的应用中的一个配置类上。所谓“观察”,是指我们会发布一次心跳事件Spring.cloud.kubernetes.discovery.catalog-services-watch-delay毫秒(默认情况下是30000).对于 http 发现服务器,这必须是部署 yaml 中设置的环境变量:spring-doc.cadn.net.cn

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

心跳事件将包含目标引用(以及所有端点地址的命名空间) (关于退还物品的具体细节,你可以查看内部Kubernetes目录观察).这是一个实现细节,以及心跳事件的听众 不应依赖细节。相反,他们应该通过以下方式观察两次后续心跳之间是否有差异等于方法。我们会确保返回符合等值契约的正确实现。 端点将在以下任一中查询: -全命名空间(通过以下方式启用Spring.cloud.kubernetes.discovery.all-namespaces=true)spring-doc.cadn.net.cn

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

目录监控的功能适用于我们支持的3个发现客户端,但对于http客户端需要注意一些注意事项。spring-doc.cadn.net.cn

  • 首先,这个功能默认是被禁用的,需要在两个地方启用:spring-doc.cadn.net.cn

    • 在发现服务器中通过部署清单中的环境变量,例如:spring-doc.cadn.net.cn

      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-doc.cadn.net.cn

      spring.cloud.kubernetes.http.discovery.catalog.watcher.enabled=true
  • 第二点是,这功能只支持自版本以来3.0.6向上。spring-doc.cadn.net.cn

  • 由于 HTTP 发现包含两个部分:服务器端和客户端,我们强烈建议它们之间的版本对齐,否则可能无法正常工作。spring-doc.cadn.net.cn

  • 如果你决定禁用目录观察器,你需要在服务器和客户端都禁用它。spring-doc.cadn.net.cn

默认情况下,我们使用端点(参见 kubernetes.io/docs/concepts/services-networking/service/#endpoints)用API来了解当前服务的状态。不过还有另一种方式,通过端点切片 (kubernetes.io/docs/concepts/services-networking/endpoint-slices/)。这种支持可以通过以下属性实现:Spring.cloud.kubernetes.discovery.use-endpoint-slices=true(默认情况下是false).当然,你的集群也必须支持它。事实上,如果你启用了这个属性,但你的集群不支持它,我们会失败启动应用程序。如果你决定启用这种支持,还需要正确的角色/集群角色设置。例如:spring-doc.cadn.net.cn

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