双子星生成的图像
你想让你的应用程序访问一个数据库,这有多难呢?
如果同一个服务提供商同时托管了你的应用程序和数据库,并且它们都使用该提供商的身份,而且它们连接到同一个网络上,同一个账户同时拥有它们,而你拥有该账户,那么这可能比较简单。这些因素中的差异越大,情况可能就越复杂。
通常应用程序需要三种信息——3个"C"——才能访问后端服务:
- 坐标:网络详情,如 IP 地址或 DNS 名称,协议,和端口(如果端口不是众所周知的(如 此处 所列)),或者服务发现的详情,例如账号、区域和资源
- 凭据:身份证明
- 配置:其他参数,比如数据库名称或 pubsub 话题
通常需要手动将这些信息从服务复制到应用配置,如环境变量,不过处理凭证通常要复杂得多,我在关于机密的文章中详细描述过。
许多平台提供了一种自动注入信息的功能,类似地,如Kubernetes服务环境变量。
- Heroku 附加组件
- Cloud Foundry 和 Open Service Broker(环境变量(VCAP-SERVICES))
- Crossplane 连接配置
- Radius 连接
- Nitric 连接助手函数
例如,在 Heroku 中,连接详情注入到环境变量中,例如 HEROKU_POSTGRESQL_RED_URL 这样的。
使用基础设施即代码(IaC)时,一般来说,这些属性通常会被定义为输出变量,然后通过远程状态数据或参数存储(由于影响范围的考虑)在输入变量定义中引用,用于应用程序配置。因为出于影响范围的考虑,这些配置应当放在单独的模块里。这些变量会被用来生成环境变量的值。
一个完整的 Terraform 示例会比较长一些,但输出定义大致如下:
output "instance_address" {
value = module.rds_instance.instance_address
description = "实例地址 (Instance Address)"
} // 实例地址
在没有定义输入变量时,引用远程状态会像这样:
资源定义 "aws_ecs_task_definition" "my_task" {
...
容器定义 = jsonencode([
{
...
环境变量 = [
{
变量名 = "DB_ADDRESS"
变量值 = data.terraform_remote_state.rds.outputs.instance_address
},
...
那对于如此常见的情况来说,这种做法相当高级,特别是对于那些可能不是IaC和基础设施API专家的应用程序开发人员来说。与通常需要的处理密钥的操作相比,这已经算简单了。特别是如果它还涉及到像Terraform和Helm这样的配置工具时,情况会更加复杂。
我还没见过这种信息自动写回Git以促进GitOps的示例,这可能是个好事。这更适合放在服务发现系统里。在Kubernetes早期,我们希望用户能用Kubernetes Services来实现这一点,为此添加了诸如[ExternalName](https://kubernetes.io/docs/concepts/services-networking/service/#externalname)
这样的功能。但是,DNS名称或IP地址需要以某种方式写入Service或EndpointSlice中,而现在还没有开箱即用的方法来实现。
正如你可能已经经历过的,相对于上述提到的平台,在IaC和Kubernetes中配置服务访问更加手动和复杂。依赖人工编写的事实来源相当有限。
除了应用中注入的信息之外,还需要解决两个额外的C项(问题),以访问服务。
- 许可:授权
- 网络连接性:包括出站和入站网络,防火墙,允许的IP范围等。
当通过自助服务机制(如模板目录)提供配置或当服务由其他角色或团队拥有时,通常需要授权给应用程序访问该服务所使用的身份。
此外,可能还需要配置网络访问,比如通过 AWS 安全组,这取决于服务和需要访问该服务的应用程序之间的相对位置关系。在 CloudFormation 中,这可能如下所示:
"Properties": {
"GroupDescription": "允许访问 RDS PostgreSQL",
"SecurityGroupIngress": [
{
"CidrIp": "0.0.0.0/0",
"FromPort": 5432,
"IpProtocol": "tcp",
"ToPort": 5432
}
],
"VpcId": { "Ref": "VPCId" }
},
这两种访问配置都可以自动化,但在实际操作中,使用基础设施即代码时,通常不会将这些配置自动化。最好的情况下,你可能会找到一个现成的模板或模块,足够接近你的需求,也不会太复杂。
连接到服务可以像在Heroku一样简单。但是,我们需要改变手动配置这些细节的想法。
你觉得配置服务访问有时是不是很困难,或者可能过于繁琐?你觉得哪一部分最难处理?是否对接各种服务(比如生产环境和服务开发环境中的服务)感到复杂?你是否更希望有一种自动化的方式来处理?你是否希望这里有一个事实上的标准?
随时可以在这里回复,或者在我的 LinkedIn、X/Twitter 或 Bluesky 上给我发消息,我打算在这几个平台上分享这条信息。
如果你觉得这很有趣,,你可能会对我的《基础设施即代码和声明式配置系列文章》中的其他帖子感兴趣。在我的Infrastructure as Code and Declarative Configuration系列中可以找到更多相关内容。