Skip to content

Commit 4bbd39f

Browse files
authored
ateom-microvm: give the micro-VM guest DNS so name-based egress works (#315)
## Problem A micro-VM (`ateom-microvm`) actor gets a guest interface, default route, and host NAT, but no `/etc/resolv.conf`: ateom drops atelet's resolv.conf bind (a host bind is meaningless inside a VM) and never sends `CreateSandbox.Dns`. The guest can reach IPs but not resolve names, so workloads doing name-based egress — e.g. an OpenShell helpdesk agent calling Ollama Cloud (`/chat`) — fail; only no-egress paths work. ## Fix Write `/etc/resolv.conf` into the bundle rootfs before `mkfs.ext4` at golden boot (`RunWorkload`), copied verbatim from the worker pod's own resolv.conf (cluster DNS) — the same source the kata shim's `getDNS` uses. Errors out if the host has no usable resolv.conf rather than guessing. The restore path reuses the golden disk, so it inherits the file. One helper + one call; no behavior change for workloads that don't resolve names. ## Validation (kind on a KVM host) - A helpdesk micro-VM actor `/chat` returns real model completions and survives suspend/resume. - counter-microvm unaffected.
1 parent 416b070 commit 4bbd39f

2 files changed

Lines changed: 31 additions & 0 deletions

File tree

cmd/ateom-microvm/restore.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,12 @@ func (s *AteomService) RestoreWorkload(ctx context.Context, req *ateompb.Restore
9999
slog.InfoContext(ctx, "Reset actor rootfs disk to golden (template)", slog.String("id", id))
100100
} else {
101101
bundleRootfs := filepath.Join(ateompath.OCIBundlePath(ns, name, id, containers[0].GetName()), "rootfs")
102+
// Cross-node restore rebuilds from the bundle (no local golden template),
103+
// so re-inject DNS here too; the same-node golden-copy path above already
104+
// carries it from the golden boot.
105+
if err := writeGuestResolvConf(bundleRootfs); err != nil {
106+
return nil, fmt.Errorf("while writing guest resolv.conf: %w", err)
107+
}
102108
if err := kata.BuildExt4Image(ctx, bundleRootfs, diskPath); err != nil {
103109
return nil, fmt.Errorf("while reconstructing rootfs disk from image: %w", err)
104110
}

cmd/ateom-microvm/run.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,28 @@ func (s *AteomService) resolveRuntime(paths map[string]string) resolvedRuntime {
150150
}
151151
}
152152

153+
// writeGuestResolvConf copies the worker pod's /etc/resolv.conf into the bundle
154+
// rootfs (before it's packed into the ext4 disk) so the guest gets cluster DNS:
155+
// ateom drops atelet's resolv.conf bind and sends no CreateSandbox.Dns, so the
156+
// guest can otherwise reach IPs but not resolve names.
157+
func writeGuestResolvConf(rootfs string) error {
158+
content, err := os.ReadFile("/etc/resolv.conf")
159+
if err != nil {
160+
return fmt.Errorf("reading host resolv.conf: %w", err)
161+
}
162+
if len(content) == 0 {
163+
return fmt.Errorf("host /etc/resolv.conf is empty")
164+
}
165+
etc := filepath.Join(rootfs, "etc")
166+
if err := os.MkdirAll(etc, 0o755); err != nil {
167+
return fmt.Errorf("creating %q: %w", etc, err)
168+
}
169+
if err := os.WriteFile(filepath.Join(etc, "resolv.conf"), content, 0o644); err != nil {
170+
return fmt.Errorf("writing guest resolv.conf: %w", err)
171+
}
172+
return nil
173+
}
174+
153175
// RunWorkload boots the actor as a cloud-hypervisor micro-VM that ateom owns.
154176
//
155177
// ateom boots cloud-hypervisor itself — no kata shim — and gives the actor a
@@ -217,6 +239,9 @@ func (s *AteomService) RunWorkload(ctx context.Context, req *ateompb.RunWorkload
217239
// Build the actor's writable rootfs as a raw ext4 virtio-blk disk from the
218240
// atelet-populated OCI bundle rootfs. This becomes /dev/vdb.
219241
diskPath := filepath.Join(actorDir, actorRootfsDiskName)
242+
if err := writeGuestResolvConf(filepath.Join(bundle, "rootfs")); err != nil {
243+
return nil, fmt.Errorf("while writing guest resolv.conf: %w", err)
244+
}
220245
if err := kata.BuildExt4Image(ctx, filepath.Join(bundle, "rootfs"), diskPath); err != nil {
221246
return nil, fmt.Errorf("while building actor rootfs disk: %w", err)
222247
}

0 commit comments

Comments
 (0)