Skip to content

Commit

Permalink
feat(cli): add 'drain' CLI command to set /status/ready to 503 (#13838)
Browse files Browse the repository at this point in the history
* feat(cli): add 'unready' CLI command to set /status/ready to 503

This command updates the `/status/ready` endpoint to return a `503 Service Unavailable` status code.
This allows external tools, such as Kubernetes, to detect when Kong is not ready to receive traffic.
Based on this response, Kubernetes can gracefully remove Kong from its load balancing pool according
to its configured policies, facilitating a smooth shutdown process.

Fix: [FTI-6276](https://konghq.atlassian.net/browse/FTI-6276)
Signed-off-by: tzssangglass <[email protected]>

---------

Signed-off-by: tzssangglass <[email protected]>
  • Loading branch information
tzssangglass authored Nov 25, 2024
1 parent fa9bed9 commit 11bc3b6
Show file tree
Hide file tree
Showing 6 changed files with 414 additions and 4 deletions.
2 changes: 2 additions & 0 deletions bin/kong
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ local cmds = {
roar = true,
hybrid = true,
vault = true,
drain = true,
}

-- unnecessary to inject nginx directives for these simple cmds
Expand All @@ -42,6 +43,7 @@ local skip_inject_cmds = {
quit = true,
health = true,
hybrid = true,
drain = true,
}

for k in pairs(cmds) do
Expand Down
3 changes: 3 additions & 0 deletions changelog/unreleased/kong/feat-kong-drain-cmd.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
message: Add the `kong drain` CLI command to make the `/status/ready` endpoint return `503 Service Unavailable` response.
type: feature
scope: CLI Command
1 change: 1 addition & 0 deletions kong-3.9.0-0.rockspec
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ build = {
["kong.cmd.vault"] = "kong/cmd/vault.lua",
["kong.cmd.version"] = "kong/cmd/version.lua",
["kong.cmd.hybrid"] = "kong/cmd/hybrid.lua",
["kong.cmd.drain"] = "kong/cmd/drain.lua",
["kong.cmd.utils.log"] = "kong/cmd/utils/log.lua",
["kong.cmd.utils.kill"] = "kong/cmd/utils/kill.lua",
["kong.cmd.utils.env"] = "kong/cmd/utils/env.lua",
Expand Down
88 changes: 88 additions & 0 deletions kong/cmd/drain.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
local http = require "resty.luasocket.http"
local print = print
local fmt = string.format

local conf_loader = require "kong.conf_loader"
local pl_path = require "pl.path"
local log = require "kong.cmd.utils.log"
local json_encode = require("cjson.safe").encode

local function execute(args)
log.disable()

-- only to retrieve the default prefix or use given one
local conf = assert(conf_loader(args.conf, {
prefix = args.prefix
}))

if pl_path.exists(conf.kong_env) then
-- load <PREFIX>/kong.conf containing running node's config
conf = assert(conf_loader(conf.kong_env))
end

log.enable()

if #conf.status_listeners == 0 then
print("No status listeners found in configuration.")
return
end

local status_listener = conf.status_listeners[1]

local scheme = "http"
if status_listener.ssl then
scheme = "https"
end

local url = scheme .. "://" .. status_listener.ip .. ":" .. status_listener.port .. "/status/ready"

local httpc = http.new()
httpc:set_timeout(1000)


local res, err = httpc:request_uri(url, {
method = "POST",
headers = {
["Content-Type"] = "application/json"
},
body = json_encode({
status = "draining"
}),
-- we don't need to verify the SSL certificate for this request
ssl_verify = false,
})

httpc:close()

if not res then
print(fmt("Failed to send request to %s: %s", url, err))
return
end

if res.status ~= 204 then
print(fmt("Unexpected response status from %s: %d", url, res.status))
return
end

print("Kong's status successfully changed to 'draining'")
end


local lapp = [[
Usage: kong drain [OPTIONS]
Make status listeners(`/status/ready`) return 503 Service Unavailable.
Example usage:
kong drain
Options:
-c,--conf (optional string) configuration file
-p,--prefix (optional string) override prefix directory
]]


return {
lapp = lapp,
execute = execute,
}
27 changes: 23 additions & 4 deletions kong/status/ready.lua
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ local PLUGINS_REBUILD_COUNTER_KEY = constants.PLUGINS_REBUILD_COUNTER_KEY
local ROUTERS_REBUILD_COUNTER_KEY = constants.ROUTERS_REBUILD_COUNTER_KEY
local DECLARATIVE_EMPTY_CONFIG_HASH = constants.DECLARATIVE_EMPTY_CONFIG_HASH

local KONG_STATUS_READY = "kong:status:ready"

local function is_dbless_ready(router_rebuilds, plugins_iterator_rebuilds)
if router_rebuilds < worker_count then
Expand Down Expand Up @@ -75,16 +76,16 @@ local function is_ready()
if not ok then
return false, "failed to connect to database"
end

kong.db:close()

if is_control_plane then
return true
end

local router_rebuilds =
local router_rebuilds =
tonumber(kong_shm:get(ROUTERS_REBUILD_COUNTER_KEY)) or 0
local plugins_iterator_rebuilds =
local plugins_iterator_rebuilds =
tonumber(kong_shm:get(PLUGINS_REBUILD_COUNTER_KEY)) or 0

local err
Expand All @@ -102,6 +103,15 @@ end
return {
["/status/ready"] = {
GET = function(self, dao, helpers)
local ready = kong_shm:get(KONG_STATUS_READY)
if ready == nil then
kong_shm:set(KONG_STATUS_READY, true)
end

if ready == false then
return kong.response.exit(503, { message = "draining" })
end

local ok, err = is_ready()
if ok then
ngx_log(ngx_DEBUG, "ready for proxying")
Expand All @@ -111,6 +121,15 @@ return {
ngx_log(ngx_NOTICE, "not ready for proxying: ", err)
return kong.response.exit(503, { message = err })
end
end,

POST = function(self, dao, helpers)
if self.params and self.params.status == "draining" then
kong_shm:set(KONG_STATUS_READY, false)
return kong.response.exit(204)
end

return kong.response.exit(400)
end
}
},
}
Loading

1 comment on commit 11bc3b6

@github-actions
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bazel Build

Docker image available kong/kong:11bc3b6c487f46f83cea1ab70b27e129d59de4b6
Artifacts available https://github.com/Kong/kong/actions/runs/12002294593

Please sign in to comment.