5. Spring Cloud 配置服务器

Spring Cloud Config Server 为外部 configuration(name-value 对或等效的 YAML 内容)提供 HTTP resource-based API。通过使用@EnableConfigServer annotation,服务器可嵌入 Spring Boot application 中。因此,以下 application 是配置服务器:

ConfigServer.java.

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

像所有 Spring Boot applications 一样,它默认运行在 port 8080 上,但是你可以通过各种方式将它切换到更传统的 port 8888。最简单的,也是设置默认的 configuration repository,是通过spring.config.name=configserver启动它(Config Server 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 和 properties files 的 git repository。

在 Windows 上,如果文件 URL 是绝对的驱动器前缀(对于 example,file:///${user.home}/config-repo),则需要在文件 URL 中添加额外的“/”。

下面的清单显示了在前面的 example 中创建 git repository 的配方:

$ 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 repository 的本地文件系统仅用于测试。您应该在 production 中使用服务器来托管 configuration repositories。

如果只保留文本 files,则 configuration repository 的初始克隆可以快速有效。如果您 store 二进制 files,特别是大型文件,您可能会遇到第一次 configuration 请求或服务器中遇到 memory 错误的延迟。

5.1 环境存储库

您应该在哪里存储配置服务器的 configuration 数据?管理此行为的策略是EnvironmentRepository,提供Environment objects。这个Environment是来自 Spring Environment的域的浅表副本(包括propertySources作为主 feature)。 Environment资源由三个变量参数化:

  • {application},在 client 端 maps 到spring.application.name

  • {profile},maps 到 client(comma-separated 列表)上的spring.profiles.active

  • {label},这是一个服务器端 feature,标记了一个“版本化”的 config files 集。

repository implementations 通常表现得象一个 Spring Boot Application,从spring.config.name等于{application}参数,和spring.profiles.active等于{profiles}参数 loading configuration files。 profiles 的优先规则也与常规 Spring Boot application 相同:Active profiles 优先于默认值,如果有多个 profiles,则最后一个获胜(类似于向Map添加条目)。

以下 sample client application 具有此引导程序 configuration:

bootstrap.yml.

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

(与 Spring Boot application 一样,这些 properties 也可以由环境变量或命令 line arguments 设置)。

如果 repository 是 file-based,则服务器从application.yml(在所有 clients 之间共享)和foo.yml(以foo.yml优先)创建Environment。如果 YAML files 中包含指向 Spring profiles 的文档,则应用优先级较高的文档(在列出的 profiles 的 order 中)。如果有 profile-specific YAML(或 properties)files,则这些文件的优先级也高于默认值。较高的优先级转换为Environment中较早列出的PropertySource。 (这些相同的规则适用于独立 Spring Boot application.)

您可以将 spring.cloud.config.server.accept-empty 设置为 false,以便服务器_return HTTP 404 状态,如果 application 不是 found.By default,则 flag 设置为 true。

5.1.1 Git 后端

EnvironmentRepository的默认_impleration 使用 Git 后端,这对于管理升级和物理环境以及审计更改非常方便。要更改 repository 的位置,可以在 Config Server 中设置spring.cloud.config.server.git.uri configuration property(对于application.yml中的 example)。如果使用file:前缀设置它,它应该从本地 repository 开始工作,这样您就可以在没有服务器的情况下快速轻松地开始使用。但是,在这种情况下,服务器直接在本地 repository 上运行而不对其进行克隆(如果它不是裸的则无关紧要,因为 Config Server 从不对“remote”repository 进行更改)。要向上扩展 Config Server 并使其具有高可用性,您需要让服务器的所有实例指向同一个 repository,因此只有共享文件系统才能工作。即使在这种情况下,最好将ssh:协议用于共享文件系统 repository,以便服务器可以克隆它并使用本地工作副本作为缓存。

此 repository implementation maps 将 HTTP 资源的{label}参数映射到 git 标签(commit id,branch name 或 tag)。如果 git 分支或标记 name 包含斜杠(/),则应使用特殊 string (_)指定 HTTP URL 中的标签(以避免与其他 URL paths 存在歧义)。对于 example,如果标签是foo/bar,则替换斜杠将导致以下标签:foo(_)bar。包含特殊 string (_)也可以应用于{application}参数。如果使用 command-line client(如 curl),请小心 URL 中的括号 - 您应该使用单引号('')将它们从 shell 中转义。

跳过 SSL 证书验证

通过将git.skipSslValidation property 设置为true(默认为false),可以禁用 configuration 服务器对 Git 服务器的 SSL 证书的验证。

spring:
  cloud:
    config:
      server:
        git:
          uri: https://example.com/my/repo
          skipSslValidation: true

设置 HTTP 连接超时

您可以配置 time 配置服务器等待获取 HTTP 连接的 time(以秒为单位)。使用git.timeout property。

spring:
  cloud:
    config:
      server:
        git:
          uri: https://example.com/my/repo
          timeout: 4

Git URI 中的占位符

Spring Cloud Config Server 支持 git repository URL,其中包含{application}{profile}的占位符(如果需要,则为{label},但请记住,标签仍然作为 git 标签应用)。因此,您可以通过使用类似于以下的结构来支持“one repository per application”policy:

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

您还可以通过使用类似的 pattern 但使用{profile}来支持“one repository per profile”policy。

此外,在{application}参数中使用特殊的 string“(_)”可以启用对多个组织的支持,如下面的示例所示:

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

其中{application}在请求 time 时以下列格式提供:organization(_)application

Pattern 匹配和多个 Repositories

Spring Cloud Config 还包括对 application 和 profile name 上的 pattern 匹配的更复杂需求的支持。 pattern 格式是带有通配符的{application}/{profile}名称的 comma-separated 列表(请注意,可能需要引用以通配符开头的 pattern),如下面的示例所示:

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”repository,pattern 是simple/*(它只匹配所有 profiles 中名为simple的一个 application)。 “local”repository 匹配所有 profiles 中以local开头的所有 application 名称(/*后缀自动添加到任何没有 profile 匹配器的 pattern)。

仅当要设置的唯一 property 是 URI 时,才能使用“简单”example 中使用的“one-liner”快捷方式。如果您需要设置其他任何内容(凭据,pattern 等),则需要使用完整表单。

repo 中的pattern property 实际上是一个 array,因此您可以使用 YAML array(或 properties files 中的[0][1]等后缀)绑定到多个模式。如果您打算使用多个 profiles 运行应用程序,则可能需要执行此操作,如下面的示例所示:

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 猜测包含 profile 但不以*结尾的 pattern 意味着您实际上想要_以_Ttern 开头的 profiles 列表(所以*/staging["*/staging", "*/staging,*"]的快捷方式,依此类推)。这是 common,例如,你需要在本地的“development”profile 中运行 applications,而远程使用“cloud”profile。

每个 repository 也可以选择在 sub-directories 中 store config files,并且搜索这些目录的模式可以指定为searchPaths。以下 example 显示顶部 level 的配置文件:

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

在前面的 example 中,服务器在 top level 和foo/ sub-directory 以及 name以bar开头的任何 sub-directory 中搜索 config files。

默认情况下,首次请求 configuration 时,服务器会克隆 remote repositories。可以将服务器配置为在启动时克隆 repositories,如下面的 top-level example 所示:

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

在前面的示例中,服务器在接受任何请求之前在启动时克隆 team-a 的 config-repo。在请求 repository 的 configuration 之前,不会克隆所有其他 repositories。

在 Config Server 启动时设置要克隆的 repository 可以帮助在 Config Server 启动时快速识别配置错误的 configuration 源(例如无效的 repository URI)。如果未启用 configuration 源,则配置服务器可能会使用配置错误或无效的 configuration 源成功启动,并且在 application 从该 configuration 源请求 configuration 之前不会检测到错误。

身份验证

要在 remote repository 上使用 HTTP 基本身份验证,请单独添加usernamepassword properties(不在 URL 中),如以下 example 所示:

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 也应该开箱即用。重要的是 Git 服务器的条目存在于~/.ssh/known_hosts文件中,并且它是ssh-rsa格式。不支持其他格式(例如ecdsa-sha2-nistp256)。为了避免意外,您应该确保 Git 服务器的known_hosts文件中只有一个条目,并且它与您提供给配置服务器的 URL 相匹配。如果您在 URL 中使用主机名,则希望在known_hosts文件中具有该主机名(而不是 IP)。使用 JGit 可以访问 repository,因此您在其上找到的任何文档都应该适用。可以使用 system properties(-Dhttps.proxyHost-Dhttps.proxyPort)在~/.git/config或(与任何其他 JVM process 相同的方式)中设置 HTTPS 代理设置。

如果您不知道~/.git目录的位置,请使用git config --global来操作设置(对于 example,git config --global http.sslVerify false)。

使用 AWS CodeCommit 进行身份验证

Spring Cloud Config Server 还支持AWS CodeCommit身份验证。从命令 line 使用 Git 时,AWS CodeCommit 使用身份验证帮助程序。此助手不与 JGit library 一起使用,因此如果 Git URI 与 AWS CodeCommit pattern 匹配,则会创建 AWS CodeCommit 的 JGit CredentialProvider。 AWS CodeCommit URI 遵循此 pattern://git-codecommit。$ {。 112} .amazonaws.com/ $ {。 113}。

如果您提供带有 AWS CodeCommit URI 的用户名和密码,则它们必须是AWS accessKeyId 和 secretAccessKey,以提供对 repository 的访问权限。如果未指定用户名和密码,则使用AWS 默认凭据提供商链检索 accessKeyId 和 secretAccessKey。

如果 Git URI 与 CodeCommit URI pattern(如前所示)匹配,则必须在用户名和密码或默认凭据提供程序链支持的某个位置提供有效的 AWS 凭据。 AWS EC2 实例可以使用IAM 对 EC2 实例的角色

aws-java-sdk-core jar 是可选的依赖项。如果aws-java-sdk-core jar 不在 classpath 上,则无论 git 服务器 URI 如何,都不会创建 AWS Code Commit 凭证提供程序。

使用 properties 创建 SSH configuration

默认情况下,当使用 SSH URI 连接到 Git repositories 时,Spring Cloud Config Server 使用的 JGit library 使用 SSH configuration files,例如~/.ssh/known_hosts/etc/ssh/ssh_config。在诸如 Cloud Foundry 之类的云环境中,本地文件系统可能是短暂的或不容易访问的。对于这些情况,可以使用 Java properties 设置 SSH configuration。在 order 中激活 property-based SSH configuration,spring.cloud.config.server.git.ignoreLocalSshSettings property 必须设置为true,如下面的 example 所示:

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-----

以下 table 描述了 SSH configuration properties。

表格 1_.SSH Configuration Properties

Property Name备注
**** ignoreLocalSshSettings如果是true,请使用 property-based 而不是 file-based SSH 配置。必须在 repository 定义中设置为spring.cloud.config.server.git.ignoreLocalSshSettings而不是
****专用密钥有效的 SSH 私有 key。如果ignoreLocalSshSettings是 true 且 Git URI 是 SSH 格式,则必须设置。
**** hostKey有效的 SSH host key。如果还设置了hostKeyAlgorithm,则必须设置。
**** hostKeyAlgorithmssh-dss, ssh-rsa, ecdsa-sha2-nistp256, ecdsa-sha2-nistp384, or ecdsa-sha2-nistp521之一。如果还设置了hostKey,则必须设置。
**** strictHostKeyCheckingtruefalse。如果 false,则忽略 host key 的错误。
**** knownHostsFile自定义.known_hosts文件的位置。
**** preferredAuthentications覆盖服务器身份验证方法 order。如果服务器在publickey方法之前具有 keyboard-interactive 身份验证,则应允许避免登录提示。

Git 中的占位符搜索 Paths

Spring Cloud Config Server 还支持带有{application}{profile}(以及{label},如果需要的话)的占位符的搜索路径,如下面的示例所示:

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

上面的清单导致在与目录相同的 name 中搜索 files 的 repository(以及 top level)。通配符在带占位符的搜索路径中也有效(搜索中包含任何匹配的目录)。

强制拉入 Git Repositories

如前所述,Spring Cloud Config Server 会复制 remote git repository 以防本地副本变脏(对于 example,文件夹内容由 OS process 更改),以便 Spring Cloud Config Server 无法从 remote repository 更新本地副本。

要解决此问题,如果本地副本是脏的,则有force-pull property 使 Spring Cloud Config Server 强制从 remote repository 拉出,如下面的示例所示:

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

如果您有 multiple-repositories configuration,则可以为__pository 配置force-pull property,如下面的示例所示:

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

force-pull property 的默认 value 是false

删除 Git Repositories 中未跟踪的分支

由于 Spring Cloud Config Server 在 check-outing 分支到本地 repo(按标签 e.g 获取 properties)之后有 remote git repository 的克隆,它将永久保留此分支或直到下一个服务器重新启动(这将创建新的本地 repo)。因此,可能存在删除 remote 分支但仍然可以获取它的本地副本的情况。如果 Spring Cloud Config Server client 服务以--spring.cloud.config.label=deletedRemoteBranch,master开头,它将从deletedRemoteBranch本地分支获取 properties,但不从master获取。

在 order 中保持本地 repository 分支清理并且最多 remote - 可以设置deleteUntrackedBranches property。它会使 Spring Cloud Config Server 强制从本地 repository 删除未跟踪的分支。 例:

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

deleteUntrackedBranches property 的默认 value 是false

Git 刷新率

您可以使用spring.cloud.config.server.git.refreshRate控制配置服务器从 Git 后端获取更新的 configuration 数据的频率。 property 的 value 以秒为单位指定。默认情况下,value 为 0,这意味着配置服务器将在每次请求时从 Git repo 获取更新的 configuration。

5.1.2 Version 控制后端文件系统使用

使用 VCS-based 后端(git,svn),files 被签出或克隆到本地文件系统。默认情况下,它们放在系统临时目录中,前缀为config-repo-。在 linux 上,对于 example,它可能是/tmp/config-repo-<randomid>。一些操作系统经常清理临时目录。这可能会导致意外行为,例如缺少 properties。要避免此问题,请通过将spring.cloud.config.server.git.basedirspring.cloud.config.server.svn.basedir设置为不驻留在系统临时结构中的目录来更改 Config Server 使用的目录。

5.1.3 文件系统后端

Config Server 中还有一个“native”profile,它不使用 Git,而是从本地 classpath 或文件系统加载 config files(任何要用spring.cloud.config.server.native.searchLocations指向的静态 URL)。要使用本机 profile,请使用spring.profiles.active=native启动配置服务器。

请记住使用file:前缀作为文件资源(没有前缀的默认值通常是 classpath)。与任何 Spring Boot configuration 一样,您可以嵌入${} -style 环境占位符,但请记住 Windows 中的绝对_path 需要额外的/(对于 example,file:///${user.home}/config-repo)。

searchLocations的默认 value 与本地 Spring Boot application(即[classpath:/, classpath:/config, file:./, file:./config])相同。这不会将application.properties从服务器暴露给所有 clients,因为服务器中存在的任何 property 源在被发送到 client 之前都会被删除。

文件系统后端非常适合快速入门和测试。要在 production 中使用它,您需要确保文件系统可靠并在 Config Server 的所有实例之间共享。

搜索位置可以包含{application}{profile}{label}的占位符。通过这种方式,您可以隔离路径中的目录并选择对您有意义的策略(例如每个 application 的子目录或每个 profile 的子目录)。

如果您不在搜索位置使用占位符,则此 repository 还会将 HTTP 资源的{label}参数附加到搜索路径上的后缀,因此 properties files 将从每个搜索位置具有相同 name 的子目录中加载作为标签(标记的 properties 在 Spring 环境中优先)。因此,没有占位符的默认行为与添加以/{label}/结尾的搜索位置相同。例如,file:/tmp/configfile:/tmp/config,file:/tmp/config/{label}相同。可以通过设置spring.cloud.config.server.native.addLabelLocations=false来禁用此行为。

5.1.4 Vault 后端

Spring Cloud Config Server 还支持Vault作为后端。


Vault 是一种安全访问机密的工具。 secret 是您要严格控制访问的任何内容,例如 API 密钥,密码,证书和其他敏感信息。 Vault 为任何 secret 提供统一的接口,同时提供严格的访问控制和记录详细的审计 log。


有关 Vault 的更多信息,请参阅Vault 快速入门指南

要使配置服务器能够使用 Vault 后端,您可以使用vault profile 运行配置服务器。例如,在配置服务器的application.properties中,您可以添加spring.profiles.active=vault

默认情况下,配置服务器假定 Vault 服务器在http://127.0.0.1:8200运行。它还假定后端的 name 是secret而 key 是application。所有这些默认值都可以在配置服务器的application.properties中配置。以下 table 描述了可配置的 Vault properties:

名称默认值
主办127.0.0.1
港口8200
方案HTTP
后端秘密
defaultKey应用
profileSeparator,
kvVersion1
skipSslValidation
超时5

前面 table 中的所有 properties 都必须以spring.cloud.config.server.vault为前缀。

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

Vault 0.10.0 引入了一个版本化的 key-value 后端(k/v 后端 version 2),它暴露了与早期版本不同的 API,它现在需要在挂载路径和实际的 context 路径之间使用data/并在data object 中包装秘密。设置kvVersion=2将考虑到这一点。

使用配置服务器 running,您可以向服务器发出 HTTP 请求以从 Vault 后端检索值。为此,您需要为 Vault 服务器提供令牌。

首先,在您的 Vault 中放置一些数据,如下面的示例所示:

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

其次,向配置服务器发出 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"
         }
      }
   ]
}

