使用 ConfigMap
PropertySource
Kubernetes 提供了一個名為 ConfigMap
的資源,用於將傳遞給應用程式的引數外部化,這些引數可以採用鍵值對或嵌入式 application.properties
或 application.yaml
檔案形式。 Spring Cloud Kubernetes Config 專案在應用程式啟動期間提供 Kubernetes ConfigMap
例項,並在檢測到被觀察的 ConfigMap
例項發生更改時觸發 Bean 或 Spring 上下文的熱過載。
以下所有內容主要參考使用 ConfigMaps 的示例進行解釋,但 Secrets 也同樣適用,即:每個功能都支援 ConfigMaps 和 Secrets。
預設行為是基於 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
的值命名的屬性內容作為yaml
(或properties
)應用(如果不存在,則使用application.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 或 properties 檔案時。 在這種情況下,鍵的名稱不必是 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
格式的 config map:
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:
enableApi: true
useNameAsPrefix: true
namespace: spring-k8s
sources:
- labels:
letter: a
這將在名稱空間 spring-k8s
中搜索所有具有標籤 {letter : a}
的 configmap。 這裡需要注意的重要一點是,與按名稱讀取 configmap 不同,這可能會導致讀取多個 config map。 和往常一樣,Secrets 也支援相同的功能。
您還可以根據讀取 ConfigMap
時合併的活動配置檔案來以不同方式配置 Spring Boot 應用程式。 您可以使用 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
在上述情況下,載入到您的具有 development
配置檔案的 Spring 應用程式中的配置如下:
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
中最後出現的屬性會覆蓋所有前面的值。
另一種選擇是為每個配置檔案建立一個不同的 config map,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 的容器規範中定義該環境變數。Deployment 資原始檔如下所示:
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"
您可能會遇到多個具有相同屬性名稱的 config map 的情況。例如:
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
中放置這些 config map 的順序,您可能會得到意想不到的結果(最後一個 config map 獲勝)。 例如:
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
。 這允許您為所有源設定一個“預設”策略,同時只覆蓋少數幾個源。
如果使用 config map 名稱不是一個選擇,您可以指定一個不同的策略,稱為:explicitPrefix
。 由於這是一個您選擇的顯式字首,因此只能應用於 sources
級別。 同時,它的優先順序高於 useNameAsPrefix
。 假設我們有第三個 config map 包含這些條目:
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
。
配置 configmaps 字首的方式同樣適用於 secrets;無論是基於名稱的 secrets 還是基於標籤的 secrets。 例如:
spring:
application:
name: prefix-based-secrets
cloud:
kubernetes:
secrets:
enableApi: 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
生成屬性源時,處理規則與 config maps 相同。 唯一的區別是,潛在地,按標籤查詢 secrets 意味著我們可能找到不止一個源。 在這種情況下,字首(如果透過 useNameAsPrefix
指定)將是為這些特定標籤找到的所有 secrets 的名稱。
還需要記住一點,我們支援按源設定 prefix
,而不是按 secret 設定。 最簡單的解釋方法是透過示例:
spring:
application:
name: prefix-based-secrets
cloud:
kubernetes:
secrets:
enableApi: true
useNameAsPrefix: true
namespace: spring-k8s
sources:
- labels:
color: blue
useNameAsPrefix: true
假設一個匹配此類標籤的查詢將返回兩個 secrets:secret-a
和 secret-b
。 這兩個 secrets 都具有相同的屬性名稱:color=sea-blue
和 color=ocean-blue
。 無法確定哪個 color
將最終成為屬性源的一部分,但其字首將是 secret-a.secret-b
(自然排序後拼接的 secret 名稱)。
如果您需要更細粒度的結果,新增更多標籤來唯一標識 secret 將是一個選項。
預設情況下,除了讀取 sources
配置中指定的 config map 外,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
;順序如前所述。 每個活動配置檔案都會生成一個這樣的配置檔案感知 config map。
儘管您的應用程式不應受此類 config map 的影響,但如果需要,可以將其停用。
spring:
application:
name: spring-k8s
cloud:
kubernetes:
config:
includeProfileSpecificSources: false
namespace: default-namespace
sources:
- name: config-map-one
includeProfileSpecificSources: false
請注意,就像之前一樣,您可以在兩個級別指定此屬性:應用於所有 config maps 或應用於單個 config maps;後者的優先順序更高。
您應該檢查安全配置部分。 要從 Pod 內部訪問 config maps,您需要具有正確的 Kubernetes 服務帳戶、角色和角色繫結。 |
使用 ConfigMap
例項的另一種選擇是,透過執行 Spring Cloud Kubernetes 應用程式並讓 Spring Cloud Kubernetes 從檔案系統讀取它們的方式,將它們掛載到 Pod 中。
此功能已被棄用,並將在未來的版本中移除(請改用 spring.config.import )。 此行為由 spring.cloud.kubernetes.config.paths 屬性控制。 您可以使用它作為之前描述機制的補充或替代。 spring.cloud.kubernetes.config.paths 需要一個包含每個屬性檔案完整路徑的 List,因為目錄不會被遞迴解析。 例如: |
spring:
cloud:
kubernetes:
config:
paths:
- /tmp/application.properties
- /var/application.yaml
如果您使用 spring.cloud.kubernetes.config.paths 或 spring.cloud.kubernetes.secrets.path ,則自動過載功能將無法工作。 您需要向 /actuator/refresh 端點發送 POST 請求或重新啟動/重新部署應用程式。 |
在某些情況下,您的應用程式可能無法使用 Kubernetes API 載入某些 ConfigMaps
。 如果您希望應用程式在這種情況下啟動失敗,可以設定 spring.cloud.kubernetes.config.fail-fast=true
使應用程式啟動時丟擲異常。
您還可以讓應用程式在載入 ConfigMap
屬性源失敗時進行重試。 首先,您需要設定 spring.cloud.kubernetes.config.fail-fast=true
。 然後您需要將 spring-retry
和 spring-boot-starter-aop
新增到您的類路徑。 您可以透過設定 spring.cloud.kubernetes.config.retry.*
屬性來配置重試屬性,例如最大嘗試次數、退避選項(如初始間隔、乘數、最大間隔)。
如果您由於某種原因已將 spring-retry 和 spring-boot-starter-aop 新增到類路徑中,並且想啟用 fail-fast,但不想啟用重試;您可以透過設定 spring.cloud.kubernetes.config.retry.enabled=false 來停用 ConfigMap PropertySources 的重試。 |
名稱 | 型別 | 預設值 | 描述 |
---|---|---|---|
|
|
|
啟用 ConfigMaps |
|
|
|
設定要查詢的 |
|
|
客戶端名稱空間 |
設定要查詢的 Kubernetes 名稱空間 |
|
|
|
設定掛載 |
|
|
|
啟用或停用透過 API 消費 |
|
|
|
啟用或停用在載入 |
|
|
|
啟用或停用配置重試。 |
|
|
|
初始重試間隔(毫秒)。 |
|
|
|
最大嘗試次數。 |
|
|
|
退避的最大間隔。 |
|
|
|
下一個間隔的乘數。 |