从AWS

时间:2016-10-27 05:52:38

标签: postgresql kubernetes amazon-rds

我的Kubernetes集群设置具有在AWS上的开发和测试环境中运行的n层Web应用程序。对于生产环境,选择了postgres RDS,以确保定期备份。在创建postgres RDS实例时,为db-subnet选择了kubernetes-vpc,以便在试运行期间保持网络简单。 此外,选择的安全组与kubernetes-minions相同。

以下是服务和端点yaml:

apiVersion: v1
kind: Service
metadata: 
  labels: 
    name: pgsql-rds
  name: pgsql-rds
spec: 
  ports: 
    - port: 5432
      protocol: TCP
      targetPort: 5432

-

apiVersion: v1
kind: Endpoints
metadata:
  name: pgsql-rds
subsets:
- addresses:
  - ip: 52.123.44.55
  ports:
  - port: 5432
    name: pgsql-rds
    protocol: TCP

创建Web应用服务和部署时,无法连接到RDS实例。 日志如下:

java.sql.SQLException:分配连接时出错。原因:无法分配连接,因为:连接到pgsql-rds:5432拒绝。检查主机名和端口是否正确以及postmaster是否接受TCP / IP连接。

我错过了什么?任何解决问题的指针都表示赞赏。

3 个答案:

答案 0 :(得分:3)

这与DNS解析有关。当您使用RDS dns名称INSIDE相同的VPC时,它将被解析为私有IP。当您在互联网或其他VPC上使用相同的DNS名称时,您将获得RDS实例的公共IP。

这是一个问题,因为除非您将RDS实例公开到公共互联网,否则从另一个VPC中无法使用负载平衡功能。

答案 1 :(得分:0)

问题已经解决了一段时间了。
现在不记得了,我错过了导致连接问题的那一步。 但是,以下是对我有用的步骤。

前提条件:使用vpc('k8s-vpc')设置kubernetes集群

  1. 创建VPC子网
    转到vpc仪表板,确保与k8s minion的aws区域相同。 (您将看到现有的“ k8s-vpc”)
    在每个可用区域中创建一个子网。
    从下拉列表中选择“ k8s-vpc”作为vpc。
    CIDR可能是172.20.16.0/24或172.20.32.0/24

  2. 为k8s minion的VPC创建DB SUBNET和SUBNET GROUP(如果尚不可用)。
    转到RDS仪表板。
    为数据库创建子网组(例如my-db-subnet-group),然后添加步骤1中的所有子网以创建子网组。

  3. 从RDS仪表板创建参数组
    (例如my-db-param-group)用于Postgres(在此示例中为9.5版)
    max_connections的值复制到max_prepared_transactions字段并保存

  4. 为Postgres DB创建RDS实例
    启动数据库实例->选择Engine Postgres->选择阶段(生产或开发/测试) ->提供实例规格(实例类型和磁盘空间等)并指定数据库设置(用户/密码) ->配置高级设置

    1. vpc选择为'k8s-vpc'
    2. 数据库子网应该是上一步中创建的子网(my-db-subnet-group)
    3. VPC安全组应该来自Kubernetes奴才-以便没有其他配置。从小兵访问所需的
    4. 选择可公开访问-从互联网连接到Postgres
    5. 选择“参数组”作为“ my-db-param-group”。
    6. 指定数据库选项,备份和维护选项,最后启动实例
  5. 还要检查VPC的安全组并添加入站规则以允许连接到postgres端口。

  6. 您可以从安装了postgres客户端的k8s pod(kubectl exec -it)中测试一个连接。
    确保将用户更改为postgres
    如下所示,使用psql连接到RDS:
    $ psql --host=my-rds-dev.cyhi3va0y2or.ap-northeast-1.rds.amazonaws.com --port=5432 --username=<masterUserName> --password --dbname=<masterDB>

如果一切设置正确,它会提示您输入数据库用户的密码。
提供正确的密码将最终连接到RDS。

This article很有帮助。

答案 2 :(得分:0)

您的 IP 格式为:52.123.44.55。这是一个公共IP。 See the official RFC

既然您说两者都在同一个 VPC 中,您可以改用内部 IP 地址。

也就是说,错误“连接到 pgsql-rds:5432 被拒绝”意味着地址已解析,否则你会得到“psql:错误:无法将主机名“psql-rds”转换为地址:名称或服务未知”。因此,这不是另一个答案中引用的 DNS 问题。

阻止的原因可能是安全组未配置为接受来自 EC2 实例外部 IP 地址的请求。如果官方AWS documentation on connecting to RDS scenarios

您可能已经将来自 VPC 的所有连接列入白名单,但请仔细检查安全组。我不建议为外部 IP 地址使用白名单,但是如果您将外部 IP 地址放在那里,它就可以工作。如果您没有弹性 IP 地址并且存在数据传输成本,除非您有更复杂的设置,否则这是一个安全问题。

也就是说,您可以避免使用 Kubernetes 资源并使用 RDS 实例的 DNS 地址。

如果您必须避免直接使用 RDS 实例的 DNS 地址,您可以使用以下方法:

apiVersion: v1
kind: Service
metadata:
  name: psql-rds
spec:
  externalName: my-rds-dev.cyhi3va0y2or.ap-northeast-1.rds.amazonaws.com
  ports:
  - port: 5432
    protocol: TCP
    targetPort: 5432
  sessionAffinity: None
  type: ExternalName

通过上述设置,您不需要 Kubernetes 端点。您可以只使用 psql-rds,或者使用名称空间作为域或完全限定版本的任何变体,例如 psql-rds.default。这是documentation for the ExternalName

我看到原发帖者提到问题已解决,但不清楚或有据可查的问题是使用外部 IP 地址和检查安全组规则的组合。