使用 ConfigMap PropertySource

Kubernetes 提供了一個名為 ConfigMap 的資源,用於以鍵值對或嵌入式 application.propertiesapplication.yaml 檔案的形式外部化要傳遞給應用程式的引數。 Spring Cloud Kubernetes Config 專案在應用程式啟動期間使 Kubernetes ConfigMap 例項可用,並在檢測到觀察到的 ConfigMap 例項發生更改時觸發 bean 或 Spring 上下文的熱過載。

以下所有內容主要透過 ConfigMap 的示例進行解釋,但 Secret 也是如此,即:所有功能都支援兩者。

預設行為是根據 Kubernetes ConfigMap 建立一個 Fabric8ConfigMapPropertySource(或 KubernetesClientConfigMapPropertySource),該 ConfigMapmetadata.name 為以下之一

  • spring.cloud.kubernetes.config.name 的值

  • 你的 Spring 應用程式的值(由 spring.application.name 屬性定義)

  • 字串字面量 "application"

但是,可以進行更高階的配置,其中可以使用多個 ConfigMap 例項。 spring.cloud.kubernetes.config.sources 列表使得這成為可能。例如,你可以定義以下 ConfigMap 例項

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

在前面的示例中,如果未設定 spring.cloud.kubernetes.config.namespace,則會在應用程式執行的名稱空間中查詢名為 c1ConfigMap。請參閱 名稱空間解析 以更好地理解應用程式的名稱空間是如何解析的。