多个 Properties 来源

使用 Vault 时,您可以为 applications 提供多个 properties 源。对于 example,假设您已将数据写入 Vault 中的以下_path:

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

写入secret/application的 Properties 可用于使用 Config Server 的所有 applications。带 name,myApp的 application 将有和secret/application可用的任何 properties。当myApp启用dev profile 时,写入所有上述_path 的 properties 将可用,其中列表中第一个路径中的 properties 优先于其他路径。

5.1.5 通过代理访问后端

configuration 服务器可以通过 HTTP 或 HTTPS 代理访问 Git 或 Vault 后端。通过proxy.httpproxy.https下的设置可以控制 Git 或 Vault 的此行为。这些设置是 repository,因此如果您使用复合环境 repository,则必须单独为复合中的每个后端配置代理设置。如果使用需要单独的代理服务器用于 HTTP 和 HTTPS URL 的网络,则可以为单个后端配置 HTTP 和 HTTPS 代理设置。

以下 table 描述了 HTTP 和 HTTPS 代理的 proxy configuration properties。所有这些 properties 必须以proxy.httpproxy.https为前缀。

表格 1_.代理 Configuration Properties

Property Name备注
主办代理的 host。
港口用于访问代理的 port。
**** nonProxyHostsconfiguration 服务器应在代理外部访问的任何主机。如果为proxy.http.nonProxyHostsproxy.https.nonProxyHosts都提供了值,则将使用proxy.http value。
用户名用于向代理进行身份验证的用户名。如果为proxy.http.usernameproxy.https.username都提供了值,则将使用proxy.http value。
密码用于向代理进行身份验证的密码。如果为proxy.http.passwordproxy.https.password都提供了值,则将使用proxy.http value。

