在 AWS ECS 上设置 Rails 6 的正确方法
Proper way to set up Rails 6 on AWS ECS
我在 AWS ECS 上部署了 Rails 6 (运行 Puma)。有一个 ECS 服务和一个 ECS 任务,该任务启动托管我的应用程序的 EC2 实例。我还使用我的 ECS 服务创建了一个 Application Load Balancer。我向负载均衡器添加了一个 HTTPS 侦听器。我的听众指向一个目标组,该目标组专门通过 HTTP
协议接受流量。
我对请求流程的理解:
HTTPS request from internet:
--> hits AWS load balancer
--> hits HTTPS listener
--> passes traffic using HTTP to Target Group
--> request finally reaches Rails app on Target Group EC2 targets *over HTTP*
这是一个有效的设置吗?我读了这篇文章 ,我的解释是我们的负载均衡器只需要 HTTPS 而不是 Puma,因此也不需要 Target Group。
我还通过 HTTP 为我的目标组设置了健康检查,该目标组期望将 301 状态代码响应作为健康目标(因为我的 Rails 配置中启用了 config.force_ssl
)。问题是,为什么来自负载均衡器的流量没有被重定向?为什么来自健康检查的流量会被重定向?他们不是都针对同一个目标群体吗?为什么一个请求结果为 200 而另一个请求结果为 301?
我画了一张图来表达我的 question/confusion/current 理解:
这是我的负载均衡器和目标组设置:
不确定这是 AWS 问题还是 Puma 问题或其他问题。采纳所有想法!谢谢!!
回答你的 2 个问题。
- 为什么来自负载均衡器的流量没有被重定向?
This answer 也对此进行了解释,但我会更深入地挖掘:当负载均衡器接收到 HTTPS 连接并通过 HTTP 将其转发到您的 Rails 服务器时,它将设置X-FORWARDED-PROTO=https
header 到请求,并且 Rails 理解这对于 force_ssl 配置来说已经足够了。
代码路径是Rails
https://github.com/rails/rails/blob/main/actionpack/lib/action_dispatch/middleware/ssl.rb
(根据该文件中的注释,当 config.force_ssl
为真时包含在请求链中)将调用 request.ssl?
request
在该上下文中是 https://github.com/rails/rails/blob/main/actionpack/lib/action_dispatch/http/request.rb
的实例,但您不会在其中找到定义的 ssl?
方法;但是,class 包括 include Rack::Request::Helpers
.
如果你查看 Rack 的源代码,你会发现 https://github.com/rack/rack/blob/master/lib/rack/request.rb
中定义的 ssl?
方法调用了 scheme
方法,而 X-Forwarded-Proto header 将在 elsif forwarded_scheme
部分进行检查。好了 :) 即使它是一个 HTTP 请求,header 的存在也会使 request.ssl?
return 为真。
- 为什么来自健康检查的流量会被重定向?
在这种情况下,它是从负载平衡器到您的应用程序的 HTTP 请求,不包含 X-Forwarded-For 或 X-Forwarded-Proto header,因此 Rail 的 config.force_ssl正在做它应该做的事情并重定向。
最后,查看 config.force_ssl 上的 documentation。您实际上可以将其设置为选项的哈希值,并从 force_ssl 行为中排除您的健康检查网址!
config.ssl_options = { redirect: { exclude: -> request { request.path =~ /healthcheck/ } } }
我在 AWS ECS 上部署了 Rails 6 (运行 Puma)。有一个 ECS 服务和一个 ECS 任务,该任务启动托管我的应用程序的 EC2 实例。我还使用我的 ECS 服务创建了一个 Application Load Balancer。我向负载均衡器添加了一个 HTTPS 侦听器。我的听众指向一个目标组,该目标组专门通过 HTTP
协议接受流量。
我对请求流程的理解:
HTTPS request from internet:
--> hits AWS load balancer
--> hits HTTPS listener
--> passes traffic using HTTP to Target Group
--> request finally reaches Rails app on Target Group EC2 targets *over HTTP*
这是一个有效的设置吗?我读了这篇文章
我还通过 HTTP 为我的目标组设置了健康检查,该目标组期望将 301 状态代码响应作为健康目标(因为我的 Rails 配置中启用了 config.force_ssl
)。问题是,为什么来自负载均衡器的流量没有被重定向?为什么来自健康检查的流量会被重定向?他们不是都针对同一个目标群体吗?为什么一个请求结果为 200 而另一个请求结果为 301?
我画了一张图来表达我的 question/confusion/current 理解:
这是我的负载均衡器和目标组设置:
不确定这是 AWS 问题还是 Puma 问题或其他问题。采纳所有想法!谢谢!!
回答你的 2 个问题。
- 为什么来自负载均衡器的流量没有被重定向?
This answer 也对此进行了解释,但我会更深入地挖掘:当负载均衡器接收到 HTTPS 连接并通过 HTTP 将其转发到您的 Rails 服务器时,它将设置X-FORWARDED-PROTO=https
header 到请求,并且 Rails 理解这对于 force_ssl 配置来说已经足够了。
代码路径是Rails
https://github.com/rails/rails/blob/main/actionpack/lib/action_dispatch/middleware/ssl.rb
(根据该文件中的注释,当 config.force_ssl
为真时包含在请求链中)将调用 request.ssl?
request
在该上下文中是 https://github.com/rails/rails/blob/main/actionpack/lib/action_dispatch/http/request.rb
的实例,但您不会在其中找到定义的 ssl?
方法;但是,class 包括 include Rack::Request::Helpers
.
如果你查看 Rack 的源代码,你会发现 https://github.com/rack/rack/blob/master/lib/rack/request.rb
中定义的 ssl?
方法调用了 scheme
方法,而 X-Forwarded-Proto header 将在 elsif forwarded_scheme
部分进行检查。好了 :) 即使它是一个 HTTP 请求,header 的存在也会使 request.ssl?
return 为真。
- 为什么来自健康检查的流量会被重定向?
在这种情况下,它是从负载平衡器到您的应用程序的 HTTP 请求,不包含 X-Forwarded-For 或 X-Forwarded-Proto header,因此 Rail 的 config.force_ssl正在做它应该做的事情并重定向。
最后,查看 config.force_ssl 上的 documentation。您实际上可以将其设置为选项的哈希值,并从 force_ssl 行为中排除您的健康检查网址!
config.ssl_options = { redirect: { exclude: -> request { request.path =~ /healthcheck/ } } }