Skip to content

Commit a87ffaf

Browse files
jkohenjcantrill
authored andcommitted
Improve Kubernetes pod lookups (#189)
This PR contains the following related fixes to pod lookup performance: Cache results from get_pods. Restrict get_pods and watch_pods requests to the current host, if provided with the K8S_NODE_NAME environment variable. Force lookup from API server cache by setting resourceVersion=0 in get_pods request.
1 parent a055a1c commit a87ffaf

File tree

4 files changed

+91
-11
lines changed

4 files changed

+91
-11
lines changed

fluent-plugin-kubernetes_metadata_filter.gemspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ Gem::Specification.new do |gem|
2323
gem.add_runtime_dependency "lru_redux"
2424
gem.add_runtime_dependency "kubeclient", '< 5'
2525

26-
gem.add_development_dependency "bundler", "~> 1.3"
26+
gem.add_development_dependency "bundler", "~> 2.0.2"
2727
gem.add_development_dependency "rake"
2828
gem.add_development_dependency "minitest", "~> 4.0"
2929
gem.add_development_dependency "test-unit", "~> 3.0.2"

lib/fluent/plugin/kubernetes_metadata_watch_pods.rb

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,20 @@ module WatchPods
2525

2626
def start_pod_watch
2727
begin
28-
resource_version = @client.get_pods.resourceVersion
29-
watcher = @client.watch_pods(resource_version)
28+
options = {
29+
resource_version: '0' # Fetch from API server.
30+
}
31+
if ENV['K8S_NODE_NAME']
32+
options[:field_selector] = 'spec.nodeName=' + ENV['K8S_NODE_NAME']
33+
end
34+
pods = @client.get_pods(options)
35+
pods.each do |pod|
36+
cache_key = pod.metadata['uid']
37+
@cache[cache_key] = parse_pod_metadata(pod)
38+
@stats.bump(:pod_cache_host_updates)
39+
end
40+
options[:resource_version] = pods.resourceVersion
41+
watcher = @client.watch_pods(options)
3042
rescue Exception => e
3143
message = "Exception encountered fetching metadata from Kubernetes API endpoint: #{e.message}"
3244
message += " (#{e.response})" if e.respond_to?(:response)

test/plugin/test_watch_pods.rb

Lines changed: 72 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,47 @@ class DefaultPodWatchStrategyTest < WatchTest
2525
include KubernetesMetadata::WatchPods
2626

2727
setup do
28+
@initial = Kubeclient::Common::EntityList.new(
29+
'PodList',
30+
'123',
31+
[
32+
Kubeclient::Resource.new({
33+
'metadata' => {
34+
'name' => 'initial',
35+
'namespace' => 'initial_ns',
36+
'uid' => 'initial_uid',
37+
'labels' => {},
38+
},
39+
'spec' => {
40+
'nodeName' => 'aNodeName',
41+
'containers' => [{
42+
'name' => 'foo',
43+
'image' => 'bar',
44+
}, {
45+
'name' => 'bar',
46+
'image' => 'foo',
47+
}]
48+
}
49+
}),
50+
Kubeclient::Resource.new({
51+
'metadata' => {
52+
'name' => 'modified',
53+
'namespace' => 'create',
54+
'uid' => 'modified_uid',
55+
'labels' => {},
56+
},
57+
'spec' => {
58+
'nodeName' => 'aNodeName',
59+
'containers' => [{
60+
'name' => 'foo',
61+
'image' => 'bar',
62+
}, {
63+
'name' => 'bar',
64+
'image' => 'foo',
65+
}]
66+
}
67+
}),
68+
])
2869
@created = OpenStruct.new(
2970
type: 'CREATED',
3071
object: {
@@ -97,11 +138,38 @@ class DefaultPodWatchStrategyTest < WatchTest
97138
)
98139
end
99140

141+
test 'pod list caches pods' do
142+
orig_env_val = ENV['K8S_NODE_NAME']
143+
ENV['K8S_NODE_NAME'] = 'aNodeName'
144+
@client.stub :get_pods, @initial do
145+
start_pod_watch
146+
assert_equal(true, @cache.key?('initial_uid'))
147+
assert_equal(true, @cache.key?('modified_uid'))
148+
assert_equal(2, @stats[:pod_cache_host_updates])
149+
end
150+
ENV['K8S_NODE_NAME'] = orig_env_val
151+
end
152+
153+
test 'pod list caches pods and watch updates' do
154+
orig_env_val = ENV['K8S_NODE_NAME']
155+
ENV['K8S_NODE_NAME'] = 'aNodeName'
156+
@client.stub :get_pods, @initial do
157+
@client.stub :watch_pods, [@modified] do
158+
start_pod_watch
159+
assert_equal(2, @stats[:pod_cache_host_updates])
160+
assert_equal(1, @stats[:pod_cache_watch_updates])
161+
end
162+
end
163+
ENV['K8S_NODE_NAME'] = orig_env_val
164+
end
165+
100166
test 'pod watch notice ignores CREATED' do
101-
@client.stub :watch_pods, [@created] do
102-
start_pod_watch
103-
assert_equal(false, @cache.key?('created_uid'))
104-
assert_equal(1, @stats[:pod_cache_watch_ignored])
167+
@client.stub :get_pods, @initial do
168+
@client.stub :watch_pods, [@created] do
169+
start_pod_watch
170+
assert_equal(false, @cache.key?('created_uid'))
171+
assert_equal(1, @stats[:pod_cache_watch_ignored])
172+
end
105173
end
106174
end
107175

test/plugin/watch_test.rb

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,16 +30,16 @@ class WatchTest < Test::Unit::TestCase
3030
def @client.resourceVersion
3131
'12345'
3232
end
33-
def @client.watch_pods(value)
33+
def @client.watch_pods(options = {})
3434
[]
3535
end
36-
def @client.watch_namespaces(value)
36+
def @client.watch_namespaces(options = {})
3737
[]
3838
end
39-
def @client.get_namespaces
39+
def @client.get_namespaces(options = {})
4040
self
4141
end
42-
def @client.get_pods
42+
def @client.get_pods(options = {})
4343
self
4444
end
4545
end

0 commit comments

Comments
 (0)