-
Notifications
You must be signed in to change notification settings - Fork 2.7k
feat(source): add Nomad service #5284
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
kiurchv
wants to merge
4
commits into
kubernetes-sigs:master
Choose a base branch
from
kiurchv:nomad-source
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
2c13ebe
feat(source): add Nomad Service source
kiurchv f997a1c
chore: add test cases for Nomad Service source
kiurchv 0959ee2
docs: add tutorial for Nomad service source
kiurchv 9e5b7eb
refactor: move duplicated service endpoint merge logic into `mergeAnd…
kiurchv File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,197 @@ | ||
# Nomad Service Source | ||
|
||
This tutorial explains how to configure ExternalDNS to use Nomad services as a source. | ||
|
||
The Nomad service source reads metadata from services registered with the Nomad agent and uses it to determine DNS configuration. | ||
|
||
By using `--source=nomad-service`, ExternalDNS can discover DNS endpoints from applications registered in a [HashiCorp Nomad](https://www.nomadproject.io/) cluster. | ||
This allows DNS records to be dynamically created and updated based on the state of Nomad services, similar to how ExternalDNS works with Kubernetes resources. | ||
|
||
## CLI Flags | ||
|
||
This source respects these external-dns CLI flags: | ||
|
||
```bash | ||
--namespace="" # Limit resources queried for endpoints to a specific namespace (default: all namespaces) | ||
--fqdn-template="" # A templated string that's used to generate DNS names from sources that don't define a hostname themselves | ||
--[no-]combine-fqdn-annotation # Combine FQDN template and Annotations instead of overwriting | ||
--[no-]ignore-hostname-annotation # Ignore hostname annotation when generating DNS names, valid only when --fqdn-template is set | ||
``` | ||
|
||
The following flags are available for customizing Nomad integration (all optional): | ||
|
||
```bash | ||
--nomad-address="" # Nomad API address. Defaults to $NOMAD_ADDR or http://127.0.0.1:4646 | ||
--nomad-region="" # Nomad region. Defaults to agent's configured region | ||
--nomad-token=NOMAD-TOKEN # Nomad ACL token for authentication | ||
--nomad-wait-time=0s # API blocking timeout (Watch WaitTime) | ||
``` | ||
|
||
Also, Nomad agent connection and authentication options can be configured via environment variables (e.g., `NOMAD_ADDR`, `NOMAD_REGION`, `NOMAD_TOKEN`, etc.) | ||
|
||
### Example: Run ExternalDNS with Nomad source | ||
|
||
You can run ExternalDNS with the Nomad service source and any supported DNS provider: | ||
|
||
```bash | ||
external-dns \ | ||
--source=nomad-service \ | ||
--provider=inmemory \ | ||
--nomad-address=http://127.0.0.1:4646 | ||
``` | ||
|
||
## Nomad Service Tags | ||
|
||
The `nomad-service` source uses Nomad [service tags](https://developer.hashicorp.com/nomad/docs/job-specification/service#tags) to define configuration that is typically specified using Kubernetes annotations in other sources. | ||
|
||
Unlike Kubernetes annotations, which are a key-value map, Nomad tags are represented as a flat array of strings. To work around this difference, the implementation expects tags to follow a `key=value` format under the `external-dns.` prefix. | ||
|
||
For example: | ||
|
||
```hcl | ||
tags = [ | ||
"external-dns.hostname=example.nomad.internal.", | ||
"external-dns.ttl=300", | ||
"external-dns.controller=dns-controller", | ||
"external-dns.set-identifier=my-id" | ||
] | ||
``` | ||
|
||
These tags are interpreted by ExternalDNS in the same way it would interpret Kubernetes annotations: | ||
|
||
```yaml | ||
annotations: | ||
external-dns.alpha.kubernetes.io/hostname: "example.nomad.internal." | ||
external-dns.alpha.kubernetes.io/ttl: "300" | ||
external-dns.alpha.kubernetes.io/controller: "dns-controller" | ||
external-dns.alpha.kubernetes.io/set-identifier: "my-id" | ||
``` | ||
|
||
To reduce verbosity and improve clarity, the Nomad tag keys are shortened versions of their corresponding Kubernetes annotations. This source supports next ExternalDNS annotation equivalents set via service tags: | ||
|
||
| Nomad Tag | Kubernetes Annotation Equivalent | | ||
|-----------|----------------------------------| | ||
| external-dns.hostname | external-dns.alpha.kubernetes.io/hostname | | ||
| external-dns.target | external-dns.alpha.kubernetes.io/target | | ||
| external-dns.ttl | external-dns.alpha.kubernetes.io/ttl | | ||
| external-dns.controller | external-dns.alpha.kubernetes.io/controller | | ||
| external-dns.set-identifier | external-dns.alpha.kubernetes.io/set-identifier | | ||
|
||
Additionally, provider-specific configuration is also supported via tags. For example: | ||
|
||
```hcl | ||
tags = [ | ||
"external-dns.hostname=app.example.org.", | ||
"external-dns.aws-weight=100", | ||
"external-dns.cloudflare-proxied=true" | ||
] | ||
``` | ||
|
||
### Example service block in a Nomad job | ||
|
||
```hcl | ||
service { | ||
name = "whoami-demo" | ||
port = "http" | ||
provider = "nomad" | ||
tags = [ | ||
"external-dns.hostname=whoami.example.org.", | ||
"external-dns.target=${attr.unique.network.ip-address}", | ||
] | ||
} | ||
``` | ||
|
||
This configuration will result in an A record for whoami.example.org. pointing to the IP of the service port. | ||
|
||
## Example Nomad Job | ||
|
||
Here's a complete job spec to demonstrate usage: | ||
|
||
```hcl | ||
job "whoami" { | ||
group "demo" { | ||
network { | ||
mode = "host" | ||
|
||
port "http" { | ||
static = 80 | ||
} | ||
} | ||
|
||
service { | ||
name = "whoami-demo" | ||
port = "http" | ||
provider = "nomad" | ||
tags = [ | ||
"external-dns.alpha.kubernetes.io/hostname=whoami.example.org.", | ||
"external-dns.alpha.kubernetes.io/ttl=60" | ||
] | ||
} | ||
|
||
task "server" { | ||
driver = "docker" | ||
|
||
config { | ||
image = "traefik/whoami" | ||
ports = ["http"] | ||
} | ||
|
||
env { | ||
WHOAMI_PORT_NUMBER = "${NOMAD_PORT_http}" | ||
} | ||
} | ||
} | ||
} | ||
``` | ||
|
||
The ExternalDNS itself can be deployed to a Nomad cluster as a regular job: | ||
|
||
```hcl | ||
job "external-dns" { | ||
group "external-dns" { | ||
network { | ||
mode = "bridge" | ||
|
||
port "http" { | ||
to = 7979 | ||
} | ||
} | ||
|
||
task "controller" { | ||
driver = "docker" | ||
|
||
config { | ||
image = "registry.k8s.io/external-dns/external-dns:latest" | ||
ports = ["http"] | ||
|
||
args = [ | ||
"--source=nomad-service", | ||
"--nomad-address=http://${attr.unique.network.ip-address}:4646", | ||
] | ||
} | ||
|
||
resources { | ||
cpu = 50 | ||
memory = 32 | ||
} | ||
|
||
service { | ||
provider = "nomad" | ||
port = "http" | ||
|
||
check { | ||
type = "http" | ||
path = "/healthz" | ||
interval = "10s" | ||
timeout = "3s" | ||
} | ||
} | ||
} | ||
} | ||
} | ||
``` | ||
|
||
## Notes | ||
|
||
* This source does not require Kubernetes; it works directly with the Nomad HTTP API. | ||
* Integration with DNS providers (e.g., AWS Route 53, Cloudflare, etc.) is handled the same as with other ExternalDNS sources. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -214,6 +214,10 @@ type Config struct { | |
TraefikDisableNew bool | ||
NAT64Networks []string | ||
ExcludeUnschedulable bool | ||
NomadAddress string | ||
NomadRegion string | ||
NomadToken string `secure:"yes"` | ||
NomadWaitTime time.Duration | ||
} | ||
|
||
var defaultConfig = &Config{ | ||
|
@@ -306,6 +310,10 @@ var defaultConfig = &Config{ | |
MinEventSyncInterval: 5 * time.Second, | ||
Namespace: "", | ||
NAT64Networks: []string{}, | ||
NomadAddress: "", | ||
NomadRegion: "", | ||
NomadToken: "", | ||
NomadWaitTime: 0, | ||
NS1Endpoint: "", | ||
NS1IgnoreSSL: false, | ||
OCIConfigFile: "/etc/kubernetes/oci.yaml", | ||
|
@@ -453,6 +461,13 @@ func App(cfg *Config) *kingpin.Application { | |
// Flags related to Skipper RouteGroup | ||
app.Flag("skipper-routegroup-groupversion", "The resource version for skipper routegroup").Default(defaultConfig.SkipperRouteGroupVersion).StringVar(&cfg.SkipperRouteGroupVersion) | ||
|
||
// Flags related to Nomad | ||
app.Flag("nomad-address", "Nomad endpoint address, if empty it defaults to NOMAD_ADDR or http://127.0.0.1:4646").Default(defaultConfig.NomadAddress).StringVar(&cfg.NomadAddress) | ||
app.Flag("nomad-region", "Nomad region to use. If not provided, the default agent region is used").Default(defaultConfig.NomadRegion).StringVar(&cfg.NomadRegion) | ||
// app.Flag("nomad-namespace", "Nomad namespace to use. If not provided the default namespace is used").Default(defaultConfig.NomadNamespace).StringVar(&cfg.NomadNamespace) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. is this required? If not let's remove commented code |
||
app.Flag("nomad-token", "Nomad per-request ACL token").StringVar(&cfg.NomadToken) | ||
app.Flag("nomad-wait-time", "WaitTime limits how long a Watch will block. If not provided, the agent default values will be used").Default(defaultConfig.NomadWaitTime.String()).DurationVar(&cfg.NomadWaitTime) | ||
|
||
// Flags related to processing source | ||
app.Flag("always-publish-not-ready-addresses", "Always publish also not ready addresses for headless services (optional)").BoolVar(&cfg.AlwaysPublishNotReadyAddresses) | ||
app.Flag("annotation-filter", "Filter resources queried for endpoints by annotation, using label selector semantics").Default(defaultConfig.AnnotationFilter).StringVar(&cfg.AnnotationFilter) | ||
|
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is nomad require no authentication? Any RBAC required to list services in namespace or in all namespaces?