diff --git a/rootfs/etc/nginx/lua/balancer.lua b/rootfs/etc/nginx/lua/balancer.lua index bd6f264f2..fb955337c 100644 --- a/rootfs/etc/nginx/lua/balancer.lua +++ b/rootfs/etc/nginx/lua/balancer.lua @@ -23,6 +23,7 @@ local ngx = ngx -- it will take + BACKENDS_SYNC_INTERVAL local BACKENDS_SYNC_INTERVAL = 1 +local BACKENDS_FORCE_SYNC_INTERVAL = 30 local DEFAULT_LB_ALG = "round_robin" local IMPLEMENTATIONS = { @@ -36,6 +37,8 @@ local IMPLEMENTATIONS = { local _M = {} local balancers = {} +local backends_with_external_name = {} +local backends_last_synced_at = 0 local function get_implementation(backend) local name = backend["load-balance"] or DEFAULT_LB_ALG @@ -92,6 +95,12 @@ local function format_ipv6_endpoints(endpoints) return formatted_endpoints end +local function is_backend_with_external_name(backend) + local serv_type = backend.service and backend.service.spec + and backend.service.spec["type"] + return serv_type == "ExternalName" +end + local function sync_backend(backend) if not backend.endpoints or #backend.endpoints == 0 then balancers[backend.name] = nil @@ -117,9 +126,7 @@ local function sync_backend(backend) return end - local service_type = backend.service and backend.service.spec - and backend.service.spec["type"] - if service_type == "ExternalName" then + if is_backend_with_external_name(backend) then backend = resolve_external_names(backend) end @@ -129,6 +136,17 @@ local function sync_backend(backend) end local function sync_backends() + local raw_backends_last_synced_at = configuration.get_raw_backends_last_synced_at() + ngx.update_time() + local current_timestamp = ngx.time() + if current_timestamp - backends_last_synced_at < BACKENDS_FORCE_SYNC_INTERVAL + and raw_backends_last_synced_at <= backends_last_synced_at then + for _, backend_with_external_name in pairs(backends_with_external_name) do + sync_backend(backend_with_external_name) + end + return + end + local backends_data = configuration.get_backends_data() if not backends_data then balancers = {} @@ -145,13 +163,19 @@ local function sync_backends() for _, new_backend in ipairs(new_backends) do sync_backend(new_backend) balancers_to_keep[new_backend.name] = balancers[new_backend.name] + if is_backend_with_external_name(new_backend) then + local backend_with_external_name = util.deepcopy(new_backend) + backends_with_external_name[backend_with_external_name.name] = backend_with_external_name + end end for backend_name, _ in pairs(balancers) do if not balancers_to_keep[backend_name] then balancers[backend_name] = nil + backends_with_external_name[backend_name] = nil end end + backends_last_synced_at = raw_backends_last_synced_at end local function route_to_alternative_balancer(balancer) diff --git a/rootfs/etc/nginx/lua/configuration.lua b/rootfs/etc/nginx/lua/configuration.lua index fbf78f208..84076c406 100644 --- a/rootfs/etc/nginx/lua/configuration.lua +++ b/rootfs/etc/nginx/lua/configuration.lua @@ -24,6 +24,14 @@ function _M.get_general_data() return configuration_data:get("general") end +function _M.get_raw_backends_last_synced_at() + local raw_backends_last_synced_at = configuration_data:get("raw_backends_last_synced_at") + if raw_backends_last_synced_at == nil then + raw_backends_last_synced_at = 1 + end + return raw_backends_last_synced_at +end + local function fetch_request_body() ngx.req.read_body() local body = ngx.req.get_body_data() @@ -187,6 +195,16 @@ local function handle_backends() return end + ngx.update_time() + local raw_backends_last_synced_at = ngx.time() + success, err = configuration_data:set("raw_backends_last_synced_at", raw_backends_last_synced_at) + if not success then + ngx.log(ngx.ERR, "dynamic-configuration: error updating when backends sync, " .. + "new upstream peers waiting for force syncing: " .. tostring(err)) + ngx.status = ngx.HTTP_BAD_REQUEST + return + end + ngx.status = ngx.HTTP_CREATED end diff --git a/rootfs/etc/nginx/lua/tcp_udp_balancer.lua b/rootfs/etc/nginx/lua/tcp_udp_balancer.lua index 0d7da9cf8..d90458762 100644 --- a/rootfs/etc/nginx/lua/tcp_udp_balancer.lua +++ b/rootfs/etc/nginx/lua/tcp_udp_balancer.lua @@ -18,6 +18,7 @@ local getmetatable = getmetatable -- it will take + BACKENDS_SYNC_INTERVAL local BACKENDS_SYNC_INTERVAL = 1 +local BACKENDS_FORCE_SYNC_INTERVAL = 30 local DEFAULT_LB_ALG = "round_robin" local IMPLEMENTATIONS = { @@ -26,6 +27,8 @@ local IMPLEMENTATIONS = { local _M = {} local balancers = {} +local backends_with_external_name = {} +local backends_last_synced_at = 0 local function get_implementation(backend) local name = backend["load-balance"] or DEFAULT_LB_ALG @@ -65,6 +68,12 @@ local function format_ipv6_endpoints(endpoints) return formatted_endpoints end +local function is_backend_with_external_name(backend) + local serv_type = backend.service and backend.service.spec + and backend.service.spec["type"] + return serv_type == "ExternalName" +end + local function sync_backend(backend) if not backend.endpoints or #backend.endpoints == 0 then return @@ -89,9 +98,7 @@ local function sync_backend(backend) return end - local service_type = backend.service and backend.service.spec and - backend.service.spec["type"] - if service_type == "ExternalName" then + if is_backend_with_external_name(backend) then backend = resolve_external_names(backend) end @@ -101,6 +108,17 @@ local function sync_backend(backend) end local function sync_backends() + local raw_backends_last_synced_at = configuration.get_raw_backends_last_synced_at() + ngx.update_time() + local current_timestamp = ngx.time() + if current_timestamp - backends_last_synced_at < BACKENDS_FORCE_SYNC_INTERVAL + and raw_backends_last_synced_at <= backends_last_synced_at then + for _, backend_with_external_name in pairs(backends_with_external_name) do + sync_backend(backend_with_external_name) + end + return + end + local backends_data = configuration.get_backends_data() if not backends_data then balancers = {} @@ -117,13 +135,19 @@ local function sync_backends() for _, new_backend in ipairs(new_backends) do sync_backend(new_backend) balancers_to_keep[new_backend.name] = balancers[new_backend.name] + if is_backend_with_external_name(new_backend) then + local backend_with_external_name = util.deepcopy(new_backend) + backends_with_external_name[backend_with_external_name.name] = backend_with_external_name + end end for backend_name, _ in pairs(balancers) do if not balancers_to_keep[backend_name] then balancers[backend_name] = nil + backends_with_external_name[backend_name] = nil end end + backends_last_synced_at = raw_backends_last_synced_at end local function get_balancer() diff --git a/rootfs/etc/nginx/lua/tcp_udp_configuration.lua b/rootfs/etc/nginx/lua/tcp_udp_configuration.lua index 40d3443da..85864b45b 100644 --- a/rootfs/etc/nginx/lua/tcp_udp_configuration.lua +++ b/rootfs/etc/nginx/lua/tcp_udp_configuration.lua @@ -9,6 +9,14 @@ function _M.get_backends_data() return tcp_udp_configuration_data:get("backends") end +function _M.get_raw_backends_last_synced_at() + local raw_backends_last_synced_at = tcp_udp_configuration_data:get("raw_backends_last_synced_at") + if raw_backends_last_synced_at == nil then + raw_backends_last_synced_at = 1 + end + return raw_backends_last_synced_at +end + function _M.call() local sock, err = ngx.req.socket(true) if not sock then @@ -35,6 +43,17 @@ function _M.call() ngx.say("error: ", err_conf) return end + + ngx.update_time() + local raw_backends_last_synced_at = ngx.time() + success, err = tcp_udp_configuration_data:set("raw_backends_last_synced_at", + raw_backends_last_synced_at) + if not success then + ngx.log(ngx.ERR, "dynamic-configuration: error updating when backends sync, " .. + "new upstream peers waiting for force syncing: " .. tostring(err)) + ngx.status = ngx.HTTP_BAD_REQUEST + return + end end return _M