diff --git a/kong/api/routes/health.lua b/kong/api/routes/health.lua index ff9d22d273d..b1aa833356e 100644 --- a/kong/api/routes/health.lua +++ b/kong/api/routes/health.lua @@ -1,5 +1,6 @@ local utils = require "kong.tools.utils" local declarative = require "kong.db.declarative" +local http = require "resty.http" local find = string.find local select = select @@ -14,6 +15,7 @@ local tonumber = tonumber local kong = kong local dbless = kong.configuration.database == "off" local data_plane_role = kong.configuration.role == "data_plane" +local nginx_status_sock = "unix:" .. ngx.config.prefix() .. "nginx_status.sock" return { @@ -42,14 +44,27 @@ return { -- nginx stats - local r = ngx.location.capture "/nginx_status" + local httpc = http.new() + local _, err = httpc:connect(nginx_status_sock) + if err ~= nil then + kong.log.err("failed to retrieve status: ", err) + return kong.response.exit(500, { message = "An unexpected error happened" }) + end + local r, err = httpc:request({ method = "GET", path = "/nginx_status", + headers = { ["Host"] = "localhost" } }) + local nginx_status_body = r:read_body() + httpc:close() + if err ~= nil then + kong.log.err("failed to retrieve status: ", err) + return kong.response.exit(500, { message = "An unexpected error happened" }) + end if r.status ~= 200 then - kong.log.err(r.body) + kong.log.err("failed to retrieve status: ", nginx_status_body) return kong.response.exit(500, { message = "An unexpected error happened" }) end local var = ngx.var - local accepted, handled, total = select(3, find(r.body, "accepts handled requests\n (%d*) (%d*) (%d*)")) + local accepted, handled, total = select(3, find(nginx_status_body, "accepts handled requests\n (%d*) (%d*) (%d*)")) local status_response = { memory = knode.get_memory_stats(unit, scale), diff --git a/kong/plugins/prometheus/exporter.lua b/kong/plugins/prometheus/exporter.lua index c06d80e1143..5667c9ff6fc 100644 --- a/kong/plugins/prometheus/exporter.lua +++ b/kong/plugins/prometheus/exporter.lua @@ -4,6 +4,7 @@ local find = string.find local lower = string.lower local concat = table.concat local select = select +local http = require "resty.http" local ngx_timer_pending_count = ngx.timer.pending_count local ngx_timer_running_count = ngx.timer.running_count local balancer = require("kong.runloop.balancer") @@ -12,6 +13,8 @@ if not balancer.get_all_upstreams then -- API changed since after Kong 2.5 get_all_upstreams = require("kong.runloop.balancer.upstreams").get_all_upstreams end +local nginx_status_sock = "unix:" .. ngx.config.prefix() .. "nginx_status.sock" + local CLUSTERING_SYNC_STATUS = require("kong.constants").CLUSTERING_SYNC_STATUS local stream_available, stream_api = pcall(require, "kong.tools.stream_api") @@ -298,18 +301,31 @@ local function metric_data() end if ngx.location then - local r = ngx.location.capture "/nginx_status" - - if r.status ~= 200 then + local httpc = http.new() + local _, err = httpc:connect(nginx_status_sock) + if err ~= nil then kong.log.warn("prometheus: failed to retrieve /nginx_status ", - "while processing /metrics endpoint") - + "while processing /metrics endpoint: ", err) else - local accepted, handled, total = select(3, find(r.body, - "accepts handled requests\n (%d*) (%d*) (%d*)")) - metrics.connections:set(accepted, { "accepted" }) - metrics.connections:set(handled, { "handled" }) - metrics.connections:set(total, { "total" }) + local r, err = httpc:request({ method = "GET", path = "/nginx_status", + headers = { ["Host"] = "localhost" } }) + local nginx_status_body = r:read_body() + httpc:close() + if err ~= nil then + kong.log.warn("prometheus: failed to retrieve /nginx_status ", + "while processing /metrics endpoint: ", err) + + elseif r.status ~= 200 then + kong.log.warn("prometheus: failed to retrieve /nginx_status ", + "while processing /metrics endpoint") + + else + local accepted, handled, total = select(3, find(nginx_status_body, + "accepts handled requests\n (%d*) (%d*) (%d*)")) + metrics.connections:set(accepted, { "accepted" }) + metrics.connections:set(handled, { "handled" }) + metrics.connections:set(total, { "total" }) + end end end diff --git a/kong/templates/nginx_kong.lua b/kong/templates/nginx_kong.lua index 002b8881a20..908e8b8fc7c 100644 --- a/kong/templates/nginx_kong.lua +++ b/kong/templates/nginx_kong.lua @@ -363,12 +363,6 @@ server { } } - location /nginx_status { - internal; - access_log off; - stub_status; - } - location /robots.txt { return 200 'User-agent: *\nDisallow: /'; } @@ -408,18 +402,24 @@ server { } } - location /nginx_status { - internal; - access_log off; - stub_status; - } - location /robots.txt { return 200 'User-agent: *\nDisallow: /'; } } > end +> if #status_listeners > 0 or (#admin_listeners > 0 and (role == "control_plane" or role == "traditional")) then +server { + server_name nginx_status; + listen unix:${{PREFIX}}/nginx_status.sock; + error_log ${{ADMIN_ERROR_LOG}} ${{LOG_LEVEL}}; + location /nginx_status { + access_log off; + stub_status; + } +} +> end -- #status_listeners > 0 or (#admin_listeners > 0 and (role == "control_plane" or role == "traditional")) + > if role == "control_plane" then server { server_name kong_cluster_listener; diff --git a/spec/02-integration/02-cmd/02-start_stop_spec.lua b/spec/02-integration/02-cmd/02-start_stop_spec.lua index cf23f1d5626..0597989f5f5 100644 --- a/spec/02-integration/02-cmd/02-start_stop_spec.lua +++ b/spec/02-integration/02-cmd/02-start_stop_spec.lua @@ -1,4 +1,5 @@ local helpers = require "spec.helpers" +local pl_path = require "pl.path" for _, strategy in helpers.each_strategy() do @@ -11,6 +12,14 @@ describe("kong start/stop #" .. strategy, function() }) -- runs migrations helpers.prepare_prefix() end) + before_each(function() + helpers.wait_until(function() + if pl_path.exists(helpers.test_conf.prefix .. "/nginx_status.sock") then + return false + end + return true + end, 10) + end) after_each(function() helpers.kill_all() end) diff --git a/spec/02-integration/04-admin_api/01-admin_api_spec.lua b/spec/02-integration/04-admin_api/01-admin_api_spec.lua index c1e97661352..d65d2e58516 100644 --- a/spec/02-integration/04-admin_api/01-admin_api_spec.lua +++ b/spec/02-integration/04-admin_api/01-admin_api_spec.lua @@ -55,7 +55,7 @@ describe("Admin API listeners", function() admin_listen = "127.0.0.1:9001, 127.0.0.1:9002", })) - assert.equals(2, count_server_blocks(helpers.test_conf.nginx_kong_conf)) + assert.equals(3, count_server_blocks(helpers.test_conf.nginx_kong_conf)) assert.same({ ["127.0.0.1:9001"] = 1, ["127.0.0.1:9002"] = 2, diff --git a/spec/02-integration/05-proxy/01-proxy_spec.lua b/spec/02-integration/05-proxy/01-proxy_spec.lua index 4630fac406a..9b711d1eeae 100644 --- a/spec/02-integration/05-proxy/01-proxy_spec.lua +++ b/spec/02-integration/05-proxy/01-proxy_spec.lua @@ -43,7 +43,7 @@ describe("Proxy interface listeners", function() proxy_listen = "off", admin_listen = "0.0.0.0:9001", })) - assert.equals(1, count_server_blocks(helpers.test_conf.nginx_kong_conf)) + assert.equals(2, count_server_blocks(helpers.test_conf.nginx_kong_conf)) assert.is_nil(get_listeners(helpers.test_conf.nginx_kong_conf).kong) end) @@ -53,7 +53,7 @@ describe("Proxy interface listeners", function() admin_listen = "0.0.0.0:9000", })) - assert.equals(2, count_server_blocks(helpers.test_conf.nginx_kong_conf)) + assert.equals(3, count_server_blocks(helpers.test_conf.nginx_kong_conf)) assert.same({ ["127.0.0.1:9001"] = 1, ["127.0.0.1:9002"] = 2, diff --git a/spec/fixtures/custom_nginx.template b/spec/fixtures/custom_nginx.template index 4c8386fb400..d694009376e 100644 --- a/spec/fixtures/custom_nginx.template +++ b/spec/fixtures/custom_nginx.template @@ -385,12 +385,6 @@ http { } } - location /nginx_status { - internal; - access_log off; - stub_status; - } - location /robots.txt { return 200 'User-agent: *\nDisallow: /'; } @@ -430,18 +424,23 @@ http { } } - location /nginx_status { - internal; - access_log off; - stub_status; - } - location /robots.txt { return 200 'User-agent: *\nDisallow: /'; } } > end +> if #status_listeners > 0 or (#admin_listeners > 0 and (role == "control_plane" or role == "traditional")) then +server { + listen unix:${{PREFIX}}/nginx_status.sock; + error_log ${{ADMIN_ERROR_LOG}} ${{LOG_LEVEL}}; + location /nginx_status { + access_log off; + stub_status; + } +} +> end -- #status_listeners > 0 or (#admin_listeners > 0 and (role == "control_plane" or role == "traditional")) + > if role == "control_plane" then server { server_name kong_cluster_listener;