以下 configuration 使用 HTTPS 代理访问 Git repository。

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

5.1.6 与所有 Applications 共享 Configuration

所有 applications 之间的共享 configuration 根据您采用的方法而有所不同,如以下主题中所述:

基于文件的存储库

使用 file-based(git,svn 和 native)repositories,application*(application.propertiesapplication.ymlapplication-*.properties等文件名)的资源在所有 client applications 之间共享。您可以使用具有这些文件名的资源来配置 global 默认值,并根据需要将它们覆盖 application-specific files。

#property_overrides [243] feature 也可用于设置 global 默认值,允许占位符 applications 在本地覆盖它们。

使用“native”profile(本地文件系统后端),您应该使用不属于服务器自己的 configuration 的显式搜索位置。否则,默认搜索位置中的application*资源将被删除,因为它们是服务器的一部分。

Vault 服务器

使用 Vault 作为后端时,可以通过在secret/application中放置 configuration 来与所有 applications 共享 configuration。例如,如果您运行以下 Vault 命令,则使用配置服务器的所有 applications 将为它们提供 properties foobaz

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

5.1.7 JDBC 后端

Spring Cloud Config Server 支持 JDBC(关系数据库)作为 configuration properties 的后端。您可以通过将spring-jdbc添加到 classpath 并使用jdbc profile 或添加类型的 bean 来启用此 feature。如果在 classpath 中包含正确的依赖项(有关详细信息,请参阅用户指南), Spring Boot 配置数据源。

