-
Notifications
You must be signed in to change notification settings - Fork 0
/
rabbitmq-cluster.hcl
360 lines (311 loc) · 12.3 KB
/
rabbitmq-cluster.hcl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
variables {
image_repository = "registry.savage.zone/rabbitmq-cluster:latest"
// automated deployments can set this to the image digest to force an update of the job
// when the image is updated.
image_digest = "sha256:...."
dns_suffix = "savage.zone"
}
job "rabbitmq-cluster" {
datacenters = ["dc1"]
type = "service"
group "rabbitmq" {
// set this to the number of nodes in the cluster
count = 3
update {
max_parallel = 1
health_check = "checks"
min_healthy_time = "20s"
healthy_deadline = "5m"
progress_deadline = "10m"
stagger = "60s"
}
constraint {
attribute = "${node.class}"
value = "proxmox"
}
// We'll be using CSI volumes for persistent storage
// this requires a number of volumes to be previously created
// with IDs "rabbitmq-cluster-data[0]", "rabbitmq-cluster-data[1]", "rabbitmq-cluster-data[2]", etc
volume "rabbitmq-cluster-data" {
type = "csi"
read_only = false
source = "rabbitmq-cluster-data"
access_mode = "single-node-writer"
attachment_mode = "file-system"
per_alloc = true
}
network {
mode = "bridge"
port "stream" { to = 5552 }
port "mqtt" { to = 1883 }
port "amqp" { to = 5672 }
// this is the ERL_EPMD_PORT
port "discovery" {
to = 4369
static = 4369
}
// this is the RABBITMQ_DIST_PORT
port "clustering" {
to = 25672
static = 25672
}
// The rabbbitmq streams plugin requires a range of ports to be open
// for stream replication across the cluster.
port "stream_replication" {
to = 6000
static = 6000
}
port "stream_replication_1" {
to = 6001
static = 6001
}
port "stream_replication_2" {
to = 6002
static = 6002
}
port "stream_replication_3" {
to = 6003
static = 6003
}
// I'm not sure these are necessary
port "ctl0" {
to = 35672
static = 35672
}
port "ctl1" {
to = 35673
static = 35673
}
port "ctl2" {
to = 35674
static = 35674
}
port "ctl4" {
to = 35675
static = 35675
}
// ensure that the DNS server is set to dnsmasq
dns {
servers = ["127.0.0.1"]
}
}
// Consul service registration for the management UI and API
service {
name = "rabbitmq-cluster-management"
tags = [
"rabbitmq",
"traefik.enable=true",
"traefik.consulcatalog.connect=true",
"traefik.http.routers.rabbitmq-cluster-management.entrypoints=https",
"traefik.http.routers.rabbitmq-cluster-management.middlewares=rabbitmq-cluster-management-compress,rabbitmq-cluster-management-retry",
"traefik.http.middlewares.rabbitmq-cluster-management-compress.compress=true",
"traefik.http.middlewares.rabbitmq-cluster-management-retry.retry.attempts=5",
"traefik.http.middlewares.rabbitmq-cluster-management-retry.retry.initialinterval=100ms",
]
port = 15672
connect {
sidecar_service {}
// Per this issue: https://github.com/hashicorp/nomad/issues/11056
// The extra_hosts field doesn't work when set in the task's config block, and should be
// set in the sidecar_task block instead. In our case we have several sidecar tasks,
// so we need to set it in each one.
sidecar_task {
config {
extra_hosts = [
"rabbitmq-cluster-${NOMAD_ALLOC_INDEX}.service.consul:127.0.0.1"
]
}
}
}
check {
expose = true
type = "http"
// /api/index.html is the only path that doesn't require authentication,
// so it's a reasonable health check endpoint
path = "/api/index.html"
interval = "30s"
timeout = "2s"
}
check_restart {
limit = 3
grace = "120s"
ignore_warnings = false
}
}
service {
name = "rabbitmq-cluster-prometheus"
tags = [
"rabbitmq",
"traefik.enable=true",
"traefik.consulcatalog.connect=true",
"traefik.http.routers.rabbitmq-cluster-prometheus.entrypoints=https",
"traefik.http.routers.rabbitmq-cluster-prometheus.middlewares=rabbitmq-cluster-prometheus-compress",
"traefik.http.middlewares.rabbitmq-cluster-prometheus-compress.compress=true",
]
port = 15692
connect {
sidecar_service {}
// See above
sidecar_task {
config {
extra_hosts = [
"rabbitmq-cluster-${NOMAD_ALLOC_INDEX}.service.consul:127.0.0.1"
]
}
}
}
}
service {
name = "rabbitmq-cluster-amqp"
tags = [
"rabbitmq",
"traefik.enable=true",
"traefik.tcp.routers.rabbitmq-cluster-amqp-ingress.entrypoints=https",
"traefik.tcp.routers.rabbitmq-cluster-amqp-ingress.rule=HostSNI(`rabbitmq-cluster-amqp.${var.dns_suffix}`)",
"traefik.tcp.routers.rabbitmq-cluster-amqp-ingress.tls=true",
]
port = "amqp"
}
service {
name = "rabbitmq-cluster-stream"
tags = [
"rabbitmq",
"traefik.enable=true",
"traefik.tcp.routers.rabbitmq-cluster-stream-ingress.entrypoints=https",
"traefik.tcp.routers.rabbitmq-cluster-stream-ingress.rule=HostSNI(`rabbitmq-cluster-stream.${var.dns_suffix}`)",
"traefik.tcp.routers.rabbitmq-cluster-stream-ingress.tls=true",
]
port = "stream"
}
service {
name = "rabbitmq-cluster-mqtt"
tags = [
"rabbitmq",
"traefik.enable=true",
"traefik.tcp.routers.rabbitmq-cluster-mqtt-ingress.entrypoints=https",
"traefik.tcp.routers.rabbitmq-cluster-mqtt-ingress.rule=HostSNI(`rabbitmq-cluster-mqtt.${var.dns_suffix}`)",
"traefik.tcp.routers.rabbitmq-cluster-mqtt-ingress.tls=true",
]
port = "mqtt"
}
service {
name = "rabbitmq-mqtt-web"
tags = [
"rabbitmq",
"traefik.enable=true",
"traefik.consulcatalog.connect=true",
"traefik.http.routers.rabbitmq-cluster-mqtt-web.entrypoints=https",
"traefik.http.routers.rabbitmq-cluster-mqtt-web.middlewares=rabbitmq-cluster-mqtt-web-compress",
"traefik.http.middlewares.rabbitmq-cluster-mqtt-web-compress.compress=true",
]
port = 15675
connect {
sidecar_service {}
// See above
sidecar_task {
config {
extra_hosts = [
"rabbitmq-cluster-${NOMAD_ALLOC_INDEX}.service.consul:127.0.0.1"
]
}
}
}
}
service {
name = "rabbitmq-cluster-${NOMAD_ALLOC_INDEX}"
tags = [
"rabbitmq",
]
port = "discovery"
}
task "rabbitmq" {
driver = "docker"
volume_mount {
volume = "rabbitmq-cluster-data"
destination = "/var/lib/rabbitmq"
read_only = false
}
env {
RABBITMQ_USE_LONGNAME = "true"
RABBITMQ_NODENAME = "rabbitmq@rabbitmq-cluster-${NOMAD_ALLOC_INDEX}.service.consul"
// You probably want to get these from vault or otherwise store them securely
RABBITMQ_DEFAULT_USER = "guest"
RABBITMQ_DEFAULT_PASS = "guest"
RABBITMQ_ERLANG_COOKIE = "somethingsecret"
// This will be used in the config template below to limit
// the memory available to the rabbitmq process, otherwise it will think
// it has access to all the memory on the host
RABBITMQ_TOTAL_MEMORY_AVAILABLE_OVERRIDE_VALUE = "1GB"
RABBITMQ_CLUSTER_NAME = "rabbitmq-cluster@${var.dns_suffix}"
// ports
ERL_EPMD_PORT = "4369"
RABBITMQ_NODE_PORT = "5672"
RABBITMQ_DIST_PORT = "25672"
RABBITMQ_CTL_DIST_PORT_MIN = "35672"
RABBITMQ_CTL_DIST_PORT_MAX = "35675"
}
config {
image = var.image_repository
volumes = [
"local/rabbitmq.conf:/etc/rabbitmq/rabbitmq.conf",
"local/enabled_plugins:/etc/rabbitmq/enabled_plugins",
"local/advanced.config:/etc/rabbitmq/advanced.config",
]
ports = [
// clustering
"discovery", "clustering",
// cli tools
"ctl0", "ctl1", "ctl2", "ctl3",
// stream replication
"stream_replication", "stream_replication_1", "stream_replication_2", "stream_replication_3",
// protocols
"stream", "mqtt", "amqp"
]
// this doesn't work per https://github.com/hashicorp/nomad/issues/11056, see above
extra_hosts = [
"rabbitmq-cluster-${NOMAD_ALLOC_INDEX}.service.consul:127.0.0.1"
]
}
meta {
image_digest = "${var.image_digest}"
}
// limit the stream replication ports to this range
template {
data = <<EOH
[{osiris, [{port_range, {6000, 6003}}]}].
EOH
destination = "local/advanced.config"
}
template {
data = <<EOH
[rabbitmq_shovel_management,rabbitmq_shovel,rabbitmq_management,rabbitmq_prometheus,rabbitmq_mqtt,rabbitmq_stomp,rabbitmq_stream,rabbitmq_web_mqtt,rabbitmq_web_mqtt_examples].
EOH
destination = "local/enabled_plugins"
}
template {
data = <<EOH
# Authentication Settings
auth_backends.1 = internal
# Clustering setup: set the number of nodes to equal the number of nodes in the cluster
cluster_formation.peer_discovery_backend = classic_config
cluster_formation.classic_config.nodes.1 = [email protected]
cluster_formation.classic_config.nodes.2 = [email protected]
cluster_formation.classic_config.nodes.3 = [email protected]
# Logging Settings
log.console = true
log.console.level = info
log.default.level = info
# General settings
total_memory_available_override_value = $(RABBITMQ_TOTAL_MEMORY_AVAILABLE_OVERRIDE_VALUE)
cluster_name = $(RABBITMQ_CLUSTER_NAME)
EOH
destination = "local/rabbitmq.conf"
}
resources {
cpu = 100
memory = 512
memory_max = 1024
}
}
}
}