Minden csapat saját klasztert akart. A QA-nak kellett egy, a staging-nek egy, minden fejlesztő akart egyet feature branch-enként. Végül 12 EKS klaszterünk lett, a legtöbb 15%-os kihasználtsággal, és mind pénzbe került.

Régóta hallottam a vCluster-ről a Loft Labs-tól, de mindig elnapoltam. Három hónapja végre kipróbáltam. Az ígéret túl szépnek tűnt: teljes Kubernetes klaszterek egyetlen host klaszteren belül, saját API szerverrel, saját erőforrásokkal, teljes izolációval. Extra node-ok nélkül, extra control plane-ek kezelése nélkül.

Spoiler: tényleg működik.

A probléma

A felállásunk tipikus mid-size platform engineering fájdalom volt. Hat fejlesztő, egy QA csapat, staging, két demo környezet, plusz pár sandbox klaszter kísérletezéshez. Minden EKS klaszternek saját node group-jai, saját ALB controller-e, saját cert-manager telepítése volt.

A számla havi ~$4,200 volt csak a dev/test klaszterekre. Nem katasztrófa, de nehéz indokolni, amikor a legtöbb 80%-ban tétlen.

A namespace izoláció nem volt elég. A fejlesztőknek CRD hozzáférés kellett, Helm chart-okat akartak telepíteni, cluster-scoped erőforrásokat akartak használni. Namespace-ekkel ezt nem lehet megoldani.

Első lépések

A vCluster CLI telepítése:

curl -L -o vcluster "https://github.com/loft-sh/vcluster/releases/latest/download/vcluster-linux-amd64"
chmod +x vcluster
sudo mv vcluster /usr/local/bin/

Egy virtuális klaszter létrehozása kb. 30 másodperc:

vcluster create dev-alice --namespace team-alice

Ennyi. A vCluster felhoz egy könnyű K3s control plane-t egy podban, létrehoz egy syncer-t ami az erőforrásokat szinkronizálja a virtuális és a host klaszter között, és ad egy kubeconfig-ot.

vcluster connect dev-alice --namespace team-alice
kubectl get nodes

A virtuális klaszter saját node-okat lát (a host-ról szinkronizálva), saját kube-system namespace-t, mindent. A fejlesztő szemszögéből ez egy igazi klaszter.

Az architektúra ami beválik

Minden vCluster-hez ez fut a host klaszteren:

host-cluster/
  namespace: team-alice/
    pod: dev-alice-0          # K3s control plane + syncer
    pvc: data-dev-alice-0     # etcd tároló (alapból SQLite)
    service: dev-alice        # API szerver endpoint

Egy pod. Egy PVC. Egy service. Ez az overhead virtuális klaszterenként. Hasonlítsd össze egy teljes EKS klaszterrel a saját VPC-jével, node group-jaival és add-on-jaival.

A syncer a kulcselem. Amikor egy fejlesztő létrehoz egy Deployment-et a virtuális klaszterben, a syncer létrehozza a megfelelő erőforrásokat a host namespace-ben. A podok a host node-okon futnak, de a fejlesztő csak a sajátjait látja.

Éles konfiguráció

Az alapbeállítás gyors kísérletekhez jó, de éles használathoz kell egy vcluster.yaml:

controlPlane:
  distro:
    k3s:
      enabled: true
  statefulSet:
    resources:
      requests:
        cpu: 200m
        memory: 256Mi
      limits:
        cpu: 1000m
        memory: 1Gi

sync:
  toHost:
    ingresses:
      enabled: true
  fromHost:
    nodes:
      enabled: true
      selector:
        labels:
          nodepool: shared

policies:
  resourceQuota:
    enabled: true
    quota:
      requests.cpu: "4"
      requests.memory: 8Gi
      limits.cpu: "8"
      limits.memory: 16Gi
  limitRange:
    enabled: true
    default:
      cpu: 500m
      memory: 512Mi
    defaultRequest:
      cpu: 100m
      memory: 128Mi
vcluster create dev-alice --namespace team-alice -f vcluster.yaml

A resource quota és limit range kritikus. Nélkülük egy fejlesztő felzabálja az összes host klaszter erőforrást, és mindenki más szív.

Mi tört el (és hogyan javítottam)

DNS feloldás virtuális klaszterek között

Az egyik vCluster service-ei alapból nem látják a másik vCluster service-eit. Ez valójában helyes viselkedés az izoláció szempontjából. Viszont a QA csapatnak el kellett érnie egy megosztott adatbázist ami egy másik vCluster-ben futott.

A megoldás a host-ról történő service mapping volt:

sync:
  fromHost:
    services:
      enabled: true
      mappings:
      - from:
          namespace: shared-services
          name: postgres-primary
        to:
          namespace: default
          name: shared-db

Persistent Volume-ok

A PVC-k működnek, de tudni kell, hogy a host klaszter storage class-ával jönnek létre. Ha a host klasztered gp3 EBS volume-okat használ, a vCluster is azt kapja. Semmi meglepetés, de a fejlesztők akik más storage class-okat vártak, zavarba jöttek.

