Skip to content

Commit

Permalink
feat(conf) implement 'node_id' for configurable node ID (#10385)
Browse files Browse the repository at this point in the history
Kong automatically generates node IDs for each node in a cluster.
Node IDs are the only unique identifiers that exist to track a Kong node
within a cluster (no assumption is made that hostname is unique across
all Kong nodes).

When integrating closely with an orchestrator, a configurable node ID
helps the operator to source the ID from the underlying orchestrator
like kubernetes instead of letting Kong generating one.

For most customers, letting Kong generate a Node ID will be sufficient.
  • Loading branch information
hbagdi authored and pull[bot] committed Aug 23, 2024
1 parent dc83ea3 commit 84abc0a
Show file tree
Hide file tree
Showing 7 changed files with 80 additions and 11 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@
- Add Postgres triggers on the core entites and entities in bundled plugins to delete the
expired rows in an efficient and timely manner.
[#10389](https://github.com/Kong/kong/pull/10389)
- Support for configurable Node IDs
[#10385](https://github.com/Kong/kong/pull/10385)

#### Admin API

Expand Down
5 changes: 5 additions & 0 deletions kong.conf.default
Original file line number Diff line number Diff line change
Expand Up @@ -1899,3 +1899,8 @@
# Setting this attribute disables the search
# behavior and explicitly instructs Kong which
# OpenResty installation to use.

#node_id = # Node ID for the Kong node. Every Kong node
# in a Kong cluster must have a unique and
# valid UUID. When empty, node ID is
# automatically generated.
4 changes: 4 additions & 0 deletions kong/conf_loader/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -1275,6 +1275,10 @@ local function check_and_parse(conf, opts)
errors[#errors + 1] = "lua_max_post_args must be an integer between 1 and 1000"
end

if conf.node_id and not utils.is_valid_uuid(conf.node_id) then
errors[#errors + 1] = "node_id must be a valid UUID"
end

return #errors == 0, errors[1], errors
end

Expand Down
38 changes: 27 additions & 11 deletions kong/pdk/node.lua
Original file line number Diff line number Diff line change
Expand Up @@ -258,20 +258,36 @@ local function new(self)
end


-- the PDK can be even when there is no configuration (for docs/tests)
-- so execute below block only when running under correct context
local prefix = self and self.configuration and self.configuration.prefix
if prefix and self.configuration.role == "data_plane" then
local id, err = private_node.load_node_id(prefix)
if id then
node_id = id
ngx.log(ngx.DEBUG, "restored node_id from the filesystem: ", node_id)

else
id = _NODE.get_id()
if err then
ngx.log(ngx.WARN, "failed to restore node_id from the filesystem: ",
err, ", so a new one was generated: ", id)
if prefix then
-- precedence order:
-- 1. user provided node id
local configuration_node_id = self and self.configuration and self.configuration.node_id
if configuration_node_id then
node_id = configuration_node_id
end
-- 2. node id (if any) on file-system
if not node_id then
if prefix and self.configuration.role == "data_plane" then
local id, err = private_node.load_node_id(prefix)
if id then
node_id = id
ngx.log(ngx.DEBUG, "restored node_id from the filesystem: ", node_id)
else
ngx.log(ngx.WARN, "failed to restore node_id from the filesystem: ",
err, ", a new node_id will be generated")
end
end
end
-- 3. generate a new id
if not node_id then
node_id = _NODE.get_id()
end
if node_id then
ngx.log(ngx.INFO, "kong node-id: " .. node_id)
end
end

return _NODE
Expand Down
1 change: 1 addition & 0 deletions kong/templates/kong_defaults.lua
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ error_template_html = NONE
error_template_json = NONE
error_template_xml = NONE
error_template_plain = NONE
node_id = NONE
proxy_listen = 0.0.0.0:8000 reuseport backlog=16384, 0.0.0.0:8443 http2 ssl reuseport backlog=16384
stream_listen = off
Expand Down
14 changes: 14 additions & 0 deletions spec/01-unit/03-conf_loader_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -667,6 +667,20 @@ describe("Configuration loader", function()
assert.is_nil(err)
assert.is_table(conf)
end)
it("errors when node_id is not a valid uuid", function()
local conf, err = conf_loader(nil, {
node_id = "foobar",
})
assert.equal("node_id must be a valid UUID", err)
assert.is_nil(conf)
end)
it("accepts a valid UUID as node_id", function()
local conf, err = conf_loader(nil, {
node_id = "8b7de2ba-0477-4667-a811-8bca46073ca9",
})
assert.is_nil(err)
assert.equal("8b7de2ba-0477-4667-a811-8bca46073ca9", conf.node_id)
end)
it("errors when the hosts file does not exist", function()
local tmpfile = "/a_file_that_does_not_exist"
local conf, err = conf_loader(nil, {
Expand Down
27 changes: 27 additions & 0 deletions spec/02-integration/04-admin_api/02-kong_routes_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -570,3 +570,30 @@ describe("Admin API - Kong routes with strategy #" .. strategy, function()
end)
end)
end
describe("Admin API - node ID is set correctly", function()
local client
local input_node_id = "592e1c2b-6678-45aa-80f9-78cfb29f5e31"
lazy_setup(function()
helpers.get_db_utils(nil, {}) -- runs migrations
assert(helpers.start_kong {
node_id = input_node_id
})
client = helpers.admin_client(10000)
end)

lazy_teardown(function()
if client then client:close() end
helpers.stop_kong()
end)

it("returns node-id set in configuration", function()
local res1 = assert(client:send {
method = "GET",
path = "/"
})

local body = assert.res_status(200, res1)
local json = cjson.decode(body)
assert.equal(input_node_id, json.node_id)
end)
end)

0 comments on commit 84abc0a

Please sign in to comment.