fluent-plugin-kubernetes-metrics 1.1.4 → 1.1.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +39 -36
- data/README.md +0 -1
- data/VERSION +1 -1
- data/fluent-plugin-kubernetes-metrics.gemspec +1 -1
- data/lib/fluent/plugin/in_kubernetes_metrics.rb +36 -15
- data/test/plugin/test_in_kubernetes_metrics.rb +14 -13
- metadata +5 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: '01494a399012dc40a3a2d9597327839453e95abc642d5510ad3e423b50c9fd25'
|
4
|
+
data.tar.gz: d7d5f2f45267de03f5e519b4ac48ad0b03ae9058a04f399e563c529da1664c7f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 870c5b311bd3157f485872149ae1d360cbfc0e44a804c92863d17fe40a114854a6722f512d58f505cdbde950f851b780aba2ceb364bc5b01ab8819bb3c37fe1a
|
7
|
+
data.tar.gz: 99b97218aa1a33de365d6ce36f8403f774cba1e2975255253fa5147241b143009082320ffd934752a2b485a42a2d2ed9af2a06d4de0f6ebf99c38ac3ad07f5cd
|
data/Gemfile.lock
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
fluent-plugin-kubernetes-metrics (1.1.
|
5
|
-
fluentd (
|
4
|
+
fluent-plugin-kubernetes-metrics (1.1.8)
|
5
|
+
fluentd (>= 1.9.1)
|
6
6
|
kubeclient (~> 4.6.0)
|
7
7
|
multi_json (~> 1.14.1)
|
8
8
|
oj (~> 3.10.2)
|
@@ -10,65 +10,67 @@ PATH
|
|
10
10
|
GEM
|
11
11
|
remote: https://rubygems.org/
|
12
12
|
specs:
|
13
|
-
addressable (2.
|
14
|
-
public_suffix (>= 2.0.2, <
|
15
|
-
concurrent-ruby (1.1.
|
16
|
-
cool.io (1.
|
17
|
-
crack (0.4.
|
18
|
-
|
19
|
-
docile (1.
|
13
|
+
addressable (2.8.0)
|
14
|
+
public_suffix (>= 2.0.2, < 5.0)
|
15
|
+
concurrent-ruby (1.1.9)
|
16
|
+
cool.io (1.7.1)
|
17
|
+
crack (0.4.5)
|
18
|
+
rexml
|
19
|
+
docile (1.4.0)
|
20
20
|
domain_name (0.5.20190701)
|
21
21
|
unf (>= 0.0.5, < 1.0.0)
|
22
|
-
ffi (1.
|
22
|
+
ffi (1.15.4)
|
23
23
|
ffi-compiler (1.0.1)
|
24
24
|
ffi (>= 1.0.0)
|
25
25
|
rake
|
26
|
-
fluentd (1.
|
26
|
+
fluentd (1.14.2)
|
27
|
+
bundler
|
27
28
|
cool.io (>= 1.4.5, < 2.0.0)
|
28
|
-
http_parser.rb (>= 0.5.1, < 0.
|
29
|
+
http_parser.rb (>= 0.5.1, < 0.8.0)
|
29
30
|
msgpack (>= 1.3.1, < 2.0.0)
|
30
|
-
serverengine (>= 2.
|
31
|
+
serverengine (>= 2.2.2, < 3.0.0)
|
31
32
|
sigdump (~> 0.2.2)
|
32
|
-
strptime (>= 0.2.
|
33
|
+
strptime (>= 0.2.4, < 1.0.0)
|
33
34
|
tzinfo (>= 1.0, < 3.0)
|
34
35
|
tzinfo-data (~> 1.0)
|
36
|
+
webrick (>= 1.4.2, < 1.8.0)
|
35
37
|
yajl-ruby (~> 1.0)
|
36
|
-
hashdiff (0.
|
37
|
-
http (4.
|
38
|
+
hashdiff (1.0.1)
|
39
|
+
http (4.4.1)
|
38
40
|
addressable (~> 2.3)
|
39
41
|
http-cookie (~> 1.0)
|
40
42
|
http-form_data (~> 2.2)
|
41
43
|
http-parser (~> 1.2.0)
|
42
44
|
http-accept (1.7.0)
|
43
|
-
http-cookie (1.0.
|
45
|
+
http-cookie (1.0.4)
|
44
46
|
domain_name (~> 0.5)
|
45
|
-
http-form_data (2.
|
46
|
-
http-parser (1.2.
|
47
|
+
http-form_data (2.3.0)
|
48
|
+
http-parser (1.2.3)
|
47
49
|
ffi-compiler (>= 1.0, < 2.0)
|
48
|
-
http_parser.rb (0.
|
49
|
-
json (2.
|
50
|
+
http_parser.rb (0.7.0)
|
51
|
+
json (2.6.1)
|
50
52
|
kubeclient (4.6.0)
|
51
53
|
http (>= 3.0, < 5.0)
|
52
54
|
recursive-open-struct (~> 1.0, >= 1.0.4)
|
53
55
|
rest-client (~> 2.0)
|
54
56
|
mime-types (3.3.1)
|
55
57
|
mime-types-data (~> 3.2015)
|
56
|
-
mime-types-data (3.
|
57
|
-
msgpack (1.
|
58
|
+
mime-types-data (3.2021.0901)
|
59
|
+
msgpack (1.4.2)
|
58
60
|
multi_json (1.14.1)
|
59
61
|
netrc (0.11.0)
|
60
|
-
oj (3.10.
|
61
|
-
power_assert (
|
62
|
-
public_suffix (
|
63
|
-
rake (13.0.
|
64
|
-
recursive-open-struct (1.1.
|
62
|
+
oj (3.10.18)
|
63
|
+
power_assert (2.0.1)
|
64
|
+
public_suffix (4.0.6)
|
65
|
+
rake (13.0.6)
|
66
|
+
recursive-open-struct (1.1.3)
|
65
67
|
rest-client (2.1.0)
|
66
68
|
http-accept (>= 1.7.0, < 2.0)
|
67
69
|
http-cookie (>= 1.0.2, < 2.0)
|
68
70
|
mime-types (>= 1.16, < 4.0)
|
69
71
|
netrc (~> 0.8)
|
70
|
-
|
71
|
-
serverengine (2.2.
|
72
|
+
rexml (3.2.5)
|
73
|
+
serverengine (2.2.4)
|
72
74
|
sigdump (~> 0.2.2)
|
73
75
|
sigdump (0.2.4)
|
74
76
|
simplecov (0.16.1)
|
@@ -76,20 +78,21 @@ GEM
|
|
76
78
|
json (>= 1.8, < 3)
|
77
79
|
simplecov-html (~> 0.10.0)
|
78
80
|
simplecov-html (0.10.2)
|
79
|
-
strptime (0.2.
|
80
|
-
test-unit (3.3.
|
81
|
+
strptime (0.2.5)
|
82
|
+
test-unit (3.3.9)
|
81
83
|
power_assert
|
82
|
-
tzinfo (2.0.
|
84
|
+
tzinfo (2.0.4)
|
83
85
|
concurrent-ruby (~> 1.0)
|
84
|
-
tzinfo-data (1.
|
86
|
+
tzinfo-data (1.2021.5)
|
85
87
|
tzinfo (>= 1.0.0)
|
86
88
|
unf (0.1.4)
|
87
89
|
unf_ext
|
88
|
-
unf_ext (0.0.
|
90
|
+
unf_ext (0.0.8)
|
89
91
|
webmock (3.5.1)
|
90
92
|
addressable (>= 2.3.6)
|
91
93
|
crack (>= 0.3.2)
|
92
94
|
hashdiff
|
95
|
+
webrick (1.7.0)
|
93
96
|
yajl-ruby (1.4.1)
|
94
97
|
|
95
98
|
PLATFORMS
|
@@ -104,4 +107,4 @@ DEPENDENCIES
|
|
104
107
|
webmock (~> 3.5.1)
|
105
108
|
|
106
109
|
BUNDLED WITH
|
107
|
-
2.
|
110
|
+
2.2.33
|
data/README.md
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
[![CircleCI](https://circleci.com/gh/git-lfs/git-lfs.svg?style=shield&circle-token=856152c2b02bfd236f54d21e1f581f3e4ebf47ad)](https://circleci.com/gh/splunk/fluent-plugin-kubernetes-metrics)
|
2
1
|
# Fluentd Plugin for Kubernetes Metrics
|
3
2
|
|
4
3
|
The [Fluentd](https://fluentd.org/) input plugin collects Kubernetes cluster metrics which are exposed by the [Kubelet API](https://kubernetes.io/docs/admin/kubelet/) and forwards them to fluentd.
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.1.
|
1
|
+
1.1.8
|
@@ -24,7 +24,7 @@ Gem::Specification.new do |spec|
|
|
24
24
|
spec.add_development_dependency 'simplecov', '~> 0.16.1'
|
25
25
|
spec.add_development_dependency 'test-unit', '~> 3.3.0'
|
26
26
|
spec.add_development_dependency 'webmock', '~> 3.5.1'
|
27
|
-
spec.add_runtime_dependency 'fluentd', '
|
27
|
+
spec.add_runtime_dependency 'fluentd', '>= 1.9.1'
|
28
28
|
spec.add_runtime_dependency 'kubeclient', '~> 4.6.0'
|
29
29
|
spec.add_runtime_dependency 'multi_json', '~> 1.14.1'
|
30
30
|
spec.add_runtime_dependency 'oj', '~> 3.10.2'
|
@@ -90,8 +90,13 @@ module Fluent
|
|
90
90
|
super
|
91
91
|
|
92
92
|
timer_execute :metric_scraper, @interval, &method(:scrape_metrics)
|
93
|
-
timer_execute :stats_metric_scraper, @interval, &method(:scrape_stats_metrics)
|
94
93
|
timer_execute :cadvisor_metric_scraper, @interval, &method(:scrape_cadvisor_metrics)
|
94
|
+
# It is done to optionally fetch from 'stats' for k8s version <1.21
|
95
|
+
if is_stats_endpoint_available?
|
96
|
+
timer_execute :stats_metric_scraper, @interval, &method(:scrape_stats_metrics)
|
97
|
+
else
|
98
|
+
log.info "'/stats' endpoint is not available. It has been deprecated since k8s v1.15, disabled since v1.18, and removed in v1.21 and onwards"
|
99
|
+
end
|
95
100
|
end
|
96
101
|
|
97
102
|
def close
|
@@ -597,33 +602,35 @@ module Fluent
|
|
597
602
|
emit_stats_breakdown(metrics['stats']) unless metrics['stats'].nil?
|
598
603
|
end
|
599
604
|
|
605
|
+
# Make sure regex has only one capturing group
|
606
|
+
def grep_using_regex(metric, regex)
|
607
|
+
match = metric.match(regex)
|
608
|
+
return nil if match.nil?
|
609
|
+
match[1]
|
610
|
+
end
|
611
|
+
|
600
612
|
def emit_cadvisor_metrics(metrics)
|
601
613
|
metrics = metrics.split("\n")
|
602
614
|
metrics.each do |metric|
|
603
|
-
|
604
|
-
|
605
|
-
next
|
606
|
-
|
615
|
+
|
616
|
+
next if metric[0] == '#' or not container_name = grep_using_regex(metric, /container(?:_name)?="([^"]*)"/)
|
617
|
+
next if container_name.empty?
|
618
|
+
|
607
619
|
metric_str, metric_val = metric.split(' ')
|
608
620
|
metric_val = metric_val.to_f if metric_val.is_a? String
|
609
621
|
first_occur = metric_str.index('{')
|
610
622
|
metric_name = metric_str[0..first_occur - 1]
|
611
|
-
pod_name = metric
|
612
|
-
|
613
|
-
|
614
|
-
image_name = image_name.split('"')[1]
|
615
|
-
namespace = metric.match(/namespace="\S*"/).to_s
|
616
|
-
namespace = namespace.split('"')[1]
|
623
|
+
pod_name = grep_using_regex(metric, /pod(?:_name)?="([^"]*)"/).to_s
|
624
|
+
image_name = grep_using_regex(metric, /image="([^"]*)"/).to_s
|
625
|
+
namespace = grep_using_regex(metric, /namespace="([^"]*)"/).to_s
|
617
626
|
metric_labels = { 'pod_name' => pod_name, 'image' => image_name, 'namespace' => namespace, 'value' => metric_val, 'node' => @node_name }
|
618
|
-
if
|
627
|
+
if container_name=="POD"
|
619
628
|
tag = 'pod'
|
620
629
|
tag = generate_tag("#{tag}#{metric_name.tr('_', '.')}")
|
621
630
|
tag = tag.gsub('container', '')
|
622
631
|
else
|
623
|
-
container_name = metric.match(/container_name="\S*"/).to_s
|
624
|
-
container_name = container_name.split('"')[1]
|
625
632
|
container_label = { 'container_name' => container_name }
|
626
|
-
metric_labels.merge(container_label)
|
633
|
+
metric_labels.merge!(container_label)
|
627
634
|
tag = generate_tag(metric_name.tr('_', '.').to_s)
|
628
635
|
end
|
629
636
|
router.emit tag, @scraped_at_cadvisor, metric_labels
|
@@ -642,6 +649,20 @@ module Fluent
|
|
642
649
|
end
|
643
650
|
end
|
644
651
|
|
652
|
+
def is_stats_endpoint_available?
|
653
|
+
if @use_rest_client
|
654
|
+
response_stats = RestClient::Request.execute request_options_stats
|
655
|
+
else
|
656
|
+
@node_names.each do |node|
|
657
|
+
@node_name = node
|
658
|
+
response_stats = stats_proxy_api(node).get(@client.headers)
|
659
|
+
end
|
660
|
+
end
|
661
|
+
true
|
662
|
+
rescue RestClient::NotFound
|
663
|
+
false
|
664
|
+
end
|
665
|
+
|
645
666
|
def scrape_stats_metrics
|
646
667
|
if @use_rest_client
|
647
668
|
response_stats = RestClient::Request.execute request_options_stats
|
@@ -35,6 +35,9 @@ class KubernetesMetricsInputTest < Test::Unit::TestCase
|
|
35
35
|
).freeze
|
36
36
|
|
37
37
|
setup do
|
38
|
+
stub_k8s_requests
|
39
|
+
|
40
|
+
return unless @@hash_map_test.empty?
|
38
41
|
Fluent::Test.setup
|
39
42
|
|
40
43
|
@@parsed_unit_string = JSON.parse(get_unit_parsed_string)
|
@@ -45,8 +48,6 @@ class KubernetesMetricsInputTest < Test::Unit::TestCase
|
|
45
48
|
get_cadvisor_parsed_string = f.read
|
46
49
|
end.close
|
47
50
|
|
48
|
-
stub_k8s_requests
|
49
|
-
|
50
51
|
@@ca_driver = create_driver
|
51
52
|
@@ca_driver.run timeout: 20, expect_emits: 1, shutdown: true
|
52
53
|
|
@@ -56,8 +57,12 @@ class KubernetesMetricsInputTest < Test::Unit::TestCase
|
|
56
57
|
metrics = get_cadvisor_parsed_string.split("\n")
|
57
58
|
metrics.each do |metric|
|
58
59
|
next unless metric.include? 'container_name='
|
60
|
+
next unless metric[0] != '#'
|
59
61
|
|
60
|
-
|
62
|
+
container_name = metric.match(/container_name="\S*"/).to_s
|
63
|
+
container_name = container_name.split('"')[1]
|
64
|
+
|
65
|
+
next if container_name.empty?
|
61
66
|
|
62
67
|
metric_str, metric_val = metric.split(' ')
|
63
68
|
metric_val = metric_val.to_f if metric_val.is_a? String
|
@@ -70,13 +75,11 @@ class KubernetesMetricsInputTest < Test::Unit::TestCase
|
|
70
75
|
namespace = metric.match(/namespace="\S*"/).to_s
|
71
76
|
namespace = namespace.split('"')[1]
|
72
77
|
metric_labels = { 'pod_name' => pod_name, 'image' => image_name, 'namespace' => namespace, 'value' => metric_val, 'node' => @node_name }
|
73
|
-
if
|
78
|
+
if container_name == 'POD'
|
74
79
|
tag = 'pod'
|
75
80
|
tag = generate_tag("#{tag}#{metric_name.tr('_', '.')}", @@driver.instance.tag)
|
76
81
|
tag = tag.gsub('container', '')
|
77
82
|
else
|
78
|
-
container_name = metric.match(/container_name="\S*"/).to_s
|
79
|
-
container_name = container_name.split('"')[1]
|
80
83
|
container_label = { 'container_name' => container_name }
|
81
84
|
metric_labels.merge(container_label)
|
82
85
|
tag = generate_tag(metric_name.tr('_', '.').to_s, @@driver.instance.tag)
|
@@ -252,11 +255,10 @@ class KubernetesMetricsInputTest < Test::Unit::TestCase
|
|
252
255
|
assert_true @@hash_map_cadvisor.key?('kube.container.fs.read.seconds.total')
|
253
256
|
assert_equal @@hash_map_cadvisor['kube.container.fs.read.seconds.total'], @@hash_map_test['kube.container.fs.read.seconds.total'][2]['value']
|
254
257
|
end
|
255
|
-
|
256
|
-
# TODO: Current Test does not work - metric present in metrics_cadvisor.txt but not being parsed by connector in test/working in production
|
258
|
+
|
257
259
|
test 'Test - metrics cadvisor: container_fs_reads_bytes_total' do
|
258
|
-
|
259
|
-
|
260
|
+
assert_true @@hash_map_cadvisor.key?('kube.container.fs.reads.bytes.total')
|
261
|
+
assert_equal @@hash_map_cadvisor['kube.container.fs.reads.bytes.total'], @@hash_map_test["kube.container.fs.reads.bytes.total"][2]["value"]
|
260
262
|
end
|
261
263
|
|
262
264
|
test 'Test - metrics cadvisor: container_fs_reads_merged_total' do
|
@@ -289,10 +291,9 @@ class KubernetesMetricsInputTest < Test::Unit::TestCase
|
|
289
291
|
assert_equal @@hash_map_cadvisor['kube.container.fs.write.seconds.total'], @@hash_map_test['kube.container.fs.write.seconds.total'][2]['value']
|
290
292
|
end
|
291
293
|
|
292
|
-
# TODO: Current Test does not work - metric present in metrics_cadvisor.txt but not being parsed by connector in test/working in production
|
293
294
|
test 'Test - metrics cadvisor: container_fs_writes_bytes_total' do
|
294
|
-
|
295
|
-
|
295
|
+
assert_true @@hash_map_cadvisor.key?('kube.container.fs.writes.bytes.total')
|
296
|
+
assert_equal @@hash_map_cadvisor['kube.container.fs.writes.bytes.total'], @@hash_map_test["kube.container.fs.writes.bytes.total"][2]["value"]
|
296
297
|
end
|
297
298
|
|
298
299
|
test 'Test - metrics cadvisor: container_fs_writes_merged_total' do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fluent-plugin-kubernetes-metrics
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.1.
|
4
|
+
version: 1.1.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Splunk Inc.
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-12-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -84,14 +84,14 @@ dependencies:
|
|
84
84
|
name: fluentd
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
|
-
- - "
|
87
|
+
- - ">="
|
88
88
|
- !ruby/object:Gem::Version
|
89
89
|
version: 1.9.1
|
90
90
|
type: :runtime
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
|
-
- - "
|
94
|
+
- - ">="
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: 1.9.1
|
97
97
|
- !ruby/object:Gem::Dependency
|
@@ -175,7 +175,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
175
175
|
- !ruby/object:Gem::Version
|
176
176
|
version: '0'
|
177
177
|
requirements: []
|
178
|
-
rubygems_version: 3.1.
|
178
|
+
rubygems_version: 3.1.4
|
179
179
|
signing_key:
|
180
180
|
specification_version: 4
|
181
181
|
summary: A fluentd input plugin that collects kubernetes cluster metrics.
|