Use CoreDNS for everything and make directives dynamic

This moves CoreDNS from Kubernetes to the network tree and uses
it for OS-side resolution too. For this to work together with Kubernetes it now
contains a dynamic directive system which allows various parts of the OS
to register and unregister directives at runtime. This system is used to hook
Kubernetes and DHCP-supplied DNS servers into the configuration.

This also enables the hosts plugin to resolve the local hostname from within
CoreDNS to avoid querying external DNS servers for that (T773).

Test Plan:
CTS covers K8s-related tests, external resolution manually tested from
a container.

Bug: T860, T773

X-Origin-Diff: phab/D628
GitOrigin-RevId: f1729237f3d17d8801506f4d299b90e7dce0893a
diff --git a/core/internal/kubernetes/service.go b/core/internal/kubernetes/service.go
index 55c20bf..e4391f5 100644
--- a/core/internal/kubernetes/service.go
+++ b/core/internal/kubernetes/service.go
@@ -33,11 +33,11 @@
 
 	"git.monogon.dev/source/nexantic.git/core/internal/common/supervisor"
 	"git.monogon.dev/source/nexantic.git/core/internal/kubernetes/clusternet"
-	"git.monogon.dev/source/nexantic.git/core/internal/kubernetes/dns"
 	"git.monogon.dev/source/nexantic.git/core/internal/kubernetes/nfproxy"
 	"git.monogon.dev/source/nexantic.git/core/internal/kubernetes/pki"
 	"git.monogon.dev/source/nexantic.git/core/internal/kubernetes/reconciler"
 	"git.monogon.dev/source/nexantic.git/core/internal/localstorage"
+	"git.monogon.dev/source/nexantic.git/core/internal/network/dns"
 	"git.monogon.dev/source/nexantic.git/core/pkg/logbuffer"
 	apb "git.monogon.dev/source/nexantic.git/core/proto/api"
 )
@@ -47,8 +47,9 @@
 	ServiceIPRange   net.IPNet
 	ClusterNet       net.IPNet
 
-	KPKI *pki.KubernetesPKI
-	Root *localstorage.Root
+	KPKI                    *pki.KubernetesPKI
+	Root                    *localstorage.Root
+	CorednsRegistrationChan chan *dns.ExtraDirective
 }
 
 type state struct {
@@ -56,7 +57,6 @@
 	controllerManagerLogs *logbuffer.LogBuffer
 	schedulerLogs         *logbuffer.LogBuffer
 	kubeletLogs           *logbuffer.LogBuffer
-	corednsLogs           *logbuffer.LogBuffer
 }
 
 type Service struct {
@@ -84,7 +84,6 @@
 		controllerManagerLogs: logbuffer.New(5000, 16384),
 		schedulerLogs:         logbuffer.New(5000, 16384),
 		kubeletLogs:           logbuffer.New(5000, 16384),
-		corednsLogs:           logbuffer.New(5000, 16384),
 	}
 	s.stateMu.Lock()
 	s.state = st
@@ -167,12 +166,6 @@
 		ClientSet:   clientSet,
 	}
 
-	dns := dns.Service{
-		Kubeconfig:    masterKubeconfig,
-		Output:        s.state.corednsLogs,
-		ClusterDomain: "cluster.local", // Hardcode this here until we make this configurable
-	}
-
 	for _, sub := range []struct {
 		name     string
 		runnable supervisor.Runnable
@@ -186,7 +179,6 @@
 		{"csi-provisioner", csiProvisioner.Run},
 		{"clusternet", clusternet.Run},
 		{"nfproxy", nfproxy.Run},
-		{"dns", dns.Run},
 	} {
 		err := supervisor.Run(ctx, sub.name, sub.runnable)
 		if err != nil {
@@ -194,8 +186,13 @@
 		}
 	}
 
+	supervisor.Logger(ctx).Info("Registering K8s CoreDNS")
+	clusterDNSDirective := dns.NewKubernetesDirective("cluster.local", masterKubeconfig)
+	s.c.CorednsRegistrationChan <- clusterDNSDirective
+
 	supervisor.Signal(ctx, supervisor.SignalHealthy)
-	supervisor.Signal(ctx, supervisor.SignalDone)
+	<-ctx.Done()
+	s.c.CorednsRegistrationChan <- dns.CancelDirective(clusterDNSDirective)
 	return nil
 }
 
@@ -216,8 +213,6 @@
 		return s.state.schedulerLogs.ReadLinesTruncated(n, "..."), nil
 	case "kubelet":
 		return s.state.kubeletLogs.ReadLinesTruncated(n, "..."), nil
-	case "coredns":
-		return s.state.corednsLogs.ReadLinesTruncated(n, "..."), nil
 	default:
 		return nil, errors.New("component not available")
 	}