---
id: 517bf76b20da9b1bac643f4bac1bfd6b
author: Lemon Mint
title: AI Ajanı RL Rollout'ları için gvx ile Hızlı ve İzole Docker Ortamları
description: SWE-bench ve kodlama ajanı pekiştirmeli öğrenme rollout'ları için, yüzlerce paralel, güçlü şekilde izole edilmiş ayrıcalıksız Docker ve Kubernetes ortamını güvenli bir biçimde nasıl çalıştırabilirsiniz; 100 milisaniyelik kopyala-üzerine-yaz (copy-on-write) ext4lite birim sıfırlamalarıyla?
language: tr
date: 2026-11-06T12:02:55.95126412Z
path: /blog/posts/fast-docker-environments-for-agent-rl-rollouts-z48916d04
go_package: z.gfire.dev/gvx
go_repourl: https://github.com/gfire-sigs/gvx.git
category: ai
---

## Kodlama Ajanı RL Rollout'larında Güvenlik ve Altyapı Darboğazı

**SWE-bench**, **SWE-ReX**, **R2E-Gym**, **SWE-Gym**, **Verl** ve **OpenHands** gibi kıyaslamalar ve pekiştirmeli öğrenme (RL) çerçeveleri genelinde yazılım mühendisliği ajanlarının eğitilmesi ve değerlendirilmesi, **güvenilmeyen, LLM tarafından üretilen kodun** binlerce eşzamanlı rollout'ta çalıştırılmasını gerektirir. Gerçek dünya yazılım mühendisliği görevlerinde bir ajan yalnızca metin dosyalarını düzenlemez: `docker build` komutunu çalıştırır, `docker compose` aracılığıyla veritabanları ve mikro hizmetleri ayağa kaldırır, entegrasyon test paketlerini yürütür ve konteyner günlüklerini inceler.

Rollout ölçeğinde (küme başına 128 ila 1.024 eşzamanlı episode), mevcut konteyner altyapısı dört sistemik güvenlik ve performans darboğazıyla karşılaşır:

1. **Host `dockerd` Kilit Çekişmesi ve Durum Sızıntısı**: Yüzlerce eşzamanlı RL worker'ını tek bir host `/var/run/docker.sock` üzerine yönlendirmek, her ajana host daemon'ına karşı root eşdeğeri erişim verir, imaj katmanı çıkarımını seri hale getirir, `docker0` alt ağ tahsislerini tüketir, host `iptables` üzerinde `Another app is currently holding the xtables lock` hatalarını tetikler ve episode'lar arasında sahipsiz konteynerlerin sızmasına yol açar.
2. **Ayrıcalıklı DinD Konteyner Kaçış Riski**: Standart `docker:dind` konteynerlerini çalıştırmak `--privileged` (`CAP_SYS_ADMIN`) gerektirir; bu da ham host blok aygıtlarını, cgroup release agent'larını ve çekirdek modüllerini güvenilmeyen RL rollout'larına açar.
3. **Donanım Sanallaştırma (`/dev/kvm`) Kısıtları**: MicroVM çalışma zamanları (`Firecracker`, `QEMU`, `Kata Containers`) iç çekirdekleri temiz biçimde izole eder, ancak `/dev/kvm` gerektirirler. İç içe sanallaştırma olmayan standart Kubernetes pod'ları, KVM'nin devre dışı bırakıldığı bare-metal bulut örnekleri ve mevcut `gVisor` (`runsc`) sandbox'ları KVM microVM'lerini başlatamaz.
4. **Yavaş Episode Sıfırlama (`env.reset()`) Gecikmesi**: Her RL episode için yeni bir `docker:dind` ortamı başlatmak ve temel imajları çekmek veya açmak 10 ila 60 saniye sürer; bu süre boyunca GPU eğitim worker'ları ortam sıfırlamalarını beklerken boşta kalır.

