From 165805452ffd538d4c72249443c50f2196479ad4 Mon Sep 17 00:00:00 2001 From: Sebastian Nickel Date: Tue, 3 Dec 2024 10:15:04 +0100 Subject: [PATCH] allow for custom domain in k8s-nameserver This allows for a custom domain in the k8s-nameserver application. It can be set via an argument to the binary and will default to ts.net if not set. --- cmd/k8s-nameserver/main.go | 16 ++++++++++------ .../deploy/crds/tailscale.com_dnsconfigs.yaml | 5 +++++ cmd/k8s-operator/deploy/manifests/operator.yaml | 5 +++++ cmd/k8s-operator/nameserver.go | 7 +++++++ k8s-operator/api.md | 1 + k8s-operator/apis/v1alpha1/types_tsdnsconfig.go | 4 ++++ 6 files changed, 32 insertions(+), 6 deletions(-) diff --git a/cmd/k8s-nameserver/main.go b/cmd/k8s-nameserver/main.go index ca4b449358083..cc1e226a79591 100644 --- a/cmd/k8s-nameserver/main.go +++ b/cmd/k8s-nameserver/main.go @@ -11,6 +11,7 @@ package main import ( "context" "encoding/json" + "flag" "fmt" "log" "net" @@ -26,9 +27,12 @@ import ( "tailscale.com/util/dnsname" ) +var ( + // domain is the DNS domain that this nameserver has registered a handler for. + domain = flag.String("domain", "ts.net", "the DNS domain to serve records for") +) + const ( - // tsNetDomain is the domain that this DNS nameserver has registered a handler for. - tsNetDomain = "ts.net" // addr is the the address that the UDP and TCP listeners will listen on. addr = ":1053" @@ -40,7 +44,7 @@ const ( ) // nameserver is a simple nameserver that responds to DNS queries for A records -// for ts.net domain names over UDP or TCP. It serves DNS responses from +// for the names of the given domain over UDP or TCP. It serves DNS responses from // in-memory IPv4 host records. It is intended to be deployed on Kubernetes with // a ConfigMap mounted at /config that should contain the host records. It // dynamically reconfigures its in-memory mappings as the contents of the @@ -78,11 +82,11 @@ func main() { // reset when the configuration changes. ns.runRecordsReconciler(ctx) - // Register a DNS server handle for ts.net domain names. Not having a + // Register a DNS server handle for names of the domain. Not having a // handle registered for any other domain names is how we enforce that - // this nameserver can only be used for ts.net domains - querying any + // this nameserver can only be used for the given domain - querying any // other domain names returns Rcode Refused. - dns.HandleFunc(tsNetDomain, ns.handleFunc()) + dns.HandleFunc(*domain, ns.handleFunc()) // Listen for DNS queries over UDP and TCP. udpSig := make(chan os.Signal) diff --git a/cmd/k8s-operator/deploy/crds/tailscale.com_dnsconfigs.yaml b/cmd/k8s-operator/deploy/crds/tailscale.com_dnsconfigs.yaml index 13aee9b9e9ebf..fd6093b00d8a3 100644 --- a/cmd/k8s-operator/deploy/crds/tailscale.com_dnsconfigs.yaml +++ b/cmd/k8s-operator/deploy/crds/tailscale.com_dnsconfigs.yaml @@ -80,6 +80,11 @@ spec: required: - nameserver properties: + domain: + description: |- + Domain is the domain for which DNS entries will be resolved. If left + empty, the default of the k8s-nameserver will be used. + type: string nameserver: description: |- Configuration for a nameserver that can resolve ts.net DNS names diff --git a/cmd/k8s-operator/deploy/manifests/operator.yaml b/cmd/k8s-operator/deploy/manifests/operator.yaml index 1a812b7362757..9777d328502ed 100644 --- a/cmd/k8s-operator/deploy/manifests/operator.yaml +++ b/cmd/k8s-operator/deploy/manifests/operator.yaml @@ -325,6 +325,11 @@ spec: More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status properties: + domain: + description: |- + Domain is the domain for which DNS entries will be resolved. If left + empty, the default of the k8s-nameserver will be used. + type: string nameserver: description: |- Configuration for a nameserver that can resolve ts.net DNS names diff --git a/cmd/k8s-operator/nameserver.go b/cmd/k8s-operator/nameserver.go index 52577c929acea..02f5912a15e4e 100644 --- a/cmd/k8s-operator/nameserver.go +++ b/cmd/k8s-operator/nameserver.go @@ -177,6 +177,9 @@ func (a *NameserverReconciler) maybeProvision(ctx context.Context, tsDNSCfg *tsa if tsDNSCfg.Spec.Nameserver.Image != nil && tsDNSCfg.Spec.Nameserver.Image.Tag != "" { dCfg.imageTag = tsDNSCfg.Spec.Nameserver.Image.Tag } + if tsDNSCfg.Spec.Domain != "" { + dCfg.domain = tsDNSCfg.Spec.Domain + } for _, deployable := range []deployable{saDeployable, deployDeployable, svcDeployable, cmDeployable} { if err := deployable.updateObj(ctx, dCfg, a.Client); err != nil { return fmt.Errorf("error reconciling %s: %w", deployable.kind, err) @@ -207,6 +210,7 @@ type deployConfig struct { labels map[string]string ownerRefs []metav1.OwnerReference namespace string + domain string } var ( @@ -227,6 +231,9 @@ var ( return fmt.Errorf("error unmarshalling Deployment yaml: %w", err) } d.Spec.Template.Spec.Containers[0].Image = fmt.Sprintf("%s:%s", cfg.imageRepo, cfg.imageTag) + if cfg.domain != "" { + d.Spec.Template.Spec.Containers[0].Args = []string{"-domain", cfg.domain} + } d.ObjectMeta.Namespace = cfg.namespace d.ObjectMeta.Labels = cfg.labels d.ObjectMeta.OwnerReferences = cfg.ownerRefs diff --git a/k8s-operator/api.md b/k8s-operator/api.md index e8a6e248a2934..913d5b9bf9fe4 100644 --- a/k8s-operator/api.md +++ b/k8s-operator/api.md @@ -211,6 +211,7 @@ _Appears in:_ | Field | Description | Default | Validation | | --- | --- | --- | --- | | `nameserver` _[Nameserver](#nameserver)_ | Configuration for a nameserver that can resolve ts.net DNS names
associated with in-cluster proxies for Tailscale egress Services and
Tailscale Ingresses. The operator will always deploy this nameserver
when a DNSConfig is applied. | | | +| `domain` _string_ | Domain is the domain for which DNS entries will be resolved. If left
empty, the default of the k8s-nameserver will be used. | | | #### DNSConfigStatus diff --git a/k8s-operator/apis/v1alpha1/types_tsdnsconfig.go b/k8s-operator/apis/v1alpha1/types_tsdnsconfig.go index 60d212279f4f5..d58214511b7d7 100644 --- a/k8s-operator/apis/v1alpha1/types_tsdnsconfig.go +++ b/k8s-operator/apis/v1alpha1/types_tsdnsconfig.go @@ -75,6 +75,10 @@ type DNSConfigSpec struct { // Tailscale Ingresses. The operator will always deploy this nameserver // when a DNSConfig is applied. Nameserver *Nameserver `json:"nameserver"` + // Domain is the domain for which DNS entries will be resolved. If left + // empty, the default of the k8s-nameserver will be used. + // +optional + Domain string `json:"domain"` } type Nameserver struct {