Gyors, izolált Docker-környezetek AI-ügynökök RL-kimenetelének (rollout) generálásához gvx segítségével

A biztonsági és infrastrukturális szűk keresztmetszet a kódoló ágensek RL rollout-jaiban
Szoftverfejlesztési ágensek betanítása és értékelése olyan benchmarkokon és megerősítéses tanulási (reinforcement learning, RL) keretrendszerekben, mint a SWE-bench, SWE-ReX, R2E-Gym, SWE-Gym, Verl és OpenHands, ezer egyidejű, megbízhatatlan, LLM által generált kód futtatását igényli. Valós szoftverfejlesztési feladatokban egy ágens nem csupán szövegfájlokat szerkeszt: lefuttatja a docker build parancsot, adatbázisokat és mikroszolgáltatásokat indít a docker compose segítségével, integrációs teszteket futtat, és konténernaplókat vizsgál.
Rollout-méretekben (klaszterenként 128 és 1,024 egyidejű epizód között) a meglévő konténerinfrastruktúra négy rendszerszintű biztonsági és teljesítménybeli szűk keresztmetszetbe ütközik:
- Host
dockerdzárversengés és állapotszivárgás: Ha több száz egyidejű RL worker mutat ugyanarra a host/var/run/docker.sockfájlra, minden ágens root-egyenértékű hozzáférést kap a host daemonhoz, sorosítja az image rétegek kicsomagolását, kimeríti adocker0alhálózati címkészletét, a hostiptablesrendszerben aAnother app is currently holding the xtables lockhibákat okoz, és árva konténereket hagy vissza az epizódok között. - Privilegizált DinD konténer-kiszökési kockázat: A szabványos
docker:dindkonténerek futtatásához--privileged(CAP_SYS_ADMIN) szükséges, amely nyers host blokkeszközöket, cgroup release agenteket és kernelmodulokat tesz elérhetővé a megbízhatatlan RL rollout-ok számára. - Hardveres virtualizáció (
/dev/kvm) korlátai: A MicroVM futtatókörnyezetek (Firecracker,QEMU,Kata Containers) tisztán izolálják a belső kernelt, de/dev/kvmeszközt igényelnek. A beágyazott virtualizáció nélküli szabványos Kubernetes podok, a KVM-et letiltott bare-metal felhőpéldányok és a meglévőgVisor(runsc) sandboxok nem tudnak KVM microVM-eket indítani. - Lassú epizódreset (
env.reset()) késleltetés: Egy frissdocker:dindkörnyezet indítása, valamint az alap image-ek letöltése és kicsomagolása minden RL epizódhoz 10 és 60 másodperc közötti időt vesz igénybe, így a GPU-s tanító workerek tétlenül várnak a környezetek újraindítására.
A gvx (rungv CLI és z.gfire.dev/gvx/pkg/gvx Go SDK) egy biztonságos, kis erőfeszítésű, tokenhatékony rollout futtatókörnyezetet biztosít, amely mind a négy szűk keresztmetszetet megoldja. Minden rollout környezet egyetlen, unprivileged, önzárolt user-space folyamatként fut (amelyet a Google gVisor Sentry kerneléje, a pkg/hostlockdown és egy memóriabeli netstack izolál), és teljes /var/lib/docker állapota egyetlen copy-on-write .ext4 fájlban (ext4lite) található.
Kis erőfeszítésű, tokenhatékony végrehajtás ügynökök számára: Ha a
docker buildvagy adocker composeminden epizódban azonnal működik (vagy az ügynök egyetlen, 3 parancsból álló körben, arungvsegítségével bootstrapelheti), az RL rollout-ok nem pazarolnak kontextusablak-tokeneket vagy lépésbüdzsét aservice docker startulimithibák, aziptables-nfthibák vagy aruncpivot_rootelutasítások hibaelhárítására. A trajektória minden tokene a tényleges szoftverfejlesztési feladat megoldására fordítódik.
Nulla jogosultságú biztonság megbízhatatlan ügynök-rollout-okhoz: Minden
gvxepizód lezárja saját host OS folyamatát, mielőtt a vendégkódot futtatná (PR_SET_NO_NEW_PRIVS+ BPFseccompLinuxon, Seatbeltdeny defaultmacOS-en, Restricted Token + Job Object Windowson). Még akkor is, ha egy RL ágens az epizódján belüldocker run --privilegedvagy rombolórm -rf /parancsokat futtat, ezek a műveletek szigorúan az adott epizód user-spaceSentrykernelébe és átmeneti.ext4kötetfájljába vannak korlátozva.
Rollout architektúra: párhuzamos unprivileged példányok + reflink pillanatképek
A gvx-ben minden rollout worker egy közönséges unprivileged OS folyamat, saját gVisor Sentry kernellel, saját user-space netstack (10.0.2.15/24) hálózattal és saját ext4lite blokkkötettel (ep-N.ext4). Mindezek mellett egy csak olvasható, tartalomcímzett erofs OCI image-gyorsítótárat osztanak meg a host oldali lapgyorsítótáron keresztül.

