简体   繁体   English

从 AWS 中的 Kubernetes 集群访问 Postgres RDS

[英]Accessing Postgres RDS from Kubernetes cluster in AWS

My Kubernetes cluster setup has n-tier web application running in dev and test environments on AWS.我的 Kubernetes 集群设置具有在 AWS 上的开发和测试环境中运行的 n 层 Web 应用程序。 For the production environment, postgres RDS was chosen, to ensure periodic backup.生产环境选择postgres RDS,保证定期备份。 While creating a postgres RDS instance, kubernetes-vpc was selected for db-subnet to keep networking stuff simple during pilot run.在创建 postgres RDS 实例时,db-subnet 选择了 kubernetes-vpc,以在试运行期间保持网络简单。 Also, security group selected is the same as kubernetes-minions.此外,选择的安全组与 kubernetes-minions 相同。

Following is the service and endpoint yaml:以下是服务和端点 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

When web-app service and deployment is created, it's unable to connect to RDS instance.创建 web-app 服务和部署时,无法连接到 RDS 实例。 The log is as follows:日志如下:

java.sql.SQLException: Error in allocating a connection. java.sql.SQLException:分配连接时出错。 Cause: Connection could not be allocated because: Connection to pgsql-rds:5432 refused.原因:无法分配连接,因为:连接到 pgsql-rds:5432 被拒绝。 Check that the hostname and port are correct and that the postmaster is accepting TCP/IP connections.检查主机名和端口是否正确以及 postmaster 是否正在接受 TCP/IP 连接。

What am I missing?我错过了什么? any pointers to resolve the issue appreciated.任何解决问题的指针表示赞赏。

This has to do with DNS resolving.这与DNS解析有关。 When you use the RDS dns name INSIDE the same VPC it will be resolved to a private ip.当您在同一 VPC 内使用 RDS dns 名称时,它将被解析为私有 ip。 When you use the same dns name on the internet or another VPC you will get the public ip of the RDS instance.当您在互联网或其他 VPC 上使用相同的 dns 名称时,您将获得 RDS 实例的公共 ip。

This is a problem because from another VPC you can not make use of the load balancing feature unless you expose the RDS instance to the public internet.这是一个问题,因为您无法从另一个 VPC 使用负载均衡功能,除非您将 RDS 实例公开给公共互联网。

It's been a while the issue was resolved.这个问题已经解决了一段时间。
Don't exactly remember now, which step I missed that caused connection problem.现在不记得了,我错过了哪一步导致连接问题。 But, below are the steps that did work for me.但是,以下是对我有用的步骤。

Pre-requisite: kubernetes cluster is set up with vpc ('k8s-vpc')先决条件:kubernetes 集群设置了 vpc ('k8s-vpc')

  1. Create VPC SUBNET创建专有网络子网
    Go to vpc dashboard, ensure same aws region as k8s minion.转到 vpc 仪表板,确保与 k8s minion 相同的 aws 区域。 (you will see existing 'k8s-vpc') (您将看到现有的“k8s-vpc”)
    Create subnet with each availability zone.为每个可用区创建子网。
    Select 'k8s-vpc' as vpc from drop-down.从下拉列表中选择“k8s-vpc”作为 vpc。
    CIDR could be 172.20.16.0/24 or 172.20.32.0/24 CIDR 可以是 172.20.16.0/24 或 172.20.32.0/24

  2. Create DB SUBNET and SUBNET GROUP FOR VPC of k8s minion if not already available.如果尚未可用,请为 k8s minion 的 VPC 创建 DB SUBNET 和 SUBNET GROUP。
    Go to RDS Dashboard.转到 RDS 仪表板。
    Create subnet group (eg my-db-subnet-group) for DB and add all subnet from step 1 to create subnet group.为 DB 创建子网组(例如 my-db-subnet-group)并添加步骤 1 中的所有子网以创建子网组。

  3. From RDS Dashboard create Parameter Group从 RDS 仪表板创建参数组
    (eg my-db-param-group) for Postgres (version 9.5 in this example) (例如 my-db-param-group)用于 Postgres(本例中为 9.5 版)
    Copy value for max_connections to the max_prepared_transactions field and savemax_connections值复制到max_prepared_transactions字段并保存

  4. Create RDS instance for Postgres DB为 Postgres DB 创建 RDS 实例
    Launch DB instance -> select Engine Postgres -> Choose stage (Production or Dev/Test) -> Give instance spec.s (instance type & disk space etc.) and specify DB settings (user/password) -> Configure Advanced settings启动数据库实例 -> 选择 Engine Postgres -> 选择阶段(生产或开发/测试)-> 提供实例规格(实例类型和磁盘空间等)并指定数据库设置(用户/密码)-> 配置高级设置

    1. vpc selection as 'k8s-vpc' vpc 选择为“k8s-vpc”
    2. DB subnet should be one created in previous step (my-db-subnet-group) DB 子网应该是在上一步中创建的子网 (my-db-subnet-group)
    3. VPC security group should be from Kubernetes minions - so that no additional config. VPC 安全组应该来自 Kubernetes minions - 这样就不需要额外的配置。 required for access from minions从minions访问需要
    4. Select Publicly Accessible - to connect to postgres from internet选择 Publicly Accessible - 从互联网连接到 postgres
    5. Select Parameter Group as 'my-db-param-group'.选择参数组作为“my-db-param-group”。
    6. Specify Database options, backup and maintenance options and finally launch the instance指定数据库选项、备份和维护选项并最终启动实例
  5. Also check security group of VPC and add inbound rule to allow connection to postgres port.还要检查 VPC 的安全组并添加入站规则以允许连接到 postgres 端口。

  6. You can test connection from one of the k8s pod ( kubectl exec -it ) where postgres client is installed.您可以从安装了 postgres 客户端的 k8s pod ( kubectl exec -it ) 之一测试连接。
    Make sure to change user to postgres .确保将用户更改为postgres
    Connect to RDS using psql as shown below:使用 psql 连接到 RDS,如下所示:
    $ psql --host=my-rds-dev.cyhi3va0y2or.ap-northeast-1.rds.amazonaws.com --port=5432 --username=<masterUserName> --password --dbname=<masterDB>

