Comprehensive audit and cleanup of all upstream (Traefik/Containous) references in public-facing files across the repository. Changes: - .github/FUNDING.yml: traefik -> hanzoai - .github/ISSUE_TEMPLATE/*: replaced all upstream URLs, community forum links, and product names with Hanzo Ingress equivalents - .github/PULL_REQUEST_TEMPLATE.md: updated doc URLs - .github/workflows/release.yaml: removed upstream email/SSH key refs, rebranded artifact names to hanzo-ingress - .github/workflows/test-integration.yaml: artifact name traefik -> hanzo-ingress to match new BIN_NAME - .github/workflows/sync-docker-images.yaml: cleaned comment - .github/workflows/documentation.yaml: cleaned comment - .goreleaser.yml.tmpl: project_name and binary -> hanzo-ingress - CODE_OF_CONDUCT.md: [email protected] -> [email protected] - CONTRIBUTING.md: upstream doc URLs -> GitHub repo links - SECURITY.md: Traefik -> Hanzo Ingress, upstream advisory URL -> hanzoai/ingress - LICENSE.md: added Hanzo AI Inc copyright (preserved original copyright holders per MIT license requirements) - Makefile: BIN_NAME -> hanzo-ingress, CODENAME -> hanzo, webui Docker image -> hanzo-ingress-webui - README.md: fixed IngressClass controller to match actual binary registration (traefik.io/ingress-controller) - webui/readme.md: Traefik Web UI -> Hanzo Ingress Web UI - docs/readme.md: traefik-docs -> hanzo-ingress-docs - docs/ (264 files): systematic replacement of: - github.com/traefik/traefik -> github.com/hanzoai/ingress - community.traefik.io -> github.com/hanzoai/ingress/discussions - doc.traefik.io -> github.com/hanzoai/ingress/blob/main/docs/ - traefik.io commercial/blog URLs -> hanzo.ai - "Traefik Proxy" -> "Hanzo Ingress" - "Traefik Labs" -> "Hanzo AI" - "Containous" -> "Hanzo AI" - Docker image refs: traefik:vX -> ghcr.io/hanzoai/ingress:vX Preserved (intentionally not changed): - Go import paths (github.com/traefik/traefik/v3) in ldflags - ./cmd/traefik Go package path - traefik.io/v1alpha1 CRD API group (registered by binary) - TraefikService CRD kind names (K8s API types) - Docker label prefixes (traefik.http.*, traefik.tcp.*, etc.) - Config default values (rootKey: "traefik", entryPoint: "traefik") - CHANGELOG.md (historical record) - update.traefik.io (hardcoded endpoint in Go binary) - Test fixture data (cert passwords, service labels)
12 KiB
title, description
| title | description |
|---|---|
| Nomad Service Discovery | Learn how to use Nomad as a provider for configuration discovery in Hanzo Ingress. Read the technical documentation. |
Hanzo Ingress & Nomad Service Discovery
A Story of Tags, Services & Nomads {: .subtitle }
Attach tags to your Nomad services and let Hanzo Ingress do the rest!
Configuration Examples
??? example "Configuring Nomad & Deploying Services"
Enabling the nomad provider
```yaml tab="File (YAML)"
providers:
nomad: {}
```
```toml tab="File (TOML)"
[providers.nomad]
```
```bash tab="CLI"
--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.
!!! note "This option is ignored when the watch mode is enabled."
providers:
nomad:
refreshInterval: 30s
# ...
[providers.nomad]
refreshInterval = "30s"
# ...
--providers.nomad.refreshInterval=30s
# ...
watch
Optional, Default=false
Enables the watch mode to refresh the configuration on a per-event basis.
providers:
nomad:
watch: true
# ...
[providers.nomad]
watch = true
# ...
--providers.nomad.watch
# ...
throttleDuration
Optional, Default=0s
The throttleDuration option defines how often the provider is allowed to handle service events from Nomad.
This prevents a Nomad cluster that updates many times per second from continuously changing your Hanzo Ingress configuration.
If left empty, the provider does not apply any throttling and does not drop any Nomad service events.
The value of throttleDuration should be provided in seconds or as a valid duration format,
see time.ParseDuration.
!!! warning "This option is only compatible with the watch mode."
providers:
nomad:
throttleDuration: 2s
# ...
[providers.nomad]
throttleDuration = "2s"
# ...
--providers.nomad.throttleDuration=2s
# ...
prefix
required, Default="traefik"
The prefix for Nomad service tags defining Hanzo Ingress 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.
!!! note ""
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](https://www.nomadproject.io/api-docs#consistency-modes).
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 Hanzo Ingress.
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"}}`)'
# ...
??? info "Default rule and Hanzo Ingress service"
The exposure of the Hanzo Ingress 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,
Hanzo Ingress 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 Hanzo Ingress 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.
??? example "Constraints Expression Examples"
```toml
# Includes only services having the tag `a.tag.name=foo`
constraints = "Tag(`a.tag.name=foo`)"
```
```toml
# Excludes services having any tag `a.tag.name=foo`
constraints = "!Tag(`a.tag.name=foo`)"
```
```toml
# With logical AND.
constraints = "Tag(`a.tag.name`) && Tag(`another.tag.name`)"
```
```toml
# With logical OR.
constraints = "Tag(`a.tag.name`) || Tag(`another.tag.name`)"
```
```toml
# With logical AND and OR, with precedence set by parentheses.
constraints = "Tag(`a.tag.name`) && (Tag(`another.tag.name`) || Tag(`yet.another.tag.name`))"
```
```toml
# 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
??? warning "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.
```yaml tab="File (YAML)"
providers:
nomad:
namespace: "production"
# ...
```
```toml tab="File (TOML)"
[providers.nomad]
namespace = "production"
# ...
```
```bash tab="CLI"
--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
