5. Kubernetes PropertySource 实现

配置 Spring Boot 应用程序的最常见方法是创建一个 or 或 一个 OR 文件,其中包含为 应用程序或 Spring Boot Starters。您可以通过指定系统属性或环境来覆盖这些属性 变量。application.propertiesapplication.yamlapplication-profile.propertiesapplication-profile.yamlspring-doc.cn

5.1. 使用 ConfigMap PropertySource

Kubernetes 提供了一个名为 ConfigMap 的资源来外部化 参数以键值对或嵌入 OR 文件的形式传递给应用程序。 Spring Cloud Kubernetes Config 项目使 Kubernetes 实例可用 在应用程序引导期间,并在检测到更改时触发 bean 或 Spring 上下文的热重载 观察到的实例。application.propertiesapplication.yamlConfigMapConfigMapspring-doc.cn

默认行为是基于 Kubernetes 创建一个 Kubernetes,该 Kubernetes 的值为 您的 Spring 应用程序(由其属性定义)或在文件中定义的自定义名称(在以下键下):。Fabric8ConfigMapPropertySourceConfigMapmetadata.namespring.application.namebootstrap.propertiesspring.cloud.kubernetes.config.namespring-doc.cn

但是,在您可以使用多个实例的情况下,可以使用更高级的配置。 该列表使这成为可能。 例如,您可以定义以下实例:ConfigMapspring.cloud.kubernetes.config.sourcesConfigMapspring-doc.cn

spring:
  application:
    name: cloud-k8s-app
  cloud:
    kubernetes:
      config:
        name: default-name
        namespace: default-namespace
        sources:
         # Spring Cloud Kubernetes looks up a ConfigMap named c1 in namespace default-namespace
         - name: c1
         # Spring Cloud Kubernetes looks up a ConfigMap named default-name in whatever namespace n2
         - namespace: n2
         # Spring Cloud Kubernetes looks up a ConfigMap named c3 in namespace n3
         - namespace: n3
           name: c3

在前面的示例中,如果未设置, 将在应用程序运行的命名空间中查找 name。 请参阅 命名空间解析 以更好地了解命名空间 的申请已解决。spring.cloud.kubernetes.config.namespaceConfigMapc1spring-doc.cn

找到的任何匹配项都将按如下方式处理:ConfigMapspring-doc.cn

上述流程的一个例外是,当 包含单个键时,该键指示 该文件是 YAML 或属性文件。在这种情况下,键的名称不必是 or(可以是任何内容),并且属性的值会被正确处理。 此功能有助于使用如下内容创建 的用例:ConfigMapapplication.yamlapplication.propertiesConfigMapspring-doc.cn

kubectl create configmap game-config --from-file=/path/to/app-config.yaml

假设我们有一个名为 Spring Boot 的应用程序,它使用以下属性来读取其线程池 配置。demospring-doc.cn

这可以按以下格式外部化到 config map 中:yamlspring-doc.cn

kind: ConfigMap
apiVersion: v1
metadata:
  name: demo
data:
  pool.size.core: 1
  pool.size.max: 16

在大多数情况下,单个属性都可以正常工作。但是,有时 embedded 更方便。在这种情况下,我们 使用一个名为 to embed our 的属性,如下所示:yamlapplication.yamlyamlspring-doc.cn

kind: ConfigMap
apiVersion: v1
metadata:
  name: demo
data:
  application.yaml: |-
    pool:
      size:
        core: 1
        max:16

以下示例也有效:spring-doc.cn

kind: ConfigMap
apiVersion: v1
metadata:
  name: demo
data:
  custom-name.yaml: |-
    pool:
      size:
        core: 1
        max:16

您还可以根据合并在一起的活动配置文件以不同的方式配置 Spring Boot 应用程序 当 被读取时。您可以通过使用 or 属性为不同的配置文件提供不同的属性值,并指定特定于配置文件的值,每个值都在其自己的文档中 (由序列指示),如下所示:ConfigMapapplication.propertiesapplication.yaml---spring-doc.cn

kind: ConfigMap
apiVersion: v1
metadata:
  name: demo
