从未通过安全组的 Docker 容器中访问 RDS?

Posted

技术标签:

【中文标题】从未通过安全组的 Docker 容器中访问 RDS?【英文标题】:Accessing RDS from within a Docker container not getting through security group? 【发布时间】:2015-12-29 21:06:15 【问题描述】:

我正在尝试在 docker 容器内运行一个使用带有 EC2 的 RDS 数据库的网络服务器。

我已设置安全组,因此允许 EC2 主机的角色访问 RDS,如果我尝试直接从主机访问它,一切正常。

但是,当我在主机上运行一个简单的容器并尝试访问 RDS 时,它会被阻止,就好像安全组不允许它通过一样。经过一堆试验和错误之后,似乎容器请求确实不是来自 EC2 主机,所以防火墙说不。

我可以通过在 docker 容器上设置 --net=host 在短期内解决这个问题,但是这破坏了很多很棒的 docker 网络功能,比如能够映射端口(即,现在我需要确保容器的每个实例手动侦听不同的端口)。

有没有人找到解决这个问题的方法?如果您实际使用任何 AWS 资源,那么在 AWS 中运行容器似乎是一个很大的限制。

【问题讨论】:

如果您无法控制容器的运行方式,也就是您无法发出docker run 命令,您如何使用--net 来运行容器?跨度> 当我尝试连接到 docker 容器内的 AWS RDS 时,我收到了 Access denied for user 'username'@'xxx.xx.xxx.x' (using password: YES) 错误。为了解决这个问题,我做了以下两种方法: 1.我创建了新用户并分配了授权。 ``` $ CREATE USER 'newuser'@'%' IDENTIFIED BY 'password'; $ GRANT ALL ON newuser@'%' IDENTIFIED BY 'password'; $刷新特权; ``` 2. docker 运行时将全局 DNS 地址8.8.8.8 添加到 docker 容器中。 ``` $ docker run --name backend-app --dns=8.8.8.8 -p 8000:8000 -d backend-app ``` 【参考方案1】:

是的,容器确实会访问 RDS 的公共 IP。但是您不需要调整低级 Docker 选项以允许您的容器与 RDS 通信。 ECS集群和RDS实例必须在同一个VPC,然后可以通过安全组配置访问。最简单的方法是:

    导航到 RDS 实例页面 选择数据库实例并深入查看详细信息 点击安全组ID 导航到“入站”选项卡并选择“编辑” 并确保有一个 mysql/Aurora 类型的规则和源自定义 输入自定义源时,只需开始输入ECS集群的名称,安全组名称将自动为您填写

This tutorial has screenshots 说明要去哪里。

全面披露:本教程介绍了来自 Bitnami 的容器,我为 Bitnami 工作。然而,这里表达的想法是我自己的想法,而不是 Bitnami 的意见。

【讨论】:

值得我自己托管运行 docker 的 ec2 机器,而不是使用 ECS(当时出于各种原因)。 我在这里是因为我的 ECS 任务无法连接到我在服务中为他们提供的安全组。我认为安全组是在启动时分配的。因此,如果您刚刚更新了 ECS 服务的安全组,我建议您重新启动您的任务。【参考方案2】:

弄清楚发生了什么,在这里发布以防万一它帮助其他人。

来自容器内的请求访问的是 RDS 的公共 IP,而不是私有 IP(这是安全组的工作方式)。看起来 docker 容器内的 DNS 使用的是 8.8.8.8 google dns,这不会执行 AWS 将 rds 端点转换为私有 ip 的黑魔法。

例如:

DOCKER_OPTS="--dns 10.0.0.2 -H tcp://127.0.0.1:4243 -H unix:///var/run/docker.sock -g /mnt/docker"

【讨论】:

所以这个问题是有道理的,但是你能回答你是如何解决它的吗? 我也对您解决问题的方式感兴趣 我也遇到了同样的问题,对于没有看到 @alex-schokking 如何修复它感到有点失望,但对于遇到同样问题的其他人来说,这是我使用的修复:我发现 this article概述“VPC 的 DNS 解析器始终位于 +2 地址,因此如果 VPC 是 172.31.0.0/16,则 DNS 服务器将位于 172.31.0.2”,这给了我 DNS 服务器的 IP。然后我不得不将它添加到 docker 守护进程启动 DOCKER_OPTS="--dns 172.31.0.2 --dns 8.8.8.8 --dns 8.8.4.4",重新启动它就可以了! 所以这对我在 EC2 中的 docker 容器中不起作用。它将主机名解析为内部地址,但拒绝访问。相同的 mysql 命令适用于 EC2 主机。 对不起,我错过了要求 dns 的 cmets,更新了当时最终为我工作的内容。【参考方案3】:

RDS 的入站规则应设置为 EC2 实例的私有 IP,而不是公共 IPv4。

【讨论】:

【参考方案4】:

正如@adamneilson 所提到的,设置 Docker 选项是您最好的选择。这是discover your Amazon DNS server on the VPC的方法。此外,Amazon EC2 容器服务开发人员指南故障排除中的 Enabling Docker Debug Output 部分提到了 Docker 选项文件的位置。

假设您正在运行 10.0.0.0/24 的 VPC 块,则 DNS 将为 10.0.0.2。

对于 CentOS、Red Hat 和 Amazon:

sed -i -r 's/(^OPTIONS=\")/\1--dns 10.0.0.2 /g' /etc/sysconfig/docker

对于 Ubuntu 和 Debian:

sed -i -r 's/(^OPTIONS=\")/\1--dns 10.0.0.2 /g' /etc/default/docker

【讨论】:

【参考方案5】:

当我尝试连接到 docker 容器内的 AWS RDS 时,我收到了 "Access denied for user 'username'@'xxx.xx.xxx.x' (using password: YES)" 错误。 为了解决这个问题,我做了以下两种方法:

    我创建了新用户并分配了授权。

    $ CREATE USER 'newuser'@'%' IDENTIFIED BY 'password';
    $ GRANT ALL ON newuser@'%' IDENTIFIED BY  'password';
    $ FLUSH PRIVILEGES;
    

    在docker容器中添加全局DNS地址8.8.8.8,使docker容器可以通过域名解析AWS RDS的IP地址。

    $ docker run --name backend-app --dns=8.8.8.8 -p 8000:8000 -d backend-app
    

然后我从 docker 容器内部成功连接到 AWS RDS。

注意:首先,我尝试了第二种方法。但是我没有解决连接问题。当我尝试两种方式时,我成功了。

【讨论】:

以上是关于从未通过安全组的 Docker 容器中访问 RDS?的主要内容,如果未能解决你的问题,请参考以下文章

AWS 安全组难题

解决亚马逊云服务器上安装nginx后无法访问的问题

容器安全之启用docker客户端命令的授权

如何在 Amazon EC2 容器服务 (ECS) 中使用不安全的 docker 注册表?

容器化 RDS:借助 CSI 扩展 Kubernetes 存储能力

docker与gosu