Traefik & Nomad Service Discovery¶
A Story of Tags, Services & Nomads
Attach tags to your Nomad services and let Traefik do the rest!
Configuration Examples¶
Configuring Nomad & Deploying Services
Enabling the nomad provider
providers:
nomad: {}
[providers.nomad]
--providers.nomad=true
Attaching tags to services:
...
service {
name = "myService"
tags = [
"traefik.http.routers.my-router.rule=Host(`example.com`)",
]
}
...
Routing Configuration¶
See the dedicated section in routing.
Provider Configuration¶
refreshInterval
¶
Optional, Default=15s
Defines the polling interval.
providers:
nomad:
refreshInterval: 30s
# ...
[providers.nomad]
refreshInterval = "30s"
# ...
--providers.nomad.refreshInterval=30s
# ...
prefix
¶
required, Default="traefik"
The prefix for Nomad service tags defining Traefik labels.
providers:
nomad:
prefix: test
# ...
[providers.nomad]
prefix = "test"
# ...
--providers.nomad.prefix=test
# ...
stale
¶
Optional, Default=false
Use stale consistency for Nomad service API reads.
This makes reads very fast and scalable at the cost of a higher likelihood of stale values.
For more information, see the Nomad documentation on consistency.
providers:
nomad:
stale: true
# ...
[providers.nomad]
stale = true
# ...
--providers.nomad.stale=true
# ...
endpoint
¶
Defines the Nomad server endpoint.
address
¶
Defines the address of the Nomad server.
Optional, Default="http://127.0.0.1:4646"
providers:
nomad:
endpoint:
address: http://127.0.0.1:4646
# ...
[providers.nomad]
[providers.nomad.endpoint]
address = "http://127.0.0.1:4646"
# ...
--providers.nomad.endpoint.address=http://127.0.0.1:4646
# ...
token
¶
Optional, Default=""
Token is used to provide a per-request ACL token, if Nomad ACLs are enabled. The appropriate ACL privilege for this token is 'read-job', as outlined in the Nomad documentation on ACL.
providers:
nomad:
endpoint:
token: test
# ...
[providers.nomad]
[providers.nomad.endpoint]
token = "test"
# ...
--providers.nomad.endpoint.token=test
# ...
endpointWaitTime
¶
Optional, Default=""
Limits the duration for which a Watch can block. If not provided, the agent default values will be used.
providers:
nomad:
endpoint:
endpointWaitTime: 15s
# ...
[providers.nomad]
[providers.nomad.endpoint]
endpointWaitTime = "15s"
# ...
--providers.nomad.endpoint.endpointwaittime=15s
# ...
tls
¶
Optional
Defines the TLS configuration used for the secure connection to the Nomad API.
ca
¶
Optional
ca
is the path to the certificate authority used for the secure connection to Nomad,
it defaults to the system bundle.
providers:
nomad:
endpoint:
tls:
ca: path/to/ca.crt
[providers.nomad.endpoint.tls]
ca = "path/to/ca.crt"
--providers.nomad.endpoint.tls.ca=path/to/ca.crt
cert
¶
Optional
cert
is the path to the public certificate used for the secure connection to the Nomad API.
When using this option, setting the key
option is required.
providers:
nomad:
endpoint:
tls:
cert: path/to/foo.cert
key: path/to/foo.key
[providers.nomad.endpoint.tls]
cert = "path/to/foo.cert"
key = "path/to/foo.key"
--providers.nomad.endpoint.tls.cert=path/to/foo.cert
--providers.nomad.endpoint.tls.key=path/to/foo.key
key
¶
Optional
key
is the path to the private key used for the secure connection to the Nomad API.
When using this option, setting the cert
option is required.
providers:
nomad:
endpoint:
tls:
cert: path/to/foo.cert
key: path/to/foo.key
[providers.nomad.endpoint.tls]
cert = "path/to/foo.cert"
key = "path/to/foo.key"
--providers.nomad.endpoint.tls.cert=path/to/foo.cert
--providers.nomad.endpoint.tls.key=path/to/foo.key
insecureSkipVerify
¶
Optional, Default=false
If insecureSkipVerify
is true
, the TLS connection to Nomad accepts any certificate presented by the server regardless of the hostnames it covers.
providers:
nomad:
endpoint:
tls:
insecureSkipVerify: true
[providers.nomad.endpoint.tls]
insecureSkipVerify = true
--providers.nomad.endpoint.tls.insecureskipverify=true
exposedByDefault
¶
Optional, Default=true
Expose Nomad services by default in Traefik.
If set to false
, services that do not have a traefik.enable=true
tag will be ignored from the resulting routing configuration.
For additional information, refer to Restrict the Scope of Service Discovery.
providers:
nomad:
exposedByDefault: false
# ...
[providers.nomad]
exposedByDefault = false
# ...
--providers.nomad.exposedByDefault=false
# ...
defaultRule
¶
Optional, Default=Host(`{{ normalize .Name }}`)
The default host rule for all services.
For a given service, if no routing rule was defined by a tag, it is defined by this defaultRule
instead.
The defaultRule
must be set to a valid Go template,
and can include sprig template functions.
The service name can be accessed with the Name
identifier,
and the template has access to all the labels (i.e. tags beginning with the prefix
) defined on this service.
The option can be overridden on an instance basis with the traefik.http.routers.{name-of-your-choice}.rule
tag.
providers:
nomad:
defaultRule: "Host(`{{ .Name }}.{{ index .Labels \"customLabel\"}}`)"
# ...
[providers.nomad]
defaultRule = "Host(`{{ .Name }}.{{ index .Labels \"customLabel\"}}`)"
# ...
--providers.nomad.defaultRule="Host(`{{ .Name }}.{{ index .Labels \"customLabel\"}}`)"
# ...
Default rule and Traefik service
The exposure of the Traefik container, combined with the default rule mechanism, can lead to create a router targeting itself in a loop. In this case, to prevent an infinite loop, Traefik adds an internal middleware to refuse the request if it comes from the same router.
constraints
¶
Optional, Default=""
The constraints
option can be set to an expression that Traefik matches against the service tags to determine whether
to create any route for that service. If none of the service tags match the expression, no route for that service is
created. If the expression is empty, all detected services are included.
The expression syntax is based on the Tag(`tag`)
, and TagRegex(`tag`)
functions,
as well as the usual boolean logic, as shown in examples below.
Constraints Expression Examples
# Includes only services having the tag `a.tag.name=foo`
constraints = "Tag(`a.tag.name=foo`)"
# Excludes services having any tag `a.tag.name=foo`
constraints = "!Tag(`a.tag.name=foo`)"
# With logical AND.
constraints = "Tag(`a.tag.name`) && Tag(`another.tag.name`)"
# With logical OR.
constraints = "Tag(`a.tag.name`) || Tag(`another.tag.name`)"
# With logical AND and OR, with precedence set by parentheses.
constraints = "Tag(`a.tag.name`) && (Tag(`another.tag.name`) || Tag(`yet.another.tag.name`))"
# Includes only services having a tag matching the `a\.tag\.t.+` regular expression.
constraints = "TagRegex(`a\.tag\.t.+`)"
providers:
nomad:
constraints: "Tag(`a.tag.name`)"
# ...
[providers.nomad]
constraints = "Tag(`a.tag.name`)"
# ...
--providers.nomad.constraints="Tag(`a.tag.name`)"
# ...
For additional information, refer to Restrict the Scope of Service Discovery.
namespaces
¶
Deprecated in favor of the namespaces
option.
Optional, Default=""
The namespace
option defines the namespace in which the Nomad services will be discovered.
Warning
One should only define either the namespaces
option or the namespace
option.
providers:
nomad:
namespace: "production"
# ...
[providers.nomad]
namespace = "production"
# ...
--providers.nomad.namespace=production
# ...
namespaces
¶
Optional, Default=""
The namespaces
option defines the namespaces in which the nomad services will be discovered.
When using the namespaces
option, the discovered object names will be suffixed as shown below:
<resource-name>@nomad-<namespace>
Warning
One should only define either the namespaces
option or the namespace
option.
providers:
nomad:
namespaces:
- "ns1"
- "ns2"
# ...
[providers.nomad]
namespaces = ["ns1", "ns2"]
# ...
--providers.nomad.namespaces=ns1,ns2
# ...
allowEmptyServices
¶
Optional, Default: false
If the parameter is set to true
,
it allows the creation of an empty servers load balancer if the targeted Nomad service has no endpoints available. This results in a 503
HTTP response instead of a 404
.
providers:
nomad:
allowEmptyServices: true
# ...
[providers.nomad]
allowEmptyServices = true
# ...
--providers.nomad.allowEmptyServices=true