data:
  application.yml: |-
    greeting:
      message: Say Hello to the World
    farewell:
      message: Say Goodbye
    ---
    spring:
      profiles: development
    greeting:
      message: Say Hello to the Developers
    farewell:
      message: Say Goodbye to the Developers
    ---
    spring:
      profiles: production
    greeting:
      message: Say Hello to the Ops

在前面的情况下,使用配置文件加载到 Spring Application 中的配置如下:developmentspring-doc.cn

  greeting:
    message: Say Hello to the Developers
  farewell:
    message: Say Goodbye to the Developers

但是,如果配置文件处于活动状态,则配置将变为:productionspring-doc.cn

  greeting:
    message: Say Hello to the Ops
  farewell:
    message: Say Goodbye

如果两个配置文件都处于活动状态,则最后显示的属性将覆盖前面的任何值。ConfigMapspring-doc.cn

另一种选择是为每个配置文件创建不同的 config map,Spring boot 将根据 在活动配置文件上spring-doc.cn

kind: ConfigMap
apiVersion: v1
metadata:
  name: demo
data:
  application.yml: |-
    greeting:
      message: Say Hello to the World
    farewell:
      message: Say Goodbye
kind: ConfigMap
apiVersion: v1
metadata:
  name: demo-development
data:
  application.yml: |-
    spring:
      profiles: development
    greeting:
      message: Say Hello to the Developers
    farewell:
      message: Say Goodbye to the Developers
kind: ConfigMap
apiVersion: v1
metadata:
  name: demo-production
data:
  application.yml: |-
    spring:
      profiles: production
    greeting:
      message: Say Hello to the Ops
    farewell:
      message: Say Goodbye

要告诉 Spring Boot 应该在 bootstrap 时启用哪个,你可以传递 environment variable。 为此,您可以使用环境变量启动 Spring Boot 应用程序,您可以在容器规范的 PodSpec 中定义该变量。 Deployment 资源文件,如下所示:profileSPRING_PROFILES_ACTIVEspring-doc.cn

apiVersion: apps/v1
kind: Deployment
metadata:
  name: deployment-name
  labels:
    app: deployment-name
spec:
  replicas: 1
  selector:
    matchLabels:
      app: deployment-name
  template:
    metadata:
      labels:
        app: deployment-name
    spec:
        containers:
        - name: container-name
          image: your-image
          env:
          - name: SPRING_PROFILES_ACTIVE
            value: "development"

你可能会遇到多个具有相同属性名称的 configs 映射的情况。例如:spring-doc.cn

kind: ConfigMap
apiVersion: v1
metadata:
  name: config-map-one
data:
  application.yml: |-
    greeting:
      message: Say Hello from one
kind: ConfigMap
apiVersion: v1
metadata:
  name: config-map-two
data:
  application.yml: |-
    greeting:
      message: Say Hello from two

根据 你把这些东西放进去的顺序,你最终可能会得到一个意想不到的结果(最后一个配置映射获胜)。例如:bootstrap.yaml|propertiesspring-doc.cn

spring:
  application:
    name: cloud-k8s-app
  cloud:
    kubernetes:
      config:
        namespace: default-namespace
        sources:
         - name: config-map-two
         - name: config-map-one

将导致属性为 。greetings.messageSay Hello from onespring-doc.cn

有一种方法可以通过指定来更改此默认配置。例如:useNameAsPrefixspring-doc.cn

spring:
  application:
    name: with-prefix
  cloud:
    kubernetes:
      config:
        useNameAsPrefix: true
        namespace: default-namespace
        sources:
          - name: config-map-one
            useNameAsPrefix: false
          - name: config-map-two

此类配置将导致生成两个属性:spring-doc.cn

  • greetings.message等于 。Say Hello from onespring-doc.cn

  • config-map-two.greetings.message等于Say Hello from twospring-doc.cn

请注意,它的优先级低于 。 这允许您为所有源设置 “default” 策略,同时只允许覆盖少数源。spring.cloud.kubernetes.config.useNameAsPrefixspring.cloud.kubernetes.config.sources.useNameAsPrefixspring-doc.cn

如果无法使用配置映射名称,则可以指定其他策略,称为 : 。由于这是一个显式的前缀, ,则只能将其提供给 Level。同时,它具有比 更高的优先级。假设我们有第三个配置映射,其中包含这些条目:explicitPrefixsourcesuseNameAsPrefixspring-doc.cn

