Skip to content

Commit 2fb2fe7

Browse files
authored
fix: correct pre/post hook typos in Kubernetes discovery and improve cleanup safety (#12288)
1 parent 3a8d6b8 commit 2fb2fe7

File tree

3 files changed

+166
-9
lines changed

3 files changed

+166
-9
lines changed

apisix/discovery/kubernetes/informer_factory.lua

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,7 @@ local function list_watch(informer, apiserver)
285285

286286
core.log.info("begin to list ", informer.kind)
287287
informer.fetch_state = "listing"
288-
if informer.pre_List then
288+
if informer.pre_list then
289289
informer:pre_list()
290290
end
291291

@@ -298,7 +298,7 @@ local function list_watch(informer, apiserver)
298298
end
299299

300300
informer.fetch_state = "list finished"
301-
if informer.post_List then
301+
if informer.post_list then
302302
informer:post_list()
303303
end
304304

apisix/discovery/kubernetes/init.lua

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ local function sort_nodes_cmp(left, right)
5151
return left.port < right.port
5252
end
5353

54-
local function on_endpoint_slices_modified(handle, endpoint)
54+
local function on_endpoint_slices_modified(handle, endpoint, operate)
5555
if handle.namespace_selector and
5656
not handle:namespace_selector(endpoint.metadata.namespace) then
5757
return
@@ -114,10 +114,15 @@ local function on_endpoint_slices_modified(handle, endpoint)
114114
if err then
115115
core.log.error("set endpoint into discovery DICT failed, ", err)
116116
handle.endpoint_dict:delete(endpoint_key .. "#version")
117+
return
118+
end
119+
if operate == "list" then
120+
handle.current_keys_hash[endpoint_key] = true
121+
handle.current_keys_hash[endpoint_key .. "#version"] = true
117122
end
118123
end
119124

120-
local function on_endpoint_modified(handle, endpoint)
125+
local function on_endpoint_modified(handle, endpoint, operate)
121126
if handle.namespace_selector and
122127
not handle:namespace_selector(endpoint.metadata.namespace) then
123128
return
@@ -177,6 +182,11 @@ local function on_endpoint_modified(handle, endpoint)
177182
if err then
178183
core.log.error("set endpoint into discovery DICT failed, ", err)
179184
handle.endpoint_dict:delete(endpoint_key .. "#version")
185+
return
186+
end
187+
if operate == "list" then
188+
handle.current_keys_hash[endpoint_key] = true
189+
handle.current_keys_hash[endpoint_key .. "#version"] = true
180190
end
181191
end
182192

@@ -195,12 +205,23 @@ end
195205

196206

197207
local function pre_list(handle)
198-
handle.endpoint_dict:flush_all()
208+
handle.current_keys_hash = {}
209+
handle.existing_keys = handle.endpoint_dict:get_keys(0)
199210
end
200211

201212

202213
local function post_list(handle)
203-
handle.endpoint_dict:flush_expired()
214+
if not handle.existing_keys or not handle.current_keys_hash then
215+
return
216+
end
217+
for _, key in ipairs(handle.existing_keys) do
218+
if not handle.current_keys_hash[key] then
219+
core.log.info("kubernetes discovery module find dirty data in shared dict, key:", key)
220+
handle.endpoint_dict:delete(key)
221+
end
222+
end
223+
handle.existing_keys = nil
224+
handle.current_keys_hash = nil
204225
end
205226

206227

@@ -369,7 +390,7 @@ local function get_apiserver(conf)
369390
end
370391

371392
local function create_endpoint_lrucache(endpoint_dict, endpoint_key, endpoint_port)
372-
local endpoint_content = endpoint_dict:get_stale(endpoint_key)
393+
local endpoint_content = endpoint_dict:get(endpoint_key)
373394
if not endpoint_content then
374395
core.log.error("get empty endpoint content from discovery DIC, this should not happen ",
375396
endpoint_key)
@@ -497,7 +518,7 @@ local function single_mode_nodes(service_name)
497518
local endpoint_dict = ctx
498519
local endpoint_key = match[1]
499520
local endpoint_port = match[2]
500-
local endpoint_version = endpoint_dict:get_stale(endpoint_key .. "#version")
521+
local endpoint_version = endpoint_dict:get(endpoint_key .. "#version")
501522
if not endpoint_version then
502523
core.log.info("get empty endpoint version from discovery DICT ", endpoint_key)
503524
return nil
@@ -612,7 +633,7 @@ local function multiple_mode_nodes(service_name)
612633

613634
local endpoint_key = match[2]
614635
local endpoint_port = match[3]
615-
local endpoint_version = endpoint_dict:get_stale(endpoint_key .. "#version")
636+
local endpoint_version = endpoint_dict:get(endpoint_key .. "#version")
616637
if not endpoint_version then
617638
core.log.info("get empty endpoint version from discovery DICT ", endpoint_key)
618639
return nil

t/kubernetes/discovery/kubernetes3.t

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,13 @@ _EOC_
242242
}
243243
}
244244
245+
location /t {
246+
content_by_lua_block {
247+
ngx.sleep(2)
248+
ngx.exit(200)
249+
}
250+
}
251+
245252
_EOC_
246253

