如何解决Rails生产在AWS负载均衡器中不起作用
My Rails 6 App在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
config / environments / 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
下面是生产(无效)
config / environments / 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),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
负载均衡器:运行状况检查不起作用!
我也尝试过:
- 将config / environments / development.rb复制到production.rb,然后在生产环境中运行,结果=====>运行状况检查不起作用!
- 将config / environment / production.rb复制到development.rb,然后在开发环境中运行=====> Health Check Work!
关于rails的配置似乎没有什么,但是它在AWS中处理生产的方式
帮助:如何使Rails 6在带负载均衡器的AWS EC2中作为生产工作?
解决方法
我认为,如果您在应用程序中创建自己的运行状况检查路径,而不是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接受请求
我的公司遇到了一个非常相似的问题。 ECS启动任务后,我们就可以通过ELB访问Rails应用程序,但是运行状况检查将失败,它将自动关闭它尝试启动的每个容器。
我们最终将IP范围添加到主机配置中。在生产中完全禁用它感觉不对,所以我们得出了类似的结论:
config.hosts = [
"publicdomain.com","localhost",IPAddr.new("10.X.X.X/23")
]
列入白名单的IP地址与在容器中创建和插入ECS时将使用的范围相匹配。希望有帮助!
,这里缺少的信息是 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 运行状况检查失败。
您有两个选择:
- 在生产中完全删除
config.hosts
。由于默认情况下这不是由 Rails 设置的,因此推测 DNS 重新绑定攻击在产品中不是问题。 - 在 production.rb 中确定请求 ip。上述解决方案将应用程序绑定到不好的基础设施。如果要将应用程序部署到新区域怎么办?您可以动态或静态地执行此操作。
- 静态:设置环境变量以拉入 ELB 请求 ip 地址。如果您使用的是 AWS,希望您使用的是 CloudFormation,这样您就可以将适当的值作为 ENV 或作为 ParameterStore 变量传递。
- 动态:使用 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,而不是域,因此rails响应403。 接受 403 或将其从主机授权中排除。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。