kind: ConfigMap
apiVersion: v1
metadata:
  name: config-map-three
data:
  application.yml: |-
    greeting:
      message: Say Hello from three

如下所示的配置:spring-doc.cn

spring:
  application:
    name: with-prefix
  cloud:
    kubernetes:
      config:
        useNameAsPrefix: true
        namespace: default-namespace
        sources:
          - name: config-map-one
            useNameAsPrefix: false
          - name: config-map-two
            explicitPrefix: two
          - name: config-map-three

将导致生成三个属性:spring-doc.cn

  • greetings.message等于 。Say Hello from onespring-doc.cn

  • two.greetings.message等于 。Say Hello from twospring-doc.cn

  • config-map-three.greetings.message等于 。Say Hello from threespring-doc.cn

默认情况下,除了读取配置中指定的 config map 之外,Spring 还会尝试读取 来自 “Profile Aware” 源的所有属性。解释这一点的最简单方法是通过一个例子。假设您的应用程序 启用名为 “dev” 的配置文件,并且您拥有如下所示的配置:sourcesspring-doc.cn

spring:
  application:
    name: spring-k8s
  cloud:
    kubernetes:
      config:
        namespace: default-namespace
        sources:
          - name: config-map-one

除了读取 , Spring 还会尝试读取 ;按此特定顺序。每个活动配置文件 生成这样的配置文件感知配置 Map。config-map-oneconfig-map-one-devspring-doc.cn

虽然你的应用程序不应该受到这种配置映射的影响,但如果需要,可以禁用它:spring-doc.cn

spring:
  application:
    name: spring-k8s
  cloud:
    kubernetes:
      config:
        includeProfileSpecificSources: false
        namespace: default-namespace
        sources:
          - name: config-map-one
            includeProfileSpecificSources: false

请注意,和之前一样,有两个级别可以指定此属性:for all config maps 或 对于单个 ID;后者具有更高的优先级。spring-doc.cn

您应该检查安全配置部分。要从 Pod 内部访问配置映射,你需要拥有正确的 Kubernetes 服务帐户、角色和角色绑定。

使用实例的另一种选择是通过运行 Spring Cloud Kubernetes 应用程序将它们挂载到 Pod 中 以及让 Spring Cloud Kubernetes 从文件系统中读取它们。 此行为由属性控制。您可以在 添加或代替前面描述的机制。 您可以使用分隔符指定多个(精确)文件路径。ConfigMapspring.cloud.kubernetes.config.pathsspring.cloud.kubernetes.config.paths,spring-doc.cn

您必须提供每个属性文件的完整确切路径,因为目录不会被递归解析。
如果您使用 或 自动重新加载 功能将不起作用。您需要向终端节点发出请求,或者 重新启动/重新部署应用程序。spring.cloud.kubernetes.config.pathsspring.cloud.kubernetes.secrets.pathPOST/actuator/refresh
表 1.性能:
名字 类型 违约 描述

spring.cloud.kubernetes.config.enabledspring-doc.cn

Booleanspring-doc.cn

truespring-doc.cn

启用 ConfigMapPropertySourcespring-doc.cn

spring.cloud.kubernetes.config.namespring-doc.cn

Stringspring-doc.cn

${spring.application.name}spring-doc.cn

设置要查找的名称ConfigMapspring-doc.cn

spring.cloud.kubernetes.config.namespacespring-doc.cn

Stringspring-doc.cn

客户端命名空间spring-doc.cn

设置要查找的 Kubernetes 命名空间spring-doc.cn

spring.cloud.kubernetes.config.pathsspring-doc.cn

Listspring-doc.cn

nullspring-doc.cn

设置实例的挂载路径ConfigMapspring-doc.cn

spring.cloud.kubernetes.config.enableApispring-doc.cn

Booleanspring-doc.cn

truespring-doc.cn

通过 API 启用或禁用消费实例ConfigMapspring-doc.cn

5.2. 秘密 PropertySource

