如何在Fargate容器中启动Rails控制台

7
我想在Fargate容器中打开Rails控制台,以与生产安装交互。然而,在搜索网络和发布AWS论坛后,我没有找到这个问题的答案。是否有人知道我如何做到这一点?这似乎是任何生产环境中必须具备的东西,但从AWS这样受人尊敬的云提供商中没有简单的方法来实现它有些令人惊讶。谢谢。

AWS是IaaS和PaaS的混合体。我的意思是,AWS提供的抽象层次比“Rails应用程序”低。当人们谈论AWS时,通常会使用数据库、负载均衡器等术语。如果我是你,我会研究fargate + 应用程序负载均衡器组合。 - Molecular Man
我已经在基于Rails的API上实现了这个功能,我不明白它与我最初的问题有什么关系,即如何在Fargate容器中打开控制台? - Fred grais
抱歉,我理解错误了。 - Molecular Man
6个回答

8

[2021更新]:现在可以使用AWS Fargate以交互模式运行命令!

新闻:https://aws.amazon.com/fr/blogs/containers/new-using-amazon-ecs-exec-access-your-containers-fargate-ec2/

要运行的命令是:

aws ecs execute-command \
  --cluster cluster-name \
  --task task-id \
  --container container-name \ # optional
  --interactive \
  --command "rails c"

故障排除:

查看AWS文档以获取IAM权限: https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs-exec.html#ecs-exec-prerequisites


5

经过尝试很多方法,我找到了一种打开指向生产环境的Rails控制台的方法,所以我在这里发布,以防有人遇到相同的问题

总结一下,我创建了一个部署在Fargate上的Rails应用程序,并连接到RDS postgres数据库

我的做法是创建一个VPN客户端端点,连接到托管Rails应用程序和RDS数据库的VPC

然后,在连接到该VPN后,我只需运行我的Rails生产容器(使用相同的环境变量),覆盖容器命令以运行控制台启动脚本 (bundle exec rails c production)

由于在我的本地计算机上运行,我可以正常附加TTY到此容器并访问我的生产控制台

我认为这个解决方案很好,因为它允许任何在该项目上工作的开发人员打开控制台,而不会产生任何费用,并且AWS端的一个经过深思熟虑的安全策略确保了控制台访问的安全性,此外你也不必将数据库暴露在你的VPC之外

希望这对某些人有所帮助


我非常感谢如果您能更详细地解释这个问题。我认为这是一个高度追求的功能,在互联网上没有很好的描述。如何从您的命令行联系到VPC,以及运行哪些命令来启动rails控制台? - bo-oz
@bo-oz 我确实在使用 Fargate 容器。 - Fred grais
嗯,我对VPN / SSH这类东西还很陌生...所以我恐怕没有一个傻瓜式的逐步手册就无法让它正常工作。奇怪的是,在互联网上竟然找不到这样的东西。 - bo-oz
好的,基本上你的意思是,在Fargate上让rails c工作将是一个具有挑战性的项目? - bo-oz
如果你不了解VPN/SSH,确实是这样。 - Fred grais
显示剩余2条评论

2

在ECS和Fargate中执行任何类型的docker exec都是一场噩梦。这使得像shell或迁移这样的操作非常困难。

幸运的是,ECS上的Fargate任务实际上只是运行了一些超级定制的docker run命令的AWS服务器。因此,如果您在EC2或本地机器上安装了dockerjq和AWS CLI,则可以自己伪造一些docker run命令并进入bash shell。我为Django这样做,以便可以运行迁移并进入python shell,但我认为对于Rails(或任何其他需要bash的容器)也是如此。

请注意,这仅适用于您只关心同时运行在任务定义中指定的1个容器的情况,尽管我想你可以很容易地将其变得更加复杂。

为此,AWS CLI将需要使用与您的fargate任务相同的IAM权限进行登录。您可以通过使用aws configure在本地提供具有正确IAM权限的用户的凭据来完成此操作,或者通过启动一个具有相同权限的角色的EC2实例(或者为了保持简单性而是您的fargate任务正在运行的角色)和具有相同访问权限的安全组(加上一个允许您SSH到堡垒主机的规则)。我喜欢使用EC2路线,因为通过公共互联网和VPN来传输所有内容是......很慢的。而且您总是保证具有与任务相同的IAM访问权限。

您还需要在与Fargate任务位于同一子网上,这通常可以通过VPN或在您的私有子网中运行此代码的堡垒EC2主机来完成。

在我的情况下,我将我的配置参数存储为AWS系统管理器参数存储中的SecureStrings,并使用ECS任务定义将它们传递进去。这些可以很容易地获取并设置为本地环境变量。

