从 EC2 访问私有 RDS:同一 VPC、peering 还是别的办法?
先选路由再选安全组:同一 VPC、peering、共享 VPC 或私有互连。
开发者的笔记本电脑通过员工 VPN 访问私有 RDS 实例,而 EC2 上的应用却完全连不上。这不是部署坏了。笔记本电脑有一条隧道,而 EC2 实例从不继承它;RDS 中的「私有」只是说数据库没有公网端点,并不是说只有人类 VPN 用户才被允许访问。应用需要自己获得授权的路径、自己与安全组的关系,以及自己的数据库身份,先决定这三样的顺序能省下大部分排查时间。先定路由,再定权限,最后从已部署的环境而不是从你的桌面去验证。
笔记本 VPN 不是应用的路径
无论员工 VPN 为人们做了什么,它对实例都不起作用,除非该实例明确属于同一条网络路径。私有子网中的 EC2 实例通过 VPC 路由、安全组和网络 ACL 访问 RDS。它不会、也不应该继承人的隧道、会话或凭据:无人值守的应用连接和员工的远程访问必须能各自独立运行。
这种独立是优点。VPN 故障时,应用照常工作;应用出问题时,没人会失去远程访问。把两者合并成一条路径的设计,往往会在事故中、在最糟糕的时刻暴露出来。
决定 1:同一 VPC,直连路径
当应用与数据库位于同一 VPC、直接路由且中间没有检查设备时,路径很简单,安全组引用就是可用的最强工具。给应用单独的安全组,然后允许来自该组的数据库端口,而不是来自某个地址段:
aws ec2 authorize-security-group-ingress --group-id sg-0db123 --protocol tcp --port 5432 --source-group sg-0app456
aws rds describe-db-instances --db-instance-identifier prod-db --query 'DBInstances[0].{Endpoint:Endpoint.Address,Port:Endpoint.Port,Public:PubliclyAccessible,Groups:VpcSecurityGroups}'
端口只是示例,必须与引擎匹配。组引用授权来自应用实例的流量,它不会复制这些实例的规则,也不会创建数据库登录。两个独立问题,两项独立修复。
然后检查路径的其余部分,而不是停在你刚添加的规则上。应用的出站策略、数据库挂载的全部安全组、子网路由表以及任何网络 ACL 都必须一致。安全组规则是有状态的,而自定义网络 ACL 必须在单独的规则中同时允许请求和返回流量,包括临时端口。一条新的窄数据库规则也不会取消之前已挂载的宽泛放行。
决定 2:不同 VPC 或不同账号
如果应用在另一个 VPC,网络所有者会选择受支持的私有互连:peering、中转设计或共享 VPC 方案。此时两个方向的路由都必须存在,名称解析必须对 RDS 端点有效,数据库策略评估的源必须与实际到达的源一致。账号名相同或共享账单关系,这些一个都提供不了。
安全组引用是会变化的部分。它在多种私有互连设计中可用,但一旦中间设备改写源或终止连接,它就会失效,因为数据库看到的是中间设备而不是你的应用组。RDS VPC 场景把同一 VPC 内访问与其他安排区分开来,在假设某种规则风格可以照搬之前,值得拿你的具体拓扑与它们对照。
不要通过让数据库可公网访问来解决缺少路由的问题。那是另一个所有者做出的另一种暴露决定,而且通常由离后果最远的人提出。
决定 3:数据库接受什么身份
网络访问和数据库认证是两层,混为一谈会产生最具误导性的错误。实例角色是用于调用 AWS API 的 AWS 身份,它不是数据库用户。IAM 数据库认证在引擎和配置允许时是受支持的功能,但它仍然映射到数据库用户,而不是替代数据库用户。
在应用配置中使用 RDS 端点名称,而不是某次查询捕获的地址。Multi-AZ 故障转移会改变该名称背后的地址,写死 IP 的应用会在最需要它的那一刻失败。保持引擎的 TLS 校验开启,而不是为了消除错误就关掉它,因为校验失败在告诉你所到达端点的一些信息。
然后只授予数据库账号应用实际所需的最小权限,并且落在它真正使用的 schema 上。这项工作枯燥、可审计,也正是事故复盘会问到的部分。
从已部署的环境验证
从实例上或从以相同组、子网和角色运行的任务中测试。四种故障从笔记本上看很像,而在这里很容易区分:名称无法解析、连接超时、TLS 校验失败、数据库登录被拒。它们各指向不同的边界,在还不知道是哪一种之前就改数据库的暴露范围,只能算猜。
psql "host=prod-db.abc123.eu-west-1.rds.amazonaws.com port=5432 dbname=app sslmode=verify-full" -c 'select 1'
如果从实例能连上而从你的桌面连不上,应用的路径没问题,要修的是你的访问。如果两边都连不上,先做上面的组和路由检查,而不是先改凭据。就这一项对比,就能避免这类工单制造的大部分折腾。