Kubernetes 具有用于存储 敏感数据,例如密码、OAuth 令牌等。此项目提供与 to make secrets 的集成 可由 Spring Boot 应用程序访问。您可以通过设置属性来显式启用或禁用此功能。Secretsspring.cloud.kubernetes.secrets.enabledspring-doc.cn

启用后,将从以下来源查找 Kubernetes:Fabric8SecretsPropertySourceSecretsspring-doc.cn

  1. 从 secrets 挂载中递归读取spring-doc.cn

  2. 以应用程序命名(由spring.application.name)spring-doc.cn

  3. 匹配一些标签spring-doc.cn

注意:spring-doc.cn

默认情况下,出于安全原因,通过 API 使用密钥(上述第 2 点和第 3 点)未启用。对 Secret 的权限 'list' 允许客户端检查指定命名空间中的 Secret 值。 此外,我们建议容器通过挂载的卷共享密钥。spring-doc.cn

如果您允许通过 API 使用 Secrets,我们建议您使用授权策略(如 RBAC)来限制对 Secrets 的访问。 有关通过 API 使用 Secrets 时的风险和最佳实践的更多信息,请参阅此文档spring-doc.cn

如果找到密钥,则其数据将可供应用程序使用。spring-doc.cn

假设我们有一个名为 Spring Boot 的应用程序,它使用 properties 来读取其数据库 配置。我们可以使用以下命令创建 Kubernetes 密钥:demospring-doc.cn

kubectl create secret generic db-secret --from-literal=username=user --from-literal=password=p455w0rd

前面的命令将创建以下密钥(您可以使用 ):kubectl get secrets db-secret -o yamlspring-doc.cn

apiVersion: v1
data:
  password: cDQ1NXcwcmQ=
  username: dXNlcg==
kind: Secret
metadata:
  creationTimestamp: 2017-07-04T09:15:57Z
  name: db-secret
  namespace: default
  resourceVersion: "357496"
  selfLink: /api/v1/namespaces/default/secrets/db-secret
  uid: 63c89263-6099-11e7-b3da-76d6186905a8
type: Opaque

请注意,数据包含命令提供的 Literals 的 Base64 编码版本。createspring-doc.cn

然后,您的应用程序可以使用此密钥 — 例如,通过将密钥的值导出为环境变量:spring-doc.cn

apiVersion: v1
kind: Deployment
metadata:
  name: ${project.artifactId}
spec:
   template:
     spec:
       containers:
         - env:
            - name: DB_USERNAME
              valueFrom:
                 secretKeyRef:
                   name: db-secret
                   key: username
            - name: DB_PASSWORD
              valueFrom:
                 secretKeyRef:
                   name: db-secret
                   key: password

您可以通过多种方式选择要使用的密钥:spring-doc.cn

  1. 通过列出映射 secret 的目录:spring-doc.cn

    -Dspring.cloud.kubernetes.secrets.paths=/etc/secrets/db-secret,etc/secrets/postgresql

    如果您已将所有密钥映射到一个公共根,则可以像这样设置它们:spring-doc.cn

    -Dspring.cloud.kubernetes.secrets.paths=/etc/secrets
  2. 通过设置命名密钥:spring-doc.cn

    -Dspring.cloud.kubernetes.secrets.name=db-secret
  3. 通过定义标签列表:spring-doc.cn

    -Dspring.cloud.kubernetes.secrets.labels.broker=activemq
    -Dspring.cloud.kubernetes.secrets.labels.db=postgresql

与 的情况一样,在可以使用多个实例的情况下,也可以使用更高级的配置。该列表使这成为可能。 例如,您可以定义以下实例:ConfigMapSecretspring.cloud.kubernetes.secrets.sourcesSecretspring-doc.cn

spring:
  application:
    name: cloud-k8s-app
  cloud:
    kubernetes:
      secrets:
        name: default-name
        namespace: default-namespace
        sources:
         # Spring Cloud Kubernetes looks up a Secret named s1 in namespace default-namespace
         - name: s1
         # Spring Cloud Kubernetes looks up a Secret named default-name in namespace n2
         - namespace: n2
         # Spring Cloud Kubernetes looks up a Secret named s3 in namespace n3
         - namespace: n3
           name: s3

