fluent-plugin-kubernetes_metadata_filter 0.10.0 → 0.11.0
Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4e0fcd32fc3504d09147c16350c4596822151394
|
4
|
+
data.tar.gz: d6032d7ec7cd42cf46fcf101e3d8579883502caf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 606ac89791ceec0de9f1f46d80ced6b126dff9325513c1bc177dcb1cb7f35896f9cdedea4a9aff657f5b0eab1569b0a0eb0143c38c51678cc86cbc5d47c6e1e7
|
7
|
+
data.tar.gz: 98c9aa0d292a7dc9d679ab46961136986ecfbfcfdd2c9276ded1bca00c67fa6ca11a52581942ff3a3d10c32267b259d0267efc0db462f2d8331454f3af6f869c
|
@@ -4,7 +4,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
4
|
|
5
5
|
Gem::Specification.new do |gem|
|
6
6
|
gem.name = "fluent-plugin-kubernetes_metadata_filter"
|
7
|
-
gem.version = "0.
|
7
|
+
gem.version = "0.11.0"
|
8
8
|
gem.authors = ["Jimmi Dyson"]
|
9
9
|
gem.email = ["jimmidyson@gmail.com"]
|
10
10
|
gem.description = %q{Filter plugin to add Kubernetes metadata}
|
@@ -34,20 +34,20 @@ module Fluent
|
|
34
34
|
:default => '\.(?<pod_name>[^\._]+)_(?<namespace>[^_]+)_(?<container_name>.+)-(?<docker_id>[a-z0-9]{64})\.log$'
|
35
35
|
config_param :bearer_token_file, :string, default: ''
|
36
36
|
config_param :merge_json_log, :bool, default: true
|
37
|
+
config_param :include_namespace_id, :bool, default: false
|
37
38
|
|
38
|
-
def get_metadata(
|
39
|
+
def get_metadata(namespace_name, pod_name, container_name)
|
39
40
|
begin
|
40
|
-
metadata = @client.get_pod(pod_name,
|
41
|
-
if metadata
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
end
|
41
|
+
metadata = @client.get_pod(pod_name, namespace_name)
|
42
|
+
return if !metadata
|
43
|
+
return {
|
44
|
+
namespace_name: namespace_name,
|
45
|
+
pod_id: metadata['metadata']['uid'],
|
46
|
+
pod_name: pod_name,
|
47
|
+
container_name: container_name,
|
48
|
+
labels: metadata['metadata']['labels'].to_h,
|
49
|
+
host: metadata['spec']['host']
|
50
|
+
}
|
51
51
|
rescue KubeException
|
52
52
|
nil
|
53
53
|
end
|
@@ -67,7 +67,10 @@ module Fluent
|
|
67
67
|
if @cache_ttl < 0
|
68
68
|
@cache_ttl = :none
|
69
69
|
end
|
70
|
-
@cache
|
70
|
+
@cache = LruRedux::TTL::ThreadSafeCache.new(@cache_size, @cache_ttl)
|
71
|
+
if @include_namespace_id
|
72
|
+
@namespace_cache = LruRedux::TTL::ThreadSafeCache.new(@cache_size, @cache_ttl)
|
73
|
+
end
|
71
74
|
@tag_to_kubernetes_name_regexp_compiled = Regexp.compile(@tag_to_kubernetes_name_regexp)
|
72
75
|
|
73
76
|
if @kubernetes_url.present?
|
@@ -97,10 +100,12 @@ module Fluent
|
|
97
100
|
end
|
98
101
|
|
99
102
|
if @watch
|
100
|
-
thread
|
101
|
-
this.start_watch
|
102
|
-
}
|
103
|
+
thread = Thread.new(self) { |this| this.start_watch }
|
103
104
|
thread.abort_on_exception = true
|
105
|
+
if @include_namespace_id
|
106
|
+
namespace_thread = Thread.new(self) { |this| this.start_namespace_watch }
|
107
|
+
namespace_thread.abort_on_exception = true
|
108
|
+
end
|
104
109
|
end
|
105
110
|
end
|
106
111
|
end
|
@@ -116,20 +121,20 @@ module Fluent
|
|
116
121
|
container_id: match_data['docker_id']
|
117
122
|
},
|
118
123
|
kubernetes: {
|
119
|
-
|
124
|
+
namespace_name: match_data['namespace'],
|
120
125
|
pod_name: match_data['pod_name'],
|
121
126
|
container_name: match_data['container_name']
|
122
127
|
}
|
123
128
|
}
|
124
129
|
|
125
130
|
if @kubernetes_url.present?
|
126
|
-
cache_key = "#{metadata[:kubernetes][:
|
131
|
+
cache_key = "#{metadata[:kubernetes][:namespace_name]}_#{metadata[:kubernetes][:pod_name]}_#{metadata[:kubernetes][:container_name]}"
|
127
132
|
|
128
133
|
this = self
|
129
134
|
metadata = @cache.getset(cache_key) {
|
130
135
|
if metadata
|
131
136
|
kubernetes_metadata = this.get_metadata(
|
132
|
-
metadata[:kubernetes][:
|
137
|
+
metadata[:kubernetes][:namespace_name],
|
133
138
|
metadata[:kubernetes][:pod_name],
|
134
139
|
metadata[:kubernetes][:container_name]
|
135
140
|
)
|
@@ -137,6 +142,14 @@ module Fluent
|
|
137
142
|
metadata
|
138
143
|
end
|
139
144
|
}
|
145
|
+
if @include_namespace_id
|
146
|
+
namespace_name = metadata[:kubernetes][:namespace_name]
|
147
|
+
namespace_id = @namespace_cache.getset(namespace_name) {
|
148
|
+
namespace = @client.get_namespace(namespace_name)
|
149
|
+
namespace['metadata']['uid'] if namespace
|
150
|
+
}
|
151
|
+
metadata[:kubernetes][:namespace_id] = namespace_id if namespace_id
|
152
|
+
end
|
140
153
|
end
|
141
154
|
end
|
142
155
|
|
@@ -196,7 +209,23 @@ module Fluent
|
|
196
209
|
}
|
197
210
|
end
|
198
211
|
else
|
199
|
-
#
|
212
|
+
# Don't pay attention to creations, since the created pod may not
|
213
|
+
# end up on this node.
|
214
|
+
end
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
def start_namespace_watch
|
219
|
+
resource_version = @client.get_namespaces.resourceVersion
|
220
|
+
watcher = @client.watch_namespaces(resource_version)
|
221
|
+
watcher.each do |notice|
|
222
|
+
puts notice
|
223
|
+
case notice.type
|
224
|
+
when 'DELETED'
|
225
|
+
@namespace_cache.delete(notice.object['metadata']['uid'])
|
226
|
+
else
|
227
|
+
# We only care about each namespace's name and UID, neither of which
|
228
|
+
# is modifiable, so we only have to care about deletions.
|
200
229
|
end
|
201
230
|
end
|
202
231
|
end
|
@@ -0,0 +1,228 @@
|
|
1
|
+
#
|
2
|
+
# Fluentd Kubernetes Metadata Filter Plugin - Enrich Fluentd events with
|
3
|
+
# Kubernetes metadata
|
4
|
+
#
|
5
|
+
# Copyright 2015 Red Hat, Inc.
|
6
|
+
#
|
7
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
8
|
+
# you may not use this file except in compliance with the License.
|
9
|
+
# You may obtain a copy of the License at
|
10
|
+
#
|
11
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
12
|
+
#
|
13
|
+
# Unless required by applicable law or agreed to in writing, software
|
14
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
15
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
16
|
+
# See the License for the specific language governing permissions and
|
17
|
+
# limitations under the License.
|
18
|
+
#
|
19
|
+
---
|
20
|
+
http_interactions:
|
21
|
+
- request:
|
22
|
+
method: get
|
23
|
+
uri: https://localhost:8443/api
|
24
|
+
body:
|
25
|
+
encoding: US-ASCII
|
26
|
+
string: ''
|
27
|
+
headers:
|
28
|
+
Accept:
|
29
|
+
- "*/*; q=0.5, application/xml"
|
30
|
+
Accept-Encoding:
|
31
|
+
- gzip, deflate
|
32
|
+
User-Agent:
|
33
|
+
- Ruby
|
34
|
+
response:
|
35
|
+
status:
|
36
|
+
code: 200
|
37
|
+
message: OK
|
38
|
+
headers:
|
39
|
+
Content-Type:
|
40
|
+
- application/json
|
41
|
+
Date:
|
42
|
+
- Fri, 08 May 2015 10:35:37 GMT
|
43
|
+
Content-Length:
|
44
|
+
- '67'
|
45
|
+
body:
|
46
|
+
encoding: UTF-8
|
47
|
+
string: |-
|
48
|
+
{
|
49
|
+
"versions": [
|
50
|
+
"v1"
|
51
|
+
]
|
52
|
+
}
|
53
|
+
http_version:
|
54
|
+
recorded_at: Fri, 08 May 2015 10:35:37 GMT
|
55
|
+
- request:
|
56
|
+
method: get
|
57
|
+
uri: https://localhost:8443/api/v1/namespaces/default/pods/fabric8-console-controller-98rqc
|
58
|
+
body:
|
59
|
+
encoding: US-ASCII
|
60
|
+
string: ''
|
61
|
+
headers:
|
62
|
+
Accept:
|
63
|
+
- "*/*; q=0.5, application/xml"
|
64
|
+
Accept-Encoding:
|
65
|
+
- gzip, deflate
|
66
|
+
User-Agent:
|
67
|
+
- Ruby
|
68
|
+
response:
|
69
|
+
status:
|
70
|
+
code: 200
|
71
|
+
message: OK
|
72
|
+
headers:
|
73
|
+
Content-Type:
|
74
|
+
- application/json
|
75
|
+
Date:
|
76
|
+
- Fri, 08 May 2015 10:35:37 GMT
|
77
|
+
Transfer-Encoding:
|
78
|
+
- chunked
|
79
|
+
body:
|
80
|
+
encoding: UTF-8
|
81
|
+
string: |-
|
82
|
+
{
|
83
|
+
"kind": "Pod",
|
84
|
+
"apiVersion": "v1",
|
85
|
+
"metadata": {
|
86
|
+
"name": "fabric8-console-controller-98rqc",
|
87
|
+
"generateName": "fabric8-console-controller-",
|
88
|
+
"namespace": "default",
|
89
|
+
"selfLink": "/api/v1/namespaces/default/pods/fabric8-console-controller-98rqc",
|
90
|
+
"uid": "c76927af-f563-11e4-b32d-54ee7527188d",
|
91
|
+
"resourceVersion": "122",
|
92
|
+
"creationTimestamp": "2015-05-08T09:22:42Z",
|
93
|
+
"labels": {
|
94
|
+
"component": "fabric8Console"
|
95
|
+
}
|
96
|
+
},
|
97
|
+
"spec": {
|
98
|
+
"volumes": [
|
99
|
+
{
|
100
|
+
"name": "openshift-cert-secrets",
|
101
|
+
"hostPath": null,
|
102
|
+
"emptyDir": null,
|
103
|
+
"gcePersistentDisk": null,
|
104
|
+
"gitRepo": null,
|
105
|
+
"secret": {
|
106
|
+
"secretName": "openshift-cert-secrets"
|
107
|
+
},
|
108
|
+
"nfs": null,
|
109
|
+
"iscsi": null,
|
110
|
+
"glusterfs": null
|
111
|
+
}
|
112
|
+
],
|
113
|
+
"containers": [
|
114
|
+
{
|
115
|
+
"name": "fabric8-console-container",
|
116
|
+
"image": "fabric8/hawtio-kubernetes:latest",
|
117
|
+
"ports": [
|
118
|
+
{
|
119
|
+
"containerPort": 9090,
|
120
|
+
"protocol": "TCP"
|
121
|
+
}
|
122
|
+
],
|
123
|
+
"env": [
|
124
|
+
{
|
125
|
+
"name": "OAUTH_CLIENT_ID",
|
126
|
+
"value": "fabric8-console"
|
127
|
+
},
|
128
|
+
{
|
129
|
+
"name": "OAUTH_AUTHORIZE_URI",
|
130
|
+
"value": "https://localhost:8443/oauth/authorize"
|
131
|
+
}
|
132
|
+
],
|
133
|
+
"resources": {},
|
134
|
+
"volumeMounts": [
|
135
|
+
{
|
136
|
+
"name": "openshift-cert-secrets",
|
137
|
+
"readOnly": true,
|
138
|
+
"mountPath": "/etc/secret-volume"
|
139
|
+
}
|
140
|
+
],
|
141
|
+
"terminationMessagePath": "/dev/termination-log",
|
142
|
+
"imagePullPolicy": "IfNotPresent",
|
143
|
+
"capabilities": {}
|
144
|
+
}
|
145
|
+
],
|
146
|
+
"restartPolicy": "Always",
|
147
|
+
"dnsPolicy": "ClusterFirst",
|
148
|
+
"host": "jimmi-redhat.localnet"
|
149
|
+
},
|
150
|
+
"status": {
|
151
|
+
"phase": "Running",
|
152
|
+
"Condition": [
|
153
|
+
{
|
154
|
+
"type": "Ready",
|
155
|
+
"status": "True"
|
156
|
+
}
|
157
|
+
],
|
158
|
+
"hostIP": "172.17.42.1",
|
159
|
+
"podIP": "172.17.0.8",
|
160
|
+
"containerStatuses": [
|
161
|
+
{
|
162
|
+
"name": "fabric8-console-container",
|
163
|
+
"state": {
|
164
|
+
"running": {
|
165
|
+
"startedAt": "2015-05-08T09:22:44Z"
|
166
|
+
}
|
167
|
+
},
|
168
|
+
"lastState": {},
|
169
|
+
"ready": true,
|
170
|
+
"restartCount": 0,
|
171
|
+
"image": "fabric8/hawtio-kubernetes:latest",
|
172
|
+
"imageID": "docker://b2bd1a24a68356b2f30128e6e28e672c1ef92df0d9ec01ec0c7faea5d77d2303",
|
173
|
+
"containerID": "docker://49095a2894da899d3b327c5fde1e056a81376cc9a8f8b09a195f2a92bceed459"
|
174
|
+
}
|
175
|
+
]
|
176
|
+
}
|
177
|
+
}
|
178
|
+
http_version:
|
179
|
+
recorded_at: Fri, 08 May 2015 10:35:37 GMT
|
180
|
+
- request:
|
181
|
+
method: get
|
182
|
+
uri: https://localhost:8443/api/v1/namespaces/default
|
183
|
+
body:
|
184
|
+
encoding: US-ASCII
|
185
|
+
string: ''
|
186
|
+
headers:
|
187
|
+
Accept:
|
188
|
+
- "*/*; q=0.5, application/xml"
|
189
|
+
Accept-Encoding:
|
190
|
+
- gzip, deflate
|
191
|
+
User-Agent:
|
192
|
+
- Ruby
|
193
|
+
response:
|
194
|
+
status:
|
195
|
+
code: 200
|
196
|
+
message: OK
|
197
|
+
headers:
|
198
|
+
Content-Type:
|
199
|
+
- application/json
|
200
|
+
Date:
|
201
|
+
- Fri, 08 May 2015 10:35:37 GMT
|
202
|
+
Transfer-Encoding:
|
203
|
+
- chunked
|
204
|
+
body:
|
205
|
+
encoding: UTF-8
|
206
|
+
string: |-
|
207
|
+
{
|
208
|
+
"kind": "Namespace",
|
209
|
+
"apiVersion": "v1",
|
210
|
+
"metadata": {
|
211
|
+
"name": "default",
|
212
|
+
"selfLink": "/api/v1/namespaces/default",
|
213
|
+
"uid": "898268c8-4a36-11e5-9d81-42010af0194c",
|
214
|
+
"resourceVersion": "6",
|
215
|
+
"creationTimestamp": "2015-05-08T09:22:01Z"
|
216
|
+
},
|
217
|
+
"spec": {
|
218
|
+
"finalizers": [
|
219
|
+
"kubernetes"
|
220
|
+
]
|
221
|
+
},
|
222
|
+
"status": {
|
223
|
+
"phase": "Active"
|
224
|
+
}
|
225
|
+
}
|
226
|
+
http_version:
|
227
|
+
recorded_at: Fri, 08 May 2015 10:35:37 GMT
|
228
|
+
recorded_with: VCR 2.9.3
|
@@ -112,8 +112,36 @@ class KubernetesMetadataFilterTest < Test::Unit::TestCase
|
|
112
112
|
host: 'jimmi-redhat.localnet',
|
113
113
|
pod_name: 'fabric8-console-controller-98rqc',
|
114
114
|
container_name: 'fabric8-console-container',
|
115
|
-
|
116
|
-
|
115
|
+
namespace_name: 'default',
|
116
|
+
pod_id: 'c76927af-f563-11e4-b32d-54ee7527188d',
|
117
|
+
labels: {
|
118
|
+
component: 'fabric8Console'
|
119
|
+
}
|
120
|
+
}
|
121
|
+
}
|
122
|
+
assert_equal(expected_kube_metadata, es.instance_variable_get(:@record_array)[0])
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
test 'with docker & kubernetes metadata & namespace_id enabled' do
|
127
|
+
VCR.use_cassette('metadata_with_namespace_id') do
|
128
|
+
es = emit({}, '
|
129
|
+
kubernetes_url https://localhost:8443
|
130
|
+
watch false
|
131
|
+
cache_size 1
|
132
|
+
include_namespace_id true
|
133
|
+
')
|
134
|
+
expected_kube_metadata = {
|
135
|
+
docker: {
|
136
|
+
container_id: '49095a2894da899d3b327c5fde1e056a81376cc9a8f8b09a195f2a92bceed459'
|
137
|
+
},
|
138
|
+
kubernetes: {
|
139
|
+
host: 'jimmi-redhat.localnet',
|
140
|
+
pod_name: 'fabric8-console-controller-98rqc',
|
141
|
+
container_name: 'fabric8-console-container',
|
142
|
+
namespace_name: 'default',
|
143
|
+
namespace_id: '898268c8-4a36-11e5-9d81-42010af0194c',
|
144
|
+
pod_id: 'c76927af-f563-11e4-b32d-54ee7527188d',
|
117
145
|
labels: {
|
118
146
|
component: 'fabric8Console'
|
119
147
|
}
|
@@ -139,8 +167,8 @@ class KubernetesMetadataFilterTest < Test::Unit::TestCase
|
|
139
167
|
host: 'jimmi-redhat.localnet',
|
140
168
|
pod_name: 'fabric8-console-controller-98rqc',
|
141
169
|
container_name: 'fabric8-console-container',
|
142
|
-
|
143
|
-
|
170
|
+
namespace_name: 'default',
|
171
|
+
pod_id: 'c76927af-f563-11e4-b32d-54ee7527188d',
|
144
172
|
labels: {
|
145
173
|
component: 'fabric8Console'
|
146
174
|
}
|
@@ -159,7 +187,7 @@ class KubernetesMetadataFilterTest < Test::Unit::TestCase
|
|
159
187
|
kubernetes: {
|
160
188
|
pod_name: 'fabric8-console-controller-98rqc',
|
161
189
|
container_name: 'fabric8-console-container',
|
162
|
-
|
190
|
+
namespace_name: 'default',
|
163
191
|
}
|
164
192
|
}
|
165
193
|
assert_equal(expected_kube_metadata, es.instance_variable_get(:@record_array)[0])
|
@@ -180,7 +208,7 @@ class KubernetesMetadataFilterTest < Test::Unit::TestCase
|
|
180
208
|
kubernetes: {
|
181
209
|
pod_name: 'fabric8-console-controller-98rqc',
|
182
210
|
container_name: 'fabric8-console-container',
|
183
|
-
|
211
|
+
namespace_name: 'default'
|
184
212
|
}
|
185
213
|
}
|
186
214
|
assert_equal(expected_kube_metadata, es.instance_variable_get(:@record_array)[0])
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fluent-plugin-kubernetes_metadata_filter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.11.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jimmi Dyson
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-09-
|
11
|
+
date: 2015-09-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: fluentd
|
@@ -225,6 +225,7 @@ files:
|
|
225
225
|
- test/cassettes/invalid_api_server_config.yml
|
226
226
|
- test/cassettes/kubernetes_docker_metadata.yml
|
227
227
|
- test/cassettes/kubernetes_docker_metadata_using_bearer_token.yml
|
228
|
+
- test/cassettes/metadata_with_namespace_id.yml
|
228
229
|
- test/cassettes/non_kubernetes_docker_metadata.yml
|
229
230
|
- test/cassettes/valid_kubernetes_api_server.yml
|
230
231
|
- test/helper.rb
|
@@ -258,6 +259,7 @@ test_files:
|
|
258
259
|
- test/cassettes/invalid_api_server_config.yml
|
259
260
|
- test/cassettes/kubernetes_docker_metadata.yml
|
260
261
|
- test/cassettes/kubernetes_docker_metadata_using_bearer_token.yml
|
262
|
+
- test/cassettes/metadata_with_namespace_id.yml
|
261
263
|
- test/cassettes/non_kubernetes_docker_metadata.yml
|
262
264
|
- test/cassettes/valid_kubernetes_api_server.yml
|
263
265
|
- test/helper.rb
|