Commit 22d44ae9 authored by Stan Hu's avatar Stan Hu

Use /-/health instead of breaking /-/liveness

parent eb2bc7d9
...@@ -18,8 +18,9 @@ class HealthController < ActionController::Base ...@@ -18,8 +18,9 @@ class HealthController < ActionController::Base
end end
def liveness def liveness
# This should never be called; it should be intercepted by LivenessHealthCheck middleware results = CHECKS.map { |check| [check.name, check.liveness] }
head :not_found
render_check_results(results)
end end
def storage_check def storage_check
......
--- ---
title: Simplify /-/liveness check to avoid connecting to the database title: Add /-/health basic health check endpoint
merge_request: merge_request: 20456
author: author:
type: changed type: added
...@@ -156,7 +156,7 @@ module Gitlab ...@@ -156,7 +156,7 @@ module Gitlab
# This middleware needs to precede ActiveRecord::QueryCache and other middlewares that # This middleware needs to precede ActiveRecord::QueryCache and other middlewares that
# connect to the database. # connect to the database.
config.middleware.insert_after "Rails::Rack::Logger", "Gitlab::Middleware::LivenessHealthCheck" 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
......
...@@ -46,7 +46,8 @@ Rails.application.routes.draw do ...@@ -46,7 +46,8 @@ 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
get 'liveness' => 'health#liveness' # Intercepted via Gitlab::Middleware::LivenessHealthCheck # '/-/health' implemented by BasicHealthMiddleware
get 'liveness' => 'health#liveness'
get 'readiness' => 'health#readiness' get 'readiness' => 'health#readiness'
post 'storage_check' => 'health#storage_check' post 'storage_check' => 'health#storage_check'
resources :metrics, only: [:index] resources :metrics, only: [:index]
......
...@@ -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`
The readiness endpoint will 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:
...@@ -57,12 +67,29 @@ Readiness example output: ...@@ -57,12 +67,29 @@ Readiness example output:
} }
``` ```
The liveness endpoint only checks whether the application server is running. It does Liveness example output:
not verify the database or other services are running. A successful response with return
a 200 status code with the following message:
``` ```
GitLab is alive {
"fs_shards_check" : {
"status" : "ok"
},
"cache_check" : {
"status" : "ok"
},
"db_check" : {
"status" : "ok"
},
"redis_check" : {
"status" : "ok"
},
"queues_check" : {
"status" : "ok"
},
"shared_state_check" : {
"status" : "ok"
}
}
``` ```
## Status ## Status
......
...@@ -9,20 +9,20 @@ ...@@ -9,20 +9,20 @@
module Gitlab module Gitlab
module Middleware module Middleware
class LivenessHealthCheck class BasicHealthCheck
# This can't be frozen because Rails::Rack::Logger wraps the body # This can't be frozen because Rails::Rack::Logger wraps the body
# rubocop:disable Style/MutableConstant # rubocop:disable Style/MutableConstant
OK_RESPONSE = [200, { 'Content-Type' => 'text/plain' }, ["GitLab is alive"]] OK_RESPONSE = [200, { 'Content-Type' => 'text/plain' }, ["GitLab OK"]]
EMPTY_RESPONSE = [404, { 'Content-Type' => 'text/plain' }, [""]] EMPTY_RESPONSE = [404, { 'Content-Type' => 'text/plain' }, [""]]
# rubocop:enable Style/MutableConstant # rubocop:enable Style/MutableConstant
LIVENESS_PATH = '/-/liveness' HEALTH_PATH = '/-/health'
def initialize(app) def initialize(app)
@app = app @app = app
end end
def call(env) def call(env)
return @app.call(env) unless env['PATH_INFO'] == LIVENESS_PATH return @app.call(env) unless env['PATH_INFO'] == HEALTH_PATH
request = Rack::Request.new(env) request = Rack::Request.new(env)
......
...@@ -109,4 +109,55 @@ describe HealthController do ...@@ -109,4 +109,55 @@ describe HealthController do
end end
end end
end end
describe '#liveness' do
shared_context 'endpoint responding with liveness data' do
subject { get :liveness }
it 'responds with liveness checks data' do
subject
expect(json_response['db_check']['status']).to eq('ok')
expect(json_response['cache_check']['status']).to eq('ok')
expect(json_response['queues_check']['status']).to eq('ok')
expect(json_response['shared_state_check']['status']).to eq('ok')
end
end
context 'accessed from whitelisted ip' do
before do
allow(Gitlab::RequestContext).to receive(:client_ip).and_return(whitelisted_ip)
end
it_behaves_like 'endpoint responding with liveness data'
end
context 'accessed from not whitelisted ip' do
before do
allow(Gitlab::RequestContext).to receive(:client_ip).and_return(not_whitelisted_ip)
end
it 'responds with resource not found' do
get :liveness
expect(response.status).to eq(404)
end
context 'accessed with valid token' do
context 'token passed in request header' do
before do
request.headers['TOKEN'] = token
end
it_behaves_like 'endpoint responding with liveness data'
end
context 'token passed as URL param' do
it_behaves_like 'endpoint responding with liveness data' do
subject { get :liveness, token: token }
end
end
end
end
end
end end
require 'spec_helper' require 'spec_helper'
describe Gitlab::Middleware::LivenessHealthCheck do describe Gitlab::Middleware::BasicHealthCheck do
let(:app) { double(:app) } let(:app) { double(:app) }
let(:middleware) { described_class.new(app) } let(:middleware) { described_class.new(app) }
let(:env) { {} } let(:env) { {} }
...@@ -12,7 +12,7 @@ describe Gitlab::Middleware::LivenessHealthCheck do ...@@ -12,7 +12,7 @@ describe Gitlab::Middleware::LivenessHealthCheck do
end end
it 'returns a 404' do it 'returns a 404' do
env['PATH_INFO'] = described_class::LIVENESS_PATH env['PATH_INFO'] = described_class::HEALTH_PATH
response = middleware.call(env) response = middleware.call(env)
...@@ -34,7 +34,7 @@ describe Gitlab::Middleware::LivenessHealthCheck do ...@@ -34,7 +34,7 @@ describe Gitlab::Middleware::LivenessHealthCheck do
end end
it 'returns 200 response when endpoint is hit' do it 'returns 200 response when endpoint is hit' do
env['PATH_INFO'] = described_class::LIVENESS_PATH env['PATH_INFO'] = described_class::HEALTH_PATH
expect(app).not_to receive(:call) expect(app).not_to receive(:call)
...@@ -42,7 +42,7 @@ describe Gitlab::Middleware::LivenessHealthCheck do ...@@ -42,7 +42,7 @@ describe Gitlab::Middleware::LivenessHealthCheck do
expect(response[0]).to eq(200) expect(response[0]).to eq(200)
expect(response[1]).to eq({ 'Content-Type' => 'text/plain' }) expect(response[1]).to eq({ 'Content-Type' => 'text/plain' })
expect(response[2]).to eq(['GitLab is alive']) expect(response[2]).to eq(['GitLab OK'])
end end
it 'forwards the call for other paths' do it 'forwards the call for other paths' do
......
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