找到的任何匹配的 ConfigMap 都將按以下方式處理

  • 應用單個配置屬性。

  • 將名為 spring.application.name 的任何屬性內容(如果不存在,則為 application.yaml/properties)應用為 yaml(或 properties

  • 將上述名稱 + 每個活動配置檔案的內容應用為屬性檔案。

一個示例應該能更好地說明問題。假設 spring.application.name=my-app,並且我們有一個名為 k8s 的活動配置檔案。對於如下配置

kind: ConfigMap
apiVersion: v1
metadata:
  name: my-app
data:
  my-app.yaml: |-
    ...
  my-app-k8s.yaml: |-
    ..
  my-app-dev.yaml: |-
    ..
  not-my-app.yaml: |-
   ..
  someProp: someValue

這就是我們最終將載入的內容

  • my-app.yaml 被視為檔案

  • my-app-k8s.yaml 被視為檔案

  • my-app-dev.yaml 被忽略,因為 dev 不是活動配置檔案

  • not-my-app.yaml 被忽略,因為它與 spring.application.name 不匹配

  • someProp: someValue 純屬性

屬性的載入順序如下

  • 首先從 my-app.yaml 載入所有屬性

  • 然後從基於配置檔案的源載入所有屬性:my-app-k8s.yaml

  • 然後載入所有純屬性 someProp: someValue

這意味著基於配置檔案的源優先於非基於配置檔案的源(就像在普通的 Spring 應用程式中一樣);並且純屬性優先於基於配置檔案和非基於配置檔案的源。以下是一個示例

kind: ConfigMap
apiVersion: v1
metadata:
  name: my-app
data:
  my-app-k8s.yaml: |-
    key1=valueA
    key2=valueB
  my-app.yaml: |-
    key1=valueC
    key2=valueA
  key1: valueD

處理完這樣的 ConfigMap 後,您將在屬性中得到:key1=valueDkey2=valueB

上述流程的唯一例外是當 ConfigMap 包含一個單個鍵表示該檔案是 YAML 或屬性檔案時。在這種情況下,鍵的名稱不必是 application.yamlapplication.properties(它可以是任何名稱),並且屬性的值會被正確處理。此功能方便了以下用例:ConfigMap 是透過使用如下方式建立的

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

假設我們有一個名為 demo 的 Spring Boot 應用程式,它使用以下屬性來讀取其執行緒池配置。

  • pool.size.core

  • pool.size.maximum

這可以按以下方式外部化為 yaml 格式的配置對映

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

對於大多數情況,單獨的屬性工作正常。然而,有時,嵌入式 yaml 更方便。在這種情況下,我們使用一個名為 application.yaml 的單個屬性來嵌入我們的 yaml,如下所示

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

以下示例也有效

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

您還可以根據標籤定義搜尋,例如

spring:
  application:
    name: labeled-configmap-with-prefix
  cloud:
    kubernetes:
      config:
        enabled: true
        useNameAsPrefix: true
        namespace: spring-k8s
        sources:
          - labels:
              letter: a

這將在名稱空間 spring-k8s 中搜索所有帶有標籤 {letter : a} 的 configmap。這裡需要注意的重要一點是,與按名稱讀取 configmap 不同,這可能導致讀取多個 configmap。像往常一樣,Secrets 也支援相同的功能。

您還可以根據活動的配置檔案以不同的方式配置 Spring Boot 應用程式,這些配置檔案在讀取 ConfigMap 時會合並在一起。您可以使用 application.propertiesapplication.yaml 屬性為不同的配置檔案提供不同的屬性值,每個值都在其自己的文件中指定(由 --- 序列指示),如下所示

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 應用程式中帶有 development 配置檔案的配置如下所示

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

但是,如果 production 配置檔案處於活動狀態,則配置變為

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

如果兩個配置檔案都處於活動狀態,則 ConfigMap 中最後出現的屬性將覆蓋所有先前的值。

另一個選項是為每個配置檔案建立一個不同的配置對映,Spring Boot 將根據活動的配置檔案自動獲取它

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 應該啟用哪個 profile,請參閱 Spring Boot 文件。在部署到 Kubernetes 時啟用特定配置檔案的一種選擇是使用環境變數啟動您的 Spring Boot 應用程式,您可以在 PodSpec 中的容器規範處定義該變數。部署資原始檔,如下所示

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"

您可能會遇到多個配置對映具有相同屬性名稱的情況。例如

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|properties 中放置這些的順序,您可能會得到意想不到的結果(最後一個配置對映獲勝)。例如

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 one

有一種方法可以透過指定 useNameAsPrefix 來更改此預設配置。例如

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

這樣的配置將生成兩個屬性

  • greetings.message 等於 Say Hello from one

  • config-map-two.greetings.message 等於 Say Hello from two

請注意,spring.cloud.kubernetes.config.useNameAsPrefix 的優先順序低於 spring.cloud.kubernetes.config.sources.useNameAsPrefix。這允許您為所有源設定“預設”策略,同時允許僅覆蓋少數幾個。

如果使用配置對映名稱不可行,您可以指定另一種策略,稱為:explicitPrefix。由於這是一個您選擇的顯式字首,因此它只能提供給 sources 級別。同時,它的優先順序高於 useNameAsPrefix。假設我們有第三個配置對映,其中包含以下條目

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

如下面的配置

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

將生成三個屬性

  • greetings.message 等於 Say Hello from one

  • two.greetings.message 等於 Say Hello from two

  • config-map-three.greetings.message 等於 Say Hello from three

以同樣的方式為 ConfigMap 配置字首,您也可以為 Secrets 進行配置;無論是基於名稱的 Secret 還是基於標籤的 Secret。例如

spring:
  application:
    name: prefix-based-secrets
  cloud:
    kubernetes:
      secrets:
        enabled: true
        useNameAsPrefix: true
        namespace: spring-k8s
        sources:
          - labels:
              letter: a
            useNameAsPrefix: false
          - labels:
              letter: b
            explicitPrefix: two
          - labels:
              letter: c
          - labels:
              letter: d
            useNameAsPrefix: true
          - name: my-secret

生成屬性源時,適用與 ConfigMap 相同的處理規則。唯一的區別是,潛在地,按標籤查詢 Secret 可能意味著我們找到不止一個源。在這種情況下,字首(如果透過 useNameAsPrefix 指定)將是為這些特定標籤找到的 Secret 的名稱。

需要記住的另一件事是,我們支援每個 Secretprefix。最簡單的解釋方法是透過一個示例

spring:
  application:
    name: prefix-based-secrets
  cloud:
    kubernetes:
      secrets:
        enabled: true
        useNameAsPrefix: true
        namespace: spring-k8s
        sources:
          - labels:
              color: blue
            useNameAsPrefix: true

假設匹配此類標籤的查詢將返回兩個 Secrets:secretAsecretB。這兩個 Secret 具有相同的屬性名稱:color=sea-bluecolor=ocean-blue。由於 useNamesAsPrefix=true,將載入兩個屬性源

  • secretA.color=sea-blue

  • secretB.color=ocean-blue

預設情況下,除了讀取 sources 配置中指定的配置對映外,Spring 還會嘗試從“配置檔案感知”源中讀取所有屬性。最簡單的解釋方法是透過一個示例。假設您的應用程式啟用了名為“dev”的配置檔案,並且您有如下配置

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

除了讀取 config-map-one,Spring 還會嘗試讀取 config-map-one-dev;按此特定順序。每個活動的配置檔案都會生成這樣一個配置檔案感知的 configmap。

您可以停用此“基於配置檔案的源”,然後將不再嘗試 config-map-one-dev

spring:
  application:
    name: spring-k8s
  cloud:
    kubernetes:
      config:
        includeProfileSpecificSources: false
        namespace: default-namespace
        sources:
          - name: config-map-one
            includeProfileSpecificSources: false
自版本 5.0.0 起,includeProfileSpecificSources 僅支援命名源 (spring.cloud.kubernetes.sources.name=XXX);對帶標籤源的支援已被移除。

請注意,就像以前一樣,您可以在兩個級別指定此屬性:針對所有配置對映或針對單個配置對映;後者具有更高的優先順序。

您應該檢查安全配置部分。要從 Pod 內部訪問配置對映,您需要擁有正確的 Kubernetes 服務帳戶、角色和角色繫結。

在某些情況下,您的應用程式可能無法使用 Kubernetes API 載入某些 ConfigMaps。如果您希望您的應用程式在這種情況下啟動失敗,您可以設定 spring.cloud.kubernetes.config.fail-fast=true,使應用程式啟動時丟擲異常。

您還可以讓應用程式在失敗時重試載入 ConfigMap 屬性源。首先,您需要設定 spring.cloud.kubernetes.config.fail-fast=true。然後您需要在類路徑中新增 spring-retryspring-boot-starter-aspectj。您可以透過設定 spring.cloud.kubernetes.config.retry.* 屬性來配置重試屬性,例如最大嘗試次數、退避選項(如初始間隔、乘數、最大間隔)。

如果您由於某種原因已將 spring-retryspring-boot-starter-aspectj 放在類路徑中,並且希望啟用快速失敗,但又不想啟用重試;您可以透過設定 spring.cloud.kubernetes.config.retry.enabled=false 來停用 ConfigMap PropertySources 的重試。
自版本 5.0.0 起,我們引入了單獨讀取源的可能性。到目前為止,我們會轉到名稱空間並讀取所有可用的 configmap / secrets,然後過濾掉請求的那些。自 5.0.0-M3 起,您可以透過設定屬性 spring.cloud.kubernetes.config.read-type=SINGLE 來指定要單獨讀取它們。以前在名稱空間中全部讀取的選項由 spring.cloud.kubernetes.config.read-type=BATCH 控制,並且是預設選項。
表 1. 屬性
名稱 型別 預設值 描述

spring.cloud.kubernetes.config.enabled

布林值

true

啟用 ConfigMaps PropertySource

spring.cloud.kubernetes.config.name

字串

${spring.application.name}

設定要查詢的 ConfigMap 的名稱

spring.cloud.kubernetes.config.namespace

字串

客戶端名稱空間

設定要查詢的 Kubernetes 名稱空間

spring.cloud.kubernetes.config.fail-fast

布林值

在載入 ConfigMap 時發生錯誤時啟用或停用應用程式啟動失敗

spring.cloud.kubernetes.config.retry.enabled

布林值

true

啟用或停用配置重試。

spring.cloud.kubernetes.config.retry.initial-interval

長整型

1000

初始重試間隔,單位為毫秒。

spring.cloud.kubernetes.config.retry.max-attempts

整數

6

最大嘗試次數。

spring.cloud.kubernetes.config.retry.max-interval

長整型

2000

回退的最大間隔。

spring.cloud.kubernetes.config.retry.multiplier

雙精度浮點型

1.1

下一個間隔的乘數。

© . This site is unofficial and not affiliated with VMware.