4.0.5

Spring Cloud Config 為分散式系統中的外部化組態提供伺服器端和客戶端支援。透過 Config 伺服器,您可以集中管理跨所有環境的應用程式的外部屬性。客戶端和伺服器上的概念都與 Spring EnvironmentPropertySource 抽象概念相同,因此它們非常適合 Spring 應用程式,但也可以與任何語言的任何應用程式一起使用。當應用程式在從開發到測試再到生產的部署管道中移動時,您可以管理這些環境之間的組態,並確保應用程式在遷移時擁有運行所需的一切。伺服器儲存後端的預設實作使用 git,因此它輕鬆支援組態環境的標記版本,並且可以被各種工具存取以管理內容。新增替代實作並透過 Spring 組態插入它們很容易。

快速開始

此快速入門將逐步引導您使用 Spring Cloud Config 伺服器的伺服器和客戶端。

首先,啟動伺服器,如下所示

$ cd spring-cloud-config-server
$ ../mvnw spring-boot:run

伺服器是一個 Spring Boot 應用程式,因此如果您願意,可以從 IDE 執行它(主類別是 ConfigServerApplication)。

接下來嘗試一個客戶端,如下所示

$ curl localhost:8888/foo/development
{
  "name": "foo",
  "profiles": [
    "development"
  ]
  ....
  "propertySources": [
    {
      "name": "https://github.com/spring-cloud-samples/config-repo/foo-development.properties",
      "source": {
        "bar": "spam",
        "foo": "from foo development"
      }
    },
    {
      "name": "https://github.com/spring-cloud-samples/config-repo/foo.properties",
      "source": {
        "foo": "from foo props",
        "democonfigclient.message": "hello spring io"
      }
    },
    ....

用於定位屬性來源的預設策略是克隆一個 git 儲存庫(在 spring.cloud.config.server.git.uri),並使用它來初始化一個迷你 SpringApplication。迷你應用程式的 Environment 用於枚舉屬性來源並將它們發佈在 JSON 端點。

HTTP 服務具有以下形式的資源

/{application}/{profile}[/{label}]
/{application}-{profile}.yml
/{label}/{application}-{profile}.yml
/{application}-{profile}.properties
/{label}/{application}-{profile}.properties

例如

curl localhost:8888/foo/development
curl localhost:8888/foo/development/master
curl localhost:8888/foo/development,db/master
curl localhost:8888/foo-development.yml
curl localhost:8888/foo-db.properties
curl localhost:8888/master/foo-db.properties

其中 application 作為 SpringApplication 中的 spring.config.name 注入(在常規 Spring Boot 應用程式中通常是 application),profile 是一個活動設定檔(或逗號分隔的屬性列表),而 label 是一個可選的 git 標籤(預設為 master)。

Spring Cloud Config 伺服器從各種來源提取遠端客戶端的組態。以下範例從 git 儲存庫(必須提供)取得組態,如下列範例所示

spring:
  cloud:
    config:
      server:
        git:
          uri: https://github.com/spring-cloud-samples/config-repo

其他來源包括任何 JDBC 相容資料庫、Subversion、Hashicorp Vault、Credhub 和本機檔案系統。

客戶端使用方式

為了在應用程式中使用這些功能,您可以將其建置為依賴 spring-cloud-config-client 的 Spring Boot 應用程式(有關範例,請參閱 config-client 的測試案例或範例應用程式)。新增依賴項最方便的方法是使用 Spring Boot Starter org.springframework.cloud:spring-cloud-starter-config。Maven 使用者還有一個父 pom 和 BOM (spring-cloud-starter-parent),Gradle 和 Spring CLI 使用者還有一個 Spring IO 版本管理屬性檔案。以下範例顯示了典型的 Maven 組態

pom.xml
   <parent>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-parent</artifactId>
       <version>{spring-boot-docs-version}</version>
       <relativePath /> <!-- lookup parent from repository -->
   </parent>

<dependencyManagement>
	<dependencies>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-dependencies</artifactId>
			<version>{spring-cloud-version}</version>
			<type>pom</type>
			<scope>import</scope>
		</dependency>
	</dependencies>
</dependencyManagement>

<dependencies>
	<dependency>
		<groupId>org.springframework.cloud</groupId>
		<artifactId>spring-cloud-starter-config</artifactId>
	</dependency>
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-test</artifactId>
		<scope>test</scope>
	</dependency>
</dependencies>

<build>
	<plugins>
           <plugin>
               <groupId>org.springframework.boot</groupId>
               <artifactId>spring-boot-maven-plugin</artifactId>
           </plugin>
	</plugins>
</build>

   <!-- repositories also needed for snapshots and milestones -->

現在您可以建立標準的 Spring Boot 應用程式,例如以下 HTTP 伺服器

@SpringBootApplication
@RestController
public class Application {

    @RequestMapping("/")
    public String home() {
        return "Hello World!";
    }

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

}

當此 HTTP 伺服器運行時,它會從預設的本機 config 伺服器(如果正在運行)在埠 8888 上取得外部組態。要修改啟動行為,您可以使用 application.properties 變更 config 伺服器的位置,如下列範例所示

spring.config.import=optional:configserver:http://myconfigserver.com

預設情況下,如果未設定應用程式名稱,將使用 application。要修改名稱,可以將以下屬性新增至 application.properties 檔案

spring.application.name: myapp
設定屬性 ${spring.application.name} 時,請勿以保留字 application- 作為應用程式名稱的前綴,以防止解決正確的屬性來源時出現問題。

Config 伺服器屬性在 /env 端點中顯示為高優先級屬性來源,如下列範例所示。

$ curl localhost:8080/env
{
  "activeProfiles": [],
  {
    "name": "servletContextInitParams",
    "properties": {}
  },
  {
    "name": "configserver:https://github.com/spring-cloud-samples/config-repo/foo.properties",
    "properties": {
      "foo": {
        "value": "bar",
        "origin": "Config Server https://github.com/spring-cloud-samples/config-repo/foo.properties:2:12"
      }
    }
  },
  ...
}

名為 configserver:<遠端儲存庫的 URL>/<檔案名稱> 的屬性來源包含值為 barfoo 屬性。

屬性來源名稱中的 URL 是 git 儲存庫,而不是 config 伺服器 URL。
如果您使用 Spring Cloud Config Client,則需要設定 spring.config.import 屬性才能綁定到 Config 伺服器。您可以在 Spring Cloud Config 參考指南中閱讀更多相關資訊。

Spring Cloud Config 伺服器

Spring Cloud Config 伺服器為外部組態(名稱-值對或等效的 YAML 內容)提供基於 HTTP 資源的 API。伺服器可透過使用 @EnableConfigServer 註解嵌入到 Spring Boot 應用程式中。因此,以下應用程式是一個 config 伺服器

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

與所有 Spring Boot 應用程式一樣,它預設在埠 8080 上運行,但您可以透過各種方式將其切換到更傳統的埠 8888。最簡單的方法(也設定預設組態儲存庫)是使用 spring.config.name=configserver 啟動它(Config 伺服器 jar 中有一個 configserver.yml)。另一種方法是使用您自己的 application.properties,如下列範例所示

application.properties
server.port: 8888
spring.cloud.config.server.git.uri: file://${user.home}/config-repo

其中 ${user.home}/config-repo 是一個包含 YAML 和屬性檔案的 git 儲存庫。

在 Windows 上,如果檔案 URL 是帶有磁碟機前綴的絕對路徑,則需要在檔案 URL 中額外新增一個 "/"(例如,file:///${user.home}/config-repo)。

以下列表顯示了在前述範例中建立 git 儲存庫的方法

$ cd $HOME
$ mkdir config-repo
$ cd config-repo
$ git init .
$ echo info.foo: bar > application.properties
$ git add -A .
$ git commit -m "Add application.properties"
將本機檔案系統用於您的 git 儲存庫僅用於測試。您應該使用伺服器來託管生產環境中的組態儲存庫。
如果您僅在組態儲存庫中保留文字檔案,則組態儲存庫的初始克隆可以快速而有效。如果您儲存二進制檔案,尤其是大型檔案,則在首次請求組態時可能會遇到延遲,或者在伺服器中遇到記憶體不足錯誤。

環境儲存庫

您應該將 Config 伺服器的組態資料儲存在哪裡?控制此行為的策略是 EnvironmentRepository,它提供 Environment 物件。此 Environment 是 Spring Environment 的網域的淺拷貝(包括 propertySources 作為主要功能)。Environment 資源由三個變數參數化

  • {application},它對應於客戶端上的 spring.application.name

  • {profile},它對應於客戶端上的 spring.profiles.active(逗號分隔列表)。

  • {label},它是一個伺服器端功能,用於標記一組「版本化」的組態檔案。

儲存庫實作通常的行為方式類似於 Spring Boot 應用程式,從 spring.config.name 等於 {application} 參數和 spring.profiles.active 等於 {profiles} 參數的位置載入組態檔案。設定檔的優先順序規則也與常規 Spring Boot 應用程式中的規則相同:活動設定檔優先於預設設定檔,並且如果有多個設定檔,則最後一個設定檔獲勝(類似於將條目新增到 Map)。

以下範例客戶端應用程式具有此引導組態

spring:
  application:
    name: foo
  profiles:
    active: dev,mysql

(與 Spring Boot 應用程式的通常情況一樣,這些屬性也可以透過環境變數或命令列引數設定)。

如果儲存庫是基於檔案的,則伺服器會從 application.yml(在所有客戶端之間共用)和 foo.ymlfoo.yml 優先)建立 Environment。如果 YAML 檔案中包含指向 Spring 設定檔的文件,則這些文件將以更高的優先順序(按列出的設定檔順序)應用。如果存在特定於設定檔的 YAML(或屬性)檔案,則這些檔案也將以高於預設設定檔的優先順序應用。更高的優先順序轉換為 Environment 中較早列出的 PropertySource。(這些相同的規則適用於獨立的 Spring Boot 應用程式。)

您可以將 spring.cloud.config.server.accept-empty 設定為 false,以便在找不到應用程式時,伺服器將傳回 HTTP 404 狀態。預設情況下,此標誌設定為 true

您不能將 spring.main.* 屬性放在遠端 EnvironmentRepository 中。這些屬性用作應用程式初始化的一部分。

Git 後端

EnvironmentRepository 的預設實作使用 Git 後端,這對於管理升級和實體環境以及稽核變更非常方便。要變更儲存庫的位置,您可以在 Config 伺服器中設定 spring.cloud.config.server.git.uri 組態屬性(例如在 application.yml 中)。如果您使用 file: 前綴設定它,它應該可以從本機儲存庫運作,以便您可以快速輕鬆地開始使用,而無需伺服器。但是,在這種情況下,伺服器直接在本機儲存庫上運作,而無需克隆它(如果它不是裸儲存庫也沒關係,因為 Config 伺服器永遠不會對「遠端」儲存庫進行變更)。要擴展 Config 伺服器並使其具有高可用性,您需要讓伺服器的所有實例都指向同一個儲存庫,因此只有共用檔案系統才能運作。即使在這種情況下,最好對共用檔案系統儲存庫使用 ssh: 協定,以便伺服器可以克隆它並使用本機工作副本作為快取。

此儲存庫實作將 HTTP 資源的 {label} 參數對應到 git 標籤(提交 ID、分支名稱或標籤)。如果 git 分支或標籤名稱包含斜線 (/),則 HTTP URL 中的標籤應改為使用特殊字串 (_) 指定(以避免與其他 URL 路徑混淆)。例如,如果標籤是 foo/bar,則替換斜線將產生以下標籤:foo(_)bar。特殊字串 (_) 的包含也可以應用於 {application} 參數。如果您使用 curl 等命令列客戶端,請小心 URL 中的括號 — 您應該使用單引號 ('') 從 shell 中逸出它們。

略過 SSL 憑證驗證

可以透過將 git.skipSslValidation 屬性設定為 true(預設為 false)來停用組態伺服器對 Git 伺服器 SSL 憑證的驗證。

spring:
  cloud:
    config:
      server:
        git:
          uri: https://example.com/my/repo
          skipSslValidation: true
設定 HTTP 連線逾時

您可以設定組態伺服器等待取得 HTTP 連線的時間(以秒為單位)。使用 git.timeout 屬性(預設為 5)。

spring:
  cloud:
    config:
      server:
        git:
          uri: https://example.com/my/repo
          timeout: 4
Git URI 中的預留位置

Spring Cloud Config 伺服器支援帶有 {application}{profile} 預留位置的 git 儲存庫 URL(如果需要,也支援 {label},但請記住,標籤無論如何都會作為 git 標籤應用)。因此,您可以透過使用類似於以下的結構來支援「每個應用程式一個儲存庫」策略

spring:
  cloud:
    config:
      server:
        git:
          uri: https://github.com/myorg/{application}

您也可以透過使用類似的模式但使用 {profile} 來支援「每個設定檔一個儲存庫」策略。

此外,在 {application} 參數中使用特殊字串 "(_)" 可以啟用對多個組織的支援,如下列範例所示

spring:
  cloud:
    config:
      server:
        git:
          uri: https://github.com/{application}

其中 {application} 在請求時以以下格式提供:organization(_)application

模式比對和多個儲存庫

Spring Cloud Config 還包括對應用程式和設定檔名稱進行模式比對以滿足更複雜需求的支援。模式格式是以逗號分隔的 {application}/{profile} 名稱列表,其中包含萬用字元(請注意,以萬用字元開頭的模式可能需要加上引號),如下列範例所示

spring:
  cloud:
    config:
      server:
        git:
          uri: https://github.com/spring-cloud-samples/config-repo
          repos:
            simple: https://github.com/simple/config-repo
            special:
              pattern: special*/dev*,*special*/dev*
              uri: https://github.com/special/config-repo
            local:
              pattern: local*
              uri: file:/home/configsvc/config-repo

如果 {application}/{profile} 與任何模式都不符,則它會使用在 spring.cloud.config.server.git.uri 下定義的預設 URI。在上面的範例中,對於「simple」儲存庫,模式是 simple/*(它僅比對所有設定檔中名為 simple 的一個應用程式)。「local」儲存庫比對所有設定檔中所有以 local 開頭的應用程式名稱(/* 後綴會自動新增到任何沒有設定檔比對器的模式)。

只有在要設定的唯一屬性是 URI 時,才能使用「simple」範例中使用的「單行」快捷方式。如果您需要設定其他任何內容(憑證、模式等),則需要使用完整形式。

儲存庫中的 pattern 屬性實際上是一個陣列,因此您可以使用 YAML 陣列(或屬性檔案中的 [0][1] 等後綴)來綁定到多個模式。如果您要運行具有多個設定檔的應用程式,您可能需要這樣做,如下列範例所示

spring:
  cloud:
    config:
      server:
        git:
          uri: https://github.com/spring-cloud-samples/config-repo
          repos:
            development:
              pattern:
                - '*/development'
                - '*/staging'
              uri: https://github.com/development/config-repo
            staging:
              pattern:
                - '*/qa'
                - '*/production'
              uri: https://github.com/staging/config-repo
Spring Cloud 猜測包含不以 * 結尾的設定檔的模式表示您實際上想要比對以此模式開頭的設定檔列表(因此 */staging["*/staging", "*/staging,*"] 等的快捷方式)。這在例如您需要在本機的「development」設定檔中以及遠端的「cloud」設定檔中運行應用程式的情況下很常見。

每個儲存庫也可以選擇性地將組態檔案儲存在子目錄中,並且可以用 search-paths 指定搜尋這些目錄的模式。以下範例顯示了頂層的組態檔案

spring:
  cloud:
    config:
      server:
        git:
          uri: https://github.com/spring-cloud-samples/config-repo
          search-paths:
            - foo
            - bar*

在前面的範例中,伺服器在頂層以及 foo/ 子目錄以及名稱以 bar 開頭的任何子目錄中搜尋組態檔案。

預設情況下,伺服器會在首次請求組態時克隆遠端儲存庫。伺服器可以設定為在啟動時克隆儲存庫,如下列頂層範例所示

spring:
  cloud:
    config:
      server:
        git:
          uri: https://git/common/config-repo.git
          repos:
            team-a:
                pattern: team-a-*
                cloneOnStart: true
                uri: https://git/team-a/config-repo.git
            team-b:
                pattern: team-b-*
                cloneOnStart: false
                uri: https://git/team-b/config-repo.git
            team-c:
                pattern: team-c-*
                uri: https://git/team-a/config-repo.git

在前面的範例中,伺服器在啟動時(在接受任何請求之前)克隆 team-a 的 config-repo。所有其他儲存庫在請求來自儲存庫的組態之前不會克隆。

將儲存庫設定為在 Config 伺服器啟動時克隆,有助於快速識別錯誤設定的組態來源(例如無效的儲存庫 URI),同時 Config 伺服器正在啟動。如果未針對組態來源啟用 cloneOnStart,則 Config 伺服器可能會使用錯誤設定或無效的組態來源成功啟動,並且在應用程式從該組態來源請求組態之前不會偵測到錯誤。
身份驗證

要在遠端儲存庫上使用 HTTP 基本身份驗證,請分別新增 usernamepassword 屬性(不在 URL 中),如下列範例所示

spring:
  cloud:
    config:
      server:
        git:
          uri: https://github.com/spring-cloud-samples/config-repo
          username: trolley
          password: strongpassword

如果您不使用 HTTPS 和使用者憑證,當您將金鑰儲存在預設目錄 (~/.ssh) 中並且 URI 指向 SSH 位置(例如 [email protected]:configuration/cloud-configuration)時,SSH 也應該可以正常運作。重要的是,~/.ssh/known_hosts 檔案中存在 Git 伺服器的條目,並且它是 ssh-rsa 格式。不支援其他格式(例如 ecdsa-sha2-nistp256)。為了避免意外,您應該確保 known_hosts 檔案中只有一個 Git 伺服器的條目,並且它與您提供給 config 伺服器的 URL 相符。如果您在 URL 中使用主機名稱,則您希望在 known_hosts 檔案中完全擁有該主機名稱(而不是 IP)。儲存庫是透過使用 JGit 存取的,因此您找到的任何相關文件都應該適用。HTTPS 代理設定可以在 ~/.git/config 中設定,也可以(與任何其他 JVM 程序相同)使用系統屬性 (-Dhttps.proxyHost-Dhttps.proxyPort) 設定。

如果您不知道您的 ~/.git 目錄在哪裡,請使用 git config --global 來操作設定(例如,git config --global http.sslVerify false)。

JGit 需要 PEM 格式的 RSA 金鑰。以下是 ssh-keygen(來自 openssh)命令的範例,它將產生正確格式的金鑰

ssh-keygen -m PEM -t rsa -b 4096 -f ~/config_server_deploy_key.rsa

警告:使用 SSH 金鑰時,預期的 ssh 私密金鑰必須以 -----BEGIN RSA PRIVATE KEY----- 開頭。如果金鑰以 -----BEGIN OPENSSH PRIVATE KEY----- 開頭,則在啟動 spring-cloud-config 伺服器時將無法載入 RSA 金鑰。錯誤看起來像

- Error in object 'spring.cloud.config.server.git': codes [PrivateKeyIsValid.spring.cloud.config.server.git,PrivateKeyIsValid]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [spring.cloud.config.server.git.,]; arguments []; default message []]; default message [Property 'spring.cloud.config.server.git.privateKey' is not a valid private key]

要更正上述錯誤,必須將 RSA 金鑰轉換為 PEM 格式。上面提供了使用 openssh 的範例,用於產生適當格式的新金鑰。

使用 AWS CodeCommit 進行身份驗證

Spring Cloud Config 伺服器也支援 AWS CodeCommit 身份驗證。從命令列使用 Git 時,AWS CodeCommit 使用身份驗證協助程式。JGit 程式庫不使用此協助程式,因此如果 Git URI 符合 AWS CodeCommit 模式,則會建立用於 AWS CodeCommit 的 JGit CredentialProvider。AWS CodeCommit URI 遵循此模式

https://git-codecommit.${AWS_REGION}.amazonaws.com/v1/repos/${repo}

如果您使用 AWS CodeCommit URI 提供使用者名稱和密碼,則它們必須是提供儲存庫存取權限的 AWS accessKeyId 和 secretAccessKey。如果您未指定使用者名稱和密碼,則 accessKeyId 和 secretAccessKey 會透過使用 預設憑證提供者鏈 擷取。

如果您的 Git URI 符合 CodeCommit URI 模式(如前所示),則您必須在使用者名稱和密碼中或在預設憑證提供者鏈支援的位置之一中提供有效的 AWS 憑證。AWS EC2 執行個體可以使用 EC2 執行個體的 IAM 角色

software.amazon.awssdk:auth jar 是一個選用依賴項。如果 software.amazon.awssdk:auth jar 不在您的類別路徑中,則無論 git 伺服器 URI 如何,都不會建立 AWS Code Commit 憑證提供者。
使用 Google Cloud Source 進行身份驗證

Spring Cloud Config 伺服器也支援針對 Google Cloud Source 儲存庫進行身份驗證。

如果您的 Git URI 使用 httphttps 協定,並且網域名稱是 source.developers.google.com,則將使用 Google Cloud Source 憑證提供者。Google Cloud Source 儲存庫 URI 的格式為 https://source.developers.google.com/p/${GCP_PROJECT}/r/${REPO}。要取得儲存庫的 URI,請在 Google Cloud Source UI 中按一下「克隆」,然後選取「手動產生的憑證」。不要產生任何憑證,只需複製顯示的 URI。

Google Cloud Source 憑證提供者將使用 Google Cloud Platform 應用程式預設憑證。請參閱 Google Cloud SDK 文件,了解如何為系統建立應用程式預設憑證。此方法適用於開發環境中的使用者帳戶和生產環境中的服務帳戶。

com.google.auth:google-auth-library-oauth2-http 是一個選用依賴項。如果 google-auth-library-oauth2-http jar 不在您的類別路徑中,則無論 git 伺服器 URI 如何,都不會建立 Google Cloud Source 憑證提供者。
使用屬性進行 Git SSH 組態

預設情況下,Spring Cloud Config 伺服器使用的 JGit 程式庫在使用 SSH URI 連接到 Git 儲存庫時,會使用 SSH 組態檔案,例如 ~/.ssh/known_hosts/etc/ssh/ssh_config。在 Cloud Foundry 等雲端環境中,本機檔案系統可能是暫時性的或不易存取的。對於這些情況,可以使用 Java 屬性設定 SSH 組態。為了啟動基於屬性的 SSH 組態,必須將 spring.cloud.config.server.git.ignoreLocalSshSettings 屬性設定為 true,如下列範例所示

  spring:
    cloud:
      config:
        server:
          git:
            uri: [email protected]:team/repo1.git
            ignoreLocalSshSettings: true
            hostKey: someHostKey
            hostKeyAlgorithm: ssh-rsa
            privateKey: |
                         -----BEGIN RSA PRIVATE KEY-----
                         MIIEpgIBAAKCAQEAx4UbaDzY5xjW6hc9jwN0mX33XpTDVW9WqHp5AKaRbtAC3DqX
                         IXFMPgw3K45jxRb93f8tv9vL3rD9CUG1Gv4FM+o7ds7FRES5RTjv2RT/JVNJCoqF
                         ol8+ngLqRZCyBtQN7zYByWMRirPGoDUqdPYrj2yq+ObBBNhg5N+hOwKjjpzdj2Ud
                         1l7R+wxIqmJo1IYyy16xS8WsjyQuyC0lL456qkd5BDZ0Ag8j2X9H9D5220Ln7s9i
                         oezTipXipS7p7Jekf3Ywx6abJwOmB0rX79dV4qiNcGgzATnG1PkXxqt76VhcGa0W
                         DDVHEEYGbSQ6hIGSh0I7BQun0aLRZojfE3gqHQIDAQABAoIBAQCZmGrk8BK6tXCd
                         fY6yTiKxFzwb38IQP0ojIUWNrq0+9Xt+NsypviLHkXfXXCKKU4zUHeIGVRq5MN9b
                         BO56/RrcQHHOoJdUWuOV2qMqJvPUtC0CpGkD+valhfD75MxoXU7s3FK7yjxy3rsG
                         EmfA6tHV8/4a5umo5TqSd2YTm5B19AhRqiuUVI1wTB41DjULUGiMYrnYrhzQlVvj
                         5MjnKTlYu3V8PoYDfv1GmxPPh6vlpafXEeEYN8VB97e5x3DGHjZ5UrurAmTLTdO8
                         +AahyoKsIY612TkkQthJlt7FJAwnCGMgY6podzzvzICLFmmTXYiZ/28I4BX/mOSe
                         pZVnfRixAoGBAO6Uiwt40/PKs53mCEWngslSCsh9oGAaLTf/XdvMns5VmuyyAyKG
                         ti8Ol5wqBMi4GIUzjbgUvSUt+IowIrG3f5tN85wpjQ1UGVcpTnl5Qo9xaS1PFScQ
                         xrtWZ9eNj2TsIAMp/svJsyGG3OibxfnuAIpSXNQiJPwRlW3irzpGgVx/AoGBANYW
                         dnhshUcEHMJi3aXwR12OTDnaLoanVGLwLnkqLSYUZA7ZegpKq90UAuBdcEfgdpyi
                         PhKpeaeIiAaNnFo8m9aoTKr+7I6/uMTlwrVnfrsVTZv3orxjwQV20YIBCVRKD1uX
                         VhE0ozPZxwwKSPAFocpyWpGHGreGF1AIYBE9UBtjAoGBAI8bfPgJpyFyMiGBjO6z
                         FwlJc/xlFqDusrcHL7abW5qq0L4v3R+FrJw3ZYufzLTVcKfdj6GelwJJO+8wBm+R
                         gTKYJItEhT48duLIfTDyIpHGVm9+I1MGhh5zKuCqIhxIYr9jHloBB7kRm0rPvYY4
                         VAykcNgyDvtAVODP+4m6JvhjAoGBALbtTqErKN47V0+JJpapLnF0KxGrqeGIjIRV
                         cYA6V4WYGr7NeIfesecfOC356PyhgPfpcVyEztwlvwTKb3RzIT1TZN8fH4YBr6Ee
                         KTbTjefRFhVUjQqnucAvfGi29f+9oE3Ei9f7wA+H35ocF6JvTYUsHNMIO/3gZ38N
                         CPjyCMa9AoGBAMhsITNe3QcbsXAbdUR00dDsIFVROzyFJ2m40i4KCRM35bC/BIBs
                         q0TY3we+ERB40U8Z2BvU61QuwaunJ2+uGadHo58VSVdggqAo0BSkH58innKKt96J
                         69pcVH/4rmLbXdcmNYGm6iu+MlPQk4BUZknHSmVHIFdJ0EPupVaQ8RHT
                         -----END RSA PRIVATE KEY-----

下表描述了 SSH 組態屬性。

表 1. SSH 組態屬性
屬性名稱 備註

ignoreLocalSshSettings

如果為 true,則使用基於屬性的 SSH 組態,而不是基於檔案的 SSH 組態。必須設定為 spring.cloud.config.server.git.ignoreLocalSshSettings而不是在儲存庫定義內。

privateKey

有效的 SSH 私密金鑰。如果 ignoreLocalSshSettings 為 true 且 Git URI 為 SSH 格式,則必須設定。

hostKey

有效的 SSH 主機金鑰。如果也設定了 hostKeyAlgorithm,則必須設定。

hostKeyAlgorithm

ssh-dss、ssh-rsa、ssh-ed25519、ecdsa-sha2-nistp256、ecdsa-sha2-nistp384 或 ecdsa-sha2-nistp521 之一。如果也設定了 hostKey,則必須設定。

strictHostKeyChecking

truefalse。如果為 false,則忽略主機金鑰錯誤。

knownHostsFile

自訂 .known_hosts 檔案的位置。

preferredAuthentications

覆寫伺服器身份驗證方法順序。如果伺服器在 publickey 方法之前具有 keyboard-interactive 身份驗證,則這應該允許規避登入提示。

Git 搜尋路徑中的預留位置

Spring Cloud Config 伺服器也支援帶有 {application}{profile} 預留位置的搜尋路徑(如果需要,也支援 {label}),如下列範例所示

spring:
  cloud:
    config:
      server:
        git:
          uri: https://github.com/spring-cloud-samples/config-repo
          search-paths: '{application}'

前面的列表會導致搜尋儲存庫中與目錄名稱相同的檔案(以及頂層)。萬用字元在帶有預留位置的搜尋路徑中也有效(任何符合的目錄都包含在搜尋中)。

強制提取 Git 儲存庫

如前所述,如果本機副本變髒(例如,資料夾內容被 OS 程序變更),以致 Spring Cloud Config 伺服器無法從遠端儲存庫更新本機副本,則 Spring Cloud Config 伺服器會克隆遠端 git 儲存庫。

為了解決此問題,有一個 force-pull 屬性,如果本機副本變髒,則該屬性會使 Spring Cloud Config 伺服器強制從遠端儲存庫提取,如下列範例所示

spring:
  cloud:
    config:
      server:
        git:
          uri: https://github.com/spring-cloud-samples/config-repo
          force-pull: true

如果您有多個儲存庫組態,則可以針對每個儲存庫設定 force-pull 屬性,如下列範例所示

spring:
  cloud:
    config:
      server:
        git:
          uri: https://git/common/config-repo.git
          force-pull: true
          repos:
            team-a:
                pattern: team-a-*
                uri: https://git/team-a/config-repo.git
                force-pull: true
            team-b:
                pattern: team-b-*
                uri: https://git/team-b/config-repo.git
                force-pull: true
            team-c:
                pattern: team-c-*
                uri: https://git/team-a/config-repo.git
force-pull 屬性的預設值為 false
刪除 Git 儲存庫中未追蹤的分支

由於 Spring Cloud Config 伺服器在將分支簽出到本機儲存庫後(例如,透過標籤提取屬性)具有遠端 git 儲存庫的克隆,因此它將永遠保留此分支,或保留到下次伺服器重新啟動(這會建立新的本機儲存庫)為止。因此,可能會出現遠端分支已刪除,但其本機副本仍然可用於提取的情況。如果 Spring Cloud Config 伺服器客戶端服務以 --spring.cloud.config.label=deletedRemoteBranch,master 啟動,它將從 deletedRemoteBranch 本機分支提取屬性,而不是從 master 提取。

為了保持本機儲存庫分支的乾淨和與遠端同步 - 可以設定 deleteUntrackedBranches 屬性。它將使 Spring Cloud Config 伺服器強制從本機儲存庫中刪除未追蹤的分支。範例

spring:
  cloud:
    config:
      server:
        git:
          uri: https://github.com/spring-cloud-samples/config-repo
          deleteUntrackedBranches: true
deleteUntrackedBranches 屬性的預設值為 false
Git 刷新率

您可以使用 spring.cloud.config.server.git.refreshRate 控制 config 伺服器從 Git 後端提取更新的組態資料的頻率。此屬性的值以秒為單位指定。預設值為 0,表示 config 伺服器將在每次請求時從 Git 儲存庫提取更新的組態。

預設標籤

用於 Git 的預設標籤是 main。如果您未設定 spring.cloud.config.server.git.defaultLabel 且名為 main 的分支不存在,則 config 伺服器預設也會嘗試簽出名為 master 的分支。如果您想要停用後備分支行為,您可以將 spring.cloud.config.server.git.tryMasterBranch 設定為 false

版本控制後端檔案系統使用

使用基於 VCS 的後端 (git、svn) 時,檔案會簽出或克隆到本機檔案系統。預設情況下,它們放在系統暫存目錄中,前綴為 config-repo-。例如,在 Linux 上,它可能是 /tmp/config-repo-<randomid>。某些作業系統 定期清理 暫存目錄。這可能會導致意外行為,例如遺失屬性。為了避免此問題,請將 Config 伺服器使用的目錄變更為不駐留在系統暫存結構中的目錄,方法是設定 spring.cloud.config.server.git.basedirspring.cloud.config.server.svn.basedir

檔案系統後端

Config 伺服器中還有一個「native」設定檔,它不使用 Git,而是從本機類別路徑或檔案系統載入組態檔案(您想要使用 spring.cloud.config.server.native.searchLocations 指向的任何靜態 URL)。要使用 native 設定檔,請使用 spring.profiles.active=native 啟動 Config 伺服器。

請記住對檔案資源使用 file: 前綴(沒有前綴的預設值通常是類別路徑)。與任何 Spring Boot 組態一樣,您可以嵌入 ${} 樣式的環境預留位置,但請記住,Windows 中的絕對路徑需要額外的 /(例如,file:///${user.home}/config-repo)。
searchLocations 的預設值與本機 Spring Boot 應用程式相同(即,[classpath:/, classpath:/config, file:./, file:./config])。這不會將伺服器中的 application.properties 公開給所有客戶端,因為伺服器中存在的任何屬性來源都會在傳送給客戶端之前移除。
檔案系統後端非常適合快速入門和測試。若要在生產環境中使用,您需要確保檔案系統是可靠的,並且在 Config Server 的所有實例之間共享。

搜尋位置可以包含 {application}{profile}{label} 的佔位符。 這樣一來,您可以區隔路徑中的目錄,並選擇適合您的策略(例如每個應用程式的子目錄或每個配置文件的子目錄)。

如果您在搜尋位置中不使用佔位符,此儲存庫也會將 HTTP 資源的 {label} 參數附加到搜尋路徑的後綴,因此屬性檔案會從每個搜尋位置與標籤同名的子目錄載入(標籤屬性在 Spring 環境中具有優先權)。 因此,沒有佔位符的預設行為與新增以 /{label}/ 結尾的搜尋位置相同。 例如,file:/tmp/configfile:/tmp/config,file:/tmp/config/{label} 相同。 可以透過設定 spring.cloud.config.server.native.addLabelLocations=false 來停用此行為。

Vault 後端

Spring Cloud Config Server 也支援 Vault 作為後端。

Vault 是一個用於安全存取密鑰的工具。 密鑰是您想要嚴格控制存取的任何事物,例如 API 密鑰、密碼、憑證和其他敏感資訊。 Vault 為任何密鑰提供統一的介面,同時提供嚴格的存取控制並記錄詳細的稽核日誌。

有關 Vault 的更多資訊,請參閱 Vault 快速入門指南

若要啟用 config server 使用 Vault 後端,您可以使用 vault profile 執行您的 config server。 例如,在您的 config server 的 application.properties 中,您可以新增 spring.profiles.active=vault

預設情況下,Spring Cloud Config Server 使用基於 Token 的身份驗證從 Vault 提取配置。 Vault 也支援其他身份驗證方法,如 AppRole、LDAP、JWT、CloudFoundry、Kubernetes Auth。 為了使用 TOKEN 或 X-Config-Token 標頭以外的任何身份驗證方法,我們需要在 classpath 上安裝 Spring Vault Core,以便 Config Server 可以將身份驗證委派給該程式庫。 請將以下依賴項新增到您的 Config Server 應用程式。

Maven (pom.xml)

<dependencies>
	<dependency>
		<groupId>org.springframework.vault</groupId>
		<artifactId>spring-vault-core</artifactId>
	</dependency>
</dependencies>

Gradle (build.gradle)

dependencies {
    implementation "org.springframework.vault:spring-vault-core"
}

預設情況下,config server 假設您的 Vault server 在 http://127.0.0.1:8200 上執行。 它還假設後端的名稱是 secret,而金鑰是 application。 所有這些預設值都可以在您的 config server 的 application.properties 中配置。 下表描述了可配置的 Vault 屬性

名稱 預設值

host

127.0.0.1

port

8200

scheme

http

backend

secret

defaultKey

application

profileSeparator

,

kvVersion

1

skipSslValidation

false

timeout

5

namespace

null

上表中的所有屬性都必須以 spring.cloud.config.server.vault 為前綴,或放置在複合配置的正確 Vault 區段中。

所有可配置的屬性都可以在 org.springframework.cloud.config.server.environment.VaultEnvironmentProperties 中找到。

Vault 0.10.0 引入了版本化鍵值後端(k/v 後端版本 2),它公開了與早期版本不同的 API,現在需要在掛載路徑和實際上下文路徑之間加入 data/,並將密鑰包裝在 data 物件中。 設定 spring.cloud.config.server.vault.kv-version=2 將會考慮到這一點。

或者,支援 Vault Enterprise X-Vault-Namespace 標頭。 若要將其傳送至 Vault,請設定 namespace 屬性。

在您的 config server 執行後,您可以向伺服器發出 HTTP 請求,以從 Vault 後端檢索值。 為此,您需要 Vault server 的 token。

首先,將一些資料放入您的 Vault,如下例所示

$ vault kv put secret/application foo=bar baz=bam
$ vault kv put secret/myapp foo=myappsbar

其次,向您的 config server 發出 HTTP 請求以檢索值,如下例所示

$ curl -X "GET" "http://localhost:8888/myapp/default" -H "X-Config-Token: yourtoken"

您應該會看到類似以下的響應

{
   "name":"myapp",
   "profiles":[
      "default"
   ],
   "label":null,
   "version":null,
   "state":null,
   "propertySources":[
      {
         "name":"vault:myapp",
         "source":{
            "foo":"myappsbar"
         }
      },
      {
         "name":"vault:application",
         "source":{
            "baz":"bam",
            "foo":"bar"
         }
      }
   ]
}

客戶端為讓 Config Server 與 Vault 通訊而提供必要身份驗證的預設方式是設定 X-Config-Token 標頭。 但是,您可以省略標頭並在伺服器中配置身份驗證,方法是設定與 Spring Cloud Vault 相同的配置屬性。 要設定的屬性是 spring.cloud.config.server.vault.authentication。 它應該設定為支援的身份驗證方法之一。 您可能還需要設定特定於您使用的身份驗證方法的其他屬性,方法是使用與 spring.cloud.vault 文件中記錄的屬性名稱相同的名稱,但改為使用 spring.cloud.config.server.vault 前綴。 有關更多詳細資訊,請參閱 Spring Cloud Vault 參考指南

如果您省略 X-Config-Token 標頭並使用伺服器屬性來設定身份驗證,則 Config Server 應用程式需要額外依賴 Spring Vault 才能啟用其他身份驗證選項。 有關如何新增該依賴項,請參閱 Spring Vault 參考指南
多個屬性來源

使用 Vault 時,您可以為您的應用程式提供多個屬性來源。 例如,假設您已將資料寫入 Vault 中的以下路徑

secret/myApp,dev
secret/myApp
secret/application,dev
secret/application

寫入 secret/application 的屬性可供所有使用 Config Server 的應用程式使用。 名稱為 myApp 的應用程式將可以使用寫入 secret/myAppsecret/application 的任何屬性。 當 myApp 啟用 dev profile 時,寫入上述所有路徑的屬性都將可供其使用,清單中第一個路徑中的屬性優先於其他路徑中的屬性。

透過 Proxy 存取後端

配置伺服器可以透過 HTTP 或 HTTPS proxy 存取 Git 或 Vault 後端。 此行為由 proxy.httpproxy.https 下的設定控制 Git 或 Vault。 這些設定是每個儲存庫的,因此如果您使用複合環境儲存庫,則必須為複合中的每個後端單獨配置 proxy 設定。 如果使用需要為 HTTP 和 HTTPS URL 使用單獨 proxy 伺服器的網路,您可以為單個後端配置 HTTP 和 HTTPS proxy 設定:在這種情況下,http 存取將使用 http proxy,而 https 存取將使用 https proxy。 此外,您可以指定一個單獨的 proxy,該 proxy 將用於應用程式和 proxy 之間的 proxy 定義協定的兩種協定。

下表描述了 HTTP 和 HTTPS proxy 的 proxy 配置屬性。 所有這些屬性都必須以 proxy.httpproxy.https 為前綴。

表 2. Proxy 配置屬性
屬性名稱 備註

host

proxy 的 host。

port

用於存取 proxy 的 port。

nonProxyHosts

配置伺服器應在 proxy 外部存取的任何 host。 如果同時為 proxy.http.nonProxyHostsproxy.https.nonProxyHosts 提供值,則將使用 proxy.http 值。

username

用於向 proxy 驗證身份的 username。 如果同時為 proxy.http.usernameproxy.https.username 提供值,則將使用 proxy.http 值。

password

用於向 proxy 驗證身份的 password。 如果同時為 proxy.http.passwordproxy.https.password 提供值,則將使用 proxy.http 值。

以下配置使用 HTTPS proxy 來存取 Git 儲存庫。

spring:
  profiles:
    active: git
  cloud:
    config:
      server:
        git:
          uri: https://github.com/spring-cloud-samples/config-repo
          proxy:
            https:
              host: my-proxy.host.io
              password: myproxypassword
              port: '3128'
              username: myproxyusername
              nonProxyHosts: example.com

與所有應用程式共享配置

在所有應用程式之間共享配置的方式因您採用的方法而異,如下列主題所述

基於檔案的儲存庫

使用基於檔案的(git、svn 和 native)儲存庫,檔案名稱為 application* 的資源(application.propertiesapplication.ymlapplication-*.properties 等)在所有客戶端應用程式之間共享。 您可以使用這些檔案名稱的資源來配置全域預設值,並根據需要讓應用程式特定的檔案覆蓋它們。

屬性覆蓋功能也可用於設定全域預設值,允許佔位符應用程式在本地覆蓋它們。

使用 “native” profile(本地檔案系統後端),您應該使用不是伺服器自身配置一部分的明確搜尋位置。 否則,預設搜尋位置中的 application* 資源會被移除,因為它們是伺服器的一部分。
Vault Server

當使用 Vault 作為後端時,您可以透過將配置放置在 secret/application 中與所有應用程式共享配置。 例如,如果您執行以下 Vault 命令,則所有使用 config server 的應用程式都將可以使用屬性 foobaz

$ vault write secret/application foo=bar baz=bam
CredHub Server

當使用 CredHub 作為後端時,您可以透過將配置放置在 /application/ 中或將其放置在應用程式的 default profile 中,從而與所有應用程式共享配置。 例如,如果您執行以下 CredHub 命令,則所有使用 config server 的應用程式都將可以使用屬性 shared.color1shared.color2

credhub set --name "/application/profile/master/shared" --type=json
value: {"shared.color1": "blue", "shared.color": "red"}
credhub set --name "/my-app/default/master/more-shared" --type=json
value: {"shared.word1": "hello", "shared.word2": "world"}

AWS Secrets Manager

當使用 AWS Secrets Manager 作為後端時,您可以透過將配置放置在 /application/ 中或將其放置在應用程式的 default profile 中,從而與所有應用程式共享配置。 例如,如果您新增具有以下金鑰的密鑰,則所有使用 config server 的應用程式都將可以使用屬性 shared.fooshared.bar

secret name = /secret/application-default/
secret value =
{
 shared.foo: foo,
 shared.bar: bar
}

secret name = /secret/application/
secret value =
{
 shared.foo: foo,
 shared.bar: bar
}
標籤版本

AWS Secrets Manager 儲存庫允許以與 Git 後端相同的方式保留配置環境的標籤版本。

儲存庫實作將 HTTP 資源的 {label} 參數映射到AWS Secrets Manager 密鑰的暫存標籤。 若要建立標籤密鑰,請建立密鑰或更新其內容,並為其定義暫存標籤(在 AWS 文件中有時稱為版本階段)。 例如

$ aws secretsmanager create-secret \
      --name /secret/test/ \
      --secret-string '{"version":"1"}'
{
    "ARN": "arn:aws:secretsmanager:us-east-1:123456789012:secret:/secret/test/-a1b2c3",
    "Name": "/secret/test/",
    "VersionId": "cd291674-de2f-41de-8f3b-37dbf4880d69"
}

$ aws secretsmanager update-secret-version-stage \
      --secret-id /secret/test/ \
      --version-stage 1.0.0 \
      --move-to-version-id cd291674-de2f-41de-8f3b-37dbf4880d69

{
    "ARN": "arn:aws:secretsmanager:us-east-1:123456789012:secret:/secret/test/-a1b2c3",
    "Name": "/secret/test/",
}

使用 spring.cloud.config.server.aws-secretsmanager.default-label 屬性設定預設標籤。 如果未定義該屬性,則後端使用 AWSCURRENT 作為暫存標籤。

spring:
  profiles:
    active: aws-secretsmanager
  cloud:
    config:
      server:
        aws-secretsmanager:
          region: us-east-1
          default-label: 1.0.0

請注意,如果未設定預設標籤且請求未定義標籤,則儲存庫將使用密鑰,就好像已停用標籤版本支援一樣。 此外,預設標籤僅在啟用標籤支援時才使用。 否則,定義此屬性是沒有意義的。

請注意,如果暫存標籤包含斜線 (/),則 HTTP URL 中的標籤應改為使用特殊字串 (_) 指定(以避免與其他 URL 路徑混淆),就像Git 後端區段描述的那樣。

使用 spring.cloud.config.server.aws-secretsmanager.ignore-label 屬性忽略 HTTP 資源的 {label} 參數以及 spring.cloud.config.server.aws-secretsmanager.default-label 屬性。 儲存庫將使用密鑰,就好像已停用標籤版本支援一樣。

spring:
  profiles:
    active: aws-secretsmanager
  cloud:
    config:
      server:
        aws-secretsmanager:
          region: us-east-1
          ignore-label: true

AWS Parameter Store

當使用 AWS Parameter Store 作為後端時,您可以透過將屬性放置在 /application 層次結構中來與所有應用程式共享配置。

例如,如果您新增具有以下名稱的參數,則所有使用 config server 的應用程式都將可以使用屬性 foo.barfred.baz

/config/application/foo.bar
/config/application-default/fred.baz

JDBC 後端

Spring Cloud Config Server 支援 JDBC(關聯式資料庫)作為配置屬性的後端。 您可以透過將 spring-boot-starter-data-jdbc 新增到 classpath 並使用 jdbc profile 或透過新增 JdbcEnvironmentRepository 類型的 bean 來啟用此功能。 如果您在 classpath 上包含正確的依賴項(有關更多詳細資訊,請參閱使用者指南),Spring Boot 將配置資料來源。

您可以透過將 spring.cloud.config.server.jdbc.enabled 屬性設定為 false 來停用 JdbcEnvironmentRepository 的自動配置。

資料庫需要有一個名為 PROPERTIES 的表,其中包含名為 APPLICATIONPROFILELABEL 的列(具有常用的 Environment 含義),以及 KEYVALUE,用於 Properties 樣式中的鍵值對。 所有欄位在 Java 中都是 String 類型,因此您可以將它們設為您需要的任何長度的 VARCHAR。 屬性值的行為方式與它們來自名為 {application}-{profile}.properties 的 Spring Boot 屬性檔案時的行為方式相同,包括所有加密和解密,這些將作為後處理步驟應用(也就是說,不是直接在儲存庫實作中)。

用於 JDBC 的預設標籤是 master。 您可以透過設定 spring.cloud.config.server.jdbc.defaultLabel 來變更它。

Redis 後端

Spring Cloud Config Server 支援 Redis 作為配置屬性的後端。 您可以透過新增對 Spring Data Redis 的依賴項來啟用此功能。

pom.xml
<dependencies>
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-data-redis</artifactId>
	</dependency>
</dependencies>

以下配置使用 Spring Data RedisTemplate 來存取 Redis。 我們可以使用 spring.redis.* 屬性來覆蓋預設連線設定。

spring:
  profiles:
    active: redis
  redis:
    host: redis
    port: 16379

屬性應儲存為 hash 中的欄位。 hash 的名稱應與 spring.application.name 屬性或 spring.application.namespring.profiles.active[n] 的組合相同。

HMSET sample-app server.port "8100" sample.topic.name "test" test.property1 "property1"

執行上面可見的命令後,hash 應包含以下具有值的金鑰

HGETALL sample-app
{
  "server.port": "8100",
  "sample.topic.name": "test",
  "test.property1": "property1"
}
當未指定 profile 時,將使用 default

AWS S3 後端

Spring Cloud Config Server 支援 AWS S3 作為配置屬性的後端。 您可以透過新增對 AWS Java SDK For Amazon S3 的依賴項來啟用此功能。

pom.xml
<dependencies>
	<dependency>
		<groupId>software.amazon.awssdk</groupId>
		<artifactId>s3</artifactId>
	</dependency>
</dependencies>

以下配置使用 AWS S3 client 來存取配置檔案。 我們可以使用 spring.cloud.config.server.awss3.* 屬性來選擇儲存配置的 bucket。

spring:
  profiles:
    active: awss3
  cloud:
    config:
      server:
        awss3:
          region: us-east-1
          bucket: bucket1

也可以指定 AWS URL 以 覆蓋 S3 服務的標準端點,使用 spring.cloud.config.server.awss3.endpoint。 這支援 S3 的 beta 區域和其他 S3 相容的儲存 API。

憑證是使用預設憑證提供者鏈找到的。 版本化和加密的 bucket 在沒有進一步配置的情況下受到支援。

配置檔案以 {application}-{profile}.properties{application}-{profile}.yml{application}-{profile}.json 形式儲存在您的 bucket 中。 可以提供可選的標籤來指定檔案的目錄路徑。

當未指定 profile 時,將使用 default

AWS Parameter Store 後端

Spring Cloud Config Server 支援 AWS Parameter Store 作為配置屬性的後端。 您可以透過新增對 AWS Java SDK for SSM 的依賴項來啟用此功能。

pom.xml
<dependency>
    <groupId>software.amazon.awssdk</groupId>
    <artifactId>ssm</artifactId>
</dependency>

以下配置使用 AWS SSM client 來存取參數。

spring:
  profiles:
    active: awsparamstore
  cloud:
    config:
      server:
        awsparamstore:
          region: eu-west-2
          endpoint: https://ssm.eu-west-2.amazonaws.com
          origin: aws:parameter:
          prefix: /config/service
          profile-separator: _
          recursive: true
          decrypt-values: true
          max-results: 5

下表描述了 AWS Parameter Store 配置屬性。

表 3. AWS Parameter Store 配置屬性
屬性名稱 必要 預設值 備註

region

AWS Parameter Store client 要使用的區域。 如果未明確設定,SDK 會嘗試使用預設區域提供者鏈來確定要使用的區域。

endpoint

AWS SSM client 的進入點 URL。 這可用於指定 API 請求的替代端點。

origin

aws:ssm:parameter

新增到屬性來源名稱的前綴,以顯示其出處。

prefix

/config

前綴,指示從 AWS Parameter Store 載入的每個屬性的參數層次結構中的 L1 層級。

profile-separator

-

將附加的 profile 與上下文名稱分隔開來的字串。

recursive

true

標誌,指示檢索層次結構中的所有 AWS 參數。

decrypt-values

true

標誌,指示檢索所有 AWS 參數及其解密值。

max-results

10

AWS Parameter Store API 呼叫要傳回的最大項目數。

AWS Parameter Store API 憑證是使用 預設憑證提供者鏈確定的。 版本化參數已透過傳回最新版本的預設行為獲得支援。

  • 當未指定應用程式時,application 是預設值,當未指定 profile 時,則使用 default

  • awsparamstore.prefix 的有效值必須以正斜線開頭,後跟一個或多個有效的路徑段,或為空。

  • awsparamstore.profile-separator 的有效值只能包含點、破折號和底線。

  • awsparamstore.max-results 的有效值必須在 [1, 10] 範圍內。

AWS Secrets Manager 後端

Spring Cloud Config Server 支援 AWS Secrets Manager 作為配置屬性的後端。 您可以透過新增對 AWS Java SDK for Secrets Manager 的依賴項來啟用此功能。

pom.xml
<dependency>
    <groupId>software.amazon.awssdk</groupId>
    <artifactId>secretsmanager</artifactId>
</dependency>

以下配置使用 AWS Secrets Manager client 來存取密鑰。

spring:
  profiles:
  	active: awssecretsmanager
  cloud:
    config:
      server:
        aws-secretsmanager:
          region: us-east-1
          endpoint: https://us-east-1.console.aws.amazon.com/
          origin: aws:secrets:
          prefix: /secret/foo
          profileSeparator: _

AWS Secrets Manager API 憑證是使用 預設憑證提供者鏈確定的。

  • 當未指定應用程式時,application 是預設值,當未指定 profile 時,則使用 default

  • ignoreLabel 設定為 true 時,labeldefaultLabel 屬性都會被忽略。

CredHub 後端

Spring Cloud Config Server 支援 CredHub 作為配置屬性的後端。 您可以透過新增對 Spring CredHub 的依賴項來啟用此功能。

pom.xml
<dependencies>
	<dependency>
		<groupId>org.springframework.credhub</groupId>
		<artifactId>spring-credhub-starter</artifactId>
	</dependency>
</dependencies>

以下配置使用相互 TLS 來存取 CredHub

spring:
  profiles:
    active: credhub
  cloud:
    config:
      server:
        credhub:
          url: https://credhub:8844

屬性應儲存為 JSON,例如

credhub set --name "/demo-app/default/master/toggles" --type=json
value: {"toggle.button": "blue", "toggle.link": "red"}
credhub set --name "/demo-app/default/master/abs" --type=json
value: {"marketing.enabled": true, "external.enabled": false}

名稱為 spring.cloud.config.name=demo-app 的所有客戶端應用程式都將可以使用以下屬性

{
    toggle.button: "blue",
    toggle.link: "red",
    marketing.enabled: true,
    external.enabled: false
}
當未指定 profile 時,將使用 default,當未指定標籤時,將使用 master 作為預設值。 注意:新增到 application 的值將由所有應用程式共享。
OAuth 2.0

您可以使用 OAuth 2.0,並使用 UAA 作為提供者進行身份驗證。

pom.xml
<dependencies>
	<dependency>
		<groupId>org.springframework.security</groupId>
		<artifactId>spring-security-config</artifactId>
	</dependency>
	<dependency>
		<groupId>org.springframework.security</groupId>
		<artifactId>spring-security-oauth2-client</artifactId>
	</dependency>
</dependencies>

以下配置使用 OAuth 2.0 和 UAA 來存取 CredHub

spring:
  profiles:
    active: credhub
  cloud:
    config:
      server:
        credhub:
          url: https://credhub:8844
          oauth2:
            registration-id: credhub-client
  security:
    oauth2:
      client:
        registration:
          credhub-client:
            provider: uaa
            client-id: credhub_config_server
            client-secret: asecret
            authorization-grant-type: client_credentials
        provider:
          uaa:
            token-uri: https://uaa:8443/oauth/token
使用的 UAA client-id 應具有 credhub.read 作為 scope。

複合環境儲存庫

在某些情況下,您可能希望從多個環境儲存庫中提取配置資料。 若要執行此操作,您可以在配置伺服器的應用程式屬性或 YAML 檔案中啟用 composite profile。 例如,如果您想從 Subversion 儲存庫以及兩個 Git 儲存庫中提取配置資料,您可以為您的配置伺服器設定以下屬性

spring:
  profiles:
    active: composite
  cloud:
    config:
      server:
        composite:
        -
          type: svn
          uri: file:///path/to/svn/repo
        -
          type: git
          uri: file:///path/to/rex/git/repo
        -
          type: git
          uri: file:///path/to/walter/git/repo

使用此配置,優先順序由儲存庫在 composite 金鑰下列出的順序決定。 在上面的範例中,Subversion 儲存庫列在第一個,因此在 Subversion 儲存庫中找到的值將覆蓋在其中一個 Git 儲存庫中找到的相同屬性的值。 在 rex Git 儲存庫中找到的值將在 walter Git 儲存庫中找到的相同屬性的值之前使用。

如果您只想從每個都是不同類型的儲存庫中提取配置資料,則可以在配置伺服器的應用程式屬性或 YAML 檔案中啟用相應的 profile,而不是 composite profile。 例如,如果您想從單個 Git 儲存庫和單個 HashiCorp Vault server 中提取配置資料,您可以為您的配置伺服器設定以下屬性

spring:
  profiles:
    active: git, vault
  cloud:
    config:
      server:
        git:
          uri: file:///path/to/git/repo
          order: 2
        vault:
          host: 127.0.0.1
          port: 8200
          order: 1

使用此配置,優先順序可以由 order 屬性確定。 您可以使用 order 屬性來指定所有儲存庫的優先順序。 order 屬性的數值越小,其優先順序越高。 儲存庫的優先順序有助於解決包含相同屬性值的儲存庫之間可能存在的任何衝突。

如果您的複合環境包含 Vault server(如上一個範例所示),則您必須在向配置伺服器發出的每個請求中包含 Vault token。 請參閱 Vault 後端
從環境儲存庫檢索值時的任何類型故障都會導致整個複合環境發生故障。 如果您希望即使在儲存庫發生故障時複合環境也能繼續,您可以將 spring.cloud.config.server.failOnCompositeError 設定為 false
當使用複合環境時,重要的是所有儲存庫都包含相同的標籤。 如果您的環境與前面範例中的環境類似,並且您請求帶有 master 標籤的配置資料,但 Subversion 儲存庫不包含名為 master 的分支,則整個請求都會失敗。
自訂複合環境儲存庫

除了使用 Spring Cloud 中的環境儲存庫之一外,您還可以提供自己的 EnvironmentRepository bean,以包含為複合環境的一部分。 為此,您的 bean 必須實作 EnvironmentRepository 介面。 如果您想控制您的自訂 EnvironmentRepository 在複合環境中的優先順序,您還應該實作 Ordered 介面並覆蓋 getOrdered 方法。 如果您不實作 Ordered 介面,則您的 EnvironmentRepository 將被賦予最低優先順序。

屬性覆蓋

Config Server 具有一個 “overrides” 功能,允許操作員為所有應用程式提供配置屬性。 覆蓋的屬性不會被應用程式透過正常的 Spring Boot hooks 意外變更。 若要宣告覆蓋,請將名稱-值對的 map 新增到 spring.cloud.config.server.overrides,如下例所示

spring:
  cloud:
    config:
      server:
        overrides:
          foo: bar

前面的範例會導致所有作為 config client 的應用程式讀取 foo=bar,而與它們自己的配置無關。

配置系統無法強制應用程式以任何特定方式使用配置資料。 因此,覆蓋是不可強制執行的。 但是,它們確實為 Spring Cloud Config client 提供了有用的預設行為。
通常,Spring 環境佔位符與 ${} 可以透過使用反斜線 (\) 來轉義 (並在 client 上解析),以轉義 ${。 例如,\${app.foo:bar} 解析為 bar,除非應用程式提供自己的 app.foo
在 YAML 中,您不需要轉義反斜線本身。 但是,在屬性檔案中,當您在伺服器上配置覆蓋時,您確實需要轉義反斜線。

您可以變更 client 中所有覆蓋的優先順序,使其更像預設值,讓應用程式在環境變數或系統屬性中提供自己的值,方法是在遠端儲存庫中設定 spring.cloud.config.overrideNone=true 標誌(預設值為 false)。

使用 Bootstrap 覆蓋屬性

如果您啟用config first bootstrap,您可以讓 client 設定覆蓋來自 config server 的配置,方法是在應用程式的配置中放置兩個屬性,這些屬性位於 config server 使用的外部環境儲存庫(例如,Git、Vault、SVN 和其他)中。

spring.cloud.config.allowOverride=true
spring.cloud.config.overrideNone=true

啟用 Bootstrap 並將這兩個屬性設定為 true 後,您將能夠在 client 應用程式配置中覆蓋來自 config server 的配置。

使用佔位符覆蓋屬性

覆蓋屬性的更簡潔方法,而無需啟用 config first bootstrap,是在來自 config server 的配置中使用屬性佔位符。

例如,如果來自 config server 的配置包含以下屬性

hello=${app.hello:Hello From Config Server!}

您可以透過在本地應用程式配置中設定 app.hello 來覆蓋來自 config server 的 hello

app.hello=Hello From Application!

使用 Profile 覆蓋屬性

覆蓋來自 config server 的屬性的最後一種方法是在 client 應用程式中的 profile 特定配置檔案中指定它們。

例如,如果您有來自 config server 的以下配置

hello="Hello From Config Server!"

您可以透過在 profile 特定配置檔案中設定 hello,然後啟用該 profile,從而在 client 應用程式中覆蓋 hello 的值。

application-overrides.properties
hello="Hello From Application!"

在上面的範例中,您必須啟用 overrides profile。

健康指示器

Config Server 附帶一個健康指示器,用於檢查配置的 EnvironmentRepository 是否正常運作。 預設情況下,它會向 EnvironmentRepository 詢問名為 app 的應用程式、default profile 以及 EnvironmentRepository 實作提供的預設標籤。

您可以配置健康指示器以檢查更多應用程式以及自訂 profile 和自訂標籤,如下例所示

spring:
  cloud:
    config:
      server:
        health:
          repositories:
            myservice:
              label: mylabel
            myservice-dev:
              name: myservice
              profiles: development

您可以透過設定 management.health.config.enabled=false 來停用健康指示器。

此外,您可以透過設定屬性 spring.cloud.config.server.health.down-health-status (預設值為 "DOWN') 來提供您自己的自訂 down 狀態。

安全性

您可以使用任何對您有意義的方式(從實體網路安全性到 OAuth2 bearer token)來保護您的 Config Server,因為 Spring Security 和 Spring Boot 為許多安全性安排提供了支援。

若要使用預設的 Spring Boot 配置的 HTTP Basic 安全性,請在 classpath 上包含 Spring Security(例如,透過 spring-boot-starter-security)。 預設值是 username 為 user 和隨機產生的密碼。 隨機密碼在實務上沒有用處,因此我們建議您配置密碼(透過設定 spring.security.user.password)並對其進行加密(請參閱下面的說明,瞭解如何執行此操作)。

Actuator 和安全性

某些平台配置健康檢查或類似的東西,並指向 /actuator/health 或其他 actuator 端點。 如果 actuator 不是 config server 的依賴項,則對 /actuator/ 的請求將會匹配 config server API /{application}/{label},可能會洩漏安全資訊。 在這種情況下,請記住新增 spring-boot-starter-actuator 依賴項並配置使用者,以便呼叫 /actuator/ 的使用者無權存取 /{application}/{label} 的 config server API。

加密和解密

若要使用加密和解密功能,您需要在 JVM 中安裝完整強度的 JCE(預設情況下未包含)。 您可以從 Oracle 下載 “Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files”,並按照安裝說明進行操作(基本上,您需要將 JRE lib/security 目錄中的兩個策略檔案替換為您下載的檔案)。

如果遠端屬性來源包含加密內容 (值以 {cipher} 開頭),則會在透過 HTTP 發送給用戶端之前解密。此設定的主要優點是屬性值在「靜止狀態」(例如,在 git 儲存庫中) 時不需要以純文字形式存在。如果值無法解密,則會從屬性來源中移除,並新增一個具有相同金鑰但前綴為 invalid 的額外屬性,以及表示「不適用」的值 (通常為 <n/a>)。這主要是為了防止密文被當作密碼使用並意外洩漏。

如果您為組態用戶端應用程式設定遠端組態儲存庫,則它可能包含類似於以下的 application.yml

application.yml
spring:
  datasource:
    username: dbuser
    password: '{cipher}FKSAJDFGYOS8F7GLHAKERGFHLSAJ'

application.properties 檔案中的加密值不得用引號括起來。否則,該值不會被解密。以下範例顯示可行的值

application.properties
spring.datasource.username: dbuser
spring.datasource.password: {cipher}FKSAJDFGYOS8F7GLHAKERGFHLSAJ

您可以安全地將此純文字推送到共用 git 儲存庫,而密碼仍然受到保護。

伺服器還公開了 /encrypt/decrypt 端點 (假設這些端點是安全的,並且僅由授權代理程式存取)。如果您編輯遠端組態檔案,則可以使用 Config Server 透過 POST 請求到 /encrypt 端點來加密值,如下列範例所示

$ curl localhost:8888/encrypt -s -d mysecret
682bc583f4641835fa2db009355293665d2647dade3375c0ee201de2a49f7bda
如果您正在使用 curl 進行測試,請使用 --data-urlencode (而不是 -d) 並在要加密的值前面加上 = (curl 需要這樣做),或者設定明確的 Content-Type: text/plain,以確保 curl 在存在特殊字元時 (特別是 '+') 正確編碼資料。
請務必不要在加密值中包含任何 curl 命令統計資訊,這就是範例中使用 -s 選項來使其靜音的原因。將值輸出到檔案可以幫助避免此問題。

反向操作也可透過 /decrypt 取得 (前提是伺服器已配置對稱金鑰或完整金鑰對),如下列範例所示

$ curl localhost:8888/decrypt -s -d 682bc583f4641835fa2db009355293665d2647dade3375c0ee201de2a49f7bda
mysecret

取得加密值,並在您將其放入 YAML 或 properties 檔案之前,以及在您提交並推送至遠端 (可能不安全) 儲存之前,新增 {cipher} 前綴。

/encrypt/decrypt 端點也都接受 /*/{application}/{profiles} 形式的路徑,可用於在用戶端呼叫主要環境資源時,針對每個應用程式 (名稱) 和每個 profile 控制密碼學。

若要以這種細緻的方式控制密碼學,您還必須提供類型為 TextEncryptorLocator@Bean,以便為每個名稱和 profile 建立不同的加密器。預設提供的加密器不會這樣做 (所有加密都使用相同的金鑰)。

spring 命令列用戶端 (安裝 Spring Cloud CLI 擴充功能) 也可用於加密和解密,如下列範例所示

$ spring encrypt mysecret --key foo
682bc583f4641835fa2db009355293665d2647dade3375c0ee201de2a49f7bda
$ spring decrypt --key foo 682bc583f4641835fa2db009355293665d2647dade3375c0ee201de2a49f7bda
mysecret

若要使用檔案中的金鑰 (例如用於加密的 RSA 公鑰),請在金鑰值前面加上 "@" 並提供檔案路徑,如下列範例所示

$ spring encrypt mysecret --key @${HOME}/.ssh/id_rsa.pub
AQAjPgt3eFZQXwt8tsHAVv/QHiY5sI2dRcR+...
--key 引數是強制性的 (儘管它有 -- 前綴)。

金鑰管理

Config Server 可以使用對稱 (共用) 金鑰或非對稱金鑰 (RSA 金鑰對)。就安全性而言,非對稱選擇更優越,但使用對稱金鑰通常更方便,因為它是在 application.properties 中配置的單一屬性值。

若要配置對稱金鑰,您需要將 encrypt.key 設定為機密字串 (或使用 ENCRYPT_KEY 環境變數,使其不顯示在純文字組態檔案中)。

如果您在類別路徑中包含 spring-cloud-starter-bootstrap 或將 spring.cloud.bootstrap.enabled=true 設定為系統屬性,則需要在 bootstrap.properties 中設定 encrypt.key
您無法使用 encrypt.key 配置非對稱金鑰。

若要配置非對稱金鑰,請使用金鑰儲存庫 (例如,由 JDK 隨附的 keytool 公用程式建立)。金鑰儲存庫屬性為 encrypt.keyStore.*,其中 * 等於

屬性 描述

encrypt.keyStore.location

包含 Resource 位置

encrypt.keyStore.password

持有解鎖金鑰儲存庫的密碼

encrypt.keyStore.alias

識別要使用的儲存庫中的哪個金鑰

encrypt.keyStore.type

要建立的 KeyStore 類型。預設為 jks

加密是使用公鑰完成的,而解密則需要私鑰。因此,原則上,如果您只想加密 (並且準備好在本地使用私鑰自行解密值),則可以僅在伺服器中配置公鑰。實際上,您可能不想在本地進行解密,因為它會將金鑰管理流程分散到所有用戶端,而不是將其集中在伺服器中。另一方面,如果您的組態伺服器相對不安全,並且只有少數用戶端需要加密屬性,則這可能是一個有用的選項。

建立用於測試的金鑰儲存庫

若要建立用於測試的金鑰儲存庫,您可以使用類似於以下的命令

$ keytool -genkeypair -alias mytestkey -keyalg RSA \
  -dname "CN=Web Server,OU=Unit,O=Organization,L=City,S=State,C=US" \
  -keypass changeme -keystore server.jks -storepass letmein
當使用 JDK 11 或更高版本時,使用上述命令時可能會收到以下警告。在這種情況下,您可能需要確保 keypassstorepass 值匹配。
Warning:  Different store and key passwords not supported for PKCS12 KeyStores. Ignoring user-specified -keypass value.

server.jks 檔案放在類別路徑中 (例如),然後在 Config Server 的 bootstrap.yml 中,建立以下設定

encrypt:
  keyStore:
    location: classpath:/server.jks
    password: letmein
    alias: mytestkey
    secret: changeme

使用多個金鑰和金鑰輪換

除了加密屬性值中的 {cipher} 前綴之外,Config Server 還會在 (Base64 編碼) 密文的開頭之前尋找零個或多個 {name:value} 前綴。金鑰會傳遞給 TextEncryptorLocator,它可以執行所需的任何邏輯來找到密碼的 TextEncryptor。如果您已配置金鑰儲存庫 (encrypt.keystore.location),則預設定位器會尋找具有 key 前綴提供的別名的金鑰,以及類似於以下的密文

foo:
  bar: `{cipher}{key:testkey}...`

定位器會尋找名為 "testkey" 的金鑰。也可以透過使用前綴中的 {secret:…​} 值來提供密碼。但是,如果未提供密碼,則預設為使用金鑰儲存庫密碼 (這是您在建立金鑰儲存庫且未指定密碼時獲得的密碼)。如果您確實提供了密碼,則還應該使用自訂 SecretLocator 加密密碼。

當金鑰僅用於加密少量組態資料時 (也就是說,它們未在其他地方使用),從密碼學的角度來看,幾乎不需要金鑰輪換。但是,您偶爾可能需要更改金鑰 (例如,在發生安全性漏洞時)。在這種情況下,所有用戶端都需要更改其來源組態檔案 (例如,在 git 中) 並在所有密碼中使用新的 {key:…​} 前綴。請注意,用戶端需要先檢查金鑰別名是否在 Config Server 金鑰儲存庫中可用。

如果您希望 Config Server 處理所有加密以及解密,則也可以將 {name:value} 前綴作為純文字新增到 POST 請求到 /encrypt 端點。

提供加密屬性

有時您希望用戶端在本地解密組態,而不是在伺服器中執行。在這種情況下,如果您提供 encrypt.* 組態來尋找金鑰,您仍然可以擁有 /encrypt/decrypt 端點,但您需要透過在 bootstrap.[yml|properties] 中放置 spring.cloud.config.server.encrypt.enabled=false 來明確關閉傳出屬性的解密。如果您不關心端點,如果您未配置金鑰或啟用標誌,則應該可以正常運作。

提供替代格式

來自環境端點的預設 JSON 格式非常適合 Spring 應用程式使用,因為它可以直接對應到 Environment 抽象概念。如果您願意,您可以透過在資源路徑中新增後綴 (".yml"、".yaml" 或 ".properties") 來使用相同的資料作為 YAML 或 Java properties。這對於不關心 JSON 端點結構或它們提供的額外元資料的應用程式使用可能很有用 (例如,不使用 Spring 的應用程式可能會受益於這種方法的簡潔性)。

YAML 和 properties 表示形式具有一個額外的標誌 (作為名為 resolvePlaceholders 的布林查詢參數提供),以指示是否應在輸出中解析來源文件中的佔位符 (以標準 Spring ${…​} 形式),如果可能的話。對於不了解 Spring 佔位符慣例的使用者來說,這是一個有用的功能。

使用 YAML 或 properties 格式存在限制,主要與元資料的遺失有關。例如,JSON 的結構化方式是屬性來源的有序清單,其名稱與來源相關聯。YAML 和 properties 形式被合併為單一地圖,即使值的來源有多個來源,原始來源檔案的名稱也會遺失。此外,YAML 表示形式也不一定是後端儲存庫中 YAML 來源的忠實表示。它是由平面屬性來源清單建構而成,並且必須對金鑰的形式做出假設。

提供純文字

您的應用程式可能需要通用純文字組態檔案,這些檔案是根據其環境量身定制的,而不是使用 Environment 抽象概念 (或 YAML 或 properties 格式的替代表示形式之一)。Config Server 透過 /{application}/{profile}/{label}/{path} 的額外端點提供這些檔案,其中 applicationprofilelabel 與常規環境端點的含義相同,但 path 是檔案名稱的路徑 (例如 log.xml)。此端點的來源檔案與環境端點的來源檔案位於相同的位置。相同的搜尋路徑用於 properties 和 YAML 檔案。但是,不是聚合所有匹配的資源,而是僅傳回第一個匹配的資源。

找到資源後,會使用提供的應用程式名稱、profile 和標籤的有效 Environment 來解析正常格式 (${…​}) 中的佔位符。透過這種方式,資源端點與環境端點緊密整合。

與環境組態的來源檔案一樣,profile 用於解析檔案名稱。因此,如果您想要 profile 特定的檔案,則 /*/development/*/logback.xml 可以由名為 logback-development.xml 的檔案解析 (優先於 logback.xml)。
如果您不想提供 label 並讓伺服器使用預設標籤,則可以提供 useDefaultLabel 請求參數。因此,前面針對 default profile 的範例可以是 /sample/default/nginx.conf?useDefaultLabel

目前,Spring Cloud Config 可以為 git、SVN、原生後端和 AWS S3 提供純文字服務。對 git、SVN 和原生後端的支援是相同的。AWS S3 的運作方式略有不同。以下各節說明了每一種運作方式

提供二進位檔案

為了從組態伺服器提供二進位檔案,您需要傳送 Accept 標頭 application/octet-stream

Git、SVN 和原生後端

考慮以下 GIT 或 SVN 儲存庫或原生後端的範例

application.yml
nginx.conf

nginx.conf 可能類似於以下清單

server {
    listen              80;
    server_name         ${nginx.server.name};
}

application.yml 可能類似於以下清單

nginx:
  server:
    name: example.com
---
spring:
  profiles: development
nginx:
  server:
    name: develop.com

/sample/default/master/nginx.conf 資源可能如下

server {
    listen              80;
    server_name         example.com;
}

/sample/development/master/nginx.conf 可能如下

server {
    listen              80;
    server_name         develop.com;
}

AWS S3

若要啟用為 AWS s3 提供純文字服務,Config Server 應用程式需要包含對 io.awspring.cloud:spring-cloud-aws-context 的依賴。有關如何設定該依賴的詳細資訊,請參閱 Spring Cloud AWS 參考指南。此外,當將 Spring Cloud AWS 與 Spring Boot 搭配使用時,包含 自動組態依賴 非常有用。然後,您需要配置 Spring Cloud AWS,如 Spring Cloud AWS 參考指南 中所述。

解密純文字

預設情況下,純文字檔案中的加密值不會被解密。為了啟用純文字檔案的解密,請在 bootstrap.[yml|properties] 中設定 spring.cloud.config.server.encrypt.enabled=truespring.cloud.config.server.encrypt.plainTextEncrypt=true

純文字檔案的解密僅支援 YAML、JSON 和 properties 檔案擴充功能。

如果啟用此功能,並且請求了不受支援的檔案擴充功能,則檔案中的任何加密值都不會被解密。

嵌入 Config Server

Config Server 作為獨立應用程式執行效果最佳。但是,如果需要,您可以將其嵌入到另一個應用程式中。若要執行此操作,請使用 @EnableConfigServer 註解。名為 spring.cloud.config.server.bootstrap 的可選屬性在這種情況下可能很有用。它是一個標誌,用於指示伺服器是否應從其自己的遠端儲存庫配置自身。預設情況下,此標誌處於關閉狀態,因為它可能會延遲啟動。但是,當嵌入到另一個應用程式中時,以與任何其他應用程式相同的方式初始化是有意義的。當將 spring.cloud.config.server.bootstrap 設定為 true 時,您還必須使用 複合環境儲存庫組態。例如

spring:
  application:
    name: configserver
  profiles:
    active: composite
  cloud:
    config:
      server:
        composite:
          - type: native
            search-locations: ${HOME}/Desktop/config
        bootstrap: true
如果您使用 bootstrap 標誌,則需要在 bootstrap.yml 中配置 config server 的名稱和儲存庫 URI。

若要變更伺服器端點的位置,您可以 (選擇性地) 設定 spring.cloud.config.server.prefix (例如,/config),以在前綴下提供資源。前綴應以 / 開頭,但不應以 / 結尾。它會應用於 Config Server 中的 @RequestMappings (也就是說,在 Spring Boot server.servletPathserver.contextPath 前綴之下)。

如果您想要直接從後端儲存庫讀取應用程式的組態 (而不是從 config server 讀取),則基本上需要一個沒有端點的嵌入式 config server。您可以完全關閉端點,方法是不使用 @EnableConfigServer 註解 (設定 spring.cloud.config.server.bootstrap=true)。

推播通知和 Spring Cloud Bus

許多原始碼儲存庫提供者 (例如 Github、Gitlab、Gitea、Gitee、Gogs 或 Bitbucket) 會透過 webhook 通知您儲存庫中的變更。您可以透過提供者的使用者介面將 webhook 配置為 URL 和一組您感興趣的事件。例如,Github 使用 POST 請求到 webhook,其中包含 JSON 主體,其中包含提交清單,以及標頭 (X-Github-Event) 設定為 push。如果您新增對 spring-cloud-config-monitor 程式庫的依賴,並在 Config Server 中啟動 Spring Cloud Bus,則會啟用 /monitor 端點。

當 webhook 啟動時,Config Server 會傳送 RefreshRemoteApplicationEvent,目標是它認為可能已變更的應用程式。變更偵測可以策略化。但是,預設情況下,它會尋找與應用程式名稱匹配的檔案中的變更 (例如,foo.properties 的目標是 foo 應用程式,而 application.properties 的目標是所有應用程式)。當您想要覆寫行為時,要使用的策略是 PropertyPathNotificationExtractor,它接受請求標頭和主體作為參數,並傳回已變更的檔案路徑清單。

預設組態可與 Github、Gitlab、Gitea、Gitee、Gogs 或 Bitbucket 開箱即用。除了來自 Github、Gitlab、Gitee 或 Bitbucket 的 JSON 通知之外,您還可以透過 POST 請求到 /monitor,並在 path={application} 模式中使用表單編碼主體參數來觸發變更通知。這樣做會廣播到與 {application} 模式 (可以包含萬用字元) 匹配的應用程式。

只有在 Config Server 和用戶端應用程式中都啟用了 spring-cloud-bus 時,才會傳輸 RefreshRemoteApplicationEvent
預設組態也會偵測本機 git 儲存庫中的檔案系統變更。在這種情況下,不會使用 webhook。但是,只要您編輯組態檔案,就會廣播重新整理。

AOT 和 Native Image 支援

4.0.0 起,Spring Cloud Config Server 支援 Spring AOT 轉換。但是,目前暫時不支援 GraalVM native image。實作 native image 支援受到 graal#5134 的阻礙,並且可能需要完成 https://github.com/graalvm/taming-build-time-initialization 的工作才能解決。

Spring Cloud Config Client

Spring Boot 應用程式可以立即利用 Spring Config Server (或應用程式開發人員提供的其他外部屬性來源)。它還會擷取與 Environment 變更事件相關的一些額外實用功能。

Spring Boot Config Data 匯入

Spring Boot 2.4 引入了一種透過 spring.config.import 屬性匯入組態資料的新方法。這現在是繫結到 Config Server 的預設方式。

若要選擇性地連線到 config server,請在 application.properties 中設定以下內容

application.properties
spring.config.import=optional:configserver:

這將連線到預設位置為 "http://localhost:8888" 的 Config Server。移除 optional: 前綴將導致 Config Client 在無法連線到 Config Server 時失敗。若要變更 Config Server 的位置,請設定 spring.cloud.config.uri 或將 URL 新增至 spring.config.import 陳述式,例如 spring.config.import=optional:configserver:http://myhost:8888。import 屬性中的位置優先於 uri 屬性。

Spring Boot Config Data 以兩步驟流程解析組態。首先,它使用 default profile 載入所有組態。這允許 Spring Boot 收集所有可能啟動任何其他 profile 的組態。在它收集所有啟動的 profile 之後,它將載入任何其他用於活動 profile 的組態。因此,您可能會看到向 Spring Cloud Config Server 發出多個請求以擷取組態。這是正常的,並且是 Spring Boot 在使用 spring.config.import 時載入組態的方式的副作用。在先前版本的 Spring Cloud Config 中,只發出一個請求,但這表示您無法從來自 Config Server 的組態啟動 profile。現在,僅使用 'default' profile 的額外請求使這成為可能。

透過 spring.config.import 匯入的 Spring Boot Config Data 方法不需要 bootstrap 檔案 (properties 或 yaml)。

Config First Bootstrap

若要使用連線到 Config Server 的舊版 bootstrap 方式,必須透過屬性或 spring-cloud-starter-bootstrap 啟動器啟用 bootstrap。該屬性為 spring.cloud.bootstrap.enabled=true。它必須設定為系統屬性或環境變數。一旦啟用 bootstrap,類別路徑中具有 Spring Cloud Config Client 的任何應用程式都將如下所示連線到 Config Server:當 config client 啟動時,它會繫結到 Config Server (透過 spring.cloud.config.uri bootstrap 組態屬性) 並使用遠端屬性來源初始化 Spring Environment

此行為的最終結果是,所有想要使用 Config Server 的用戶端應用程式都需要一個 bootstrap.yml (或環境變數),其中伺服器位址設定在 spring.cloud.config.uri 中 (預設為 "http://localhost:8888")。

Discovery First 查找

除非您使用 config first bootstrap,否則您需要在組態屬性中使用帶有 optional: 前綴的 spring.config.import 屬性。例如,spring.config.import=optional:configserver:

如果您使用 DiscoveryClient 實作,例如 Spring Cloud Netflix 和 Eureka Service Discovery 或 Spring Cloud Consul,您可以讓 Config Server 向 Discovery Service 註冊。

如果您偏好使用 DiscoveryClient 來尋找 Config Server,您可以透過設定 spring.cloud.config.discovery.enabled=true 來執行此操作 (預設為 false)。例如,使用 Spring Cloud Netflix,您需要定義 Eureka 伺服器位址 (例如,在 eureka.client.serviceUrl.defaultZone 中)。使用此選項的代價是在啟動時進行額外的網路往返,以尋找服務註冊。好處是,只要 Discovery Service 是一個固定點,Config Server 就可以變更其座標。預設服務 ID 為 configserver,但您可以透過設定 spring.cloud.config.discovery.serviceId 在用戶端變更它 (以及在伺服器上,以服務的通常方式,例如透過設定 spring.application.name)。

discovery client 實作都支援某種元資料地圖 (例如,我們有 Eureka 的 eureka.instance.metadataMap)。Config Server 的一些額外屬性可能需要在其服務註冊元資料中配置,以便用戶端可以正確連線。如果 Config Server 使用 HTTP Basic 保護,您可以將認證配置為 userpassword。此外,如果 Config Server 具有 context path,您可以設定 configPath。例如,以下 YAML 檔案適用於作為 Eureka 用戶端的 Config Server

eureka:
  instance:
    ...
    metadataMap:
      user: osufhalskjrtl
      password: lviuhlszvaorhvlo5847
      configPath: /config

使用 Eureka 和 WebClient 的 Discovery First Bootstrap

如果您使用來自 Spring Cloud Netflix 的 Eureka DiscoveryClient,並且也想要使用 WebClient 而不是 Jersey 或 RestTemplate,則需要將 WebClient 包含在類別路徑中,並設定 eureka.client.webclient.enabled=true

Config Client 快速失敗

在某些情況下,如果服務無法連線到 Config Server,您可能希望使服務啟動失敗。如果這是所需的行為,請設定 bootstrap 組態屬性 spring.cloud.config.fail-fast=true,以使用戶端因異常而停止。

若要使用 spring.config.import 取得類似的功能,只需省略 optional: 前綴。

Config Client 重試

如果您預期 config server 在您的應用程式啟動時偶爾可能不可用,您可以使其在失敗後繼續嘗試。首先,您需要設定 spring.cloud.config.fail-fast=true。然後,您需要將 spring-retryspring-boot-starter-aop 新增到您的類別路徑中。預設行為是重試六次,初始退避間隔為 1000 毫秒,後續退避的指數乘數為 1.1。您可以透過設定 spring.cloud.config.retry.* 組態屬性來配置這些屬性 (和其他屬性)。若要使用隨機指數退避策略,請將 spring.cloud.config.retry.useRandomPolicy 設定為 true

若要完全控制重試行為並使用舊版 bootstrap,請新增類型為 RetryOperationsInterceptor 且 ID 為 configServerRetryInterceptor@Bean。Spring Retry 具有 RetryInterceptorBuilder,支援建立一個。

使用 spring.config.import 的 Config Client 重試

重試適用於 Spring Boot spring.config.import 陳述式,並且普通屬性也適用。但是,如果 import 陳述式位於 profile 中,例如 application-prod.properties,則您需要不同的方式來配置重試。組態需要作為 URL 參數放置在 import 陳述式上。

application-prod.properties
spring.config.import=configserver:http://configserver.example.com?fail-fast=true&max-attempts=10&max-interval=1500&multiplier=1.2&initial-interval=1100"

這會設定 spring.cloud.config.fail-fast=true (請注意上面缺少前綴) 和所有可用的 spring.cloud.config.retry.* 組態屬性。

尋找遠端組態資源

Config Service 從 /{application}/{profile}/{label} 提供屬性來源,其中用戶端應用程式中的預設繫結如下

  • "application" = ${spring.application.name}

  • "profile" = ${spring.profiles.active} (實際上是 Environment.getActiveProfiles())

  • "label" = "master"

設定屬性 ${spring.application.name} 時,請勿以保留字 application- 作為應用程式名稱的前綴,以防止解決正確的屬性來源時出現問題。

您可以透過設定 spring.cloud.config.* (其中 *nameprofilelabel) 來覆寫所有這些。label 對於回滾到先前版本的組態很有用。使用預設 Config Server 實作,它可以是 git 標籤、分支名稱或提交 ID。標籤也可以作為逗號分隔清單提供。在這種情況下,清單中的項目會逐一嘗試,直到其中一個成功。當在功能分支上工作時,此行為可能很有用。例如,您可能想要將組態標籤與您的分支對齊,但使其成為可選的 (在這種情況下,請使用 spring.cloud.config.label=myfeature,develop)。

為 Config Server 指定多個 URL

為了確保在高可用性方面,當您部署了多個 Config Server 實例,並且預期一個或多個實例在一段時間內不可用或無法處理請求時 (例如,如果 Git 伺服器關閉),您可以指定多個 URL (作為 spring.cloud.config.uri 屬性下的逗號分隔清單) 或讓您的所有實例在服務註冊中心 (如 Eureka) 中註冊 (如果使用 Discovery-First Bootstrap 模式)。

spring.cloud.config.uri 下列出的 URL 會依列出順序嘗試。預設情況下,Config Client 將嘗試從每個 URL 擷取屬性,直到嘗試成功以確保高可用性。

但是,如果您只想在 Config Server 未執行時 (也就是說,當應用程式已退出時) 或發生連線逾時時才確保高可用性,請將 spring.cloud.config.multiple-uri-strategy 設定為 connection-timeout-only。(spring.cloud.config.multiple-uri-strategy 的預設值為 always。) 例如,如果 Config Server 傳回 500 (內部伺服器錯誤) 回應,或 Config Client 從 Config Server 收到 401 (由於錯誤的認證或其他原因),則 Config Client 不會嘗試從其他 URL 擷取屬性。400 錯誤 (可能除了 404 之外) 表示使用者問題,而不是可用性問題。請注意,如果 Config Server 設定為使用 Git 伺服器,並且對 Git 伺服器的呼叫失敗,則可能會發生 404 錯誤。

可以在單一 spring.config.import 金鑰下指定多個位置,而不是 spring.cloud.config.uri。位置將按照定義的順序處理,後面的 import 優先。但是,如果 spring.cloud.config.fail-fasttrue,則如果第一個 Config Server 呼叫因任何原因失敗,Config Client 將會失敗。如果 fail-fastfalse,則無論失敗的原因為何,它都會嘗試所有 URL,直到一個呼叫成功。(當在 spring.config.import 下指定 URL 時,spring.cloud.config.multiple-uri-strategy 不適用。)

如果您在 Config Server 上使用 HTTP basic 安全性,則目前只有在您將認證嵌入到您在 spring.cloud.config.uri 屬性下指定的每個 URL 中時,才有可能支援每個 Config Server 的驗證認證。如果您使用任何其他類型的安全性機制,則 (目前) 無法支援每個 Config Server 的身分驗證和授權。

配置逾時

如果您想要配置逾時閾值

  • 可以使用屬性 spring.cloud.config.request-read-timeout 配置讀取逾時。

  • 可以使用屬性 spring.cloud.config.request-connect-timeout 配置連線逾時。

安全性

如果您在伺服器上使用 HTTP Basic 安全性,則用戶端需要知道密碼 (以及使用者名稱,如果它不是預設值)。您可以透過 config server URI 或透過單獨的使用者名稱和密碼屬性來指定使用者名稱和密碼,如下列範例所示

spring:
  cloud:
    config:
     uri: https://user:[email protected]

以下範例顯示了傳遞相同資訊的替代方法

spring:
  cloud:
    config:
     uri: https://myconfig.mycompany.com
     username: user
     password: secret

spring.cloud.config.passwordspring.cloud.config.username 值會覆寫 URI 中提供的任何內容。

如果您將應用程式部署在 Cloud Foundry 上,則提供密碼的最佳方法是透過服務認證 (例如在 URI 中,因為它不需要在組態檔案中)。以下範例適用於本機以及 Cloud Foundry 上名為 configserver 的使用者提供的服務

spring:
  cloud:
    config:
     uri: ${vcap.services.configserver.credentials.uri:http://user:password@localhost:8888}

如果 config server 需要用戶端 TLS 憑證,您可以透過屬性配置用戶端 TLS 憑證和信任儲存庫,如下列範例所示

spring:
  cloud:
    config:
      uri: https://myconfig.myconfig.com
      tls:
        enabled: true
        key-store: <path-of-key-store>
        key-store-type: PKCS12
        key-store-password: <key-store-password>
        key-password: <key-password>
        trust-store: <path-of-trust-store>
        trust-store-type: PKCS12
        trust-store-password: <trust-store-password>

需要將 spring.cloud.config.tls.enabled 設定為 true 才能啟用 Config Client 端的 TLS。當省略 spring.cloud.config.tls.trust-store 時,會使用 JVM 預設的信任儲存庫。spring.cloud.config.tls.key-store-typespring.cloud.config.tls.trust-store-type 的預設值為 PKCS12。當密碼屬性被省略時,會假設為空密碼。

如果您使用其他形式的安全性,您可能需要提供一個 RestTemplateConfigServicePropertySourceLocator(例如,透過在啟動引導 (bootstrap) 內容中抓取並注入它)。

健康指示器 (Health Indicator)

Config Client 提供一個 Spring Boot 健康指示器,用於嘗試從 Config Server 載入配置。可以透過設定 health.config.enabled=false 來停用健康指示器。回應也會基於效能考量而被快取。預設快取存活時間為 5 分鐘。若要變更該值,請設定 health.config.time-to-live 屬性(以毫秒為單位)。

提供自訂的 RestTemplate

在某些情況下,您可能需要自訂從用戶端發送到 Config Server 的請求。通常,這樣做涉及到傳遞特殊的 Authorization 標頭,以驗證對伺服器的請求。

使用配置資料 (Config Data) 提供自訂的 RestTemplate

在使用 Config Data 時提供自訂的 RestTemplate

  1. 建立一個實作 BootstrapRegistryInitializer 的類別

    CustomBootstrapRegistryInitializer.java
    public class CustomBootstrapRegistryInitializer implements BootstrapRegistryInitializer {
    
    	@Override
    	public void initialize(BootstrapRegistry registry) {
    		registry.register(RestTemplate.class, context -> {
    			RestTemplate restTemplate = new RestTemplate();
    			// Customize RestTemplate here
    			return restTemplate;
    		});
    	}
    
    }
    
  2. resources/META-INF 中,建立一個名為 spring.factories 的檔案,並指定您的自訂配置,如下列範例所示

    spring.factories
    org.springframework.boot.BootstrapRegistryInitializer=com.my.config.client.CustomBootstrapRegistryInitializer
使用啟動引導 (Bootstrap) 提供自訂的 RestTemplate

在使用啟動引導 (Bootstrap) 時提供自訂的 RestTemplate

  1. 建立一個新的配置 Bean,並帶有一個 PropertySourceLocator 的實作,如下列範例所示

    CustomConfigServiceBootstrapConfiguration.java
    @Configuration
    public class CustomConfigServiceBootstrapConfiguration {
        @Bean
        public ConfigServicePropertySourceLocator configServicePropertySourceLocator() {
            ConfigClientProperties clientProperties = configClientProperties();
           ConfigServicePropertySourceLocator configServicePropertySourceLocator =  new ConfigServicePropertySourceLocator(clientProperties);
            configServicePropertySourceLocator.setRestTemplate(customRestTemplate(clientProperties));
            return configServicePropertySourceLocator;
        }
    }
    
    為了簡化新增 Authorization 標頭的方法,可以使用 spring.cloud.config.headers.* 屬性來替代。
  2. resources/META-INF 中,建立一個名為 spring.factories 的檔案,並指定您的自訂配置,如下列範例所示

    spring.factories
    org.springframework.cloud.bootstrap.BootstrapConfiguration = com.my.config.client.CustomConfigServiceBootstrapConfiguration

Vault

當使用 Vault 作為 Config Server 的後端時,用戶端需要提供一個 token,供伺服器從 Vault 檢索值。這個 token 可以在用戶端中設定 bootstrap.yml 中的 spring.cloud.config.token 來提供,如下列範例所示

spring:
  cloud:
    config:
      token: YourVaultToken

Vault 中的巢狀金鑰 (Nested Keys)

Vault 支援在儲存在 Vault 中的值中巢狀金鑰的能力,如下列範例所示

echo -n '{"appA": {"secret": "appAsecret"}, "bar": "baz"}' | vault write secret/myapp -

此命令會將一個 JSON 物件寫入您的 Vault。若要在 Spring 中存取這些值,您可以使用傳統的點 (.) 註釋,如下列範例所示

@Value("${appA.secret}")
String name = "World";

上述程式碼會將 name 變數的值設定為 appAsecret

AOT 和原生映像檔 (Native Image) 支援

4.0.0 版本起,Spring Cloud Config Client 支援 Spring AOT 轉換和 GraalVM 原生映像檔。

AOT 和原生映像檔支援不適用於配置優先啟動引導 (config first bootstrap)(使用 spring.config.use-legacy-processing=true)。
原生映像檔不支援 Refresh scope。如果您打算以原生映像檔形式執行您的 Config Client 應用程式,請務必將 spring.cloud.refresh.enabled 屬性設定為 false
在建置包含 Spring Cloud Config Client 的專案時,您必須確保它連接的配置資料來源(例如 Spring Cloud Config Server、Consul、Zookeeper、Vault 和其他)是可用的。例如,如果您從 Spring Cloud Config Server 檢索配置資料,請確保您已執行其執行個體,並且可在 Config Client 設定中指示的埠上使用。這是必要的,因為應用程式上下文在建置時會被最佳化,並且需要解析目標環境。
由於在 AOT 和原生模式下,配置正在被處理且上下文正在建置時被最佳化,因此任何會影響 Bean 建立的屬性(例如在啟動引導 (bootstrap) 上下文內使用的屬性)都應在建置時和執行時設定為相同的值,以避免意外行為。
由於 Config Client 從原生映像檔啟動時會連接到正在運行的資料來源(例如 Config Server),因此快速啟動時間會因進行此網路通訊所需的時間而減慢。

附錄 (Appendices)

可觀測性中繼資料 (Observability metadata)

可觀測性 - 指標 (Metrics)

您可以在下方找到此專案宣告的所有指標列表。

環境儲存庫 (Environment Repository)

圍繞 EnvironmentRepository 建立的 Observation。

指標名稱 (Metric name) spring.cloud.config.environment.find (由慣例類別 org.springframework.cloud.config.server.environment.ObservationEnvironmentRepositoryObservationConvention 定義)。類型 (Type) timer

指標名稱 (Metric name) spring.cloud.config.environment.find.active (由慣例類別 org.springframework.cloud.config.server.environment.ObservationEnvironmentRepositoryObservationConvention 定義)。類型 (Type) long task timer

在啟動 Observation 後新增的 KeyValues 可能會從 *.active 指標中遺失。
Micrometer 在內部使用 nanoseconds 作為基本單位。但是,每個後端都會決定實際的基本單位。(即 Prometheus 使用秒)

封閉類別的完整名稱 org.springframework.cloud.config.server.environment.DocumentedConfigObservation

所有標籤都必須以 spring.cloud.config.environment 前綴開頭!
表 4. 低基數金鑰 (Low cardinality Keys)

名稱

描述

spring.cloud.config.environment.application (必要)

正在查詢其屬性的應用程式名稱。

spring.cloud.config.environment.class (必要)

EnvironmentRepository 的實作。

spring.cloud.config.environment.label (必要)

正在查詢其屬性的標籤。

spring.cloud.config.environment.profile (必要)

正在查詢其屬性的應用程式名稱。

可觀測性 - Span

您可以在下方找到此專案宣告的所有 Span 列表。

環境儲存庫 Span (Environment Repository Span)

圍繞 EnvironmentRepository 建立的 Observation。

Span 名稱 (Span name) spring.cloud.config.environment.find (由慣例類別 org.springframework.cloud.config.server.environment.ObservationEnvironmentRepositoryObservationConvention 定義)。

封閉類別的完整名稱 org.springframework.cloud.config.server.environment.DocumentedConfigObservation

所有標籤都必須以 spring.cloud.config.environment 前綴開頭!
表 5. 標籤金鑰 (Tag Keys)

名稱

描述

spring.cloud.config.environment.application (必要)

正在查詢其屬性的應用程式名稱。

spring.cloud.config.environment.class (必要)

EnvironmentRepository 的實作。

spring.cloud.config.environment.label (必要)

正在查詢其屬性的標籤。

spring.cloud.config.environment.profile (必要)

正在查詢其屬性的應用程式名稱。