**[gvx](https://github.com/gfire-sigs/gvx)** (`rungv` CLI ve `z.gfire.dev/gvx/pkg/gvx` Go SDK), dört darboğazın tamamını çözen **güvenli, katmanlı savunmaya sahip bir rollout çalışma zamanı** sunar. Her rollout ortamı, **tek başına çalışan, ayrıcalıksız ve kendini kilitleyen bir kullanıcı alanı süreci** olarak çalışır (Google'ın gVisor `Sentry` çekirdeği, `pkg/hostlockdown` ve bellek içi `netstack` ile izole edilmiştir); bu sürecin tüm `/var/lib/docker` durumu **tek bir copy-on-write `.ext4` dosyasının (`ext4lite`)** içinde bulunur.

> **Güvenilmeyen Ajan Rollout'ları için Sıfır Ayrıcalık Güvenliği**: Her `gvx` episode'u, misafir kodu çalıştırmadan önce kendi host işletim sistemi sürecini kilitler (Linux'ta `PR_SET_NO_NEW_PRIVS` + BPF `seccomp`, macOS'ta Seatbelt `deny default`, Windows'ta Restricted Token + Job Object). Bir RL ajanı episode'u içinde `docker run --privileged` veya yıkıcı `rm -rf /` komutlarını çalıştırsa bile, bu işlemler kesin olarak o episode'un kullanıcı alanı `Sentry` çekirdeği ve geçici `.ext4` hacim dosyasıyla sınırlı kalır.

---

## Rollout Mimarisi: Paralel Ayrıcalıksız Örnekler + Reflink Anlık Görüntüleri

`gvx` içinde her rollout worker'ı, kendi gVisor `Sentry` çekirdeğine, kendi kullanıcı alanı `netstack` yapılandırmasına (`10.0.2.15/24`) ve kendi `ext4lite` blok hacmine (`ep-N.ext4`) sahip sıradan bir ayrıcalıksız işletim sistemi sürecidir; host sayfa önbelleğini ise salt okunur, içerik adresli bir `erofs` OCI imaj önbelleğiyle paylaşır.

![gvx ile Paralel Ajan RL Rollout Mimarisi](/assets/images/gvx/gvx-rl-rollout-snapshot.png)

### Tek Dosyalı `ext4lite` Hacimleri RL Sıfırlama Ekonomisini Neden Değiştirir

`gvx`'in `ext4lite` dosya sistemi, tüm JBD2 günlüklemeli `ext4` hacmini (Docker'ın `overlayfs` katman dizinleri, `trusted.overlay.*` genişletilmiş öznitelikleri, whiteout aygıt düğümleri ve imaj meta verileri dahil) tek bir normal host dosyasında sakladığından, episode yaşam döngüsü yönetimi tek bir dosya işlemine dönüşür:

1. **`cp --reflink=always` ile 100 Milisaniyelik `env.reset()`**:
   - Önceden çekilmiş temel imajları (`python:3.11`, `postgres:16`, `redis:7` veya göreve özgü `SWE-bench` temel imajları) içeren bir `golden-docker.ext4` dosyasını bir kez oluşturursunuz.
   - Her RL episode'unun başında, `cp --reflink=always golden-docker.ext4 ep-0042.ext4` komutu (XFS, Btrfs, ZFS veya macOS APFS üzerinde), altta yatan disk bloklarını kopyalamadan 100 milisaniyenin altında bağımsız bir Copy-on-Write klonu oluşturur.
   - Yalnızca o belirli episode sırasında kirlenen 4 KiB'lik bloklar ek disk alanı tüketir.
2. **Artık Bırakmayan Kapatma (`env.close()`)**:
   - `rungv` sürecinin sonlandırılması (Go'da `sb.Close()`) ve `ep-0042.ext4` dosyasının bağlantısının kaldırılması, episode'un tüm süreçlerini, ağ soketlerini, bağlama noktalarını ve depolamasını yaklaşık 10 milisaniyede %100 geri kazanır. Host çekirdeğinin bağlama tablosuna hiçbir şey bağlanmaz ve host cgroup'larına hiçbir şey kaydedilmez.

---

## Adım Adım İş Akışı: Golden `.ext4` Anlık Görüntüsü ve Hızlı Episode Sıfırlama

`rungv` aracını her rollout worker düğümüne, ya [GitHub Releases](https://github.com/gfire-sigs/gvx/releases) adresinden SLSA ile doğrulanmış önceden derlenmiş ikiliyi indirerek (`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`) ya da `CGO_ENABLED=0 go install z.gfire.dev/gvx/cmd/rungv@latest` komutunu çalıştırarak kurabilirsiniz.

### Adım 1: Golden `docker:dind` Hacmini Bir Kez Oluşturun

```sh
mkdir -p /srv/rl-snapshots /srv/rl-episodes

# 1. golden-docker.ext4 ile desteklenen bir tohum docker:dind örneği başlatın
rungv run \
  -p unix:/srv/rl-snapshots/seed.sock:2375 \
  --mount type=volume,src=/srv/rl-snapshots/golden-docker.ext4,dst=/var/lib/docker \
  -e DOCKER_TLS_CERTDIR= \
  docker:dind --tls=false &
SEED_PID=$!

# 2. golden-docker.ext4 içinde temel imajları ve derleme önbelleğini önceden doldurun
export DOCKER_HOST="unix:///srv/rl-snapshots/seed.sock"
until docker info >/dev/null 2>&1; do sleep 0.5; done

docker pull python:3.11-slim
docker pull redis:7-alpine
docker pull postgres:16-alpine

# 3. ext4lite'ın imajı boşaltıp sıkıştırması için tohum örneğini zarifçe durdurun
kill -INT $SEED_PID
wait $SEED_PID
```

### Adım 2: Paralel RL Episode'larını 100 Milisaniyede Başlatın

Her paralel rollout worker'ı `golden-docker.ext4` dosyasını reflink ile klonlar ve tüm imajları zaten `/var/lib/docker` içinde bulunan yalıtılmış bir `docker:dind` örneğini başlatır:

```sh
EPISODE_ID="ep-0042"
SOCK="/srv/rl-episodes/${EPISODE_ID}.sock"

# Anlık Copy-on-Write klonu (XFS/Btrfs/APFS üzerinde ~100 ms)
cp --reflink=always \
  /srv/rl-snapshots/golden-docker.ext4 \
  "/srv/rl-episodes/${EPISODE_ID}.ext4"

# 4 GiB RAM ve 2 CPU ile yalıtılmış ayrıcalıksız episode'u başlatın
rungv run \
  -m 4g --cpus 2 \
  -p "unix:${SOCK}:2375" \
  --mount "type=volume,src=/srv/rl-episodes/${EPISODE_ID}.ext4,dst=/var/lib/docker" \
  -e DOCKER_TLS_CERTDIR= \
  docker:dind --tls=false &
EP_PID=$!

export DOCKER_HOST="unix://${SOCK}"
until docker info >/dev/null 2>&1; do sleep 0.2; done

# Rollout worker'ının içinde imajlar ağ üzerinden çekilmeden hemen kullanılabilir
docker images

# Ödül hesaplamasından sonra episode'un kapatılması (~10 ms)
kill -KILL $EP_PID
rm -f "/srv/rl-episodes/${EPISODE_ID}.ext4" "${SOCK}"
```

---

## `z.gfire.dev/gvx/pkg/gvx` Go SDK'sını Kullanan Programatik Rollout Havuzu

RL ortam sunucunuz veya değerlendirme altyapınız Go ile yazılmışsa (ya da gRPC üzerinden bir Go rollout daemon'ını çağırıyorsa), paralel konteyner episode'larını doğrudan `z.gfire.dev/gvx/pkg/gvx` üzerinden yönetebilirsiniz:

```go
package main

import (
	"bytes"
	"context"
	"fmt"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"time"

	"z.gfire.dev/gvx/pkg/gvx"
)

func runEpisode(ctx context.Context, goldenExt4, scratchDir string, epID int) error {
	epExt4 := filepath.Join(scratchDir, fmt.Sprintf("ep-%04d.ext4", epID))
	defer os.Remove(epExt4)

	// 1. Golden ext4lite hacminin reflink klonunu oluşturun
	cpCmd := exec.CommandContext(ctx, "cp", "--reflink=always", goldenExt4, epExt4)
	if err := cpCmd.Run(); err != nil {
		return fmt.Errorf("clone golden volume: %w", err)
	}

	// 2. Episode başına duvar saati zaman aşımı uygulayın
	epCtx, cancel := context.WithTimeout(ctx, 2*time.Minute)
	defer cancel()

	var stdout, stderr bytes.Buffer
	sb, err := gvx.New(epCtx, gvx.Config{
		Platform:               gvx.PlatformAuto,
		NetworkMode:            gvx.NetModeNAT,
		NetRaw:                 true,
		AllowPacketSocketWrite: true,
		AllowSUID:              true,
		OCIImage:               "docker:dind",
		Entrypoint:             []string{"sh", "-c"},
		EntrypointSet:          true,
		Cmd: []string{
			"dockerd-entrypoint.sh --tls=false >/var/log/dockerd.log 2>&1 & " +
				"until docker info >/dev/null 2>&1; do sleep 0.2; done && " +
				"docker run --rm python:3.11-slim python -c 'print(6 * 7)'",
		},
		Envv: []string{"DOCKER_TLS_CERTDIR="},
		Mounts: []gvx.Mount{
			{
				Kind:      gvx.MountVolume,
				ImagePath: epExt4,
				GuestPath: "/var/lib/docker",
			},
		},
		Resources: gvx.Resources{
			MemoryBytes: 4 << 30, // 4 GiB sınırı
			CPUMillis:   2000,    // 2.0 CPU
		},
		Stdout: &stdout,
		Stderr: &stderr,
	})
	if err != nil {
		return fmt.Errorf("init episode %d: %w", epID, err)
	}
	defer sb.Close()

	exitCode, err := sb.Run(epCtx)
	if err != nil {
		return fmt.Errorf("run episode %d: %w", epID, err)
	}

	log.Printf("episode %d finished: exit=%d stdout=%q", epID, exitCode, stdout.String())
	return nil
}

func main() {
	ctx := context.Background()
	if err := runEpisode(ctx, "/srv/rl-snapshots/golden-docker.ext4", "/srv/rl-episodes", 1); err != nil {
		log.Fatal(err)
	}
}
```

---

## Agent RL Sandbox Çalışma Zamanlarının Karşılaştırması

| Metrik / Gereksinim                                       | Paylaşımlı Host `dockerd`         | Ayrıcalıklı `docker:dind` | Firecracker / KVM MicroVM      | Standart `gVisor` (`runsc`)       | `gvx` (`rungv` / `pkg/gvx`)                 |
| :-------------------------------------------------------- | :-------------------------------- | :----------------------- | :----------------------------- | :-------------------------------- | :------------------------------------------ |
| **Host `root` veya `--privileged` gerekli mi**            | Evet (`docker.sock` = root)       | Evet (`--privileged`)    | `/dev/kvm` + `TAP` kurulumu gerekir | Evet (veya `userns` + `mount`) | **Hayır (tek ayrıcalıksız süreç)**          |
| **Ayrıcalıksız K8s Pod'ları / mevcut `runsc` içinde çalışır mı** | Hayır                      | Hayır                    | Hayır (`/dev/kvm` yok)         | Başarısız (iç içe seccomp üzerinde `EBUSY`) | **Evet (otomatik futex döngüsü yedeği)** |
| **İç `docker build` ve `docker compose` desteği**         | Host daemon'ını paylaşır          | Evet                     | Evet                           | Host DinD ayarı olmadan başarısız | **Evet (`ext4lite` üzerinde `overlayfs`)**  |
| **Episode başına ağ yalıtımı**                            | Paylaşımlı `docker0` / `xtables` kilidi | Ayrı namespace     | Ayrı VM NIC                    | Ayrı netns                        | **Süreç içi yalıtılmış `netstack`**         |
| **Sıcak episode sıfırlama gecikmesi (`env.reset()`)**     | 5 sn ila 30 sn (konteyner/hacim temizliği) | 10 sn ila 60 sn (soğuk daemon) | ~150 ms (VM anlık görüntüsü) | 5 sn ila 20 sn          | **~100 ms (`cp --reflink=always` `.ext4`)** |
| **Platformlar arası yerel geliştirme (Windows / macOS / Linux)** | Linux VM gerekir            | Linux VM gerekir         | Yalnızca Linux KVM             | Yalnızca Linux                    | **Windows, macOS ve Linux üzerinde yerel**  |

---

## Bu Serideki Diğer Okumalar

1. **[gvx: Linux Konteynerlerini, Docker'ı ve Kubernetes'i Tek Bir Ayrıcalıksız Süreçte Çalıştırmak](/blog/posts/gvx-cross-platform-linux-containers-z48916d01)**: Windows (`whpx`, `systrap`), macOS (`hvf`) ve Linux (`systrap`) üzerinde `gvx` için eksiksiz bir mimari inceleme.
2. **[Root veya Kullanıcı Namespace'leri Olmadan Docker, docker build ve docker compose Çalıştırmak](/blog/posts/run-docker-without-root-or-userns-gvx-z48916d02)**: `sudo`, `unshare(CLONE_NEWUSER)`, `mount(2)` ve `/dev/fuse` engellendiğinde hızlı 3 adımlı başlangıç ve sorun giderme kılavuzu.
3. **[gvx ile gVisor ve İç İçe Sandbox'lar İçinde Docker-in-Docker Çalıştırmak](/blog/posts/docker-in-docker-inside-gvisor-with-gvx-z48916d03)**: `docker.io` ve iç içe `runsc`'nin `gVisor` (`runsc`) içinde neden başarısız olduğuna ve `gvx`'in `EBUSY` durumunda `_RUN_SYSCALL_LOOP` futex döngüsüne nasıl geri döndüğüne dair ayrıntılı inceleme.
4. **[gvx ile AI Ajanı RL Rollout'ları için Hızlı Yalıtılmış Docker Ortamları](/blog/posts/fast-docker-environments-for-agent-rl-rollouts-z48916d04)** (bu yazı)