在前面的示例中,如果未设置, 将在应用程序运行的命名空间中查找 name。 请参阅 namespace-resolution 以更好地了解命名空间 的申请已解决。spring.cloud.kubernetes.secrets.namespaceSecrets1spring-doc.cn

表 2.性能:
名字 类型 违约 描述

spring.cloud.kubernetes.secrets.enabledspring-doc.cn

Booleanspring-doc.cn

truespring-doc.cn

启用 SecretPropertySourcespring-doc.cn

spring.cloud.kubernetes.secrets.namespring-doc.cn

Stringspring-doc.cn

${spring.application.name}spring-doc.cn

设置要查找的 secret 的名称spring-doc.cn

spring.cloud.kubernetes.secrets.namespacespring-doc.cn

Stringspring-doc.cn

客户端命名空间spring-doc.cn

设置要查找的 Kubernetes 命名空间spring-doc.cn

spring.cloud.kubernetes.secrets.labelsspring-doc.cn

Mapspring-doc.cn

nullspring-doc.cn

设置用于查找密钥的标签spring-doc.cn

spring.cloud.kubernetes.secrets.pathsspring-doc.cn

Listspring-doc.cn

nullspring-doc.cn

设置 secret 的挂载路径(示例 1)spring-doc.cn

spring.cloud.kubernetes.secrets.enableApispring-doc.cn

Booleanspring-doc.cn

falsespring-doc.cn

启用或禁用通过 API 使用密钥(示例 2 和 3)spring-doc.cn

笔记:spring-doc.cn

您可以在 spring-boot-camel-config 中找到使用 Secret 的应用程序示例(尽管它尚未更新以使用新项目)spring-cloud-kubernetesspring-doc.cn

5.3. 命名空间解析

查找应用程序命名空间是尽最大努力进行的。我们按顺序迭代一些步骤 找到它。最简单和最常见的一种是在适当的配置中指定它,例如:spring-doc.cn

spring:
  application:
    name: app
  cloud:
    kubernetes:
      secrets:
        name: secret
        namespace: default
        sources:
         # Spring Cloud Kubernetes looks up a Secret named 'a' in namespace 'default'
         - name: a
         # Spring Cloud Kubernetes looks up a Secret named 'secret' in namespace 'b'
         - namespace: b
         # Spring Cloud Kubernetes looks up a Secret named 'd' in namespace 'c'
         - namespace: c
           name: d

请记住,也可以对 config maps 执行相同的操作。如果未指定这样的命名空间,则将读取它(按此顺序):spring-doc.cn

  1. from property (从属性)spring.cloud.kubernetes.client.namespacespring-doc.cn

  2. 从驻留在由 property 表示的文件中的 Stringspring.cloud.kubernetes.client.serviceAccountNamespacePathspring-doc.cn

  3. 从驻留在文件中的 String (Kubernetes 默认命名空间路径)/var/run/secrets/kubernetes.io/serviceaccount/namespacespring-doc.cn

  4. 从指定的客户端方法调用(例如 fabric8 的 : ),如果客户端提供 这样的方法。反过来,这可以通过环境属性进行配置。例如,fabric8 客户端可以通过 “KUBERNETES_NAMESPACE” 属性;有关确切的详细信息,请参阅客户端文档。KubernetesClient::getNamespacespring-doc.cn

如果无法从上述步骤中找到命名空间,将导致引发 Exception。spring-doc.cn

5.4. PropertySource 重新加载

此功能在 2020.0 版本中已弃用。请参阅 Spring Cloud Kubernetes Configuration Watcher 控制器作为另一种方式 以实现相同的功能。

某些应用程序可能需要检测外部属性源上的更改并更新其内部状态以反映新配置。 Spring Cloud Kubernetes 的 reload 功能能够在相关或更改时触发应用程序重新加载。ConfigMapSecretspring-doc.cn

默认情况下,此功能处于禁用状态。您可以使用 configuration 属性(例如,在 file) 中启用它。spring.cloud.kubernetes.reload.enabled=trueapplication.propertiesspring-doc.cn

