kubernetes/kops · error

error building dns scope: %v

Error message

error building dns scope: %v

What it means

NewNodeController wraps any failure from dnsContext.CreateScope("node") with this message. CreateScope fails only when a scope named "node" already exists, so this indicates the node scope was already created on the same DNSContext — the node watcher is being constructed twice or shares a context with prior initialization.

Source

Thrown at dns-controller/pkg/watchers/node.go:49

	kopsutil "k8s.io/kops/pkg/apis/kops/util"
	"k8s.io/kops/upup/pkg/fi/utils"
)

// NodeController watches for nodes
//
// Unlike other watchers, NodeController only creates alias records referenced by records from other controllers
type NodeController struct {
	util.Stoppable
	client   kubernetes.Interface
	scope    dns.Scope
	haveType map[dns.RecordType]bool
}

// NewNodeController creates a NodeController
func NewNodeController(client kubernetes.Interface, dnsContext dns.Context, internalRecordTypes []dns.RecordType) (*NodeController, error) {
	scope, err := dnsContext.CreateScope("node")
	if err != nil {
		return nil, fmt.Errorf("error building dns scope: %v", err)
	}

	c := &NodeController{
		client:   client,
		scope:    scope,
		haveType: map[dns.RecordType]bool{},
	}

	for _, recordType := range internalRecordTypes {
		c.haveType[recordType] = true
	}

	return c, nil
}

// Run starts the NodeController.
func (c *NodeController) Run() {
	klog.Infof("starting node controller")

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Ensure initializeWatchers runs once per DNSController
  2. Construct a fresh DNSController if watchers must be reinitialized
  3. Check the wrapped %v cause for "duplicate scope" and find the earlier CreateScope("node") call site
  4. Use a distinct scope name for any custom node DNS records

Example fix

// before
dnsContext := dns.NewDNSController(...)
NewNodeController(client, dnsContext, types)
NewNodeController(client, dnsContext, types) // duplicate
// after
nodeCtl := NewNodeController(client, dnsContext, types) // single instance owns the "node" scope
Defensive patterns

Strategy: try-catch

Validate before calling

var watchersOnce sync.Once
func ensureWatchers(client kubernetes.Interface, dnsCtx dns.Context, types []dns.RecordType) error {
    var err error
    watchersOnce.Do(func() { err = initializeWatchers(client, dnsCtx, types) })
    return err
}

Try / catch

ctl, err := watchers.NewNodeController(client, dnsContext, internalTypes)
if err != nil {
    if strings.Contains(err.Error(), "duplicate scope") {
        return nil // node watcher already running on this context
    }
    return fmt.Errorf("starting node watcher: %w", err)
}

Prevention

When it happens

Trigger: initializeWatchers calls NewNodeController on a DNSContext that already has a "node" scope — duplicate initializeWatchers invocation, or another component created the "node" scope first.

Common situations: Calling initializeWatchers twice (reload path, test double-setup); constructing both a custom node recorder and the built-in node controller against one DNSController; reusing a DNSController after a failed previous start.

Related errors


AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05). Data as JSON: /api/errors/aa8e3a9f18d5e3fe. Report an issue: GitHub.