Commit 1adfb156 authored by Robert Speicher's avatar Robert Speicher

Merge branch 'sh-simplify-liveness-check' into 'master'

Add /-/health basic health check endpoint

See merge request gitlab-org/gitlab-ce!20456
parents 934f1f69 22d44ae9
---
title: Add /-/health basic health check endpoint
merge_request: 20456
author:
type: added
...@@ -154,6 +154,10 @@ module Gitlab ...@@ -154,6 +154,10 @@ module Gitlab
config.action_view.sanitized_allowed_protocols = %w(smb) config.action_view.sanitized_allowed_protocols = %w(smb)
# This middleware needs to precede ActiveRecord::QueryCache and other middlewares that
# connect to the database.
config.middleware.insert_after "Rails::Rack::Logger", "Gitlab::Middleware::BasicHealthCheck"
config.middleware.insert_after Warden::Manager, Rack::Attack config.middleware.insert_after Warden::Manager, Rack::Attack
# Allow access to GitLab API from other domains # Allow access to GitLab API from other domains
......
...@@ -46,6 +46,7 @@ Rails.application.routes.draw do ...@@ -46,6 +46,7 @@ Rails.application.routes.draw do
get 'health_check(/:checks)' => 'health_check#index', as: :health_check get 'health_check(/:checks)' => 'health_check#index', as: :health_check
scope path: '-' do scope path: '-' do
# '/-/health' implemented by BasicHealthMiddleware
get 'liveness' => 'health#liveness' get 'liveness' => 'health#liveness'
get 'readiness' => 'health#readiness' get 'readiness' => 'health#readiness'
post 'storage_check' => 'health#storage_check' post 'storage_check' => 'health#storage_check'
......
...@@ -20,14 +20,24 @@ To access monitoring resources, the client IP needs to be included in a whitelis ...@@ -20,14 +20,24 @@ To access monitoring resources, the client IP needs to be included in a whitelis
[Read how to add IPs to a whitelist for the monitoring endpoints][admin]. [Read how to add IPs to a whitelist for the monitoring endpoints][admin].
## Using the endpoint ## Using the endpoints
With default whitelist settings, the probes can be accessed from localhost: With default whitelist settings, the probes can be accessed from localhost:
- `http://localhost/-/health`
- `http://localhost/-/readiness` - `http://localhost/-/readiness`
- `http://localhost/-/liveness` - `http://localhost/-/liveness`
which will then provide a report of system health in JSON format.
The first endpoint, `/-/health/`, only checks whether the application server is running. It does
-not verify the database or other services are running. A successful response with return
a 200 status code with the following message:
```
GitLab OK
```
The readiness and liveness probes will provide a report of system health in JSON format.
Readiness example output: Readiness example output:
......
# frozen_string_literal: true
# This middleware provides a health check that does not hit the database. Its purpose
# is to notify the prober that the application server is handling requests, but a 200
# response does not signify that the database or other services are ready.
#
# See https://thisdata.com/blog/making-a-rails-health-check-that-doesnt-hit-the-database/ for
# more details.
module Gitlab
module Middleware
class BasicHealthCheck
# This can't be frozen because Rails::Rack::Logger wraps the body
# rubocop:disable Style/MutableConstant
OK_RESPONSE = [200, { 'Content-Type' => 'text/plain' }, ["GitLab OK"]]
EMPTY_RESPONSE = [404, { 'Content-Type' => 'text/plain' }, [""]]
# rubocop:enable Style/MutableConstant
HEALTH_PATH = '/-/health'
def initialize(app)
@app = app
end
def call(env)
return @app.call(env) unless env['PATH_INFO'] == HEALTH_PATH
request = Rack::Request.new(env)
return OK_RESPONSE if client_ip_whitelisted?(request)
EMPTY_RESPONSE
end
def client_ip_whitelisted?(request)
ip_whitelist.any? { |e| e.include?(request.ip) }
end
def ip_whitelist
@ip_whitelist ||= Settings.monitoring.ip_whitelist.map(&IPAddr.method(:new))
end
end
end
end
require 'spec_helper'
describe Gitlab::Middleware::BasicHealthCheck do
let(:app) { double(:app) }
let(:middleware) { described_class.new(app) }
let(:env) { {} }
describe '#call' do
context 'outside IP' do
before do
env['REMOTE_ADDR'] = '8.8.8.8'
end
it 'returns a 404' do
env['PATH_INFO'] = described_class::HEALTH_PATH
response = middleware.call(env)
expect(response[0]).to eq(404)
end
it 'forwards the call for other paths' do
env['PATH_INFO'] = '/'
expect(app).to receive(:call)
middleware.call(env)
end
end
context 'whitelisted IP' do
before do
env['REMOTE_ADDR'] = '127.0.0.1'
end
it 'returns 200 response when endpoint is hit' do
env['PATH_INFO'] = described_class::HEALTH_PATH
expect(app).not_to receive(:call)
response = middleware.call(env)
expect(response[0]).to eq(200)
expect(response[1]).to eq({ 'Content-Type' => 'text/plain' })
expect(response[2]).to eq(['GitLab OK'])
end
it 'forwards the call for other paths' do
env['PATH_INFO'] = '/-/readiness'
expect(app).to receive(:call)
middleware.call(env)
end
end
end
end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment