簡體   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