mkit 0.10.3 → 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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 87ebdfac894683e95586a4631c94dd82b3ae5dadc94d6e6fb218977a54bd8952
4
- data.tar.gz: 022f8de5a56588ac6e7cc590d421de1810b2240c4a6938010bf0ed846de524f4
3
+ metadata.gz: 0fc21ab718559c64d16f2dd68a7778fb496530325d18bdcf91d99305ff54c1c5
4
+ data.tar.gz: e8805a10f7bf5a79418a4752031951c336c6191d2b5ff08068ec48d658a74916
5
5
  SHA512:
6
- metadata.gz: 7dd2eb993061589bd7fc87360e97e44640cdb411f0b0b6933799cb20a753db146100e46f96cba0fa86d7c5dfb412795016896174b3e360e6adcf64be29cd959a
7
- data.tar.gz: '01982702618f9a282def8d33cb8d08e02d07e08bfe4190ecfa982418545f40f9374b2d24785fd408eae232ebb4087c4f8e563154bd4c63ff7c50542137b0d728'
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
@@ -30,7 +30,7 @@ class ServicesController < MKIt::Server
30
30
  get '/services/:id' do
31
31
  srv = find_by_id_or_name
32
32
  resp = if params[:format] == 'yaml'
33
- srv.to_h({details: params[:details] == 'true'}).to_yaml
33
+ srv.to_h({details: params[:details] == 'true'}).to_yaml(line_width: -1)
34
34
  elsif params[:format] == 'json'
35
35
  JSON.pretty_generate(srv.to_h({details: params[:details] == 'true'}))
36
36
  else
@@ -107,7 +107,7 @@ class ServicesController < MKIt::Server
107
107
  if params[:file]
108
108
  tempfile = params[:file][:tempfile]
109
109
  yaml = YAML.safe_load(tempfile.read)
110
- srv = migrate_service(yaml).to_yaml
110
+ srv = migrate_service(yaml).to_yaml(line_width: -1)
111
111
  end
112
112
  srv
113
113
  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
- unless config.resources.nil?
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
- data = { service_id: self.id, version: self.version }
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%> <%service.service_config&.select{ |x| x.ctype == MKIt::CType::ENVIRONMENT.to_s }.each { |env|%><%=" -e #{env.key}=\"#{env.value}\""%><%}%> <%service.volume&.each { |vol|%><%=" -v \"#{vol.name}:#{vol.path}\""%><%}%> --network <%=service.pods_network%> --dns <%=service.my_dns%> <%=service.image%> <%=service.command unless service.command.nil?%>
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?%>
@@ -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 response") if !$?.nil? && $?.exitstatus != 0
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
@@ -1,4 +1,4 @@
1
1
  module MKIt
2
- VERSION = "0.10.3"
2
+ VERSION = "0.10.5"
3
3
  end
4
4
 
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
- srv.deploy_network
142
- srv.update_status!
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
- MKItLogger.debug 'restarting proxy...'
147
- MKIt::HAProxy.restart
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: {})
@@ -40,6 +40,10 @@ service:
40
40
  resources:
41
41
  min_replicas: 1
42
42
  max_replicas: 1
43
+ limits:
44
+ cpu: 250m
45
+ memory: 250m
46
+ memory_swap: 250m
43
47
  volumes: []
44
48
  environment:
45
49
  LOG4J_LEVEL: WARN
@@ -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.3
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-03-09 00:00:00.000000000 Z
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