数据库需要有一个名为PROPERTIES的 table,其列名为APPLICATIONPROFILELABEL(通常为Environment含义),加KEYVALUE表示Properties样式中的 key 和 value 对。所有字段都是 Java 中的 String 类型,因此您可以将它们设置为所需长度的VARCHAR。 Property 值的行为方式与它们来自 Spring Boot properties files 命名为{application}-{profile}.properties的方式相同,包括所有加密和解密,它们将作为 post-processing 步骤应用(即不直接在 repository implementation 中)。

5.1.8 复合环境存储库

在某些情况下,您可能希望从多个环境 repositories 中提取 configuration 数据。为此,您可以在 configuration 服务器的 application properties 或 YAML 文件中启用composite profile。例如,如果要从 Subversion repository 以及两个 Git repositories 中提取 configuration 数据,则可以为 configuration 服务器设置以下 properties:

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

使用此 configuration,优先级由 order 存储在composite key 下的 order 确定。在上面的示例中,首先列出 Subversion repository,因此在 Subversion repository 中找到的 value 将覆盖在 Git repositories 之一中为相同 property 找到的值。在为walter Git repository 中的同一 property 找到 value 之前,将使用rex Git repository 中找到的 value。

如果只想从每个不同类型的 reposit 中提取 configuration 数据,可以在 configuration 服务器的 application properties 或 YAML 文件中启用相应的 profiles,而不是composite profile。例如,如果要从单个 Git repository 和单个 HashiCorp Vault 服务器提取 configuration 数据,则可以为 configuration 服务器设置以下 properties:

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