247254
$block->set_value("config", $config);
@@ -493,3 +500,132 @@ GET /dump
493500
GET /dump
494501
--- response_body_like
495502
.*"name":"default/kubernetes".*
503+
504+
505+
506+
=== TEST 7: test pre_list and post_list work for single-k8s with endpoint_slices
507+
--- log_level: info
508+
--- yaml_config eval: $::single_yaml_config
509+
--- extra_init_by_lua
510+
local ngx = ngx
511+
local core = require("apisix.core")
512+
513+
local dict = ngx.shared["kubernetes"]
514+
local ok,err = dict:set("dirty_key", true)
515+
if not ok then
516+
core.log.error("set dirty_key to dict fail, err: ", err)
517+
end
518+
--- request
519+
GET /t
520+
--- no_error_log
521+
[error]
522+
--- grep_error_log eval
523+
qr/kubernetes discovery module find dirty data in shared dict/
524+
--- grep_error_log_out
525+
kubernetes discovery module find dirty data in shared dict
526+
527+
528+
529+
=== TEST 8: test pre_list and post_list work for multi-k8s with endpoint_slices
530+
--- log_level: info
531+
--- yaml_config eval: $::yaml_config
532+
--- extra_init_by_lua
533+
local ngx = ngx
534+
local core = require("apisix.core")
535+
536+
local dict = ngx.shared["kubernetes-first"]
537+
local ok,err = dict:set("dirty_key", true)
538+
if not ok then
539+
core.log.error("set dirty_key to dict fail, err: ", err)
540+
end
541+
--- request
542+
GET /t
543+
--- no_error_log
544+
[error]
545+
--- grep_error_log eval
546+
qr/kubernetes discovery module find dirty data in shared dict/
547+
--- grep_error_log_out
548+
kubernetes discovery module find dirty data in shared dict
549+
550+
551+
552+
=== TEST 9: test pre_list and post_list work for single-k8s with endpoints
553+
--- log_level: info
554+
--- yaml_config
555+
apisix:
556+
node_listen: 1984
557+
deployment:
558+
role: data_plane
559+
role_data_plane:
560+
config_provider: yaml
561+
discovery:
562+
kubernetes:
563+
service:
564+
host: "127.0.0.1"
565+
port: "6443"
566+
client:
567+
token_file: "/tmp/var/run/secrets/kubernetes.io/serviceaccount/token"
568+
watch_endpoint_slices: false
569+
--- extra_init_by_lua
570+
local ngx = ngx
571+
local core = require("apisix.core")
572+
573+
local dict = ngx.shared["kubernetes"]
574+
local ok,err = dict:set("dirty_key", true)
575+
if not ok then
576+
core.log.error("set dirty_key to dict fail, err: ", err)
577+
end
578+
--- request
579+
GET /t
580+
--- no_error_log
581+
[error]
582+
--- grep_error_log eval
583+
qr/kubernetes discovery module find dirty data in shared dict/
584+
--- grep_error_log_out
585+
kubernetes discovery module find dirty data in shared dict
586+
587+
588+
589+
=== TEST 10: test pre_list and post_list work for multi-k8s with endpoints
590+
--- log_level: info
591+
--- yaml_config
592+
apisix:
593+
node_listen: 1984
594+
deployment:
595+
role: data_plane
596+
role_data_plane:
597+
config_provider: yaml
598+
discovery:
599+
kubernetes:
600+
- id: first
601+
service:
602+
host: "127.0.0.1"
603+
port: "6443"
604+
client:
605+
token_file: "/tmp/var/run/secrets/kubernetes.io/serviceaccount/token"
606+
watch_endpoint_slices: false
607+
- id: second
608+
service:
609+
schema: "http"
610+
host: "127.0.0.1"
611+
port: "6445"
612+
client:
613+
token_file: "/tmp/var/run/secrets/kubernetes.io/serviceaccount/token"
614+
watch_endpoint_slices: false
615+
--- extra_init_by_lua
616+
local ngx = ngx
617+
local core = require("apisix.core")
618+
619+
local dict = ngx.shared["kubernetes-first"]
620+
local ok,err = dict:set("dirty_key", true)
621+
if not ok then
622+
core.log.error("set dirty_key to dict fail, err: ", err)
623+
end
624+
--- request
625+
GET /t
626+
--- no_error_log
627+
[error]
628+
--- grep_error_log eval
629+
qr/kubernetes discovery module find dirty data in shared dict/
630+
--- grep_error_log_out
631+
kubernetes discovery module find dirty data in shared dict

0 commit comments

Comments
 (0)