支持以下级别的重新加载(通过设置属性):spring.cloud.kubernetes.reload.strategyspring-doc.cn

  • refresh(默认):仅带有 Comments 或 reloaded 的配置 bean。 此重新加载级别利用 Spring Cloud Context 的刷新功能。@ConfigurationProperties@RefreshScopespring-doc.cn

  • restart_context:整个 Spring 正常重启。使用新配置重新创建 Bean。 为了使 restart context 功能正常工作,您必须启用并公开 restart actuator 端点ApplicationContextspring-doc.cn

management:
  endpoint:
    restart:
      enabled: true
  endpoints:
    web:
      exposure:
        include: restart
  • shutdown:Spring 关闭以激活容器的重新启动。 使用此级别时,请确保所有非守护进程线程的生命周期都绑定到 ,并且将复制控制器或副本集配置为重新启动 Pod。ApplicationContextApplicationContextspring-doc.cn

假设使用默认设置( mode )启用了重新加载功能,则当 config map 更改时,将刷新以下 bean:refreshspring-doc.cn

@Configuration
@ConfigurationProperties(prefix = "bean")
public class MyConfig {

    private String message = "a message that can be changed live";

    // getter and setters

}

要查看更改有效地发生,您可以创建另一个定期打印消息的 bean,如下所示spring-doc.cn

@Component
public class MyBean {

    @Autowired
    private MyConfig config;

    @Scheduled(fixedDelay = 5000)
    public void hello() {
        System.out.println("The message is: " + config.getMessage());
    }
}

您可以使用 更改应用程序打印的消息,如下所示:ConfigMapspring-doc.cn

apiVersion: v1
kind: ConfigMap
metadata:
  name: reload-example
data:
  application.properties: |-
    bean.message=Hello World!

对 关联的 中命名的属性的任何更改都会反映在 输出。更一般地说,与以 Comments 字段定义的值为前缀的属性关联的更改将被检测并反映在应用程序中。本章前面介绍了如何将 ConfigMap 与 Pod 相关联bean.messageConfigMapprefix@ConfigurationPropertiesspring-doc.cn

完整的示例可在spring-cloud-kubernetes-reload-example中找到。spring-doc.cn

重新加载功能支持两种操作模式: * 事件 (默认):使用 Kubernetes API (Web 套接字) 监视配置映射或 secret 中的更改。 任何事件都会对配置产生重新检查,如果发生更改,则会重新加载。 需要服务帐户上的角色才能侦听配置映射更改。密钥需要更高级别的角色(例如 ) (默认情况下,不监控密钥)。 * 轮询:定期从配置映射和 secret 重新创建配置,以查看它是否已更改。 您可以使用 属性 配置轮询周期,默认为 15 秒。 它需要与受监控属性源相同的角色。 这意味着,例如,对文件挂载的密钥源使用轮询不需要特定权限。vieweditspring.cloud.kubernetes.reload.periodspring-doc.cn

表 3.性能:
名字 类型 违约 描述

spring.cloud.kubernetes.reload.enabledspring-doc.cn

Booleanspring-doc.cn

falsespring-doc.cn

支持监控资产源和配置重新加载spring-doc.cn

spring.cloud.kubernetes.reload.monitoring-config-mapsspring-doc.cn

Booleanspring-doc.cn

truespring-doc.cn

允许监控配置映射中的更改spring-doc.cn

spring.cloud.kubernetes.reload.monitoring-secretsspring-doc.cn

Booleanspring-doc.cn

falsespring-doc.cn

允许监控密钥中的更改spring-doc.cn

spring.cloud.kubernetes.reload.strategyspring-doc.cn

Enumspring-doc.cn

refreshspring-doc.cn

开火装填时使用的策略(、 、 或refreshrestart_contextshutdown)spring-doc.cn

spring.cloud.kubernetes.reload.modespring-doc.cn

Enumspring-doc.cn

eventspring-doc.cn

指定如何侦听属性源 ( 或eventpolling)spring-doc.cn

spring.cloud.kubernetes.reload.periodspring-doc.cn

Durationspring-doc.cn

15sspring-doc.cn

使用策略时验证更改的时间段pollingspring-doc.cn

笔记: * 您不应该在配置映射或 secret 中使用 properties 。在运行时更改此类属性可能会导致意外结果。 * 使用级别时,删除属性或整个配置映射不会恢复 bean 的原始状态。spring.cloud.kubernetes.reloadrefreshspring-doc.cn