繁体   English   中英

Rails 生产在 AWS 负载均衡器中不起作用

[英]Rails production not work in AWS load balancer

我的 Rails 6 应用程序在 EC2 实例中的开发模式下运行良好。 但是当配置使用生产模式时。 负载均衡器无法进行健康检查,也无法运行应用程序。

我的健康检查:

在此处输入图像描述

安全性:负载均衡器

在此处输入图像描述

在此处输入图像描述

安全性:Rails 应用程序

在此处输入图像描述

在此处输入图像描述

负载均衡器在开发中工作

在此处输入图像描述

这里是使用负载均衡器的开发

启动轨道:

rails s -p 3000 -b 0.0.0.0

然后回应

=> Booting Puma
=> Rails 6.0.3.2 application starting in development 
=> Run `rails server --help` for more startup options
Puma starting in single mode...
* Version 4.3.5 (ruby 2.6.3-p62), codename: Mysterious Traveller
* Min threads: 5, max threads: 5
* Environment: development
* Listening on tcp://0.0.0.0:3000

配置/环境/development.rb

Rails.application.configure do
  config.hosts << "xxxxxxxx.us-east-2.elb.amazonaws.com" #This is public dns of load balance
  config.cache_classes = false
  config.eager_load = false
  config.consider_all_requests_local = true
  if Rails.root.join('tmp', 'caching-dev.txt').exist?
    config.action_controller.perform_caching = true
    config.action_controller.enable_fragment_cache_logging = true

    config.cache_store = :memory_store
    config.public_file_server.headers = {
      'Cache-Control' => "public, max-age=#{2.days.to_i}"
    }
  else
    config.action_controller.perform_caching = false

    config.cache_store = :null_store
  end
  config.action_mailer.raise_delivery_errors = false
  config.action_mailer.default_url_options = { :host => 'localhost:3000' }

  config.action_mailer.perform_caching = false
  config.active_support.deprecation = :log
  config.assets.debug = true
  config.assets.quiet = true
  config.file_watcher = ActiveSupport::EventedFileUpdateChecker
end

以下是生产(不工作)

配置/环境/production.rb

启动轨道:

RAILS_ENV=production rails s -p 3000 -b 0.0.0.0

然后回复:

=> Booting Puma
=> Rails 6.0.3.2 application starting in production 
=> Run `rails server --help` for more startup options
Puma starting in single mode...
* Version 4.3.5 (ruby 2.6.3-p62), codename: Mysterious Traveller
* Min threads: 5, max threads: 5
* Environment: production
* Listening on tcp://0.0.0.0:3000


Rails.application.configure do
  config.hosts << "xxxxxxxx.us-east-2.elb.amazonaws.com" #This is public dns of load balance
  config.hosts << "3.14.65.84"
  config.cache_classes = true
  config.eager_load = true
  config.consider_all_requests_local       = false
  config.action_controller.perform_caching = true
  config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present?
  config.assets.compile = false
  config.log_level = :debug
  config.log_tags = [ :request_id ]
  config.action_mailer.perform_caching = false
  config.i18n.fallbacks = true
  config.active_support.deprecation = :notify
  config.log_formatter = ::Logger::Formatter.new
  if ENV["RAILS_LOG_TO_STDOUT"].present?
    logger           = ActiveSupport::Logger.new(STDOUT)
    logger.formatter = config.log_formatter
    config.logger    = ActiveSupport::TaggedLogging.new(logger)
  end
end

负载均衡器:运行状况检查不起作用!

在此处输入图像描述

我也试过:

  1. 将 config/environments/development.rb 复制到 production.rb 然后作为生产环境运行,结果 =====> 健康检查不起作用!
  2. 将 config/environment/production.rb 复制到 development.rb 然后作为开发环境运行结果 =====> 健康检查工作!

rails 配置似乎与它无关,而是它在 AWS 中处理生产的方式

帮助:如何使用负载均衡器使这个 Rails 6 在 AWS EC2 中作为生产环境工作?

我的公司刚刚遇到了一个听起来非常相似的问题。 一旦 ECS 启动任务,我们就可以通过 ELB 访问 Rails 应用程序,但是健康检查会失败,它会自动关闭它尝试启动的每个容器。

我们最终将 IP 范围添加到主机配置中。 在生产中完全禁用它感觉不对,所以我们得出了类似这样的结果:

config.hosts = [
  "publicdomain.com",
  "localhost",
  IPAddr.new("10.X.X.X/23")
]

列入白名单的 IP 地址与 ECS 在容器中创建和插入时将使用的范围相匹配。 希望这会有所帮助!

而不是 ping 到根路径,我认为如果您创建自己的路由以在应用程序中进行健康检查,如下所示:

# controller
class HealthCheckController < ApplicationController
  def show
    render body: nil, status: 200
  end
end

# routes
get '/health_check', to: 'health_check#show'

然后将 LB 健康检查中的 ping 路径更新为/health_check

编辑:

在生产配置文件中添加config.hosts.clear替换config.hosts << "xxxxxxxx.us-east-2.elb.amazonaws.com"以使 Rails 接受请求

这里缺少的信息是 Rails 默认情况下不会在生产环境中设置config.hosts config.hosts的目的是防止由于web-console的存在而在开发环境中重新绑定 DNS。

这是我在该主题上找到的最好的文章: https://prathamesh.tech/2019/09/02/dns-rebinding-attacks-protection-in-rails-6/

对于我们来说,我们在 application.rb 中为我们的主域和子域设置了config.hosts ,然后在所有其他环境中对其进行了自定义。 因此,这会导致config.hosts在生产中强制执行,然后 OP 观察到的 AWS 运行状况检查失败。

你有两个选择:

  1. 在生产环境中完全删除config.hosts 由于默认情况下 Rails 未设置此设置,因此假设 DNS 重新绑定攻击在 prod 中不是问题。
  2. 在production.rb中确定请求ip。 上述解决方案将应用程序绑定到不好的基础设施。 如果您想将应用程序部署到新区域怎么办? 您可以动态或静态地执行此操作。
    1. Static:设置环境变量以拉入 ELB 请求 ip 地址。 如果您使用的是 AWS,希望您使用的是 CloudFormation,因此您可以将适当的值作为 ENV 或作为 ParameterStore 变量传递。
    2. 动态:使用 AWS Ruby SDK 拉入 ELB ip 地址

另一个遇到这个问题的人在这里: https://discuss.rubyonrails.org/t/feature-proposal-list-of-paths-to-skip-when-checking-host-authorization/76246

今天有同样的问题。 就我而言,我只是降低标准以接受 403 是健康的。 这并不理想,但我们不应该牺牲主机保护或为可预测的 IP 广泛开放它。

健康检查配置


更新1:

Rails 已经支持从 6.1 中排除配置

config.host_authorization = { exclude: ->(request) { request.path =~ /healthcheck/ } }

参考: https://api.rubyonrails.org/classes/ActionDispatch/HostAuthorization.html

主要原因是从目标组到容器的健康检查连接使用 IP,而不是域,所以轨道响应 403。接受 403 或将其从主机授权中排除。

暂无
暂无

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

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