fluent-plugin-kubernetes_metadata_filter 2.5.1 → 2.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.circleci/config.yml +7 -7
- data/.rubocop.yml +57 -0
- data/Gemfile +4 -2
- data/Gemfile.lock +49 -47
- data/README.md +4 -2
- data/Rakefile +15 -11
- data/fluent-plugin-kubernetes_metadata_filter.gemspec +25 -27
- data/lib/fluent/plugin/filter_kubernetes_metadata.rb +110 -121
- data/lib/fluent/plugin/kubernetes_metadata_cache_strategy.rb +22 -18
- data/lib/fluent/plugin/kubernetes_metadata_common.rb +44 -63
- data/lib/fluent/plugin/kubernetes_metadata_stats.rb +6 -6
- data/lib/fluent/plugin/kubernetes_metadata_test_api_adapter.rb +68 -0
- data/lib/fluent/plugin/kubernetes_metadata_util.rb +53 -0
- data/lib/fluent/plugin/kubernetes_metadata_watch_namespaces.rb +75 -59
- data/lib/fluent/plugin/kubernetes_metadata_watch_pods.rb +92 -81
- data/test/helper.rb +20 -2
- data/test/plugin/test_cache_stats.rb +10 -13
- data/test/plugin/test_cache_strategy.rb +158 -160
- data/test/plugin/test_filter_kubernetes_metadata.rb +366 -346
- data/test/plugin/test_utils.rb +56 -0
- data/test/plugin/test_watch_namespaces.rb +188 -125
- data/test/plugin/test_watch_pods.rb +282 -226
- data/test/plugin/watch_test.rb +14 -15
- metadata +49 -66
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
#
|
2
4
|
# Fluentd Kubernetes Metadata Filter Plugin - Enrich Fluentd events with
|
3
5
|
# Kubernetes metadata
|
@@ -20,6 +22,7 @@
|
|
20
22
|
require_relative 'kubernetes_metadata_cache_strategy'
|
21
23
|
require_relative 'kubernetes_metadata_common'
|
22
24
|
require_relative 'kubernetes_metadata_stats'
|
25
|
+
require_relative 'kubernetes_metadata_util'
|
23
26
|
require_relative 'kubernetes_metadata_watch_namespaces'
|
24
27
|
require_relative 'kubernetes_metadata_watch_pods'
|
25
28
|
|
@@ -33,6 +36,7 @@ module Fluent::Plugin
|
|
33
36
|
|
34
37
|
include KubernetesMetadata::CacheStrategy
|
35
38
|
include KubernetesMetadata::Common
|
39
|
+
include KubernetesMetadata::Util
|
36
40
|
include KubernetesMetadata::WatchNamespaces
|
37
41
|
include KubernetesMetadata::WatchPods
|
38
42
|
|
@@ -49,7 +53,7 @@ module Fluent::Plugin
|
|
49
53
|
config_param :verify_ssl, :bool, default: true
|
50
54
|
config_param :tag_to_kubernetes_name_regexp,
|
51
55
|
:string,
|
52
|
-
:
|
56
|
+
default: 'var\.log\.containers\.(?<pod_name>[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*)_(?<namespace>[^_]+)_(?<container_name>.+)-(?<docker_id>[a-z0-9]{64})\.log$'
|
53
57
|
config_param :bearer_token_file, :string, default: nil
|
54
58
|
config_param :secret_dir, :string, default: '/var/run/secrets/kubernetes.io/serviceaccount'
|
55
59
|
config_param :de_dot, :bool, default: true
|
@@ -65,7 +69,7 @@ module Fluent::Plugin
|
|
65
69
|
# parse format is defined here: https://github.com/kubernetes/kubernetes/blob/release-1.6/pkg/kubelet/dockertools/docker.go#L317
|
66
70
|
config_param :container_name_to_kubernetes_regexp,
|
67
71
|
:string,
|
68
|
-
:
|
72
|
+
default: '^(?<name_prefix>[^_]+)_(?<container_name>[^\._]+)(\.(?<container_hash>[^_]+))?_(?<pod_name>[^_]+)_(?<namespace>[^_]+)_[^_]+_[^_]+$'
|
69
73
|
|
70
74
|
config_param :annotation_match, :array, default: []
|
71
75
|
config_param :stats_interval, :integer, default: 30
|
@@ -81,6 +85,11 @@ module Fluent::Plugin
|
|
81
85
|
config_param :skip_container_metadata, :bool, default: false
|
82
86
|
config_param :skip_master_url, :bool, default: false
|
83
87
|
config_param :skip_namespace_metadata, :bool, default: false
|
88
|
+
|
89
|
+
# A classname in the form of Test::APIAdapter which will try
|
90
|
+
# to be resolved from a relative named file 'test_api_adapter'
|
91
|
+
config_param :test_api_adapter, :string, default: nil
|
92
|
+
|
84
93
|
# The time interval in seconds for retry backoffs when watch connections fail.
|
85
94
|
config_param :watch_retry_interval, :integer, default: 1
|
86
95
|
# The base number of exponential backoff for retries.
|
@@ -90,35 +99,25 @@ module Fluent::Plugin
|
|
90
99
|
|
91
100
|
def fetch_pod_metadata(namespace_name, pod_name)
|
92
101
|
log.trace("fetching pod metadata: #{namespace_name}/#{pod_name}") if log.trace?
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
return metadata
|
106
|
-
rescue Exception=>e
|
107
|
-
log.debug(e)
|
108
|
-
@stats.bump(:pod_cache_api_nil_bad_resp_payload)
|
109
|
-
log.trace("returning empty metadata for #{namespace_name}/#{pod_name} due to error '#{e}'") if log.trace?
|
110
|
-
end
|
111
|
-
end
|
112
|
-
rescue Exception=>e
|
113
|
-
@stats.bump(:pod_cache_api_nil_error)
|
114
|
-
log.debug "Exception '#{e}' encountered fetching pod metadata from Kubernetes API #{@apiVersion} endpoint #{@kubernetes_url}"
|
115
|
-
end
|
102
|
+
options = {
|
103
|
+
resource_version: '0' # Fetch from API server cache instead of etcd quorum read
|
104
|
+
}
|
105
|
+
pod_object = @client.get_pod(pod_name, namespace_name, options)
|
106
|
+
log.trace("raw metadata for #{namespace_name}/#{pod_name}: #{pod_object}") if log.trace?
|
107
|
+
metadata = parse_pod_metadata(pod_object)
|
108
|
+
@stats.bump(:pod_cache_api_updates)
|
109
|
+
log.trace("parsed metadata for #{namespace_name}/#{pod_name}: #{metadata}") if log.trace?
|
110
|
+
@cache[metadata['pod_id']] = metadata
|
111
|
+
rescue StandardError => e
|
112
|
+
@stats.bump(:pod_cache_api_nil_error)
|
113
|
+
log.debug "Exception '#{e}' encountered fetching pod metadata from Kubernetes API #{@apiVersion} endpoint #{@kubernetes_url}"
|
116
114
|
{}
|
117
115
|
end
|
118
116
|
|
119
117
|
def dump_stats
|
120
118
|
@curr_time = Time.now
|
121
119
|
return if @curr_time.to_i - @prev_time.to_i < @stats_interval
|
120
|
+
|
122
121
|
@prev_time = @curr_time
|
123
122
|
@stats.set(:pod_cache_size, @cache.count)
|
124
123
|
@stats.set(:namespace_cache_size, @namespace_cache.count) if @namespace_cache
|
@@ -132,29 +131,18 @@ module Fluent::Plugin
|
|
132
131
|
|
133
132
|
def fetch_namespace_metadata(namespace_name)
|
134
133
|
log.trace("fetching namespace metadata: #{namespace_name}") if log.trace?
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
return metadata
|
148
|
-
rescue Exception => e
|
149
|
-
log.debug(e)
|
150
|
-
@stats.bump(:namespace_cache_api_nil_bad_resp_payload)
|
151
|
-
log.trace("returning empty metadata for #{namespace_name} due to error '#{e}'") if log.trace?
|
152
|
-
end
|
153
|
-
end
|
154
|
-
rescue Exception => kube_error
|
155
|
-
@stats.bump(:namespace_cache_api_nil_error)
|
156
|
-
log.debug "Exception '#{kube_error}' encountered fetching namespace metadata from Kubernetes API #{@apiVersion} endpoint #{@kubernetes_url}"
|
157
|
-
end
|
134
|
+
options = {
|
135
|
+
resource_version: '0' # Fetch from API server cache instead of etcd quorum read
|
136
|
+
}
|
137
|
+
namespace_object = @client.get_namespace(namespace_name, nil, options)
|
138
|
+
log.trace("raw metadata for #{namespace_name}: #{namespace_object}") if log.trace?
|
139
|
+
metadata = parse_namespace_metadata(namespace_object)
|
140
|
+
@stats.bump(:namespace_cache_api_updates)
|
141
|
+
log.trace("parsed metadata for #{namespace_name}: #{metadata}") if log.trace?
|
142
|
+
@namespace_cache[metadata['namespace_id']] = metadata
|
143
|
+
rescue StandardError => e
|
144
|
+
@stats.bump(:namespace_cache_api_nil_error)
|
145
|
+
log.debug "Exception '#{e}' encountered fetching namespace metadata from Kubernetes API #{@apiVersion} endpoint #{@kubernetes_url}"
|
158
146
|
{}
|
159
147
|
end
|
160
148
|
|
@@ -174,12 +162,12 @@ module Fluent::Plugin
|
|
174
162
|
require 'lru_redux'
|
175
163
|
@stats = KubernetesMetadata::Stats.new
|
176
164
|
|
177
|
-
if @de_dot &&
|
165
|
+
if @de_dot && @de_dot_separator.include?('.')
|
178
166
|
raise Fluent::ConfigError, "Invalid de_dot_separator: cannot be or contain '.'"
|
179
167
|
end
|
180
168
|
|
181
169
|
if @cache_ttl < 0
|
182
|
-
log.info
|
170
|
+
log.info 'Setting the cache TTL to :none because it was <= 0'
|
183
171
|
@cache_ttl = :none
|
184
172
|
end
|
185
173
|
|
@@ -197,11 +185,11 @@ module Fluent::Plugin
|
|
197
185
|
|
198
186
|
# Use Kubernetes default service account if we're in a pod.
|
199
187
|
if @kubernetes_url.nil?
|
200
|
-
log.debug
|
188
|
+
log.debug 'Kubernetes URL is not set - inspecting environ'
|
201
189
|
|
202
190
|
env_host = ENV['KUBERNETES_SERVICE_HOST']
|
203
191
|
env_port = ENV['KUBERNETES_SERVICE_PORT']
|
204
|
-
if
|
192
|
+
if present?(env_host) && present?(env_port)
|
205
193
|
if env_host =~ Resolv::IPv6::Regex
|
206
194
|
# Brackets are needed around IPv6 addresses
|
207
195
|
env_host = "[#{env_host}]"
|
@@ -209,7 +197,7 @@ module Fluent::Plugin
|
|
209
197
|
@kubernetes_url = "https://#{env_host}:#{env_port}/api"
|
210
198
|
log.debug "Kubernetes URL is now '#{@kubernetes_url}'"
|
211
199
|
else
|
212
|
-
log.debug
|
200
|
+
log.debug 'No Kubernetes URL could be found in config or environ'
|
213
201
|
end
|
214
202
|
end
|
215
203
|
|
@@ -219,24 +207,23 @@ module Fluent::Plugin
|
|
219
207
|
ca_cert = File.join(@secret_dir, K8_POD_CA_CERT)
|
220
208
|
pod_token = File.join(@secret_dir, K8_POD_TOKEN)
|
221
209
|
|
222
|
-
if
|
210
|
+
if !present?(@ca_file) && File.exist?(ca_cert)
|
223
211
|
log.debug "Found CA certificate: #{ca_cert}"
|
224
212
|
@ca_file = ca_cert
|
225
213
|
end
|
226
214
|
|
227
|
-
if
|
215
|
+
if !present?(@bearer_token_file) && File.exist?(pod_token)
|
228
216
|
log.debug "Found pod token: #{pod_token}"
|
229
217
|
@bearer_token_file = pod_token
|
230
218
|
end
|
231
219
|
end
|
232
220
|
|
233
|
-
if @kubernetes_url
|
234
|
-
|
221
|
+
if present?(@kubernetes_url)
|
235
222
|
ssl_options = {
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
223
|
+
client_cert: present?(@client_cert) ? OpenSSL::X509::Certificate.new(File.read(@client_cert)) : nil,
|
224
|
+
client_key: present?(@client_key) ? OpenSSL::PKey::RSA.new(File.read(@client_key)) : nil,
|
225
|
+
ca_file: @ca_file,
|
226
|
+
verify_ssl: @verify_ssl ? OpenSSL::SSL::VERIFY_PEER : OpenSSL::SSL::VERIFY_NONE
|
240
227
|
}
|
241
228
|
|
242
229
|
if @ssl_partial_chain
|
@@ -244,39 +231,53 @@ module Fluent::Plugin
|
|
244
231
|
require 'openssl'
|
245
232
|
ssl_store = OpenSSL::X509::Store.new
|
246
233
|
ssl_store.set_default_paths
|
247
|
-
if defined? OpenSSL::X509::V_FLAG_PARTIAL_CHAIN
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
234
|
+
flagval = if defined? OpenSSL::X509::V_FLAG_PARTIAL_CHAIN
|
235
|
+
OpenSSL::X509::V_FLAG_PARTIAL_CHAIN
|
236
|
+
else
|
237
|
+
# this version of ruby does not define OpenSSL::X509::V_FLAG_PARTIAL_CHAIN
|
238
|
+
0x80000
|
239
|
+
end
|
253
240
|
ssl_store.flags = OpenSSL::X509::V_FLAG_CRL_CHECK_ALL | flagval
|
254
241
|
ssl_options[:cert_store] = ssl_store
|
255
242
|
end
|
256
243
|
|
257
244
|
auth_options = {}
|
258
245
|
|
259
|
-
if @bearer_token_file
|
246
|
+
if present?(@bearer_token_file)
|
260
247
|
bearer_token = File.read(@bearer_token_file)
|
261
248
|
auth_options[:bearer_token] = bearer_token
|
262
249
|
end
|
263
250
|
|
264
|
-
log.debug
|
265
|
-
@client = Kubeclient::Client.new
|
266
|
-
|
267
|
-
|
251
|
+
log.debug 'Creating K8S client'
|
252
|
+
@client = Kubeclient::Client.new(
|
253
|
+
@kubernetes_url,
|
254
|
+
@apiVersion,
|
255
|
+
ssl_options: ssl_options,
|
256
|
+
auth_options: auth_options,
|
257
|
+
as: :parsed_symbolized
|
258
|
+
)
|
259
|
+
|
260
|
+
if @test_api_adapter
|
261
|
+
log.info "Extending client with test api adaper #{@test_api_adapter}"
|
262
|
+
require_relative @test_api_adapter.underscore
|
263
|
+
@client.extend(eval(@test_api_adapter))
|
264
|
+
end
|
268
265
|
|
269
266
|
begin
|
270
267
|
@client.api_valid?
|
271
|
-
rescue KubeException =>
|
272
|
-
raise Fluent::ConfigError, "Invalid Kubernetes API #{@apiVersion} endpoint #{@kubernetes_url}: #{
|
268
|
+
rescue KubeException => e
|
269
|
+
raise Fluent::ConfigError, "Invalid Kubernetes API #{@apiVersion} endpoint #{@kubernetes_url}: #{e.message}"
|
273
270
|
end
|
274
271
|
|
275
272
|
if @watch
|
276
|
-
|
273
|
+
if ENV['K8S_NODE_NAME'].nil? || ENV['K8S_NODE_NAME'].strip.empty?
|
274
|
+
log.warn("!! The environment variable 'K8S_NODE_NAME' is not set to the node name which can affect the API server and watch efficiency !!")
|
275
|
+
end
|
276
|
+
|
277
|
+
pod_thread = Thread.new(self, &:set_up_pod_thread)
|
277
278
|
pod_thread.abort_on_exception = true
|
278
279
|
|
279
|
-
namespace_thread = Thread.new(self
|
280
|
+
namespace_thread = Thread.new(self, &:set_up_namespace_thread)
|
280
281
|
namespace_thread.abort_on_exception = true
|
281
282
|
end
|
282
283
|
end
|
@@ -287,25 +288,22 @@ module Fluent::Plugin
|
|
287
288
|
|
288
289
|
@annotations_regexps = []
|
289
290
|
@annotation_match.each do |regexp|
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
log.error "Error: invalid regular expression in annotation_match: #{e}"
|
294
|
-
end
|
291
|
+
@annotations_regexps << Regexp.compile(regexp)
|
292
|
+
rescue RegexpError => e
|
293
|
+
log.error "Error: invalid regular expression in annotation_match: #{e}"
|
295
294
|
end
|
296
|
-
|
297
295
|
end
|
298
296
|
|
299
297
|
def get_metadata_for_record(namespace_name, pod_name, container_name, container_id, create_time, batch_miss_cache)
|
300
298
|
metadata = {
|
301
|
-
'docker' => {'container_id' => container_id},
|
299
|
+
'docker' => { 'container_id' => container_id },
|
302
300
|
'kubernetes' => {
|
303
|
-
'container_name'
|
304
|
-
'namespace_name'
|
305
|
-
'pod_name'
|
301
|
+
'container_name' => container_name,
|
302
|
+
'namespace_name' => namespace_name,
|
303
|
+
'pod_name' => pod_name
|
306
304
|
}
|
307
305
|
}
|
308
|
-
if @kubernetes_url
|
306
|
+
if present?(@kubernetes_url)
|
309
307
|
pod_metadata = get_pod_metadata(container_id, namespace_name, pod_name, create_time, batch_miss_cache)
|
310
308
|
|
311
309
|
if (pod_metadata.include? 'containers') && (pod_metadata['containers'].include? container_id) && !@skip_container_metadata
|
@@ -319,22 +317,9 @@ module Fluent::Plugin
|
|
319
317
|
metadata
|
320
318
|
end
|
321
319
|
|
322
|
-
def create_time_from_record(record, internal_time)
|
323
|
-
time_key = @time_fields.detect{ |ii| record.has_key?(ii) }
|
324
|
-
time = record[time_key]
|
325
|
-
if time.nil? || time.chop.empty?
|
326
|
-
# `internal_time` is a Fluent::EventTime, it can't compare with Time.
|
327
|
-
return Time.at(internal_time.to_f)
|
328
|
-
end
|
329
|
-
if ['_SOURCE_REALTIME_TIMESTAMP', '__REALTIME_TIMESTAMP'].include?(time_key)
|
330
|
-
timei= time.to_i
|
331
|
-
return Time.at(timei / 1000000, timei % 1000000)
|
332
|
-
end
|
333
|
-
return Time.parse(time)
|
334
|
-
end
|
335
|
-
|
336
320
|
def filter_stream(tag, es)
|
337
321
|
return es if (es.respond_to?(:empty?) && es.empty?) || !es.is_a?(Fluent::EventStream)
|
322
|
+
|
338
323
|
new_es = Fluent::MultiEventStream.new
|
339
324
|
tag_match_data = tag.match(@tag_to_kubernetes_name_regexp_compiled) unless @use_journal
|
340
325
|
tag_metadata = nil
|
@@ -342,23 +327,23 @@ module Fluent::Plugin
|
|
342
327
|
es.each do |time, record|
|
343
328
|
if tag_match_data && tag_metadata.nil?
|
344
329
|
tag_metadata = get_metadata_for_record(tag_match_data['namespace'], tag_match_data['pod_name'], tag_match_data['container_name'],
|
345
|
-
|
330
|
+
tag_match_data['docker_id'], create_time_from_record(record, time), batch_miss_cache)
|
346
331
|
end
|
347
332
|
metadata = Marshal.load(Marshal.dump(tag_metadata)) if tag_metadata
|
348
333
|
if (@use_journal || @use_journal.nil?) &&
|
349
|
-
|
334
|
+
(j_metadata = get_metadata_for_journal_record(record, time, batch_miss_cache))
|
350
335
|
metadata = j_metadata
|
351
336
|
end
|
352
|
-
if @lookup_from_k8s_field && record.
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
337
|
+
if @lookup_from_k8s_field && record.key?('kubernetes') && record.key?('docker') &&
|
338
|
+
record['kubernetes'].respond_to?(:has_key?) && record['docker'].respond_to?(:has_key?) &&
|
339
|
+
record['kubernetes'].key?('namespace_name') &&
|
340
|
+
record['kubernetes'].key?('pod_name') &&
|
341
|
+
record['kubernetes'].key?('container_name') &&
|
342
|
+
record['docker'].key?('container_id') &&
|
343
|
+
(k_metadata = get_metadata_for_record(record['kubernetes']['namespace_name'], record['kubernetes']['pod_name'],
|
344
|
+
record['kubernetes']['container_name'], record['docker']['container_id'],
|
345
|
+
create_time_from_record(record, time), batch_miss_cache))
|
346
|
+
metadata = k_metadata
|
362
347
|
end
|
363
348
|
|
364
349
|
record = record.merge(metadata) if metadata
|
@@ -370,16 +355,16 @@ module Fluent::Plugin
|
|
370
355
|
|
371
356
|
def get_metadata_for_journal_record(record, time, batch_miss_cache)
|
372
357
|
metadata = nil
|
373
|
-
if record.
|
358
|
+
if record.key?('CONTAINER_NAME') && record.key?('CONTAINER_ID_FULL')
|
374
359
|
metadata = record['CONTAINER_NAME'].match(@container_name_to_kubernetes_regexp_compiled) do |match_data|
|
375
360
|
get_metadata_for_record(match_data['namespace'], match_data['pod_name'], match_data['container_name'],
|
376
|
-
|
361
|
+
record['CONTAINER_ID_FULL'], create_time_from_record(record, time), batch_miss_cache)
|
377
362
|
end
|
378
363
|
unless metadata
|
379
364
|
log.debug "Error: could not match CONTAINER_NAME from record #{record}"
|
380
365
|
@stats.bump(:container_name_match_failed)
|
381
366
|
end
|
382
|
-
elsif record.
|
367
|
+
elsif record.key?('CONTAINER_NAME') && record['CONTAINER_NAME'].start_with?('k8s_')
|
383
368
|
log.debug "Error: no container name and id in record #{record}"
|
384
369
|
@stats.bump(:container_name_id_missing)
|
385
370
|
end
|
@@ -388,13 +373,17 @@ module Fluent::Plugin
|
|
388
373
|
|
389
374
|
def de_dot!(h)
|
390
375
|
h.keys.each do |ref|
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
376
|
+
next unless h[ref] && ref =~ /\./
|
377
|
+
|
378
|
+
v = h.delete(ref)
|
379
|
+
newref = ref.to_s.gsub('.', @de_dot_separator)
|
380
|
+
h[newref] = v
|
396
381
|
end
|
397
382
|
end
|
398
383
|
|
384
|
+
# copied from activesupport
|
385
|
+
def present?(object)
|
386
|
+
object.respond_to?(:empty?) ? !object.empty? : !!object
|
387
|
+
end
|
399
388
|
end
|
400
389
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
#
|
2
4
|
# Fluentd Kubernetes Metadata Filter Plugin - Enrich Fluentd events with
|
3
5
|
# Kubernetes metadata
|
@@ -21,31 +23,20 @@ module KubernetesMetadata
|
|
21
23
|
def get_pod_metadata(key, namespace_name, pod_name, record_create_time, batch_miss_cache)
|
22
24
|
metadata = {}
|
23
25
|
ids = @id_cache[key]
|
24
|
-
if
|
26
|
+
if ids.nil?
|
25
27
|
# FAST PATH
|
26
28
|
# Cache hit, fetch metadata from the cache
|
27
|
-
metadata = @cache.fetch(ids[:pod_id]) do
|
28
|
-
@stats.bump(:pod_cache_miss)
|
29
|
-
m = fetch_pod_metadata(namespace_name, pod_name)
|
30
|
-
(m.nil? || m.empty?) ? {'pod_id'=>ids[:pod_id]} : m
|
31
|
-
end
|
32
|
-
metadata.merge!(@namespace_cache.fetch(ids[:namespace_id]) do
|
33
|
-
@stats.bump(:namespace_cache_miss)
|
34
|
-
m = fetch_namespace_metadata(namespace_name) unless @skip_namespace_metadata
|
35
|
-
(m.nil? || m.empty?) ? {'namespace_id'=>ids[:namespace_id]} : m
|
36
|
-
end)
|
37
|
-
else
|
38
|
-
# SLOW PATH
|
39
29
|
@stats.bump(:id_cache_miss)
|
40
30
|
return batch_miss_cache["#{namespace_name}_#{pod_name}"] if batch_miss_cache.key?("#{namespace_name}_#{pod_name}")
|
31
|
+
|
41
32
|
pod_metadata = fetch_pod_metadata(namespace_name, pod_name)
|
42
33
|
if @skip_namespace_metadata
|
43
|
-
ids = { :
|
34
|
+
ids = { pod_id: pod_metadata['pod_id'] }
|
44
35
|
@id_cache[key] = ids
|
45
36
|
return pod_metadata
|
46
37
|
end
|
47
38
|
namespace_metadata = fetch_namespace_metadata(namespace_name)
|
48
|
-
ids = { :
|
39
|
+
ids = { pod_id: pod_metadata['pod_id'], namespace_id: namespace_metadata['namespace_id'] }
|
49
40
|
if !ids[:pod_id].nil? && !ids[:namespace_id].nil?
|
50
41
|
# pod found and namespace found
|
51
42
|
metadata = pod_metadata
|
@@ -59,7 +50,7 @@ module KubernetesMetadata
|
|
59
50
|
# namespace is older then record for pod
|
60
51
|
ids[:pod_id] = key
|
61
52
|
metadata = @cache.fetch(ids[:pod_id]) do
|
62
|
-
|
53
|
+
{ 'pod_id' => ids[:pod_id] }
|
63
54
|
end
|
64
55
|
end
|
65
56
|
metadata.merge!(namespace_metadata)
|
@@ -87,12 +78,25 @@ module KubernetesMetadata
|
|
87
78
|
end
|
88
79
|
end
|
89
80
|
@id_cache[key] = ids unless batch_miss_cache.key?("#{namespace_name}_#{pod_name}")
|
81
|
+
else
|
82
|
+
# SLOW PATH
|
83
|
+
metadata = @cache.fetch(ids[:pod_id]) do
|
84
|
+
@stats.bump(:pod_cache_miss)
|
85
|
+
m = fetch_pod_metadata(namespace_name, pod_name)
|
86
|
+
m.nil? || m.empty? ? { 'pod_id' => ids[:pod_id] } : m
|
87
|
+
end
|
88
|
+
metadata.merge!(@namespace_cache.fetch(ids[:namespace_id]) do
|
89
|
+
m = unless @skip_namespace_metadata
|
90
|
+
@stats.bump(:namespace_cache_miss)
|
91
|
+
fetch_namespace_metadata(namespace_name)
|
92
|
+
end
|
93
|
+
m.nil? || m.empty? ? { 'namespace_id' => ids[:namespace_id] } : m
|
94
|
+
end)
|
90
95
|
end
|
91
96
|
|
92
97
|
# remove namespace info that is only used for comparison
|
93
98
|
metadata.delete('creation_timestamp')
|
94
|
-
metadata.delete_if{|
|
99
|
+
metadata.delete_if { |_k, v| v.nil? }
|
95
100
|
end
|
96
|
-
|
97
101
|
end
|
98
102
|
end
|