使用此 configuration,优先级可以由order property 确定。您可以使用order property 为所有 repositories 指定优先级 order。 order property 的数值值越低,它的优先级越高。 repository 的 priority order 有助于解决包含相同 properties 值的 repositories 之间的任何潜在冲突。

如果复合环境包含 Vault 服务器,如上一个 example,则必须在对 configuration 服务器发出的每个请求中包含 Vault 令牌。见Vault 后端

从环境 repository 检索值时的任何类型的失败都会导致整个复合环境失败。

使用复合环境时,所有 repositories 都必须包含相同的标签。如果您的环境与前面示例中的环境类似,并且您使用master标签请求 configuration 数据但 Subversion repository 不包含名为master的分支,则整个请求将失败。

自定义复合环境存储库

除了使用 Spring Cloud 中的一个环境 repositories 之外,您还可以提供自己的EnvironmentRepository bean 作为复合环境的一部分。为此,您的 bean 必须实现EnvironmentRepository接口。如果要在复合环境中控制自定义EnvironmentRepository的优先级,还应实现Ordered接口并覆盖getOrdered方法。如果未实现Ordered接口,则EnvironmentRepository的优先级最低。

5.1.9 Property 覆盖

Config Server 具有“覆盖”feature,允许 operator 为所有 applications 提供 configuration properties。使用普通 Spring Boot 挂钩的 application 不会意外更改被覆盖的 properties。要声明覆盖,请将 name-value 对的 map 添加到spring.cloud.config.server.overrides,如以下 example 所示:

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

