From cf7e333579561316a8f41cca9d378c1e33e5c2aa Mon Sep 17 00:00:00 2001 From: Pavel Sviderski Date: Thu, 1 May 2025 11:27:27 +1000 Subject: [PATCH] feat(dns-server): use embedded DNS server for all service containers --- Makefile | 4 ++++ internal/machine/docker/server.go | 22 +++++++++++++++++++--- internal/machine/machine.go | 12 +++++++----- 3 files changed, 30 insertions(+), 8 deletions(-) diff --git a/Makefile b/Makefile index 4ba7a397..4254ae39 100644 --- a/Makefile +++ b/Makefile @@ -36,6 +36,10 @@ demo-reset: ssh root@5.223.45.199 "AUTO_CONFIRM=true sudo -E uncloud-uninstall" ssh spy@192.168.40.243 "AUTO_CONFIRM=true sudo -E uncloud-uninstall" +.PHONY: ucind-cluster +ucind-cluster: + go run ./cmd/ucind cluster rm && go run ./cmd/ucind cluster create -m 3 + .PHONY: proto proto: protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative \ diff --git a/internal/machine/docker/server.go b/internal/machine/docker/server.go index e011afe5..10d2fbba 100644 --- a/internal/machine/docker/server.go +++ b/internal/machine/docker/server.go @@ -8,6 +8,7 @@ import ( "fmt" "io" "log/slog" + "net/netip" "regexp" "slices" "strconv" @@ -30,6 +31,7 @@ import ( "github.com/opencontainers/go-digest" ocispec "github.com/opencontainers/image-spec/specs-go/v1" "github.com/psviderski/uncloud/internal/machine/api/pb" + "github.com/psviderski/uncloud/internal/machine/dns" "github.com/psviderski/uncloud/internal/secret" "github.com/psviderski/uncloud/pkg/api" "google.golang.org/grpc" @@ -45,13 +47,17 @@ type Server struct { pb.UnimplementedDockerServer client *client.Client db *sqlx.DB + // internalDNSIP is a function that returns the IP address of the internal DNS server. It may return an empty + // address if the address is unknown (e.g. when the machine is not initialised yet). + internalDNSIP func() netip.Addr } // NewServer creates a new Docker gRPC server with the provided Docker client. -func NewServer(cli *client.Client, db *sqlx.DB) *Server { +func NewServer(cli *client.Client, db *sqlx.DB, internalDNSIP func() netip.Addr) *Server { return &Server{ - client: cli, - db: db, + client: cli, + db: db, + internalDNSIP: internalDNSIP, } } @@ -505,6 +511,16 @@ func (s *Server) CreateServiceContainer( }, } + // Configure the container to use the internal DNS server if it's available. + dnsIP := s.internalDNSIP() + if dnsIP.IsValid() { + hostConfig.DNS = []string{dnsIP.String()} + // Optimize DNS resolution for service discovery by appending the search domain to names without a dot. + // For example, the first attempt for "my-service" will be "my-service.internal". + hostConfig.DNSOptions = []string{"ndots:1"} + hostConfig.DNSSearch = []string{dns.InternalDomain} + } + if spec.Container.LogDriver != nil { hostConfig.LogConfig = container.LogConfig{ Type: spec.Container.LogDriver.Name, diff --git a/internal/machine/machine.go b/internal/machine/machine.go index fb64ea78..e1293b4d 100644 --- a/internal/machine/machine.go +++ b/internal/machine/machine.go @@ -220,7 +220,6 @@ func NewMachine(config *Config) (*Machine, error) { if err != nil { return nil, fmt.Errorf("init machine database: %w", err) } - dockerServer := machinedocker.NewServer(dockerCli, db) // Init a local gRPC proxy server that proxies requests to the local or remote machine API servers. proxyDirector := apiproxy.NewDirector(config.MachineSockPath, APIPort) @@ -238,11 +237,16 @@ func NewMachine(config *Config) (*Machine, error) { initialised: make(chan struct{}, 1), store: corroStore, cluster: c, - docker: dockerServer, localProxyServer: localProxyServer, proxyDirector: proxyDirector, } - m.localMachineServer = newGRPCServer(m, c, dockerServer) + + // Machine IP will only be available after the machine is initialised as a cluster member so wrap it in a function. + internalDNSIP := func() netip.Addr { + return m.IP() + } + m.docker = machinedocker.NewServer(dockerCli, db, internalDNSIP) + m.localMachineServer = newGRPCServer(m, c, m.docker) if m.Initialised() { m.initialised <- struct{}{} @@ -359,8 +363,6 @@ func (m *Machine) Run(ctx context.Context) error { var err error m.cluster.UpdateMachineID(m.state.ID) - // TODO: set DNS server to m.IP() on the docker server so it knows which addr to pass as --dns - // for service containers. // Ensure the corrosion config is up to date, including a new gossip address if the machine // has just joined a cluster.