使用 ConfigMap PropertySource
Kubernetes 提供了一個名為 ConfigMap 的資源,用於以鍵值對或嵌入式 application.properties 或 application.yaml 檔案的形式外部化要傳遞給應用程式的引數。 Spring Cloud Kubernetes Config 專案在應用程式啟動期間使 Kubernetes ConfigMap 例項可用,並在檢測到觀察到的 ConfigMap 例項發生更改時觸發 bean 或 Spring 上下文的熱過載。
以下所有內容主要透過 ConfigMap 的示例進行解釋,但 Secret 也是如此,即:所有功能都支援兩者。
預設行為是根據 Kubernetes ConfigMap 建立一個 Fabric8ConfigMapPropertySource(或 KubernetesClientConfigMapPropertySource),該 ConfigMap 的 metadata.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,則會在應用程式執行的名稱空間中查詢名為 c1 的 ConfigMap。請參閱 名稱空間解析 以更好地理解應用程式的名稱空間是如何解析的。
找到的任何匹配的 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=valueD,key2=valueB。
上述流程的唯一例外是當 ConfigMap 包含一個單個鍵表示該檔案是 YAML 或屬性檔案時。在這種情況下,鍵的名稱不必是 application.yaml 或 application.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.properties 或 application.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.message 為 Say 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 的名稱。
需要記住的另一件事是,我們支援每個 Secret 的 prefix。最簡單的解釋方法是透過一個示例
spring:
application:
name: prefix-based-secrets
cloud:
kubernetes:
secrets:
enabled: true
useNameAsPrefix: true
namespace: spring-k8s
sources:
- labels:
color: blue
useNameAsPrefix: true
假設匹配此類標籤的查詢將返回兩個 Secrets:secretA 和 secretB。這兩個 Secret 具有相同的屬性名稱:color=sea-blue 和 color=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-retry 和 spring-boot-starter-aspectj。您可以透過設定 spring.cloud.kubernetes.config.retry.* 屬性來配置重試屬性,例如最大嘗試次數、退避選項(如初始間隔、乘數、最大間隔)。
如果您由於某種原因已將 spring-retry 和 spring-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 控制,並且是預設選項。 |
| 名稱 | 型別 | 預設值 | 描述 |
|---|---|---|---|
|
|
|
啟用 ConfigMaps |
|
|
|
設定要查詢的 |
|
|
客戶端名稱空間 |
設定要查詢的 Kubernetes 名稱空間 |
|
|
|
在載入 |
|
|
|
啟用或停用配置重試。 |
|
|
|
初始重試間隔,單位為毫秒。 |
|
|
|
最大嘗試次數。 |
|
|
|
回退的最大間隔。 |
|
|
|
下一個間隔的乘數。 |