Miért változtatják meg az egyfájlos ext4lite kötetek az RL reset gazdaságtanát
Mivel a gvx ext4lite fájlrendszere egy teljes JBD2-naplózott ext4 kötetet tárol (beleértve a Docker overlayfs rétegkönyvtárait, a trusted.overlay.* bővített attribútumokat, a whiteout eszköz-csomópontokat és az image metaadatokat) egyetlen szabályos host fájlban, az epizód életciklus-kezelése egyetlen fájlműveletté válik:
- 100 milliszekundumos
env.reset()acp --reflink=alwayssegítségével:- Egyszer kell létrehozni egy
golden-docker.ext4fájlt, amely előre letöltött alap image-eket tartalmaz (python:3.11,postgres:16,redis:7, vagy feladatspecifikusSWE-benchalap image-eket). - Minden RL epizód elején a
cp --reflink=always golden-docker.ext4 ep-0042.ext4parancs (XFS, Btrfs, ZFS vagy macOS APFS esetén) 100 milliszekundumon belül létrehoz egy független Copy-on-Write klónt, anélkül hogy a mögöttes lemezblokkokat másolná. - Csak az adott epizódban módosított 4 KiB-os blokkok foglalnak el további lemezterületet.
- Egyszer kell létrehozni egy
- Nulla maradványt hagyó leállítás (
env.close()):- A
rungvfolyamat leállítása (Go-bansb.Close()) és azep-0042.ext4fájl törlése az epizód összes folyamatát, hálózati socketjét, csatolását és tárolóját kb. 10 milliszekundum alatt felszabadítja. Semmi nincs csatolva a host kernel mount-táblájában, és semmi nincs regisztrálva a host cgroupjaiban.
- A
Lépésenkénti munkafolyamat: golden .ext4 pillanatkép és gyors epizódreset
A rungv telepíthető minden rollout worker csomópontra, vagy a SLSA-val igazolt, előre lefordított bináris letöltésével a GitHub Releases oldalról (gh attestation verify rungv-v0.2.0-linux-amd64.tar.gz --repo gfire-sigs/gvx --signer-workflow gfire-sigs/gvx/.github/workflows/release.yml --deny-self-hosted-runners), vagy a CGO_ENABLED=0 go install z.gfire.dev/gvx/cmd/rungv@latest parancs futtatásával.
1. lépés: A golden docker:dind kötet egyszeri létrehozása
1mkdir -p /srv/rl-snapshots /srv/rl-episodes
2
3# 1. Seed docker:dind példány indítása golden-docker.ext4 háttértárral
4rungv run \
5 -p unix:/srv/rl-snapshots/seed.sock:2375 \
6 --mount type=volume,src=/srv/rl-snapshots/golden-docker.ext4,dst=/var/lib/docker \
7 -e DOCKER_TLS_CERTDIR= \
8 docker:dind --tls=false &
9SEED_PID=$!
10
11# 2. Alap image-ek és build-gyorsítótár előtöltése a golden-docker.ext4 fájlon belül
12export DOCKER_HOST="unix:///srv/rl-snapshots/seed.sock"
13until docker info >/dev/null 2>&1; do sleep 0.5; done
14
15docker pull python:3.11-slim
16docker pull redis:7-alpine
17docker pull postgres:16-alpine
18
19# 3. A seed példány szabályos leállítása, hogy az ext4lite kiürítse és tömörítse az image-et
20kill -INT $SEED_PID
21wait $SEED_PID
2. lépés: Párhuzamos RL epizódok indítása 100 milliszekundum alatt
Minden párhuzamos rollout worker reflinkkel klónozza a golden-docker.ext4 fájlt, és elindít egy izolált docker:dind példányt, amelyben az összes image már jelen van a /var/lib/docker könyvtárban:
1EPISODE_ID="ep-0042"
2SOCK="/srv/rl-episodes/${EPISODE_ID}.sock"
3
4# Azonnali Copy-on-Write klón (~100 ms XFS/Btrfs/APFS esetén)
5cp --reflink=always \
6 /srv/rl-snapshots/golden-docker.ext4 \
7 "/srv/rl-episodes/${EPISODE_ID}.ext4"
8
9# Izolált, unprivileged epizód indítása 4 GiB RAM-mal és 2 CPU-val
10rungv run \
11 -m 4g --cpus 2 \
12 -p "unix:${SOCK}:2375" \
13 --mount "type=volume,src=/srv/rl-episodes/${EPISODE_ID}.ext4,dst=/var/lib/docker" \
14 -e DOCKER_TLS_CERTDIR= \
15 docker:dind --tls=false &
16EP_PID=$!
17
18export DOCKER_HOST="unix://${SOCK}"
19until docker info >/dev/null 2>&1; do sleep 0.2; done
20
21# A rollout workeren belül az image-ek azonnal elérhetők hálózati letöltés nélkül
22docker images
23
24# Epizód leállítása a jutalom kiszámítása után (~10 ms)
25kill -KILL $EP_PID
26rm -f "/srv/rl-episodes/${EPISODE_ID}.ext4" "${SOCK}"
Programozott rollout-készlet a z.gfire.dev/gvx/pkg/gvx Go SDK használatával
Ha az RL környezetszerver vagy az értékelő keretrendszer Go-ban íródott (vagy gRPC-n keresztül egy Go rollout daemont hív), a párhuzamos konténer-epizódokat közvetlenül a z.gfire.dev/gvx/pkg/gvx csomagon keresztül kezelheti:
1package main
2
3import (
4 "bytes"
5 "context"
6 "fmt"
7 "log"
8 "os"
9 "os/exec"
10 "path/filepath"
11 "time"
12
13 "z.gfire.dev/gvx/pkg/gvx"
14)
15
16func runEpisode(ctx context.Context, goldenExt4, scratchDir string, epID int) error {
17 epExt4 := filepath.Join(scratchDir, fmt.Sprintf("ep-%04d.ext4", epID))
18 defer os.Remove(epExt4)
19
20 // 1. A golden ext4lite kötet reflink-klónozása
21 cpCmd := exec.CommandContext(ctx, "cp", "--reflink=always", goldenExt4, epExt4)
22 if err := cpCmd.Run(); err != nil {
23 return fmt.Errorf("clone golden volume: %w", err)
24 }
25
26 // 2. Epizódonkénti valós idejű (wall-clock) időkorlát alkalmazása
27 epCtx, cancel := context.WithTimeout(ctx, 2*time.Minute)
28 defer cancel()
29
30 var stdout, stderr bytes.Buffer
31 sb, err := gvx.New(epCtx, gvx.Config{
32 Platform: gvx.PlatformAuto,
33 NetworkMode: gvx.NetModeNAT,
34 NetRaw: true,
35 AllowPacketSocketWrite: true,
36 AllowSUID: true,
37 OCIImage: "docker:dind",
38 Entrypoint: []string{"sh", "-c"},
39 EntrypointSet: true,
40 Cmd: []string{
41 "dockerd-entrypoint.sh --tls=false >/var/log/dockerd.log 2>&1 & " +
42 "until docker info >/dev/null 2>&1; do sleep 0.2; done && " +
43 "docker run --rm python:3.11-slim python -c 'print(6 * 7)'",
44 },
45 Envv: []string{"DOCKER_TLS_CERTDIR="},
46 Mounts: []gvx.Mount{
47 {
48 Kind: gvx.MountVolume,
49 ImagePath: epExt4,
50 GuestPath: "/var/lib/docker",
51 },
52 },
53 Resources: gvx.Resources{
54 MemoryBytes: 4 << 30, // 4 GiB felső korlát
55 CPUMillis: 2000, // 2.0 CPU
56 },
57 Stdout: &stdout,
58 Stderr: &stderr,
59 })
60 if err != nil {
61 return fmt.Errorf("init episode %d: %w", epID, err)
62 }
63 defer sb.Close()
64
65 exitCode, err := sb.Run(epCtx)
66 if err != nil {
67 return fmt.Errorf("run episode %d: %w", epID, err)
68 }
69
70 log.Printf("episode %d finished: exit=%d stdout=%q", epID, exitCode, stdout.String())
71 return nil
72}
73
74func main() {
75 ctx := context.Background()
76 if err := runEpisode(ctx, "/srv/rl-snapshots/golden-docker.ext4", "/srv/rl-episodes", 1); err != nil {
77 log.Fatal(err)
78 }
79}
Agent RL homokozó futtatókörnyezetek összehasonlítása
| Metrika / Követelmény | Megosztott host dockerd | Privilegizált docker:dind | Firecracker / KVM MicroVM | Standard gVisor (runsc) | gvx (rungv / pkg/gvx) |
|---|---|---|---|---|---|
Host root vagy --privileged szükséges | Igen (docker.sock = root) | Igen (--privileged) | /dev/kvm és TAP beállítás szükséges | Igen (vagy userns + mount) | Nem (egyetlen unprivileged folyamat) |
Unprivileged K8s Podokban / meglévő runsc alatt működik | Nem | Nem | Nem (nincs /dev/kvm) | Hibázik (EBUSY beágyazott seccomp esetén) | Igen (automatikus futex loop visszalépés) |
Támogatja a belső docker build és docker compose parancsokat | Megosztja a host daemont | Igen | Igen | Hibázik host DinD hangolás nélkül | Igen (overlayfs az ext4lite felett) |
| Epizódonkénti hálózati izoláció | Megosztott docker0 / xtables zár | Külön namespace | Külön VM NIC | Külön netns | Folyamaton belüli izolált netstack |
Meleg epizódreset késleltetés (env.reset()) | 5 s és 30 s között (konténer/kötet törlés) | 10 s és 60 s között (hideg daemon) | ~150 ms (VM pillanatkép) | 5 s és 20 s között | ~100 ms (cp --reflink=always .ext4) |
| Platformfüggetlen helyi fejlesztés (Windows / macOS / Linux) | Linux VM szükséges | Linux VM szükséges | Csak Linux KVM | Csak Linux | Natív módon Windows, macOS és Linux alatt |
További olvasnivaló ebben a sorozatban
- gvx: Linux konténerek, Docker és Kubernetes futtatása egyetlen unprivileged folyamatban: A
gvxteljes architekturális bemutatója Windowson (whpx,systrap), macOS-en (hvf) és Linuxon (systrap). - Docker, docker build és docker compose futtatása root vagy user namespace nélkül: Gyors, 3 lépéses bootstrap és hibaelhárítási útmutató arra az esetre, ha a
sudo, azunshare(CLONE_NEWUSER), amount(2)és a/dev/fusele van tiltva. - Docker-in-Docker futtatása gVisorban és beágyazott homokozókban a gvx segítségével: Részletes elemzés arra, miért hibázik a
docker.ioés a beágyazottrunscagVisor(runsc) környezetben, és hogyan lép vissza agvxaz_RUN_SYSCALL_LOOPfutex ciklusraEBUSYhiba esetén. - Gyors, izolált Docker környezetek AI ágens RL rollout-okhoz a gvx-szel (ez a bejegyzés)