kumonos 0.10.2 → 0.11.0
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 +5 -5
- data/example/envoy_config.yml +1 -4
- data/lib/kumonos/envoy.rb +95 -25
- data/lib/kumonos/version.rb +1 -1
- data/lib/schemas/envoy.json +2 -17
- metadata +3 -5
- data/exe/kumonos-relay +0 -135
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 952ff01c0ea52b0ec8b24acf94fc2e58da06ae47d467e349f120c9b7eaff2102
|
4
|
+
data.tar.gz: 6ca2a61ce2a1022a7a7cc7bfda0129c15a2a7d145b8afb8f4ed14e7d31db8aa8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2036f5f8649540ef1e43f4292dfe0b497320046fda0937459778d7b163c5e9073c0102796e854b68da2adff98ae1bd51bc391d07df1fb7d65a22777b7747592c
|
7
|
+
data.tar.gz: d65444682fde1eb1b8b7c881a777670c49e4ce68d52e86c1deef573b3da7e59e76dc1351a765c879185a59edae77f444c661c29d192ffb6cee3cb356f7eeed34
|
data/example/envoy_config.yml
CHANGED
data/lib/kumonos/envoy.rb
CHANGED
@@ -14,7 +14,7 @@ module Kumonos
|
|
14
14
|
new(
|
15
15
|
h.fetch('version'),
|
16
16
|
discovery_service,
|
17
|
-
h['statsd'] ?
|
17
|
+
h['statsd'] ? h['statsd'].fetch('address') : nil,
|
18
18
|
Listener.build(h.fetch('listener'), discovery_service),
|
19
19
|
Admin.build(h.fetch('admin'))
|
20
20
|
)
|
@@ -41,12 +41,41 @@ module Kumonos
|
|
41
41
|
h.delete(:statsd)
|
42
42
|
h.delete(:listener)
|
43
43
|
h[:admin] = admin.to_h
|
44
|
-
h[:
|
45
|
-
|
44
|
+
h[:static_resources] = {
|
45
|
+
listeners: [listener.to_h],
|
46
|
+
clusters: [discovery_service.cluster.to_h]
|
47
|
+
}
|
48
|
+
h[:dynamic_resources] = {
|
49
|
+
cds_config: {
|
50
|
+
api_config_source: {
|
51
|
+
cluster_names: [discovery_service.cluster.name],
|
52
|
+
refresh_delay: {
|
53
|
+
seconds: discovery_service.refresh_delay_ms / 1000.0
|
54
|
+
}
|
55
|
+
}
|
56
|
+
}
|
57
|
+
}
|
46
58
|
|
47
59
|
if statsd
|
48
|
-
|
49
|
-
h[:
|
60
|
+
statsd_address, statsd_port = statsd.split(':')
|
61
|
+
h[:stats_sinks] = [
|
62
|
+
{
|
63
|
+
name: 'envoy.dog_statsd',
|
64
|
+
config: {
|
65
|
+
address: {
|
66
|
+
socket_address: {
|
67
|
+
protocol: 'UDP',
|
68
|
+
address: statsd_address,
|
69
|
+
port_value: Integer(statsd_port)
|
70
|
+
}
|
71
|
+
}
|
72
|
+
}
|
73
|
+
}
|
74
|
+
]
|
75
|
+
h[:stats_config] = {
|
76
|
+
use_all_default_tags: true,
|
77
|
+
stats_tags: []
|
78
|
+
}
|
50
79
|
end
|
51
80
|
|
52
81
|
h
|
@@ -56,7 +85,8 @@ module Kumonos
|
|
56
85
|
Listener = Struct.new(:address, :access_log_path, :discovery_service) do
|
57
86
|
class << self
|
58
87
|
def build(h, discovery_service)
|
59
|
-
|
88
|
+
address = AddressParser.call(h.fetch('address'))
|
89
|
+
new(address, h.fetch('access_log_path'), discovery_service)
|
60
90
|
end
|
61
91
|
end
|
62
92
|
|
@@ -64,21 +94,38 @@ module Kumonos
|
|
64
94
|
h = super
|
65
95
|
h.delete(:discovery_service)
|
66
96
|
h.delete(:access_log_path)
|
67
|
-
h[:
|
97
|
+
h[:name] = 'egress'
|
98
|
+
h[:filter_chains] = [
|
68
99
|
{
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
100
|
+
filters: [
|
101
|
+
{
|
102
|
+
name: 'envoy.http_connection_manager',
|
103
|
+
config: {
|
104
|
+
codec_type: 'AUTO',
|
105
|
+
stat_prefix: 'egress_http',
|
106
|
+
access_log: [
|
107
|
+
{
|
108
|
+
name: 'envoy.file_access_log',
|
109
|
+
config: {
|
110
|
+
path: access_log_path
|
111
|
+
}
|
112
|
+
}
|
113
|
+
],
|
114
|
+
rds: {
|
115
|
+
config_source: {
|
116
|
+
api_config_source: {
|
117
|
+
cluster_names: [discovery_service.cluster.name],
|
118
|
+
refresh_delay: {
|
119
|
+
seconds: discovery_service.refresh_delay_ms / 1000.0
|
120
|
+
}
|
121
|
+
}
|
122
|
+
},
|
123
|
+
route_config_name: DEFAULT_ROUTE_NAME
|
124
|
+
},
|
125
|
+
http_filters: [{ name: 'envoy.router' }]
|
126
|
+
}
|
127
|
+
}
|
128
|
+
]
|
82
129
|
}
|
83
130
|
]
|
84
131
|
h
|
@@ -89,13 +136,14 @@ module Kumonos
|
|
89
136
|
class << self
|
90
137
|
def build(h)
|
91
138
|
lb = h.fetch('lb')
|
139
|
+
host, port = lb.split(':')
|
92
140
|
cluster = Cluster.new(
|
93
141
|
lb.split(':').first,
|
94
|
-
'
|
142
|
+
'STRICT_DNS',
|
95
143
|
h.fetch('tls'),
|
96
144
|
h.fetch('connect_timeout_ms'),
|
97
|
-
'
|
98
|
-
[{ '
|
145
|
+
'ROUND_ROBIN',
|
146
|
+
[{ 'socket_address' => { 'address' => host, 'port_value' => Integer(port) } }]
|
99
147
|
)
|
100
148
|
new(h.fetch('refresh_delay_ms'), cluster)
|
101
149
|
end
|
@@ -117,8 +165,15 @@ module Kumonos
|
|
117
165
|
|
118
166
|
def to_h
|
119
167
|
h = super
|
168
|
+
h[:type] = type.upcase
|
169
|
+
h.delete(:lb_type)
|
170
|
+
h[:lb_policy] = lb_type.upcase
|
120
171
|
h.delete(:tls)
|
121
|
-
h[:
|
172
|
+
h[:tls_context] = {} if tls
|
173
|
+
h.delete(:connect_timeout_ms)
|
174
|
+
h[:connect_timeout] = {
|
175
|
+
seconds: connect_timeout_ms / 1000.0
|
176
|
+
}
|
122
177
|
h
|
123
178
|
end
|
124
179
|
end
|
@@ -126,9 +181,24 @@ module Kumonos
|
|
126
181
|
Admin = Struct.new(:address, :access_log_path) do
|
127
182
|
class << self
|
128
183
|
def build(h)
|
129
|
-
|
184
|
+
address = AddressParser.call(h.fetch('address'))
|
185
|
+
new(address, h.fetch('access_log_path'))
|
130
186
|
end
|
131
187
|
end
|
132
188
|
end
|
189
|
+
|
190
|
+
# Parse old address string
|
191
|
+
module AddressParser
|
192
|
+
def self.call(address)
|
193
|
+
raise "invalid address given: #{address}" if address !~ %r{tcp://([^:]+):(\d+)}
|
194
|
+
|
195
|
+
{
|
196
|
+
socket_address: {
|
197
|
+
address: Regexp.last_match(1),
|
198
|
+
port_value: Integer(Regexp.last_match(2))
|
199
|
+
}
|
200
|
+
}
|
201
|
+
end
|
202
|
+
end
|
133
203
|
end
|
134
204
|
end
|
data/lib/kumonos/version.rb
CHANGED
data/lib/schemas/envoy.json
CHANGED
@@ -85,29 +85,14 @@
|
|
85
85
|
"statsd": {
|
86
86
|
"type": "object",
|
87
87
|
"id": "/properties/statsd",
|
88
|
-
"additionalProperties":
|
88
|
+
"additionalProperties": true,
|
89
89
|
"required": [
|
90
|
-
"address"
|
91
|
-
"tls",
|
92
|
-
"type",
|
93
|
-
"connect_timeout_ms"
|
90
|
+
"address"
|
94
91
|
],
|
95
92
|
"properties": {
|
96
93
|
"address": {
|
97
94
|
"type": "string",
|
98
95
|
"id": "/properties/statsd/properties/address"
|
99
|
-
},
|
100
|
-
"tls": {
|
101
|
-
"type": "boolean",
|
102
|
-
"id": "/properties/statsd/properties/tls"
|
103
|
-
},
|
104
|
-
"type": {
|
105
|
-
"type": "string",
|
106
|
-
"id": "/properties/statsd/properties/type"
|
107
|
-
},
|
108
|
-
"connect_timeout_ms": {
|
109
|
-
"type": "integer",
|
110
|
-
"id": "/properties/statsd/properties/connect_timeout_ms"
|
111
96
|
}
|
112
97
|
}
|
113
98
|
}
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: kumonos
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.11.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Taiki Ono
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2018-01-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: json-schema
|
@@ -141,7 +141,6 @@ email:
|
|
141
141
|
- taiks.4559@gmail.com
|
142
142
|
executables:
|
143
143
|
- kumonos
|
144
|
-
- kumonos-relay
|
145
144
|
extensions: []
|
146
145
|
extra_rdoc_files: []
|
147
146
|
files:
|
@@ -162,7 +161,6 @@ files:
|
|
162
161
|
- example/envoy_config.yml
|
163
162
|
- example/example-with-tls.yml
|
164
163
|
- exe/kumonos
|
165
|
-
- exe/kumonos-relay
|
166
164
|
- kumonos.gemspec
|
167
165
|
- lib/kumonos.rb
|
168
166
|
- lib/kumonos/clusters.rb
|
@@ -193,7 +191,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
193
191
|
version: '0'
|
194
192
|
requirements: []
|
195
193
|
rubyforge_project:
|
196
|
-
rubygems_version: 2.
|
194
|
+
rubygems_version: 2.7.3
|
197
195
|
signing_key:
|
198
196
|
specification_version: 4
|
199
197
|
summary: A "control plane" for Microservices "service mesh".
|
data/exe/kumonos-relay
DELETED
@@ -1,135 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
require 'optparse'
|
3
|
-
require 'socket'
|
4
|
-
require 'logger'
|
5
|
-
|
6
|
-
# Convert metric name
|
7
|
-
class StatConvertor
|
8
|
-
def initialize(options)
|
9
|
-
@options = options
|
10
|
-
end
|
11
|
-
|
12
|
-
def call(line)
|
13
|
-
convert_status_code(convert_listener(convert_cluster(add_default_tag(line)))) + "\n"
|
14
|
-
end
|
15
|
-
|
16
|
-
private
|
17
|
-
|
18
|
-
STATS_CODE_PATTERN = /(upstream|downstream)_rq_(\dxx|\d{3})/
|
19
|
-
def convert_status_code(line)
|
20
|
-
if line.match(STATS_CODE_PATTERN)
|
21
|
-
stream = Regexp.last_match(1)
|
22
|
-
code = Regexp.last_match(2)
|
23
|
-
[
|
24
|
-
line.gsub(STATS_CODE_PATTERN, "#{stream}_rq_by_code"),
|
25
|
-
",status_code:#{code}"
|
26
|
-
].join
|
27
|
-
|
28
|
-
else
|
29
|
-
line
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
# envoy.cluster.ab-testing.external.upstream_rq_200:1|c
|
34
|
-
CLUSTER_PATTERN = /\Aenvoy\.cluster\.([^.]+)\./
|
35
|
-
def convert_cluster(line)
|
36
|
-
if line.match(CLUSTER_PATTERN)
|
37
|
-
name = Regexp.last_match(1)
|
38
|
-
[
|
39
|
-
line.gsub(CLUSTER_PATTERN, 'envoy.cluster.'),
|
40
|
-
",cluster:#{name}"
|
41
|
-
].join
|
42
|
-
else
|
43
|
-
line
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
# XXX: ipv4 only
|
48
|
-
# envoy.listener.0.0.0.0_9211.http.egress_http.downstream_rq_5xx:0|c
|
49
|
-
LISTENER_PATTERN = /\Aenvoy\.listener\.(\d+\.\d+\.\d+.\d+_\d+)./
|
50
|
-
def convert_listener(line)
|
51
|
-
if line.match(LISTENER_PATTERN)
|
52
|
-
listener = Regexp.last_match(1)
|
53
|
-
[
|
54
|
-
line.gsub(LISTENER_PATTERN, 'envoy.listener.'),
|
55
|
-
",listener:#{listener}"
|
56
|
-
].join
|
57
|
-
else
|
58
|
-
line
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
def add_default_tag(line)
|
63
|
-
[
|
64
|
-
"#{line.chomp}|#",
|
65
|
-
"service_cluster:#{@options[:service_cluster]},",
|
66
|
-
"service_node:#{@options[:service_node]},",
|
67
|
-
"host:#{@options[:host]}"
|
68
|
-
].join
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
logger = Logger.new($stderr)
|
73
|
-
logger.level = ENV['LOG_LEVEL'] || 'info'
|
74
|
-
|
75
|
-
options = {
|
76
|
-
service_cluster: '',
|
77
|
-
service_node: '',
|
78
|
-
host: Socket.gethostname
|
79
|
-
}
|
80
|
-
parser = OptionParser.new do |opts|
|
81
|
-
opts.banner = "Usage: #{__FILE__} [options] bind_address:port remote_address:port"
|
82
|
-
|
83
|
-
opts.on('--service-cluster=VAL (required)') { |v| options[:service_cluster] = v }
|
84
|
-
opts.on('--service-node=VAL (required)') { |v| options[:service_node] = v }
|
85
|
-
opts.on('--host=VAL') { |v| options[:host] = v }
|
86
|
-
end
|
87
|
-
|
88
|
-
argv = parser.parse(ARGV)
|
89
|
-
|
90
|
-
if argv.size != 2
|
91
|
-
warn parser.help
|
92
|
-
exit 1
|
93
|
-
end
|
94
|
-
if options[:service_cluster].empty? || options[:service_node].empty?
|
95
|
-
warn '--service-cluster and --service-node are required'
|
96
|
-
warn parser.help
|
97
|
-
exit 1
|
98
|
-
end
|
99
|
-
|
100
|
-
convertor = StatConvertor.new(options)
|
101
|
-
|
102
|
-
bind_option = argv.shift
|
103
|
-
remote_option = argv.shift
|
104
|
-
|
105
|
-
source_ip, source_port = *bind_option.split(':')
|
106
|
-
unless source_ip && source_port
|
107
|
-
warn "Invalid bind option given: #{bind_option}"
|
108
|
-
exit 1
|
109
|
-
end
|
110
|
-
|
111
|
-
remote_ip, remote_port = *remote_option.split(':')
|
112
|
-
unless remote_ip && remote_port
|
113
|
-
warn "Invalid remote option given: #{remote_option}"
|
114
|
-
exit 1
|
115
|
-
end
|
116
|
-
|
117
|
-
Thread.abort_on_exception = true
|
118
|
-
logger.info("Starting relay: source=#{bind_option} remote=#{remote_option}")
|
119
|
-
source = TCPServer.open(source_ip, source_port)
|
120
|
-
|
121
|
-
loop do
|
122
|
-
Thread.start(source.accept) do |s|
|
123
|
-
while (body = s.gets)
|
124
|
-
logger.debug("recieved #{body.bytesize} bytes")
|
125
|
-
logger.debug(body)
|
126
|
-
next if body.empty?
|
127
|
-
|
128
|
-
b = convertor.call(body)
|
129
|
-
UDPSocket.new.send(b, Socket::MSG_DONTWAIT, remote_ip, remote_port)
|
130
|
-
logger.debug("write #{b.bytesize} bytes")
|
131
|
-
logger.debug(b)
|
132
|
-
end
|
133
|
-
s.close
|
134
|
-
end
|
135
|
-
end
|