mkit 0.10.4 → 0.10.5
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/README.md +4 -0
- data/db/migrate/008_create_resources.rb +17 -0
- data/db/migrate/009_migrate_resources.rb +16 -0
- data/lib/mkit/app/helpers/docker_helper.rb +15 -0
- data/lib/mkit/app/model/resource.rb +61 -0
- data/lib/mkit/app/model/service.rb +6 -15
- data/lib/mkit/app/templates/docker/docker_run.sh.erb +10 -1
- data/lib/mkit/cmd_runner.rb +1 -1
- data/lib/mkit/version.rb +1 -1
- data/lib/mkit.rb +17 -4
- data/samples/apps/httpbin.yml +4 -0
- data/samples/apps/swiss-army-knife.yml +38 -0
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0fc21ab718559c64d16f2dd68a7778fb496530325d18bdcf91d99305ff54c1c5
|
4
|
+
data.tar.gz: e8805a10f7bf5a79418a4752031951c336c6191d2b5ff08068ec48d658a74916
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0a43e99260fe7082c992f360de46d1d09ef28ed53bd0dd4064abd63666503fce3555ff9f41a1f8e9d84cc66c6f7f57d0f3be92ba8db22e7e1c16dbc051e524a2
|
7
|
+
data.tar.gz: 3456970eadebec1cef12ac64a6caede473b0f5570736b0d3ce5228e50513c81837b9bdb7f3ded8ae35c1dac036914dbc83b49b89d0ff992c0978af6188e00b5d
|
data/README.md
CHANGED
@@ -176,6 +176,10 @@ service:
|
|
176
176
|
resources:
|
177
177
|
min_replicas: 1 # default value. Pods will be available on internal DNS as '<service_name>.internal'
|
178
178
|
max_replicas: 1 # default value
|
179
|
+
limits:
|
180
|
+
cpu: 250m # cpu limit - 1000m represents 1 cpu core. minimum 10m. default is empty
|
181
|
+
memory: 250m # memory limit - default is empty
|
182
|
+
memory_swap: 250m # memory + swap limit - default is empty
|
179
183
|
volumes:
|
180
184
|
- docker://mkit_rabbitmq_data:/var/lib/rabbitmq # a docker volume - it will be created if it does not exists
|
181
185
|
- /var/log/rabbitmq/logs:/var/log/rabbitmq # a local volume
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class CreateResources < ActiveRecord::Migration[5.1]
|
4
|
+
def up
|
5
|
+
create_table :resources do |t|
|
6
|
+
t.string :service_id
|
7
|
+
t.string :version
|
8
|
+
t.integer :min_replicas, default: 1
|
9
|
+
t.integer :max_replicas, default: 1
|
10
|
+
t.string :cpu_limits
|
11
|
+
t.string :memory_limits
|
12
|
+
t.string :memory_swap_limits
|
13
|
+
t.timestamp :created_at
|
14
|
+
t.timestamp :updated_at
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class MigrateResources < ActiveRecord::Migration[5.1]
|
4
|
+
|
5
|
+
#
|
6
|
+
# migrate the resource data from service
|
7
|
+
#
|
8
|
+
def up
|
9
|
+
Service.all.each do |service|
|
10
|
+
resource = Resource.new
|
11
|
+
resource.max_replicas = service.max_replicas
|
12
|
+
resource.min_replicas = service.min_replicas
|
13
|
+
service.resource = resource
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -87,5 +87,20 @@ module MKIt
|
|
87
87
|
x = MKIt::CmdRunner.run("docker volume inspect #{volume_name}")
|
88
88
|
JSON.parse(x).first
|
89
89
|
end
|
90
|
+
|
91
|
+
##
|
92
|
+
# cpu limits
|
93
|
+
def to_docker_cpu_limit(k8s_cpu_limits)
|
94
|
+
if k8s_cpu_limits.nil?
|
95
|
+
nil
|
96
|
+
else
|
97
|
+
cpu_limit = k8s_cpu_limits.to_s
|
98
|
+
if cpu_limit.include?('m')
|
99
|
+
cpu_limit = cpu_limit.delete_suffix('m')
|
100
|
+
cpu_limit = (cpu_limit.to_f / 1000).to_s
|
101
|
+
end
|
102
|
+
cpu_limit
|
103
|
+
end
|
104
|
+
end
|
90
105
|
end
|
91
106
|
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Resource < ActiveRecord::Base
|
4
|
+
belongs_to :service
|
5
|
+
|
6
|
+
def self.create(yaml)
|
7
|
+
resource = Resource.new
|
8
|
+
if yaml.nil?
|
9
|
+
resource.max_replicas = 1
|
10
|
+
resource.min_replicas = 1
|
11
|
+
else
|
12
|
+
validate(yaml)
|
13
|
+
if yaml["min_replicas"]
|
14
|
+
resource.min_replicas = yaml["min_replicas"]
|
15
|
+
else
|
16
|
+
resource.min_replicas = 1
|
17
|
+
end
|
18
|
+
if yaml["max_replicas"]
|
19
|
+
resource.max_replicas = yaml["max_replicas"]
|
20
|
+
else
|
21
|
+
resource.max_replicas = resource.min_replicas
|
22
|
+
end
|
23
|
+
resource.cpu_limits = yaml["limits"]["cpu"] if yaml["limits"] && yaml["limits"]["cpu"]
|
24
|
+
resource.memory_limits = yaml["limits"]["memory"] if yaml["limits"] && yaml["limits"]["memory"]
|
25
|
+
resource.memory_swap_limits = yaml["limits"]["memory_swap"] if yaml["limits"] && yaml["limits"]["memory_swap"]
|
26
|
+
end
|
27
|
+
resource
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.validate(yaml)
|
31
|
+
unless yaml.nil?
|
32
|
+
raise_bad_configuration "resource min_replicas must be bigger or equal than 1" if yaml["min_replicas"] && yaml["min_replicas"] < 1
|
33
|
+
raise_bad_configuration "resource max_replicas must be bigger or equal than 1" if yaml["max_replicas"] && yaml["max_replicas"] < 1
|
34
|
+
if yaml["min_replicas"] && yaml["max_replicas"]
|
35
|
+
raise_bad_configuration "resource max_replicas must be bigger or equal than min_replicas" if yaml["min_replicas"] > yaml["max_replicas"]
|
36
|
+
end
|
37
|
+
end
|
38
|
+
# validate limits
|
39
|
+
unless yaml.nil? || yaml["limits"].nil?
|
40
|
+
resources = yaml["limits"]
|
41
|
+
raise_bad_configuration "resource cpu limits must match '\\d+m'" if resources["cpu"] && resources["cpu"] !~ /\d+m$/
|
42
|
+
raise_bad_configuration "resource memory limits must match '\\d+m'" if resources["memory"] && resources["memory"] !~ /\d+m$/
|
43
|
+
raise_bad_configuration "resource memory_swap limits must match '\\d+m'" if resources["memory_swap"] && resources["memory_swap"] !~ /\d+m$/
|
44
|
+
end
|
45
|
+
true
|
46
|
+
end
|
47
|
+
|
48
|
+
def to_h(options = {})
|
49
|
+
hash = {
|
50
|
+
min_replicas: self.min_replicas,
|
51
|
+
max_replicas: self.max_replicas
|
52
|
+
}
|
53
|
+
if self.cpu_limits || self.memory_limits || self.memory_swap_limits
|
54
|
+
hash[:limits] = {}
|
55
|
+
hash[:limits][:cpu] = self.cpu_limits if self.cpu_limits
|
56
|
+
hash[:limits][:memory] = self.memory_limits if self.memory_limits
|
57
|
+
hash[:limits][:memory_swap] = self.memory_swap_limits if self.memory_swap_limits
|
58
|
+
end
|
59
|
+
hash.remove_symbols_from_keys
|
60
|
+
end
|
61
|
+
end
|
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'mkit/app/model/volume'
|
2
2
|
require 'mkit/app/model/ingress'
|
3
|
+
require 'mkit/app/model/resource'
|
3
4
|
require 'mkit/app/model/service_port'
|
4
5
|
require 'mkit/app/model/service_config'
|
5
6
|
require 'mkit/app/model/pod'
|
@@ -23,6 +24,7 @@ class Service < ActiveRecord::Base
|
|
23
24
|
has_one :lease, dependent: :destroy
|
24
25
|
has_one :dns_host, dependent: :destroy
|
25
26
|
has_one :ingress, dependent: :destroy
|
27
|
+
has_one :resource, dependent: :destroy
|
26
28
|
|
27
29
|
before_destroy :clean_up
|
28
30
|
|
@@ -64,7 +66,7 @@ class Service < ActiveRecord::Base
|
|
64
66
|
srv.save!
|
65
67
|
data = { service_id: srv.id, version: srv.version }
|
66
68
|
# create pod
|
67
|
-
(1..srv.min_replicas).each { |i|
|
69
|
+
(1..srv.resource.min_replicas).each { |i|
|
68
70
|
pd = Pod.new( status: MKIt::Status::CREATED, name: SecureRandom.uuid.gsub('-','')[0..11])
|
69
71
|
srv.pod << pd
|
70
72
|
MkitJob.publish(topic: :create_pod_saga, data: {pod_name: pd.name})
|
@@ -77,14 +79,7 @@ class Service < ActiveRecord::Base
|
|
77
79
|
self.image = config.image if config.image != self.image
|
78
80
|
self.command = config.command if config.command != self.command
|
79
81
|
|
80
|
-
|
81
|
-
self.max_replicas = config.resources.max_replicas unless config.resources.max_replicas.nil? || config.resources.max_replicas < 1
|
82
|
-
self.min_replicas = config.resources.min_replicas unless config.resources.min_replicas.nil? || config.resources.min_replicas < 1
|
83
|
-
else
|
84
|
-
self.min_replicas = 1
|
85
|
-
self.max_replicas = 1
|
86
|
-
end
|
87
|
-
self.max_replicas = self.min_replicas if self.min_replicas > self.max_replicas
|
82
|
+
self.resource = Resource.create(config.resources)
|
88
83
|
|
89
84
|
# docker network
|
90
85
|
if config.network.nil? || config.network.empty?
|
@@ -122,8 +117,7 @@ class Service < ActiveRecord::Base
|
|
122
117
|
# destroy old pods...
|
123
118
|
self.pod.destroy_all
|
124
119
|
# create pod
|
125
|
-
|
126
|
-
(1..self.min_replicas).each { |i|
|
120
|
+
(1..self.resource.min_replicas).each { |i|
|
127
121
|
pd = Pod.new( status: MKIt::Status::CREATED, name: SecureRandom.uuid.gsub('-','')[0..11])
|
128
122
|
self.pod << pd
|
129
123
|
MkitJob.publish(topic: :create_pod_saga, data: {pod_name: pd.name})
|
@@ -276,12 +270,9 @@ class Service < ActiveRecord::Base
|
|
276
270
|
}
|
277
271
|
end
|
278
272
|
|
279
|
-
# ingress
|
280
273
|
srv['ingress'] = self.ingress.to_h(options)
|
274
|
+
srv['resources'] = self.resource.to_h
|
281
275
|
|
282
|
-
srv['resources'] = {}
|
283
|
-
srv['resources']['min_replicas'] = self.min_replicas
|
284
|
-
srv['resources']['max_replicas'] = self.max_replicas
|
285
276
|
srv['volumes'] = []
|
286
277
|
self.volume.each { |v|
|
287
278
|
if v.ctype == MKIt::CType::DOCKER_STORAGE.to_s
|
@@ -1 +1,10 @@
|
|
1
|
-
docker run -d --name <%=name%>
|
1
|
+
docker run -d --name <%=name%> \
|
2
|
+
<%service.service_config&.select{ |x| x.ctype == MKIt::CType::ENVIRONMENT.to_s }.each { |env|%><%=" -e #{env.key}=\"#{env.value}\""%><%}%> \
|
3
|
+
<%service.volume&.each { |vol|%><%=" -v \"#{vol.name}:#{vol.path}\""%><%}%> \
|
4
|
+
--network <%=service.pods_network%> \
|
5
|
+
--dns <%=service.my_dns%> \
|
6
|
+
<%="--cpus #{to_docker_cpu_limit(service.resource.cpu_limits)}" unless service.resource.cpu_limits.nil?%> \
|
7
|
+
<%="--memory #{service.resource.memory_limits}" unless service.resource.memory_limits.nil?%> \
|
8
|
+
<%="--memory-swap #{service.resource.memory_swap_limits}" unless service.resource.memory_swap_limits.nil?%> \
|
9
|
+
<%=service.image%> \
|
10
|
+
<%=service.command unless service.command.nil?%>
|
data/lib/mkit/cmd_runner.rb
CHANGED
@@ -19,7 +19,7 @@ module MKIt
|
|
19
19
|
rescue PTY::ChildExited
|
20
20
|
# nothing
|
21
21
|
end
|
22
|
-
raise CmdRunnerException.new("command '#{cmd[0..30]}...' returned an error
|
22
|
+
raise CmdRunnerException.new("command '#{cmd[0..30]}...' returned an error [#{result}] (#{$?})") if !$?.nil? && $?.exitstatus != 0
|
23
23
|
result
|
24
24
|
end
|
25
25
|
end
|
data/lib/mkit/version.rb
CHANGED
data/lib/mkit.rb
CHANGED
@@ -138,13 +138,26 @@ module MKIt
|
|
138
138
|
MKItLogger.info 'restoring operations...'
|
139
139
|
# create interfaces of deployed apps otherwise haproxy won't start
|
140
140
|
Service.all.each do |srv|
|
141
|
-
|
142
|
-
|
141
|
+
begin
|
142
|
+
srv.deploy_network
|
143
|
+
srv.update_status!
|
144
|
+
rescue => e
|
145
|
+
MKItLogger.warn "Error restoring service #{srv.name}: #{e.message}"
|
146
|
+
end
|
143
147
|
end
|
144
148
|
# daemontools would eventually start haproxy; systemd does not.
|
145
149
|
# so, restart here.
|
146
|
-
|
147
|
-
|
150
|
+
Thread.new do
|
151
|
+
begin
|
152
|
+
MKItLogger.debug 'restarting proxy...'
|
153
|
+
MKIt::HAProxy.stop
|
154
|
+
sleep 10
|
155
|
+
MKIt::HAProxy.restart
|
156
|
+
MKItLogger.debug 'restarting proxy done.'
|
157
|
+
rescue => e
|
158
|
+
MKItLogger.error "Error in restart_proxy thread: #{e.message}"
|
159
|
+
end
|
160
|
+
end
|
148
161
|
end
|
149
162
|
|
150
163
|
def self.startup(options: {})
|
data/samples/apps/httpbin.yml
CHANGED
@@ -0,0 +1,38 @@
|
|
1
|
+
---
|
2
|
+
service:
|
3
|
+
name: swiss-army-knife
|
4
|
+
image: leodotcloud/swiss-army-knife
|
5
|
+
command: swiss-army-knife
|
6
|
+
network: bridge
|
7
|
+
ingress:
|
8
|
+
frontend:
|
9
|
+
- name: http-in
|
10
|
+
options:
|
11
|
+
- option httpclose
|
12
|
+
- option forwardfor
|
13
|
+
bind:
|
14
|
+
port: 80
|
15
|
+
mode: http
|
16
|
+
default_backend: server
|
17
|
+
backend:
|
18
|
+
- name: server
|
19
|
+
balance: round_robin
|
20
|
+
options:
|
21
|
+
- cookie JSESSIONID prefix
|
22
|
+
bind:
|
23
|
+
port: 8080
|
24
|
+
mode: http
|
25
|
+
options:
|
26
|
+
- cookie A
|
27
|
+
- check
|
28
|
+
resources:
|
29
|
+
min_replicas: 1
|
30
|
+
max_replicas: 1
|
31
|
+
limits:
|
32
|
+
cpu: 500m
|
33
|
+
memory: 512m
|
34
|
+
memory_swap: 512m
|
35
|
+
volumes: []
|
36
|
+
environment:
|
37
|
+
LOG4J_LEVEL: WARN
|
38
|
+
LOGGING_LEVEL_ROOT: WARN
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mkit
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.10.
|
4
|
+
version: 0.10.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Vasco Santos
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-
|
11
|
+
date: 2025-04-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: async-dns
|
@@ -393,6 +393,8 @@ files:
|
|
393
393
|
- db/migrate/005_create_frontend.rb
|
394
394
|
- db/migrate/006_create_backend.rb
|
395
395
|
- db/migrate/007_migrate_schema.rb
|
396
|
+
- db/migrate/008_create_resources.rb
|
397
|
+
- db/migrate/009_migrate_resources.rb
|
396
398
|
- db/schema.rb
|
397
399
|
- lib/mkit.rb
|
398
400
|
- lib/mkit/app/controllers/mkit_controller.rb
|
@@ -416,6 +418,7 @@ files:
|
|
416
418
|
- lib/mkit/app/model/mkit_job.rb
|
417
419
|
- lib/mkit/app/model/pod.rb
|
418
420
|
- lib/mkit/app/model/pool.rb
|
421
|
+
- lib/mkit/app/model/resource.rb
|
419
422
|
- lib/mkit/app/model/service.rb
|
420
423
|
- lib/mkit/app/model/service_config.rb
|
421
424
|
- lib/mkit/app/model/service_port.rb
|
@@ -476,6 +479,7 @@ files:
|
|
476
479
|
- samples/apps/rabbitmq.yml
|
477
480
|
- samples/apps/redis-sentinel.yml
|
478
481
|
- samples/apps/redis.yml
|
482
|
+
- samples/apps/swiss-army-knife.yml
|
479
483
|
- samples/daemontools/log/run
|
480
484
|
- samples/daemontools/run
|
481
485
|
- samples/systemd/mkitd.service
|