Skip to content

Commit 4d32085

Browse files
authoredMar 9, 2025··
feat - introducing new ingress configuration (#22)
This PR adds a new ingress configuration that replaces the [port] list. I needed more `haproxy` configuration options and a line just won't scale, so a new configuration was added. A new `sample` service configuration is added - `httpbin` - as example for the new schema. Tools to migrate old format service file is also included via `mkit` client: ``` mkit migrate <service_old_format.yml> ``` The current ones will be migrated at boot time. This PR also makes a small refactor on internal saga and on docker listener services.
1 parent 178875b commit 4d32085

40 files changed

+914
-161
lines changed
 

‎README.md

+50-15
Original file line numberDiff line numberDiff line change
@@ -127,18 +127,52 @@ service:
127127
name: rabbitmq # unique. Available on internal DNS as 'rabbitmq'
128128
image: rabbitmq:3-management-alpine # image
129129
network: bridge # docker network - it will be created if it does not exists
130-
ports: # haproxy port mapping
131-
# <external_port>:[internal_port]:<tcp|http>:[round_robin (default)|leastconn]
132-
# to define a range on `external_port`, leave `internal_port` blank
133-
# - 5000-5100::tcp:round_robin
134-
# range on `internal_port` is not supported
135-
# ssl suport
136-
# <external_port>:[internal_port]:<tcp|http>:round_robin|leastconn[:ssl[,<cert.pem>(mkit.pem default)>]]
137-
# e.g.
138-
# - 443:80:http:round_robin:ssl # uses mkitd default crt file (mkit.pem)
139-
# - 443:80:http:round_robin:ssl,/etc/pki/foo.pem # custom crt file full path
140-
- 5672:5672:tcp:round_robin
141-
- 80:15672:http:round_robin
130+
ingress:
131+
# ingress configuration
132+
# see https://docs.haproxy.org/3.1/configuration.html
133+
frontend: # frontend section
134+
- name: http-in-ssl # frontend name - must be unique
135+
options: # frontend global section options
136+
- option httpclose
137+
- option forwardfor
138+
bind:
139+
port: 443 # to define a range (e.g. 8000-8080), backend `port` must be blank
140+
ssl: true # ssl support - default is false
141+
mode: http # tcp|http
142+
cert: /etc/ssl/certs/server.crt # if empty uses mkit default crt file (mkit.pem)
143+
options: # frontend bind section options
144+
- accept-proxy
145+
- transparent
146+
- defer-accept
147+
default_backend: admin # backend to use - must point to a backend name
148+
- name: http-in
149+
bind:
150+
port: 80
151+
mode: http
152+
default_backend: admin
153+
- name: server-in
154+
bind:
155+
port: 5672
156+
mode: tcp
157+
default_backend: server
158+
backend: # backend section
159+
- name: admin # backend name - must be unique
160+
balance: round_robin # round_robin|least_conn - default is round_robin
161+
options: # backend global section options
162+
- option httpclose
163+
- option forwardfor
164+
- cookie JSESSIONID prefix
165+
bind:
166+
port: 15672 # if this backend is used by a frontend with a range port, this port must be blank
167+
mode: http
168+
options: # backend bind section options
169+
- cookie A
170+
- check
171+
- name: server
172+
balance: round_robin
173+
bind:
174+
port: 5672
175+
mode: tcp
142176
resources:
143177
min_replicas: 1 # default value. Pods will be available on internal DNS as '<service_name>.internal'
144178
max_replicas: 1 # default value
@@ -163,9 +197,9 @@ Usage: mkitd [options]
163197
-b bind specify bind address (e.g. 0.0.0.0)
164198
-e env set the environment (default is development)
165199
-o addr alias for '-b' option
166-
--no-ssl disable ssl - use http for local server. (default is https)
167-
--ssl-key-file PATH Path to private key (default mkit internal)
168-
--ssl-cert-file PATH Path to certificate (default mkit internal)
200+
--no-ssl disable ssl - use http for local server. (default is https)
201+
--ssl-key-file PATH Path to private key (default mkit internal)
202+
--ssl-cert-file PATH Path to certificate (default mkit internal)
169203
```
170204

171205
There's also samples for [systemd](samples/systemd) and [daemontools](samples/daemontools) as well for some miscellaneous [spps](samples/apps).
@@ -193,6 +227,7 @@ create create new service
193227
update update service
194228
get print service configuration
195229
rm remove service
230+
migrate migrate local service definition to the new schema version
196231
exec execute a command in a running pod
197232
logs view service logs
198233
version prints mkit client and server version

‎db/migrate/004_create_ingress.rb

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# frozen_string_literal: true
2+
3+
class CreateIngress < ActiveRecord::Migration[5.1]
4+
def up
5+
create_table :ingresses do |t|
6+
t.string :service_id
7+
t.string :version
8+
t.timestamp :created_at
9+
t.timestamp :updated_at
10+
end
11+
end
12+
end

‎db/migrate/005_create_frontend.rb

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# frozen_string_literal: true
2+
3+
class CreateFrontend < ActiveRecord::Migration[5.1]
4+
def up
5+
create_table :frontends do |t|
6+
t.string :ingress_id
7+
t.string :name
8+
t.string :mode
9+
t.string :port
10+
t.string :ssl
11+
t.string :crt
12+
t.text :options, default: '[]'
13+
t.text :bind_options, default: '[]'
14+
t.text :default_backend
15+
t.string :version
16+
t.timestamp :created_at
17+
t.timestamp :updated_at
18+
end
19+
end
20+
end

‎db/migrate/006_create_backend.rb

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# frozen_string_literal: true
2+
3+
class CreateBackend < ActiveRecord::Migration[5.1]
4+
def up
5+
create_table :backends do |t|
6+
t.string :ingress_id
7+
t.string :name
8+
t.string :mode
9+
t.string :load_bal
10+
t.string :port
11+
t.text :options, default: '[]'
12+
t.text :bind_options, default: '[]'
13+
t.string :version
14+
t.timestamp :created_at
15+
t.timestamp :updated_at
16+
end
17+
end
18+
end

‎db/migrate/007_migrate_schema.rb

+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# frozen_string_literal: true
2+
3+
class MigrateSchema < ActiveRecord::Migration[5.1]
4+
5+
#
6+
# migrate the schema from service_ports to ingress
7+
#
8+
def up
9+
Service.all.each do |service|
10+
ingress_config = service_ports_to_ingress service.service_port
11+
service.ingress = Ingress.create(ingress_config)
12+
service.service_port.destroy_all
13+
end
14+
end
15+
16+
def service_ports_to_ingress(ports)
17+
ingress = { frontend: [], backend: [] }
18+
19+
ports.each do |port|
20+
frontend = {
21+
name: "frontend-#{port.external_port}",
22+
bind: {
23+
port: port.external_port,
24+
mode: port.mode
25+
},
26+
options: [],
27+
default_backend: "backend-#{port.external_port}"
28+
}
29+
30+
if port.ssl.start_with?('true')
31+
frontend[:bind][:ssl] = true
32+
frontend[:bind][:cert] = port.crt
33+
end
34+
35+
backend = {
36+
name: "backend-#{port.external_port}",
37+
bind: {
38+
port: port.internal_port,
39+
mode: port.mode
40+
},
41+
balance: port.load_bal
42+
}
43+
44+
if port.mode == 'http'
45+
a= [
46+
'option httpclose',
47+
'option forwardfor',
48+
'cookie JSESSIONID prefix'
49+
]
50+
backend[:options] = a
51+
backend[:bind][:options] = [ 'cookie A check' ]
52+
end
53+
ingress[:frontend] << frontend
54+
ingress[:backend] << backend
55+
end
56+
57+
ingress.remove_symbols_from_keys
58+
end
59+
end

‎lib/mkit/app/controllers/services_controller.rb

+12
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,14 @@
33
require 'mkit/app/model/service'
44
require 'mkit/app/helpers/services_helper'
55
require 'mkit/app/helpers/params_helper'
6+
require 'mkit/app/helpers/migrations_helper'
67
require 'mkit/pods/docker_log_listener'
78
require 'mkit/pods/docker_exec_command'
89

910
class ServicesController < MKIt::Server
1011
helpers MKIt::ServicesHelper
1112
helpers MKIt::ParamsHelper
13+
helpers MKIt::MigrationsHelper
1214

1315
# curl localhost:4567/services
1416
get '/services' do
@@ -100,6 +102,16 @@ class ServicesController < MKIt::Server
100102
format_response(srv)
101103
end
102104

105+
post '/services/migrate' do
106+
srv = 'no file'
107+
if params[:file]
108+
tempfile = params[:file][:tempfile]
109+
yaml = YAML.safe_load(tempfile.read)
110+
srv = migrate_service(yaml).to_yaml
111+
end
112+
srv
113+
end
114+
103115
#
104116
# operations
105117
#
+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
# frozen_string_literal: true
2+
3+
module MKIt
4+
module MigrationsHelper
5+
6+
def migrate_service(yaml)
7+
yaml['service']['ingress'] = ports_to_ingress(yaml['service']['ports'])
8+
yaml['service'].delete('ports')
9+
yaml
10+
end
11+
12+
def ports_to_ingress(ports)
13+
ingress = { frontend: [], backend: [] }
14+
15+
ports.each_with_index do |port_config, index|
16+
match = port_config.match(/^(.*?):(.*?):(tcp|http):(.*?)($|:ssl$|:ssl,(.+))$/)
17+
next unless match
18+
19+
external_port, internal_port, mode, load_bal, ssl, cert = match.captures
20+
21+
frontend = {
22+
name: "frontend-#{external_port}",
23+
options: [],
24+
bind: {
25+
port: external_port,
26+
mode: mode
27+
},
28+
default_backend: "backend-#{external_port}"
29+
}
30+
31+
if ssl.start_with?(':ssl')
32+
frontend[:bind][:ssl] = true
33+
frontend[:bind][:cert] = cert
34+
end
35+
36+
backend = {
37+
name: "backend-#{external_port}",
38+
bind: {
39+
port: internal_port,
40+
mode: mode
41+
},
42+
balance: load_bal
43+
}
44+
45+
if mode == 'http'
46+
a= [
47+
'option httpclose',
48+
'option forwardfor',
49+
'cookie JSESSIONID prefix'
50+
]
51+
backend[:options] = a
52+
backend[:bind][:options] = [ 'cookie A check' ]
53+
end
54+
ingress[:frontend] << frontend
55+
ingress[:backend] << backend
56+
end
57+
58+
ingress.remove_symbols_from_keys
59+
end
60+
61+
end
62+
end

‎lib/mkit/app/helpers/services_helper.rb

+4-15
Original file line numberDiff line numberDiff line change
@@ -34,27 +34,16 @@ def find_srv_pod_by_id_or_name(srv)
3434
end
3535

3636
def build_table_row(data)
37-
ports = data.service_port&.each.map { |p| build_port(p) }.join(',')
37+
ports = data.ingress.frontends&.each.map { |f| build_port(f) }.join(',')
3838
pods = data.pod.each.map { |p| p.name.to_s }.join(' ')
3939
[data.id, data.name, data.lease&.ip, ports, pods, data.status]
4040
end
4141

4242
def build_port(p)
43-
case p.mode
44-
when 'http'
45-
if p.ssl?
46-
"#{p.mode}s/#{p.external_port}"
47-
else
48-
"#{p.mode}/#{p.external_port}"
49-
end
50-
when 'tcp'
51-
if p.ssl?
52-
"s#{p.mode}/#{p.external_port}"
53-
else
54-
"#{p.mode}/#{p.external_port}"
55-
end
43+
if p.ssl?
44+
"#{p.mode}s/#{p.port}"
5645
else
57-
"#{p.mode}/#{p.external_port}"
46+
"#{p.mode}/#{p.port}"
5847
end
5948
end
6049
end

‎lib/mkit/app/model/backend.rb

+58
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
# frozen_string_literal: true
2+
3+
class Backend < ActiveRecord::Base
4+
belongs_to :ingress
5+
serialize :options, JSON
6+
serialize :bind_options, JSON
7+
8+
def self.create(yaml)
9+
validate(yaml)
10+
backend = Backend.new
11+
backend.name = yaml["name"]
12+
backend.port = yaml["bind"]["port"] if yaml["bind"]["port"]
13+
backend.mode = yaml["bind"]["mode"] if yaml["bind"]["mode"]
14+
backend.options = yaml["options"] if yaml["options"]
15+
backend.load_bal = yaml["balance"] if yaml["balance"]
16+
backend.bind_options = yaml["bind"]["options"] if yaml["bind"]["options"]
17+
backend
18+
end
19+
20+
def self.validate(yaml)
21+
raise_bad_configuration "name is mandatory" unless yaml["name"]
22+
raise_bad_configuration "bind is mandatory" unless yaml["bind"]
23+
raise_bad_configuration "mode is mandatory" unless yaml["bind"]["mode"]
24+
raise_bad_configuration "mode must match tcp|http" unless yaml["bind"]["mode"] =~ /^(tcp|http)$/
25+
if yaml["balance"]
26+
raise_bad_configuration "balance must match round_robin|least_conn" unless yaml["balance"] =~ /^(round_robin|least_conn)$/
27+
end
28+
end
29+
30+
def load_balance
31+
case self.load_bal
32+
when /^round_robin$/
33+
"roundrobin"
34+
when /^least_conn$/
35+
"leastconn"
36+
else
37+
"roundrobin"
38+
end
39+
end
40+
41+
def to_h(options = {})
42+
hash = {
43+
name: self.name,
44+
balance: self.load_bal,
45+
options: self.options,
46+
bind: {
47+
port: self.port,
48+
mode: self.mode,
49+
options: self.bind_options
50+
}
51+
}
52+
53+
if self.port.nil? || self.port.empty?
54+
hash[:bind].delete(:port)
55+
end
56+
hash.remove_symbols_from_keys
57+
end
58+
end

‎lib/mkit/app/model/frontend.rb

+63
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# frozen_string_literal: true
2+
require 'mkit/exceptions'
3+
4+
class Frontend < ActiveRecord::Base
5+
belongs_to :ingress
6+
serialize :options, JSON
7+
serialize :bind_options, JSON
8+
has_one :backend
9+
10+
def self.create(yaml)
11+
validate(yaml)
12+
frontend = Frontend.new
13+
14+
frontend.name = yaml["name"]
15+
frontend.port = yaml["bind"]["port"] if yaml["bind"]["port"]
16+
frontend.mode = yaml["bind"]["mode"] if yaml["bind"]["mode"]
17+
frontend.bind_options = yaml["bind"]["options"] if yaml["bind"]["options"]
18+
frontend.options = yaml["options"] if yaml["options"]
19+
frontend.default_backend = yaml["use_backend"]
20+
21+
has_ssl = !yaml["bind"]["ssl"].nil? && yaml["bind"]["ssl"].to_s.start_with?('true')
22+
frontend.ssl = has_ssl ? 'true' : 'false'
23+
if has_ssl
24+
frontend.crt = yaml["bind"]["cert"].nil? ? MKIt::Utils.proxy_cert : yaml["bind"]["cert"]
25+
end
26+
27+
frontend
28+
end
29+
30+
def self.validate(yaml)
31+
raise_bad_configuration "name is mandatory" unless yaml["name"]
32+
raise_bad_configuration "default_backend is mandatory" unless yaml["default_backend"]
33+
raise_bad_configuration "bind is mandatory" unless yaml["bind"]
34+
raise_bad_configuration "mode is mandatory" unless yaml["bind"]["mode"]
35+
raise_bad_configuration "frontend port is mandatory" unless yaml["bind"]["port"]
36+
raise_bad_configuration "mode must match tcp|http" unless yaml["bind"]["mode"] =~ /^(tcp|http)$/
37+
end
38+
39+
def ssl?
40+
self.ssl == 'true'
41+
end
42+
43+
def to_h(options = {})
44+
hash = {
45+
name: self.name,
46+
options: self.options,
47+
bind: {
48+
port: self.port,
49+
mode: self.mode,
50+
ssl: self.ssl,
51+
cert: self.ssl? ? self.crt : nil,
52+
options: self.bind_options
53+
},
54+
default_backend: self.default_backend
55+
}
56+
57+
unless self.ssl?
58+
hash[:bind].delete(:ssl)
59+
hash[:bind].delete(:cert)
60+
end
61+
hash.remove_symbols_from_keys
62+
end
63+
end

‎lib/mkit/app/model/ingress.rb

+98
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
# frozen_string_literal: true
2+
require 'mkit/app/model/backend'
3+
require 'mkit/app/model/frontend'
4+
5+
class Ingress < ActiveRecord::Base
6+
belongs_to :service
7+
has_many :frontends, dependent: :destroy
8+
has_many :backends, dependent: :destroy
9+
10+
def self.create(yaml)
11+
validate(yaml)
12+
ingress = Ingress.new
13+
14+
yaml["backend"].each do |back|
15+
ingress.backends << Backend.create(back)
16+
end
17+
18+
yaml["frontend"].each do |front|
19+
ingress.frontends << Frontend.create(front)
20+
end
21+
ingress
22+
end
23+
24+
def self.validate(yaml)
25+
frontend_names = []
26+
frontend_ports = []
27+
28+
# must have at least one frontend and one backend
29+
raise_bad_configuration "Ingress section is mandatory" unless yaml
30+
raise_bad_configuration "At least one frontend is mandatory" unless yaml["frontend"]
31+
raise_bad_configuration "At least one backend is mandatory" unless yaml["backend"]
32+
# frontend name is mandatory
33+
yaml["frontend"].each { |front| raise "Frontend name is mandatory" unless front["name"] }
34+
# backend name is mandatory
35+
yaml["backend"].each { |back| raise "Backend name is mandatory" unless back["name"] }
36+
# frontend must point to a valid backend name - backend names list
37+
backend_names = yaml["backend"].map { |back| back["name"] }
38+
39+
# frontend validation
40+
yaml["frontend"].each do |front|
41+
# name is mandatory
42+
raise_bad_configuration "Frontend name is mandatory" unless front["name"]
43+
# frontend name must be unique
44+
if frontend_names.include?(front["name"])
45+
raise_bad_configuration "Frontend name '#{front["name"]}' must be unique"
46+
end
47+
frontend_names << front["name"]
48+
49+
# bind and mode are mandatory, port is not
50+
raise_bad_configuration "Frontend bind and mode are mandatory" unless front["bind"] && front["bind"]["mode"]
51+
52+
# port must be unique
53+
if frontend_ports.include?(front["bind"]["port"])
54+
raise_bad_configuration "Frontend port '#{front["bind"]["port"]}' must be unique"
55+
end
56+
frontend_ports << front["bind"]["port"]
57+
58+
# default_backend must point to a valid backend name
59+
unless backend_names.include?(front["default_backend"])
60+
raise_bad_configuration "Frontend default_backend '#{front["default_backend"]}' must point to a valid backend name"
61+
end
62+
63+
end
64+
65+
# backend validation
66+
backend_names.each do |name|
67+
if backend_names.count(name) > 1
68+
raise_bad_configuration "Backend name '#{name}' must be unique"
69+
end
70+
end
71+
72+
# global validations
73+
# each backend must point to a valid frontend default_backend
74+
frontend_default_backends = yaml["frontend"].map { |front| front["default_backend"] }
75+
yaml["backend"].each do |back|
76+
unless frontend_default_backends.include?(back["name"])
77+
raise_bad_configuration "Backend '#{back["name"]}' must be referenced by at least one frontend default_backend"
78+
end
79+
end
80+
81+
# when frontend port is range - e.g. 1200-1220, referred backend port must be empty
82+
yaml["frontend"].each do |front|
83+
if front["bind"]["port"] =~ /^\d+-\d+$/
84+
referred_backend = yaml["backend"].find { |back| back["name"] == front["default_backend"] }
85+
raise_bad_configuration "Frontend port range '#{front["bind"]["port"]}' must have an empty backend port" unless referred_backend && (referred_backend["bind"]["port"].nil?)
86+
end
87+
end
88+
89+
true
90+
end
91+
92+
def to_h(options = {})
93+
{
94+
frontend: self.frontends.map { |front| front.to_h },
95+
backend: self.backends.map { |back| back.to_h }
96+
}.remove_symbols_from_keys
97+
end
98+
end

‎lib/mkit/app/model/pod.rb

+7-13
Original file line numberDiff line numberDiff line change
@@ -58,13 +58,7 @@ def parse
5858
end
5959

6060
def start
61-
if self.instance.nil?
62-
docker_run = parse
63-
MKItLogger.info("deploying docker pod, cmd [#{docker_run}]")
64-
create_instance(docker_run)
65-
else
66-
start_instance(self.name) unless instance.State.Running
67-
end
61+
start_instance(self.name) unless instance.State.Running
6862
end
6963

7064
def stop
@@ -78,12 +72,12 @@ def instance
7872
end
7973

8074
def clean_up
81-
begin
82-
remove_instance(self.name) unless self.instance.nil?
83-
rescue => e
84-
MKItLogger.warn(e)
85-
end
86-
MkitJob.publish(topic: :pod_destroyed, service_id: self.service.id, data: {pod_id: self.id})
75+
# stop and destroy pod
76+
MkitJob.publish(topic: :destroy_pod_saga,
77+
service_id: self.service.id,
78+
pod_id: self.id,
79+
data: {pod_name: self.name}
80+
)
8781
end
8882

8983
def to_h

‎lib/mkit/app/model/service.rb

+21-23
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
require 'mkit/app/model/volume'
2+
require 'mkit/app/model/ingress'
23
require 'mkit/app/model/service_port'
34
require 'mkit/app/model/service_config'
45
require 'mkit/app/model/pod'
@@ -21,6 +22,7 @@ class Service < ActiveRecord::Base
2122

2223
has_one :lease, dependent: :destroy
2324
has_one :dns_host, dependent: :destroy
25+
has_one :ingress, dependent: :destroy
2426

2527
before_destroy :clean_up
2628

@@ -63,7 +65,9 @@ def self.create(yaml)
6365
data = { service_id: srv.id, version: srv.version }
6466
# create pod
6567
(1..srv.min_replicas).each { |i|
66-
MkitJob.publish(topic: :create_pod_saga, service_id: srv.id, data: data)
68+
pd = Pod.new( status: MKIt::Status::CREATED, name: SecureRandom.uuid.gsub('-','')[0..11])
69+
srv.pod << pd
70+
MkitJob.publish(topic: :create_pod_saga, data: {pod_name: pd.name})
6771
}
6872
srv
6973
end
@@ -90,12 +94,8 @@ def configure(config)
9094
end
9195
self.create_pods_network
9296

93-
# haproxy ports
94-
self.service_port = []
95-
config.ports&.each do |p|
96-
port = ServicePort.create(service: self, config: p)
97-
self.service_port << port
98-
end
97+
# haproxy config
98+
self.ingress = Ingress.create(config.ingress)
9999

100100
# volumes
101101
self.volume = []
@@ -119,12 +119,14 @@ def update!(yaml)
119119
self.version+=1
120120
self.configure(config)
121121

122-
# start new pod, destroy old pod...
123-
self.pod.each { |pod| MkitJob.publish(topic: :destroy_pod, pod_id: pod.id, data: {}) }
122+
# destroy old pods...
123+
self.pod.destroy_all
124124
# create pod
125125
data = { service_id: self.id, version: self.version }
126126
(1..self.min_replicas).each { |i|
127-
MkitJob.publish(topic: :create_pod_saga, service_id: self.id, data: data)
127+
pd = Pod.new( status: MKIt::Status::CREATED, name: SecureRandom.uuid.gsub('-','')[0..11])
128+
self.pod << pd
129+
MkitJob.publish(topic: :create_pod_saga, data: {pod_name: pd.name})
128130
}
129131
self.save
130132
end
@@ -164,6 +166,9 @@ def my_dns
164166
MKIt::Interface.ip
165167
end
166168

169+
# TODO
170+
# refactor to remove it from db model and check if it is needed
171+
# this will be the pod status
167172
def update_status!
168173
combined_status = nil
169174
self.pod.each { |pod|
@@ -252,6 +257,7 @@ def log
252257
end
253258
def to_h(options = {})
254259
details = options[:details] || false
260+
255261
yaml = {}
256262
yaml['service'] = {}
257263
srv = yaml['service']
@@ -269,18 +275,10 @@ def to_h(options = {})
269275
srv['pods'] << p.to_h
270276
}
271277
end
272-
srv['ports'] = []
273-
self.service_port.each { |p|
274-
"#{p.external_port}:#{p.internal_port}:#{p.mode}:#{p.load_bal}".tap { |x|
275-
if p.ssl == 'true'
276-
x << ':ssl'
277-
if !p.crt.nil? && p.crt != MKIt::Utils.proxy_cert
278-
x << ":#{p.crt}"
279-
end
280-
end
281-
srv['ports'] << x
282-
}
283-
}
278+
279+
# ingress
280+
srv['ingress'] = self.ingress.to_h(options)
281+
284282
srv['resources'] = {}
285283
srv['resources']['min_replicas'] = self.min_replicas
286284
srv['resources']['max_replicas'] = self.max_replicas
@@ -301,7 +299,7 @@ def to_h(options = {})
301299

302300
def as_json(options = {})
303301
srv = super
304-
a=[:pod, :volume, :service_config, :service_port]
302+
a=[:pod, :volume, :service_config, :ingress]
305303
a.each { | k |
306304
srv[k] ||= []
307305
self.send(k).each { |v|

‎lib/mkit/app/model/service_port.rb

-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ def parse_config(config)
3434
ports = config.match(CONFIG_EXPRESSION)
3535
raise MKIt::InvalidPortsConfiguration.new("no match with config expression $#{CONFIG_EXPRESSION}") if ports.nil?
3636

37-
puts ports
3837
self.external_port = ports[1]
3938
self.internal_port = ports[2]
4039
self.mode = ports[3]

‎lib/mkit/app/templates/haproxy/0000_defaults.cfg

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
global
22
log 127.0.0.1 local2
33
maxconn 4096
4-
user nobody
5-
group nobody
4+
user haproxy
5+
group haproxy
66

77
defaults
88
log global
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#
2+
# MKIt generated file
3+
# Service <%=name%>
4+
#
5+
6+
#
7+
# frontends
8+
#
9+
<% ingress.frontends.each { |fe|%>
10+
frontend <%=name%>-<%=fe.name%>-front
11+
bind <%=lease.ip%>:<%=fe.port%> <%=if fe.ssl? then "ssl crt #{fe.crt}" end%> <%=fe.bind_options.join(' ')%>
12+
mode <%=fe.mode%>
13+
<%=fe.options.join("\n ")%>
14+
15+
use_backend <%=name%>-<%=fe.default_backend%>-back
16+
<%}%>
17+
#
18+
# backends
19+
#
20+
<% ingress.backends.each { |be|%>
21+
backend <%=name%>-<%=be.name%>-back
22+
mode <%=be.mode%>
23+
balance <%=be.load_balance%>
24+
<%=be.options.join("\n ")%>
25+
<%pod.each { | pod | %>
26+
server <%=pod.name%> <%=pod.ip%><%unless be.port.nil? || be.port.empty? then%><%=":#{be.port}"%> <%=be.bind_options.join(' ')%> <%end%>
27+
<%}%>
28+
<%}%>

‎lib/mkit/client/commands.yaml

+13
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,19 @@
159159
request:
160160
verb: delete
161161
uri: "/services/<%=id%>"
162+
- cmd: migrate
163+
usage:
164+
- "<service.yaml>"
165+
help: migrate local service definition to the new schema version
166+
args:
167+
- name: file
168+
help:
169+
- file
170+
- Service definition
171+
mandatory: true
172+
request:
173+
verb: post
174+
uri: "/services/migrate"
162175
- cmd: exec
163176
usage:
164177
- "<service_id_or_name> [options] -- <command> [args...]"

‎lib/mkit/config/environment.rb

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
require_relative 'initializers/001_hash'
88
require_relative 'initializers/002_openstruct'
9+
require_relative 'initializers/003_custom_exceptions'
910

1011
SOCKET_PATH = File.expand_path('/tmp/app.sock')
1112

‎lib/mkit/config/initializers/001_hash.rb

+14
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,18 @@ def to_os
88
memo[key] = val.is_a?(Hash) ? val.to_os : val
99
end
1010
end
11+
12+
def remove_symbols_from_keys
13+
self.each_with_object({}) do |(k, v), new_hash|
14+
new_key = k.to_s
15+
new_value = if v.is_a?(Hash)
16+
v.remove_symbols_from_keys
17+
elsif v.is_a?(Array)
18+
v.map { |item| item.is_a?(Hash) ? item.remove_symbols_from_keys : item }
19+
else
20+
v
21+
end
22+
new_hash[new_key] = new_value
23+
end
24+
end
1125
end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# Load custom exceptions
2+
require 'mkit/exceptions'
3+
4+
module CustomExceptions
5+
def raise_bad_configuration(message)
6+
raise MKIt::InvalidConfigurationException, "MKIt :: Invalid Configuration :: #{message}"
7+
end
8+
end
9+
10+
Object.include(CustomExceptions)

‎lib/mkit/ctypes.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ module CType
2525
module Templates
2626
DOCKER_RUN = 'docker/docker_run.sh'
2727
DOCKER_BUILD = 'docker/docker_build.sh'
28-
HAPROXY = 'haproxy/xapp_haproxy.cfg'
28+
HAPROXY = 'haproxy/app_haproxy.cfg'
2929
HAPROXY_DEFAULTS = 'haproxy/0000_defaults.cfg'
3030
end
3131
end

‎lib/mkit/exceptions.rb

+13-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,19 @@ def initialize(message = nil)
2222
super(400, message)
2323
end
2424
end
25-
class ServiceNotFoundException < StandardError; end
25+
26+
class ServiceNotFoundException < BaseException
27+
def initialize(message = nil)
28+
super(404, message)
29+
end
30+
end
31+
32+
class InvalidConfigurationException < BaseException
33+
def initialize(message = nil)
34+
super(400, message)
35+
end
36+
end
37+
2638
class PodNotFoundException < StandardError; end
2739
class AppAlreadyDeployedException < StandardError; end
2840
class InvalidPortMappingTypeException < StandardError; end

‎lib/mkit/pods/docker_listener.rb

+19-14
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
# https://docs.docker.com/engine/reference/commandline/events
77
require 'mkit/app/helpers/docker_helper'
88
module MKIt
9-
class StopThread < RuntimeError; end
9+
class StopThread < RuntimeError; end
1010

1111
class DockerListener
1212
include MKIt::DockerHelper
@@ -67,22 +67,27 @@ def parse_message(msg)
6767
end
6868
when :network
6969
pod_id = msg.Actor.Attributes.container
70-
inspect = inspect_instance(pod_id).to_o
71-
pod_name = inspect.Name[1..]
72-
pod = Pod.find_by(name: pod_name)
73-
unless pod.nil?
74-
case action
75-
when :connect
76-
MKItLogger.info("docker network #{action} received: #{msg} for pod #{pod_name}")
77-
pod.update_ip
78-
pod.save
79-
when :disconnect
80-
MKItLogger.debug(" #{type} #{action} <<NOOP / TODO>>")
70+
inspect = inspect_instance(pod_id)
71+
unless inspect.nil?
72+
inspect = inspect.to_o
73+
pod_name = inspect.Name[1..]
74+
pod = Pod.find_by(name: pod_name)
75+
unless pod.nil?
76+
case action
77+
when :connect
78+
MKItLogger.info("docker network #{action} received: #{msg} for pod #{pod_name}")
79+
pod.update_ip
80+
pod.save
81+
when :disconnect
82+
MKItLogger.debug(" #{type} #{action} <<NOOP / TODO>>")
83+
else
84+
MKItLogger.debug(" #{type} #{action} <<TODO>>")
85+
end
8186
else
82-
MKItLogger.debug(" #{type} #{action} <<TODO>>")
87+
MKItLogger.warn("docker <<#{type}>> <#{action}> received: #{msg}. But I don't know anything about pod #{pod_id}/#{pod_name}")
8388
end
8489
else
85-
MKItLogger.warn("docker <<#{type}>> <#{action}> received: #{msg}. But I don't know anything about pod #{pod_id}/#{pod_name}")
90+
MKItLogger.warn("docker <<#{type}>> <#{action}> received: #{msg}. But I don't know anything about pod #{pod_id}")
8691
end
8792
else
8893
MKItLogger.info("\t#{type} #{action} <<unknown>>")

‎lib/mkit/sagas/create_pod_saga.rb

+9-7
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
1+
require 'mkit/app/helpers/docker_helper'
2+
13
module MKIt
24
class CreatePodSaga < ASaga
5+
include MKIt::DockerHelper
36

47
def topics
58
%w{create_pod_saga}
@@ -9,20 +12,19 @@ def topics
912
# create_pod_saga:
1013
#
1114
# payload:
12-
# * service_id
15+
# * pod_name
1316
#
1417
# triggers
1518
# * nothing
1619
#
1720
def do_the(job)
1821
MKItLogger.info("#{self.class} <#{job.topic}> #{job.inspect}....")
19-
service = Service.find(job.service_id)
20-
# create pod
2122

22-
pd = Pod.new( service: service, status: MKIt::Status::CREATED, name: SecureRandom.uuid.gsub('-','')[0..11])
23-
service.pod << pd
24-
service.save
25-
MkitJob.publish(topic: :start_pod, service_id: job.service_id, pod_id: pd.id)
23+
pod_name = job.data['pod_name']
24+
pod = Pod.find_by_name(pod_name)
25+
docker_run = pod.parse
26+
MKItLogger.info("deploying docker pod, cmd [#{docker_run}]")
27+
create_instance(docker_run)
2628
end
2729
end
2830
end

‎lib/mkit/sagas/destroy_pod_saga.rb

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
require 'mkit/app/helpers/docker_helper'
2+
3+
module MKIt
4+
class DestroyPodSaga < ASaga
5+
include MKIt::DockerHelper
6+
7+
def topics
8+
%w{destroy_pod_saga}
9+
end
10+
11+
#
12+
# destroy_pod_saga:
13+
#
14+
# payload:
15+
# * pod_name
16+
# * pod.id
17+
#
18+
# triggers
19+
# * pod_destroyed?
20+
#
21+
def do_the(job)
22+
MKItLogger.info("#{self.class} <#{job.topic}> #{job.inspect}....")
23+
24+
begin
25+
remove_instance(job.data['pod_name'])
26+
rescue => e
27+
MKItLogger.warn(e)
28+
end
29+
30+
end
31+
end
32+
end

‎lib/mkit/sagas/saga_manager.rb

+2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
require 'mkit/sagas/asaga'
22
require 'mkit/sagas/create_pod_saga'
3+
require 'mkit/sagas/destroy_pod_saga'
34

45
module MKIt
56
class SagaManager
67
def self.register_workers
78
CreatePodSaga.new
9+
DestroyPodSaga.new
810
end
911
end
1012
end

‎lib/mkit/version.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
module MKIt
2-
VERSION = "0.9.1"
2+
VERSION = "0.10.0"
33
end
44

‎lib/mkit/workers/pod_worker.rb

+3-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,9 @@ def do_the(job)
2828
MkitJob.publish(topic: :update_proxy_config, service_id: job.service_id)
2929
end
3030
when :pod_ip_updated
31-
MkitJob.publish(topic: :update_proxy_config, service_id: job.service_id)
31+
if Service.exists?(job.service_id)
32+
MkitJob.publish(topic: :update_proxy_config, service_id: job.service_id)
33+
end
3234
else
3335
MKItLogger.info("#{self.class} <<TODO>> job #{job.inspect}....")
3436
end

‎lib/mkit/workers/service_worker.rb

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
2+
13
module MKIt
24
class ServiceWorker < AWorker
35

‎samples/apps/httpbin.yml

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
---
2+
service:
3+
name: httpbin
4+
image: mccutchen/go-httpbin
5+
command:
6+
network: bridge
7+
ingress:
8+
frontend:
9+
- name: http-in-ssl
10+
options:
11+
- option httpclose
12+
- option forwardfor
13+
bind:
14+
port: 443
15+
mode: http
16+
ssl: true
17+
options:
18+
- accept-proxy
19+
- transparent
20+
- defer-accept
21+
default_backend: server
22+
- name: http-in
23+
options:
24+
- option forwardfor
25+
bind:
26+
port: 80
27+
mode: http
28+
default_backend: server
29+
backend:
30+
- name: server
31+
balance: round_robin
32+
options:
33+
- cookie JSESSIONID prefix
34+
bind:
35+
port: 8080
36+
mode: http
37+
options:
38+
- cookie A
39+
- check
40+
resources:
41+
min_replicas: 1
42+
max_replicas: 1
43+
volumes: []
44+
environment:
45+
LOG4J_LEVEL: WARN
46+
LOGGING_LEVEL_ROOT: WARN

‎samples/apps/kafka-cluster.yml

+18-8
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,31 @@
1-
#
1+
---
22
service:
33
name: kafka-cluster
44
network: kafka-cluster
55
image: confluentinc/cp-kafka:7.1.6
6-
ports:
7-
- 9092:9092:tcp:round_robin
86
volumes:
9-
- docker://kafka_cluster_secrets:/etc/kafka/secrets
10-
- docker://kafka_cluster_data:/var/lib/kafka/data
7+
- docker://kafka_cluster_secrets:/etc/kafka/secrets
8+
- docker://kafka_cluster_data:/var/lib/kafka/data
119
environment:
1210
KAFKA_BROKER_ID: 1
1311
KAFKA_ZOOKEEPER_CONNECT: kafka-zookeeper:2181
14-
KAFKA_AUTO_CREATE_TOPICS_ENABLE: "true"
12+
KAFKA_AUTO_CREATE_TOPICS_ENABLE: 'true'
1513
KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka-cluster:9092
1614
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT
17-
# KAFKA_CONFLUENT_SCHEMA_REGISTRY_URL: http://kafka-schema-registry
1815
KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
1916
KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: 1
2017
KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: 1
21-
18+
ingress:
19+
frontend:
20+
- name: frontend-9092
21+
options: []
22+
bind:
23+
port: '9092'
24+
mode: tcp
25+
default_backend: backend-9092
26+
backend:
27+
- name: backend-9092
28+
bind:
29+
port: '9092'
30+
mode: tcp
31+
balance: round_robin

‎samples/apps/kafka-magic.yml

+27-10
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,33 @@
1-
#
1+
---
22
service:
33
name: kafka-magic
44
network: kafka-cluster
5-
ports:
6-
- 80:80:http:round_robin
75
image: digitsy/kafka-magic
86
environment:
9-
KMAGIC_ALLOW_TOPIC_DELETE: "true"
10-
KMAGIC_ALLOW_SCHEMA_DELETE: "true"
11-
KMAGIC_CONFIG_STORE_TYPE: "file"
12-
KMAGIC_CONFIG_STORE_CONNECTION: "Data Source=/config/KafkaMagicConfig.db;"
13-
KMAGIC_CONFIG_ENCRYPTION_KEY: "123456"
7+
KMAGIC_ALLOW_TOPIC_DELETE: 'true'
8+
KMAGIC_ALLOW_SCHEMA_DELETE: 'true'
9+
KMAGIC_CONFIG_STORE_TYPE: file
10+
KMAGIC_CONFIG_STORE_CONNECTION: Data Source=/config/KafkaMagicConfig.db;
11+
KMAGIC_CONFIG_ENCRYPTION_KEY: '123456'
1412
volumes:
15-
- docker://kafka_magic_config:/config
16-
13+
- docker://kafka_magic_config:/config
14+
ingress:
15+
frontend:
16+
- name: frontend-80
17+
options: []
18+
bind:
19+
port: '80'
20+
mode: http
21+
default_backend: backend-80
22+
backend:
23+
- name: backend-80
24+
bind:
25+
port: '80'
26+
mode: http
27+
options:
28+
- cookie A check
29+
balance: round_robin
30+
options:
31+
- option httpclose
32+
- option forwardfor
33+
- cookie JSESSIONID prefix

‎samples/apps/kafka-zookeeper.yml

+18-7
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,26 @@
1-
#
1+
---
22
service:
33
name: kafka-zookeeper
44
image: confluentinc/cp-zookeeper:7.1.6
55
network: kafka-cluster
6-
ports:
7-
- 2181:2181:tcp:round_robin
86
volumes:
9-
- docker://kafka_zookeeper_secrets:/etc/zookeeper/secrets
10-
- docker://kafka_zookeeper_data:/var/lib/zookeeper/data
11-
- docker://kafka_zookeeper_log:/var/lib/zookeeper/log
7+
- docker://kafka_zookeeper_secrets:/etc/zookeeper/secrets
8+
- docker://kafka_zookeeper_data:/var/lib/zookeeper/data
9+
- docker://kafka_zookeeper_log:/var/lib/zookeeper/log
1210
environment:
1311
ZOOKEEPER_CLIENT_PORT: 2181
1412
ZOOKEEPER_TICK_TIME: 2000
15-
13+
ingress:
14+
frontend:
15+
- name: frontend-2181
16+
options: []
17+
bind:
18+
port: '2181'
19+
mode: tcp
20+
default_backend: backend-2181
21+
backend:
22+
- name: backend-2181
23+
bind:
24+
port: '2181'
25+
mode: tcp
26+
balance: round_robin

‎samples/apps/minio.yml

+33-7
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,42 @@
1-
#
1+
---
22
service:
33
name: minio
44
image: minio/minio
55
command: server /data --console-address ":9001"
66
network: bridge
7-
ports:
8-
- 9001:9001:http:round_robin
9-
- 9000:9000:tcp:round_robin
107
environment:
118
MINIO_ACCESS_KEY: minio
129
MINIO_SECRET_KEY: minio123
1310
volumes:
14-
- docker://minio_data:/data
15-
#- /tmp/minio_data:/data
16-
11+
- docker://minio_data:/data
12+
ingress:
13+
frontend:
14+
- name: frontend-9001
15+
options: []
16+
bind:
17+
port: '9001'
18+
mode: http
19+
default_backend: backend-9001
20+
- name: frontend-9000
21+
options: []
22+
bind:
23+
port: '9000'
24+
mode: tcp
25+
default_backend: backend-9000
26+
backend:
27+
- name: backend-9001
28+
bind:
29+
port: '9001'
30+
mode: http
31+
options:
32+
- cookie A check
33+
balance: round_robin
34+
options:
35+
- option httpclose
36+
- option forwardfor
37+
- cookie JSESSIONID prefix
38+
- name: backend-9000
39+
bind:
40+
port: '9000'
41+
mode: tcp
42+
balance: round_robin

‎samples/apps/mongo.yml

+15-4
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,20 @@
1-
#
1+
---
22
service:
33
name: mongo
44
image: mongo:4.0
55
command: "--smallfiles"
66
network: bridge
7-
ports:
8-
- 27017:27017:tcp:round_robin
9-
7+
ingress:
8+
frontend:
9+
- name: frontend-27017
10+
options: []
11+
bind:
12+
port: '27017'
13+
mode: tcp
14+
default_backend: backend-27017
15+
backend:
16+
- name: backend-27017
17+
bind:
18+
port: '27017'
19+
mode: tcp
20+
balance: round_robin

‎samples/apps/nexus.yml

+41-6
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,49 @@
1-
#
1+
---
22
service:
33
name: nexus
44
image: sonatype/nexus3
55
network: bridge
6-
ports:
7-
- 80:8081:http:round_robin
8-
- 443:8081:http:round_robin:ssl
96
resources:
107
max_replicas: 1
118
min_replicas: 1
129
volumes:
13-
- docker://nexus_data:/nexus-data
14-
10+
- docker://nexus_data:/nexus-data
11+
ingress:
12+
frontend:
13+
- name: frontend-80
14+
options: []
15+
bind:
16+
port: '80'
17+
mode: http
18+
default_backend: backend-80
19+
- name: frontend-443
20+
options: []
21+
bind:
22+
port: '443'
23+
mode: http
24+
ssl: true
25+
cert:
26+
default_backend: backend-443
27+
backend:
28+
- name: backend-80
29+
bind:
30+
port: '8081'
31+
mode: http
32+
options:
33+
- cookie A check
34+
balance: round_robin
35+
options:
36+
- option httpclose
37+
- option forwardfor
38+
- cookie JSESSIONID prefix
39+
- name: backend-443
40+
bind:
41+
port: '8081'
42+
mode: http
43+
options:
44+
- cookie A check
45+
balance: round_robin
46+
options:
47+
- option httpclose
48+
- option forwardfor
49+
- cookie JSESSIONID prefix

‎samples/apps/postgres.yml

+17-7
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,32 @@
1-
#
1+
---
22
service:
33
name: postgres
44
network: bridge
5-
image: "postgres:14"
6-
ports:
7-
- 5432:5432:tcp:round_robin
5+
image: postgres:14
86
environment:
97
POSTGRES_USER: postgres
108
POSTGRES_PASSWORD: postgres
119
POSTGRES_DB: postgres
1210
volumes:
13-
- docker://postgresql_14_data:/var/lib/postgresql/data
11+
- docker://postgresql_14_data:/var/lib/postgresql/data
1412
restart: always
1513
resources:
1614
max_replicas: 1
1715
min_replicas: 1
1816
limits:
1917
cpu: 1000m
2018
ram: 1Gi
21-
22-
19+
ingress:
20+
frontend:
21+
- name: frontend-5432
22+
options: []
23+
bind:
24+
port: '5432'
25+
mode: tcp
26+
default_backend: backend-5432
27+
backend:
28+
- name: backend-5432
29+
bind:
30+
port: '5432'
31+
mode: tcp
32+
balance: round_robin

‎samples/apps/rabbitmq.yml

+35-8
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,46 @@
1-
#
1+
---
22
service:
33
name: rabbitmq
44
image: rabbitmq:3-management-alpine
5-
network: bridge # docker network
6-
ports:
7-
- 5672:5672:tcp:round_robin
8-
- 80:15672:http:round_robin
5+
network: bridge
96
resources:
107
max_replicas: 1
118
min_replicas: 1
129
volumes:
13-
- docker://mkit_rabbitmq_data:/var/lib/rabbitmq
14-
- docker://mkit_rabbitmq_logs:/var/log/rabbitmq
10+
- docker://mkit_rabbitmq_data:/var/lib/rabbitmq
11+
- docker://mkit_rabbitmq_logs:/var/log/rabbitmq
1512
environment:
1613
RABBITMQ_DEFAULT_USER: admin
1714
RABBITMQ_DEFAULT_PASS: admin
1815
RABBITMQ_DEFAULT_VHOST: mkit
19-
16+
ingress:
17+
frontend:
18+
- name: frontend-5672
19+
options: []
20+
bind:
21+
port: '5672'
22+
mode: tcp
23+
default_backend: backend-5672
24+
- name: frontend-80
25+
options: []
26+
bind:
27+
port: '80'
28+
mode: http
29+
default_backend: backend-80
30+
backend:
31+
- name: backend-5672
32+
bind:
33+
port: '5672'
34+
mode: tcp
35+
balance: round_robin
36+
- name: backend-80
37+
bind:
38+
port: '15672'
39+
mode: http
40+
options:
41+
- cookie A check
42+
balance: round_robin
43+
options:
44+
- option httpclose
45+
- option forwardfor
46+
- cookie JSESSIONID prefix

‎samples/apps/redis-sentinel.yml

+15-5
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,21 @@
1-
#
1+
---
22
service:
33
name: redis-sentinel
44
image: bitnami/redis-sentinel:latest
55
network: bridge
6-
ports:
7-
- 26379:26379:tcp:round_robin
86
environment:
97
REDIS_MASTER_HOST: redis
10-
11-
8+
ingress:
9+
frontend:
10+
- name: frontend-26379
11+
options: []
12+
bind:
13+
port: '26379'
14+
mode: tcp
15+
default_backend: backend-26379
16+
backend:
17+
- name: backend-26379
18+
bind:
19+
port: '26379'
20+
mode: tcp
21+
balance: round_robin

‎samples/apps/redis.yml

+15-5
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,19 @@
1-
#
1+
---
22
service:
33
name: redis
44
image: redis:4.0-alpine
55
network: bridge
6-
ports:
7-
- 6379:6379:tcp:round_robin
8-
9-
6+
ingress:
7+
frontend:
8+
- name: frontend-6379
9+
options: []
10+
bind:
11+
port: '6379'
12+
mode: tcp
13+
default_backend: backend-6379
14+
backend:
15+
- name: backend-6379
16+
bind:
17+
port: '6379'
18+
mode: tcp
19+
balance: round_robin

0 commit comments

Comments
 (0)
Please sign in to comment.