Csináltam egy tiszta onboarding dokumentumot, és explicit módon mappeltem a storage class-okat:

sync:
  fromHost:
    storageClasses:
      enabled: true

Ingress ütközések

Több vCluster nem osztozhat ugyanazon a hostname-en egy Ingress-ben. A syncer átírja az Ingress neveket az ütközések elkerülésére, de a hostname-eknek egyedinek kell lenniük. Ezt egy elnevezési konvencióval oldottuk meg:

<service>.<vcluster-name>.dev.example.com

Wildcard DNS + wildcard TLS cert, kész.

GitOps integráció

A vCluster-eket ArgoCD-vel kezeljük. Minden fejlesztő kap egy Git-ben definiált vCluster-t:

# clusters/dev-alice.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: vcluster-dev-alice
  namespace: argocd
spec:
  project: platform
  source:
    repoURL: https://charts.loft.sh
    chart: vcluster
    targetRevision: 0.24.x
    helm:
      valuesObject:
        controlPlane:
          distro:
            k3s:
              enabled: true
        sync:
          toHost:
            ingresses:
              enabled: true
  destination:
    server: https://kubernetes.default.svc
    namespace: team-alice
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
    syncOptions:
      - CreateNamespace=true

Új fejlesztő csatlakozik? Nyit egy PR-t a klaszter konfigjával. Merge, és az ArgoCD kiépíti. Fejlesztő elmegy? Törli a fájlt, az ArgoCD takarít.

CI/CD ideiglenes klaszterek

Az igazi nyereség a CI/CD volt. A megosztott staging klasztert lecseréltük pull request-enkénti vCluster-ekre:

# .github/workflows/pr-env.yaml
name: PR Environment
on:
  pull_request:
    types: [opened, synchronize]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Create ephemeral vCluster
        run: |
          vcluster create pr-${{ github.event.number }} \
            --namespace pr-envs \
            --connect=false \
            -f .vcluster/ephemeral.yaml          

      - name: Connect and deploy
        run: |
          vcluster connect pr-${{ github.event.number }} \
            --namespace pr-envs
          helm upgrade --install myapp ./charts/myapp \
            --set image.tag=${{ github.sha }}          

      - name: Run integration tests
        run: |
          kubectl wait --for=condition=ready pod -l app=myapp --timeout=120s
          ./scripts/integration-tests.sh          

Cleanup workflow PR lezárásakor:

vcluster delete pr-${{ github.event.number }} --namespace pr-envs

Minden PR kap egy teljes Kubernetes környezetet 30 másodperc alatt, a tesztek teljes izolációban futnak, és minden lebontásra kerül amikor a PR merge-elődik vagy lezárul. Nincs több “ki törte el a staging-et” beszélgetés.

A számok

Három hónap után:

Előtte Utána
12 EKS klaszter 1 EKS klaszter (3 node group)
~$4,200/hó ~$1,700/hó
15% átlag kihasználtság 55% átlag kihasználtság
20 perc új környezet 30 másodperc
Kézi takarítás Automatikus TTL-lel

A költségmegtakarítás azonnal megtérült. De az igazi érték a fejlesztői sebesség. Senki nem vár klaszterre. Senki nem oszt meg környezetet amit más eltörhet.

Mit csinálnék másképp

Resource quota-kat az első naptól. Én nem tettem, és az első héten valaki deployolt egy stressz tesztet ami OOM-killt okozott három másik virtuális klaszter podjaiban. A host klaszter erőforrásai megosztottak, akár tetszik, akár nem.

K3s-t használj, ne K8s disztrót. A vCluster támogatja a teljes K8s-t mint virtuális control plane, de a K3s könnyebb és gyorsabban indul. Ha nincs szükséged specifikus K8s API funkciókra, a K3s a jó választás.

Monitoringot a host klaszterre telepítsd, ne a vCluster-ekbe. Prometheus minden virtuális klaszterben pazarlás. Egyetlen Prometheus a host-on képes scrape-elni az összes podot, és label-ökkel szétválaszthatod a metrikákat tenant-enként.

Kinek való ez

Ha háromnál több klasztert futtatsz és a legtöbb nem production, a vCluster valószínűleg megéri a vizsgálatot. A legjobb felhasználási esetek amiket láttam:

  • Dev/test környezetek fejlesztőnként vagy csapatonként
  • CI/CD ideiglenes környezetek pull request-enként
  • Multi-tenant SaaS ahol minden ügyfélnek klaszter szintű izoláció kell
  • Training/demo környezetek amik gyakran jönnek létre és bontódnak le

Ha egyetlen production klasztert futtatsz multi-tenancy igény nélkül, valószínűleg túlzás.

A projekt nyílt forráskódú, jól karbantartott, és a Loft Labs áll mögötte. A közösség aktív, a dokumentáció szolid. Három hónap után nem találkoztam showstopper-rel, és a fejlesztőim boldogabbak mint korábban. Ez számít valamit.