export DATABASE_URL=$(aws ssm get-parameter --region $REGION \
                      --with-decryption --name parameter.name.database_url \
                      | jq '.Parameter["Value"]' -r)

我将我的容器存储在ECR上,因此我需要登录本地Docker容器以连接ECR。
eval $(aws ecr get-login --no-include-email --region $REGION)

接下来只需要运行一个交互式的docker容器,将DATABASE_URL传入,从ECR中获取正确的镜像并进入bash。我还暴露了端口8000,这样我就可以在shell内运行web服务器(如果需要的话),但这是可选的。

docker run -i -t \
           -e DATABASE_URL \
           -p 8000:8000 \
           $ACCOUNT_ID.dkr.ecr.$REGION.amazonaws.com/$DOCKER_REPO_NAME:$TAG \
           /bin/bash

一旦你运行了这个命令,你应该看到docker从容器库下载镜像,然后启动bash(假设在你的容器中已经安装了bash)。 Docker有一个相当稳定的缓存,因此第一次下载和启动需要一些时间,但之后应该会很快。

以下是我的完整脚本:

#!/bin/bash

REGION=${REGION:-us-west-2}
ENVIRONMENT=${ENVIRONMENT:-staging}
DOCKER_REPO_NAME=${DOCKER_REPO_NAME:-reponame}
TAG=${TAG:-latest}

ACCOUNT_ID=$(aws sts get-caller-identity | jq -r ".Account")

export DATABASE_URL=$(aws ssm get-parameter --region $REGION \
                      --with-decryption --name projectname.$ENVIRONMENT.database_url \
                      | jq '.Parameter["Value"]' -r)

eval $(aws ecr get-login --no-include-email --region $REGION)

IMAGE=$ACCOUNT_ID.dkr.ecr.$REGION.amazonaws.com/$DOCKER_REPO_NAME:$TAG

docker run -i -t \
           -e DATABASE_URL \
           -p 8000:8000 \
           $IMAGE \
           /bin/bash

1

当您使用Fargate执行类型的ECS时,无法通过ssh连接到底层主机。这意味着您无法在运行中的容器中使用docker exec。


那么在Rails API中使用Fargate是被禁止的吗?因为为了在生产环境中正确调试任何内容都需要控制台?或者我漏掉了一些明显的东西,能够启动控制台而不必支付全职EC2实例来运行它(更不用提这将限制能够同时运行的控制台数量)。我认为这来自AWS是令人惊讶的。 - Fred grais
1
我找到了一种方法,可以使用Rails控制台从我的本地机器连接到生产数据库(请参见其他回复)。 - Fred grais

0

我在Fargate上没有尝试过这个方法,但是你应该可以创建一个fargate任务,其中命令为rails console

然后,如果你将任务配置为交互式, 你应该能够启动交互式容器,并通过stdin访问控制台。


你好,感谢回答。我已经尝试过这个方法,但即使在指定了交互和伪终端标志后,当我使用AWS运行任务时,它仍然只是异步地启动任务,并没有将我的终端连接到它上面。 - Fred grais
这也听起来是一个不错的解决方案,你知道有没有任何文件可以解释如何设置和连接吗? - bo-oz
1
在Fargate上不可能实现。 - sj26
这仅适用于EC2启动类型环境,而不适用于Fargate。https://aws.amazon.com/about-aws/whats-new/2018/09/amazon-ecs-now-allows-three-additional-docker-flags/ - Zulhilmi Zainudin

0

好的,我最终以稍微不同的方式处理了事情。我没有尝试在Fargate上运行控制台,而是在本地主机上运行控制台,但将其配置为使用RAILS_ENV='production'并让它使用我的RDS实例。

当然,要使此工作正常,您必须通过安全组中的出站规则公开RDS实例。明智的做法是以仅允许本地IP的方式进行配置,以使其更加安全。

然后docker-compose.yml看起来像这样:

version: '3'
  web:
    stdin_open: true
    tty: true
    build: .
    volumes:
      - ./rails/.:/your-app
    ports:
      - "3000:3000"
    environment: &env_vars
      RAILS_ENV: 'production'
      PORT: '8080'
      RAILS_LOG_TO_STDOUT: 'true'
      RAILS_SERVE_STATIC_FILES: 'true'
      DATABASE_URL: 'postgresql://username:password@yours-aws-rds-instance:5432/your-db'

当您运行docker-compose run web rails c时,它将使用您本地的Rails代码库,但会对您的RDS数据库进行实时更改(这也是您想要访问rails控制台的主要原因)。

2
是的,这基本上就是我建议你使用VPN连接托管RDS的VPC,这样有额外的好处,不会暴露你的RDS。但是,由于运行VPN终结点相当昂贵,因此可能会变得昂贵。 - Fred grais

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接