Git 后端
Git 后端
EnvironmentRepository
的默认实现使用 Git 作为后端,这对于管理升级和物理环境以及审计变更非常方便。要更改存储库的位置,你可以在 Config Server 中设置 spring.cloud.config.server.git.uri
配置属性(例如在 application.yml
中)。如果你使用 file:
前缀设置它,它应该可以从本地存储库中工作,这样你就可以快速轻松地开始,而不需要服务器。然而,在这种情况下,服务器直接操作本地存储库而不克隆它(即使它不是裸存储库也没关系,因为 Config Server 永远不会对“远程”存储库进行更改)。为了扩展 Config Server 并使其具有高可用性,你需要让所有服务器实例指向同一个存储库,因此只有共享文件系统才能工作。即使在这种情况下,最好使用 ssh:
协议来处理共享文件系统存储库,以便服务器可以克隆它并使用本地工作副本作为缓存。
此仓库的实现将 HTTP 资源的 {label}
参数映射到 git 标签(提交 ID、分支名称或标签)。如果 git 分支或标签名称包含斜杠 (/
),则 HTTP URL 中的标签应使用特殊字符串 ({special-string})
来指定(以避免与其他 URL 路径产生歧义)。例如,如果标签是 foo/bar
,替换斜杠后将得到以下标签:foo({special-string})bar
。特殊字符串 ({special-string})
的包含也可以应用于 {application}
参数。如果你使用诸如 curl 的命令行客户端,请注意 URL 中的括号——你应该使用单引号('')对它们进行转义。
跳过 SSL 证书验证
可以通过将 git.skipSslValidation
属性设置为 true
来禁用配置服务器对 Git 服务器的 SSL 证书验证(默认值为 false
)。
spring:
cloud:
config:
server:
git:
uri: https://example.com/my/repo
skipSslValidation: true
设置连接超时
你可以配置配置服务器等待获取 HTTP 或 SSH 连接的时间(以秒为单位)。使用 git.timeout
属性(默认值为 5
)。
spring:
cloud:
config:
server:
git:
uri: https://example.com/my/repo
timeout: 4
Git URI 中的占位符
Spring Cloud Config Server 支持带有占位符的 git 仓库 URL,这些占位符包括 {application}
和 {profile}
(如果需要,还可以包括 {label}
,但请记住,{label}
最终还是作为 git 标签应用)。因此,您可以通过使用类似于以下的结构来支持“每个应用程序一个仓库”的策略:
spring:
cloud:
config:
server:
git:
uri: https://github.com/myorg/{application}
你也可以通过使用类似的模式来支持“每个配置文件一个仓库”的策略,但使用 {profile}
。
此外,在 {application}
参数中使用特殊字符串 "({special-string})" 可以启用对多个组织的支持,如下例所示:
spring:
cloud:
config:
server:
git:
uri: https://github.com/{application}
其中 {application}
在请求时以以下格式提供:organization({special-string})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 的情况。如果需要设置其他内容(如凭证、模式等),则需要使用完整形式。
repo
中的 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 Server 启动时设置要克隆的仓库可以帮助快速识别配置错误的配置源(例如无效的仓库 URI)。如果没有为配置源启用 cloneOnStart
,Config Server 可能会在配置源配置错误或无效的情况下成功启动,并且直到应用程序从该配置源请求配置时才会检测到错误。
认证
要在远程仓库上使用 HTTP 基本身份验证,请分别添加 username
和 password
属性(不要在 URL 中),如下例所示:
spring:
cloud:
config:
server:
git:
uri: https://github.com/spring-cloud-samples/config-repo
username: trolley
password: strongpassword
如果不使用 HTTPS 和用户凭证,当您将密钥存储在默认目录(~/.ssh
)中且 URI 指向 SSH 位置(例如 git@github.com:configuration/cloud-configuration
)时,SSH 也应该可以直接使用。重要的是,Git 服务器的条目必须存在于 ~/.ssh/known_hosts
文件中,并且格式为 ssh-rsa
。不支持其他格式(例如 ecdsa-sha2-nistp256
)。为了避免意外情况,您应确保 known_hosts
文件中只有一个与 Git 服务器对应的条目,并且该条目与您提供给配置服务器的 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 要求 RSA 密钥采用 PEM 格式。以下是一个 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 Server 也支持 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 实例可以使用 IAM Roles for EC2 Instances。
software.amazon.awssdk:auth
jar 是一个可选的依赖项。如果 software.amazon.awssdk:auth
jar 不在你的 classpath 中,无论 git 服务器的 URI 是什么,AWS Code Commit 凭证提供者都不会被创建。
使用 Google Cloud Source 进行身份验证
Spring Cloud Config Server 还支持对 Google Cloud Source 仓库进行身份验证。
如果你的 Git URI 使用 http
或 https
协议,并且域名是 source.developers.google.com
,则将使用 Google Cloud Source 凭据提供程序。Google Cloud Source 仓库 URI 的格式为 [source.developers.google.com/p/$\{GCP\_PROJECT}/r/$\{REPO}](https://source.developers.google.com/p/${GCP_PROJECT}/r/${REPO})
。要获取你的仓库 URI,请在 Google Cloud Source UI 中点击“Clone”,然后选择“Manually generated credentials”。不要生成任何凭据,只需复制显示的 URI。
Google Cloud Source 凭据提供者将使用 Google Cloud Platform 的应用程序默认凭据。有关如何为系统创建应用程序默认凭据,请参阅 Google Cloud SDK 文档。这种方法适用于开发环境中的用户账户以及生产环境中的服务账户。
com.google.auth:google-auth-library-oauth2-http
是一个可选的依赖项。如果 google-auth-library-oauth2-http
jar 不在你的 classpath 中,无论 git 服务器的 URI 是什么,Google Cloud Source 凭证提供者都不会被创建。
使用属性配置 Git SSH
默认情况下,Spring Cloud Config Server 使用的 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: git@gitserver.com: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 | true 或 false 。如果为 false,则忽略主机密钥错误。 |
knownHostsFile | 自定义 .known_hosts 文件的位置。 |
preferredAuthentications | 覆盖服务器认证方法的顺序。如果服务器在 publickey 方法之前有键盘交互式认证,这应该允许避免登录提示。 |
Git 搜索路径中的占位符
Spring Cloud Config Server 还支持带有占位符的搜索路径,用于 {application}
和 {profile}
(如果需要的话,还可以使用 {label}
),如下例所示:
spring:
cloud:
config:
server:
git:
uri: https://github.com/spring-cloud-samples/config-repo
search-paths: '{application}'
前面的列表会导致在存储库中搜索与目录同名的文件(以及顶层文件)。在搜索路径中使用通配符也是有效的,可以使用占位符(任何匹配的目录都会被包含在搜索中)。
强制拉取 Git 仓库
如前所述,Spring Cloud Config Server 会克隆远程 git 仓库,以防本地副本变脏(例如,文件夹内容被操作系统进程更改),这样 Spring Cloud Config Server 就无法从远程仓库更新本地副本。
为了解决这个问题,有一个 force-pull
属性,它使得 Spring Cloud Config Server 在本地副本不干净时强制从远程仓库拉取,如下例所示:
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 Server 在检出分支到本地仓库后(例如通过标签获取属性),它会永久保留这个分支,直到下次服务器重启(这将创建一个新的本地仓库)。因此,可能会出现远程分支被删除但本地副本仍然可用于获取的情况。如果 Spring Cloud Config Server 客户端服务以 --spring.cloud.config.label=deletedRemoteBranch,master
启动,它将从 deletedRemoteBranch
本地分支获取属性,而不是从 master
分支。
为了保持本地仓库分支的干净并与远程同步,可以设置 deleteUntrackedBranches
属性。这将使 Spring Cloud Config Server 强制删除本地仓库中未跟踪的分支。示例:
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
来控制配置服务器从 Git 后端获取更新配置数据的频率。该属性的值以秒为单位指定。默认值为 0,意味着配置服务器每次请求时都会从 Git 仓库获取更新的配置。如果该值为负数,则不会进行刷新。
默认标签
Git 使用的默认标签是 main
。如果你没有设置 spring.cloud.config.server.git.defaultLabel
并且不存在名为 main
的分支,配置服务器默认也会尝试检出名为 master
的分支。如果你想禁用这种回退分支的行为,可以将 spring.cloud.config.server.git.tryMasterBranch
设置为 false
。
在容器中使用 Git 运行配置服务器
如果你在运行 Config Server 的容器中遇到类似于以下的 java.io.IOException
:
2022-01-03 20:04:02,892 [tributeWriter-2] ERROR org.eclipse.jgit.util.FS$FileStoreAttributes.saveToConfig - Cannot save config file 'FileBasedConfig[/.config/jgit/config]'
java.io.IOException: Creating directories for /.config/jgit failed
你必须执行以下操作之一:
-
为用户提供一个在容器内可写的家目录。
-
在容器内设置环境变量
XDG_CONFIG_HOME
,使其指向一个 Java 进程具有写权限的目录。