前面的示例使得所有 applications 是 config clients 读取foo=bar,与其自己的 configuration 无关。

configuration 系统不能强制 application 以任何特定方式使用 configuration 数据。因此,覆盖是不可执行的。但是,它们确实为 Spring Cloud Config clients 提供了有用的默认行为。

通常,带有${}的 Spring 环境占位符可以使用反斜杠(\)转义(并在 client 上解析)以转义${。对于 example,\${app.foo:bar}解析为bar,除非应用程序提供自己的app.foo

在 YAML 中,您不需要逃避反斜杠本身。但是,在 properties files 中,在服务器上配置替代时,需要转义反斜杠。

您可以通过在 remote repository 中设置spring.cloud.config.overrideNone=true flag(默认值为 false),将 client 中所有覆盖的优先级更改为更像默认值,让 applications 在环境变量或 System properties 中提供自己的值。

5.2 健康指标

Config Server 附带一个运行状况指示器,用于检查配置的EnvironmentRepository是否正常工作。默认情况下,它会向EnvironmentRepository请求名为app的 application,default __ofile 以及EnvironmentRepository implementation 提供的默认标签。

您可以配置运行状况指示器以检查更多 applications 以及自定义 profiles 和自定义标签,如以下 example 所示:

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

您可以通过设置spring.cloud.config.server.health.enabled=false来禁用健康指标。

5.3 安全

您可以以对您有意义的任何方式保护您的配置服务器(从物理网络安全到 OAuth2 承载令牌),因为 Spring Security 和 Spring Boot 为许多安全安排提供支持。

要使用默认的 Spring Boot-configured HTTP Basic 安全性,请在 classpath 上包含 Spring Security(对于 example,通过spring-boot-starter-security)。默认值为user的用户名和随机生成的密码。随机密码在实践中没有用,因此我们建议您配置密码(通过设置spring.security.user.password)并对其进行加密(有关如何执行此操作的说明,请参阅下文)。

5.4 加密和解密

要使用加密和解密 features,您需要在 JVM 中安装 full-strength JCE(默认情况下不包括它)。您可以从 Oracle 下载“Java Cryptography Extension(JCE)Unlimited Strength Jurisdiction Policy Files”并遵循安装说明(实质上,您需要将 JRE lib/security 目录中的两个 policy files 替换为您下载的那些_filefiles)。

如果 remote property 源包含加密内容(以{cipher}开头的值),则在通过 HTTP 发送到 clients 之前对它们进行解密。这种设置的主要优点是 property 值在“atrest”时不需要是纯文本(对于 example,在 git repository 中)。如果无法解密 value,则会从 property 源中删除它,并添加一个额外的 property,其中包含相同的 key,但前缀为invalid和 value,表示“不适用”(通常为<n/a>)。这主要是为了防止密文被用作密码并意外泄露。

如果为 config client applications 设置 remote config repository,它可能包含类似于以下内容的application.yml

application.yml.

spring:
  datasource:
    username: dbuser
    password: '{cipher}FKSAJDFGYOS8F7GLHAKERGFHLSAJ'

.properties 文件中的加密值不得用引号括起来。否则,value 不会被解密。以下 example 显示了可行的值:

application.properties.

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

您可以安全地将此纯文本推送到共享的 git repository,并且 secret 密码仍然受到保护。

服务器还公开/encrypt/decrypt endpoints(假设这些是安全的并且只能由授权代理访问)。如果编辑 remote 配置文件,则可以使用配置服务器通过 POST 到/encrypt端点来加密值,如下面的示例所示:

$ curl localhost:8888/encrypt -d mysecret
682bc583f4641835fa2db009355293665d2647dade3375c0ee201de2a49f7bda

如果您加密的 value 中包含需要进行 URL 编码的字符,则应使用--data-urlencode选项curl以确保它们已正确编码。

请确保不要在加密的 value 中包含任何 curl 命令统计信息。将 value 输出到文件可以帮助避免此问题。

反向操作也可通过/decrypt(如果服务器配置了对称 key 或完整的 key 对),如下面的示例所示:

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

如果使用 curl 进行测试,则使用--data-urlencode(而不是-d)或设置显式Content-Type: text/plain以确保在有特殊字符时(''特别棘手)curl 正确编码数据。

获取加密的 value 并添加{cipher}前缀,然后再将其放入 YAML 或 properties 文件中,然后再提交并将其推送到 remote(可能不安全)store。

/encrypt/decrypt endpoints 也都接受/*/{name}/{profiles}形式的_path,当 clients 调用主环境资源时,它可用于控制 per-application(name)和 per-profile 基础上的加密。

要以这种精细的方式控制加密,您还必须提供@Bean类型TextEncryptorLocator,它为每个 name 和 profiles 创建不同的加密器。默认情况下提供的那个不会这样做(所有加密都使用相同的 key)。

spring命令 line client(安装了 Spring Cloud CLI extensions)也可用于加密和解密,如下例所示 example:

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

要在文件中使用 key(例如用于加密的 RSA public key),请在_ @ 前面添加“@”并提供文件路径,如下面的示例所示:

$ spring encrypt mysecret --key @${HOME}/.ssh/id_rsa.pub
AQAjPgt3eFZQXwt8tsHAVv/QHiY5sI2dRcR+...

--key参数是必需的(尽管有一个--前缀)。

5.5 Key Management

Config Server 可以使用对称(共享)key 或非对称 key(RSA key 对)。非对称选择在安全性方面更优越,但使用对称 key 通常更方便,因为它是在bootstrap.properties中配置的单个 property value。

要配置对称 key,需要将encrypt.key设置为 secret String(或使用ENCRYPT_KEY环境变量使其远离 plain-text configuration files)。

要配置非对称 key,可以将 key 设置为 PEM-encoded text value(在encrypt.key中)或使用密钥库(例如由 JDK 附带的keytool实用程序创建的密钥库)。以下 table 描述了密钥库 properties:

属性描述
encrypt.keyStore.location包含Resource位置
encrypt.keyStore.password保存解锁密钥库的密码
encrypt.keyStore.alias标识要使用的 store 中的 key

加密是使用 public key 完成的,解密时需要私有 key。因此,原则上,如果只想加密(并准备使用 private key 在本地解密值),则只能在服务器中配置 public key。实际上,您可能不希望在本地进行解密,因为它会围绕所有 clients 传播 key management process,而不是将其集中在服务器中。另一方面,如果您的配置服务器相对不安全且只有少数客户端需要加密的 properties,它可能是一个有用的选项。

5.6 创建一个 Key Store 进行测试

要创建用于测试的密钥库,可以使用类似于以下内容的命令:

$ 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

server.jks文件放在 classpath(例如)中,然后在bootstrap.yml中为 Config Server 放置,创建以下设置:

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

5.7 使用多个键和 Key 旋转

除了加密的 property 值中的{cipher}前缀之外,Config Server 还会在(Base64 编码的)密码文本开始之前查找零个或多个{name:value}前缀。密钥传递给TextEncryptorLocator,它可以执行为密码定位TextEncryptor所需的任何逻辑。如果已配置密钥库(encrypt.keystore.location),则默认定位器将查找具有key前缀提供的别名的密钥,其密码文本类似于以下内容:

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

定位器查找名为“testkey”的 key。也可以通过在前缀中使用{secret:…} value 来提供 secret。但是,如果未提供,则默认使用密钥库密码(这是您在构建密钥库时未获得 secret 的密码)。如果你提供了 secret,你还应该使用自定义SecretLocator加密 secret。

当密钥仅用于加密几个字节的 configuration 数据时(也就是说,它们没有在别处使用),在密码学习的基础上几乎不需要 key 轮换。但是,您可能偶尔需要更改密钥(对于 example,在安全漏洞的 event 中)。在这种情况下,所有 clients 都需要更改其源配置 files(对于 example,在 git 中)并在所有密码中使用新的{key:…}前缀。请注意,客户端需要首先检查配置服务器密钥库中是否有 key 别名。

如果您想让 Config Server 处理所有加密和解密,也可以将{name:value}前缀添加为发布到/encrypt端点的纯文本,。

5.8 提供加密 Properties

有时您希望 clients 在本地解密 configuration,而不是在服务器中执行此操作。在这种情况下,如果您提供encrypt.* configuration 来查找 key,您仍然可以拥有/encrypt/decrypt endpoints,但是您需要通过在bootstrap.[yml|properties]中放置spring.cloud.config.server.encrypt.enabled=false来显式关闭传出 properties 的解密。如果您不关心 endpoints,那么如果您不配置 key 或启用 flag,它应该可以工作。