293 lines
8.4 KiB
HCL
293 lines
8.4 KiB
HCL
job "[[ .instance ]]" {
|
|
|
|
[[ template "common/job_start" . ]]
|
|
|
|
group "mongo" {
|
|
|
|
[[- $c := merge .mongo . ]]
|
|
[[ template "common/group_start" $c ]]
|
|
|
|
network {
|
|
mode = "bridge"
|
|
port "mongo" {
|
|
[[- if has $c "port" ]]
|
|
static = [[ $c.port ]]
|
|
[[- end ]]
|
|
}
|
|
[[- if conv.ToBool $c.prometheus.enabled ]]
|
|
port "metrics" {}
|
|
[[- end ]]
|
|
}
|
|
|
|
[[ template "common/volumes" $c ]]
|
|
|
|
# The main service client will use to locate mongo servers
|
|
service {
|
|
name = "[[ .instance ]][[ .consul.suffix ]]"
|
|
port = "mongo"
|
|
|
|
[[ template "common/service_meta" $c ]]
|
|
|
|
check {
|
|
type = "script"
|
|
command = "sh"
|
|
args = ["-c", "/local/bin/mongosh --eval 'db.runCommand(\"ping\").ok'"]
|
|
interval = "[[ $c.consul.check.interval ]]"
|
|
timeout = "[[ $c.consul.check.timeout ]]"
|
|
task = "mongod"
|
|
}
|
|
|
|
tags = [
|
|
"mongo-${NOMAD_ALLOC_INDEX}"
|
|
]
|
|
}
|
|
|
|
# This service is just used by the different nodes to find themself and configure the replica set
|
|
service {
|
|
name = "[[ .instance ]]-rs[[ .consul.suffix ]]"
|
|
port = "mongo"
|
|
|
|
meta {
|
|
[[- range $k, $v := $c.consul.meta ]]
|
|
[[ $k ]] = "[[ $v ]]"
|
|
[[- end ]]
|
|
}
|
|
|
|
tags = [
|
|
"mongo-${NOMAD_ALLOC_INDEX}"
|
|
]
|
|
}
|
|
|
|
# This task will init the cluster on first boot
|
|
task "mongo-init" {
|
|
driver = "docker"
|
|
|
|
lifecycle {
|
|
hook = "poststart"
|
|
}
|
|
|
|
config {
|
|
[[ template "common/image" $c ]]
|
|
command = "/usr/local/bin/rs_config.sh"
|
|
pids_limit = 200
|
|
# Mount a few files from the main task
|
|
# Just to reduce the verbosity of templates {} sections
|
|
volumes = [
|
|
"../mongod/secrets/mongo.bundle.pem:/secrets/mongo.bundle.pem:ro",
|
|
"../mongod/secrets/mongo.ca.pem:/secrets/mongo.ca.pem:ro",
|
|
"../mongod/local/bin/mongosh:/usr/local/bin/mongosh:ro",
|
|
"../mongod/local/bin/rs_config.sh:/usr/local/bin/rs_config.sh:ro"
|
|
]
|
|
[[ template "common/tmpfs" "/tmp" ]]
|
|
}
|
|
|
|
# As the task exits after its done, only reserve little memory
|
|
# but allow it to use up to 256MB
|
|
resources {
|
|
cpu = 20
|
|
memory = 20
|
|
memory_max = 256
|
|
}
|
|
}
|
|
|
|
[[- if conv.ToBool $c.prometheus.enabled ]]
|
|
|
|
task "exporter" {
|
|
|
|
[[- $e := merge $c.exporter $c ]]
|
|
|
|
driver = "[[ $e.nomad.driver ]]"
|
|
user = "9216"
|
|
|
|
config {
|
|
[[ template "common/image" $e ]]
|
|
args = [
|
|
"--mongodb.uri=mongodb://127.0.0.1:${NOMAD_ALLOC_PORT_mongo}/%24external?replicaSet=[[ .mongo.replica_set ]]&authMechanism=MONGODB-X509&tls=true&tlsCertificateKeyFile=%2Fsecrets%2Fmongo.bundle.pem&tlsCAFile=%2Fsecrets%2Fmongo.ca.pem",
|
|
"--web.listen-address=:${NOMAD_ALLOC_PORT_metrics}",
|
|
"--web.config=/local/web_tls.yml",
|
|
"--collect-all"
|
|
]
|
|
pids_limit = 100
|
|
}
|
|
|
|
lifecycle {
|
|
hook = "poststart"
|
|
sidecar = true
|
|
}
|
|
|
|
[[ template "common/vault.policies" $e ]]
|
|
[[ template "common/artifacts" $e ]]
|
|
[[ template "common/metrics_cert" $e ]]
|
|
|
|
# TLS config for the exporter
|
|
template {
|
|
data = <<_EOT
|
|
[[ template "mongodb/exporter_tls.yml" $e ]]
|
|
_EOT
|
|
destination = "local/web_tls.yml"
|
|
}
|
|
|
|
# Get a certificate with monitoring capabilities
|
|
template {
|
|
data = <<_EOT
|
|
{{ with pkiCert "[[ $e.vault.pki.path ]]/issue/mongo-monitor"
|
|
"common_name=mongo.monitor"
|
|
"ttl=168h" }}
|
|
{{ .Cert }}
|
|
{{ .Key }}
|
|
{{ end }}
|
|
_EOT
|
|
destination = "secrets/mongo.bundle.pem"
|
|
uid = 109216
|
|
gid = 109216
|
|
perms = "0640"
|
|
}
|
|
|
|
# CA cert used to validate remote (mongo servers') certificate. Both root and intermediate
|
|
template {
|
|
data = <<_EOT
|
|
{{ with secret "[[ $e.vault.pki.path ]]/cert/ca_chain" }}{{ .Data.ca_chain }}{{ end }}
|
|
_EOT
|
|
destination = "secrets/mongo.ca.pem"
|
|
}
|
|
|
|
[[ template "common/resources" $c.exporter ]]
|
|
}
|
|
[[- end ]]
|
|
|
|
task "mongod" {
|
|
|
|
driver = "[[ $c.nomad.driver ]]"
|
|
leader = true
|
|
|
|
# Give mongod some time to shutdown
|
|
kill_timeout = "60s"
|
|
|
|
config {
|
|
[[ template "common/image" $c ]]
|
|
command = "mongod"
|
|
args = ["--config", "/local/mongod.conf"]
|
|
pids_limit = 500
|
|
volumes = [
|
|
"local/bin/mongosh:/usr/local/bin/mongosh:ro"
|
|
]
|
|
[[ template "common/tmpfs" "/tmp" ]]
|
|
}
|
|
|
|
[[ template "common/vault.policies" $c ]]
|
|
[[ template "common/artifacts" $c ]]
|
|
|
|
template {
|
|
data = <<_EOT
|
|
[[- if isKind "map" $c.config ]]
|
|
[[ merge $c.config (tmpl.Exec "mongodb/mongod.conf" $c | yaml) | toYAML ]]
|
|
[[- else if isKind "string" $c.config ]]
|
|
[[ merge ($c.config | yaml) (tmpl.Exec "mongodb/mongod.conf" $c | yaml) | toYAML ]]
|
|
[[- else ]]
|
|
[[ template "mongodb/mongod.conf" $c ]]
|
|
[[- end ]]
|
|
_EOT
|
|
destination = "local/mongod.conf"
|
|
}
|
|
|
|
# This is the certificate used by the mongod process
|
|
# Note : we ask for a cert valid for the host IP address, and also for the XXXXX.addr.dc1.consul address
|
|
# as it's what is published in the SRV record. The XXXX is the hex representation of the IP.
|
|
# Something like {{ range (env "NOMAD_IP_mongo" | split ".") }}{{ printf "%02x" (. | parseInt) }}{{ end }}
|
|
# would be cleaner, but can't find how to use it in this context
|
|
# Also : each instance will have a slightly differnt ttl so all cert will not expire at the same time
|
|
template {
|
|
data = <<_EOT
|
|
{{- with pkiCert "[[ $c.vault.pki.path ]]/issue/mongod"
|
|
(printf "common_name=mongo-%s.[[ .instance ]][[ .consul.suffix ]].service.[[ .consul.domain ]]" (env "NOMAD_ALLOC_INDEX"))
|
|
(
|
|
printf "alt_names=%02x%02x%02x%02x.addr.dc1.[[ .consul.domain ]]"
|
|
(env "NOMAD_HOST_IP_mongo" | regexReplaceAll "^(\\d+)\\..*" "$1" | parseInt)
|
|
(env "NOMAD_HOST_IP_mongo" | regexReplaceAll "^\\d+\\.(\\d+)\\..*" "$1" | parseInt)
|
|
(env "NOMAD_HOST_IP_mongo" | regexReplaceAll "^\\d+\\.\\d+\\.(\\d+)\\..*" "$1" | parseInt)
|
|
(env "NOMAD_HOST_IP_mongo" | regexReplaceAll "^\\d+\\.\\d+\\.\\d+\\.(\\d+)$" "$1" | parseInt)
|
|
)
|
|
(printf "ip_sans=%s,127.0.0.1" (env "NOMAD_HOST_IP_mongo"))
|
|
(printf "ttl=%dh" (env "NOMAD_ALLOC_INDEX" | parseInt | multiply 8 | add 600)) }}
|
|
{{ .Cert }}
|
|
{{ .Key }}
|
|
{{- end }}
|
|
_EOT
|
|
destination = "secrets/mongo.bundle.pem"
|
|
uid = 100999
|
|
gid = 100999
|
|
perms = "0640"
|
|
change_mode = "script"
|
|
change_script {
|
|
command = "/local/bin/rotate-cert.sh"
|
|
# If cert rotation fails, kill the task and restart it
|
|
fail_on_error = true
|
|
}
|
|
}
|
|
|
|
# CA cert used to validate remote certs
|
|
template {
|
|
data = <<_EOT
|
|
{{- with secret "[[ $c.vault.pki.path ]]/cert/ca_chain" }}
|
|
{{ .Data.ca_chain }}
|
|
{{- end }}
|
|
_EOT
|
|
destination = "secrets/mongo.ca.pem"
|
|
change_mode = "script"
|
|
change_script {
|
|
command = "/local/bin/rotate-cert.sh"
|
|
# If cert rotation fails, kill the task and restart it
|
|
fail_on_error = true
|
|
}
|
|
}
|
|
|
|
# A mongosh wrapper which will automatically use the x509 root cert
|
|
template {
|
|
data = <<_EOT
|
|
[[ template "mongodb/mongosh" $c ]]
|
|
_EOT
|
|
destination = "local/bin/mongosh"
|
|
uid = 100000
|
|
gid = 100000
|
|
perms = "0755"
|
|
}
|
|
|
|
# A script to dynamically reconfigure members' address when mongo instances restart
|
|
template {
|
|
data = <<_EOT
|
|
[[ template "mongodb/rs_config.sh" $c ]]
|
|
_EOT
|
|
destination = "local/bin/rs_config.sh"
|
|
uid = 100000
|
|
gid = 100000
|
|
perms = "0755"
|
|
change_mode = "script"
|
|
change_script {
|
|
command = "/local/bin/rs_config.sh"
|
|
# Will fail when mongod is shuting down. We don't want Nomad to kill the task
|
|
fail_on_error = false
|
|
}
|
|
}
|
|
|
|
# A script to rotate certificates
|
|
template {
|
|
data = <<_EOT
|
|
[[ template "mongodb/rotate-cert.sh" $c ]]
|
|
_EOT
|
|
destination = "local/bin/rotate-cert.sh"
|
|
uid = 100000
|
|
gid = 100000
|
|
perms = "0755"
|
|
}
|
|
|
|
# Persistent data
|
|
volume_mount {
|
|
volume = "mongo"
|
|
destination = "/data"
|
|
}
|
|
|
|
[[ template "common/resources" $c ]]
|
|
}
|
|
}
|
|
}
|