If everything is set up correctly, it should prompt you for password of db user.如果一切设置正确,它应该提示您输入 db 用户的密码。
Providing correct password will finally connect to RDS.提供正确的密码将最终连接到 RDS。

This article was of great help. 这篇文章很有帮助。

Your IP is of the form: 52.123.44.55.您的 IP 格式为:52.123.44.55。 This is a public IP.这是一个公共IP。 See the official RFC查看官方 RFC

Since you said both are in the same VPC, you could have used the internal IP address instead.由于您说两者都在同一个 VPC 中,因此您可以改用内部 IP 地址。

That said, the error "Connection to pgsql-rds:5432 refused" means that the address was resolved, otherwise you would get "psql: error: could not translate host name "psql-rds" to address: Name or service not known".也就是说,错误“连接到 pgsql-rds:5432 被拒绝”意味着地址已解析,否则你会得到“psql:错误:无法将主机名“psql-rds”转换为地址:名称或服务未知” . Therefore, it is not a DNS issue as cited on another answer.因此,这不是另一个答案中引用的 DNS 问题。

The cause of the block is likely that the security group was not configured to accept requests from the EC2 instance external IP address.阻止的原因可能是安全组未配置为接受来自 EC2 实例外部 IP 地址的请求。 This if the official AWS documentation on connecting to RDS scenarios .这如果AWS官方文档连接到 RDS 方案

You might have already whitelisted all connections from VPC, however double check the security groups.您可能已经将来自 VPC 的所有连接列入白名单,但请仔细检查安全组。 I would not recommend using a whitelist for the external IP address, however it works if you put the external IP address there.我不建议为外部 IP 地址使用白名单,但是如果您将外部 IP 地址放在那里,它就可以工作。 It is a security concern when you don't have an elastic IP address and there are data transfer costs unless you have a more complex setup.当您没有弹性 IP 地址并且有数据传输成本时,这是一个安全问题,除非您有更复杂的设置。

That said, you could have avoided the Kubernetes resources and used the DNS address of the RDS instance.也就是说,您可以避免使用 Kubernetes 资源并使用 RDS 实例的 DNS 地址。

If you had to avoid using the DNS address of the RDS instance directly, you could have used the following:如果您必须避免直接使用 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

With the setup above, you don't need a Kubernetes Endpoint.通过上述设置,您不需要 Kubernetes 端点。 You can just use psql-rds, or any variation using the namespace as the domain or the fully qualified version, such as psql-rds.default.您可以只使用 psql-rds,或者使用名称空间作为域或完全限定版本的任何变体,例如 psql-rds.default。 This is the documentation for the ExternalName这是ExternalName文档

I see that the original poster mentioned the problem was solved, however it is not clear or well documented that the problem was a combination of using the external IP address and checking the security group rules.我看到原始海报提到问题已解决,但不清楚或有据可查的问题是使用外部 IP 地址和检查安全组规则的组合。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM