Dynamic ballooning?

Dunuin

Distinguished Member
Jun 30, 2020
14,793
4,628
258
Germany
Nachtrag: Post kann man wohl leider ignorieren. Ist wohl doch schlecht umsetzbar ohne eine Anpassung des qemu-guest-agent.

Moin,

Hat sich mal wer daran versucht ein dynamisches Ballooning umzusetzen?
Das Hauptproblem beim Ballooning finde ich ist, dass da PVE halt stupide den RAM der VMs senkt ohne Rücksicht darauf zu nehmen, wieviel von ihrem RAM die Gäste denn überhaupt nutzen.

Sagen wir ich habe 32GB RAM auf dem Host und 4 identische VMs mit aktiviertem Ballooning mit je "Min RAM = 3GB" und "Max RAM = 6GB". Alle VMs haben das selbe Share Ratio von 1000.

Bis 80% RAM-Auslastung des Hosts macht Ballooning ja überhaupt nichts und alle VMs können bis 6 GB RAM nutzen. Sobald dann der RAM des Hosts die 80% überschreitet setzt Ballooning ein und drosselt langsam den RAM der VMs in z.B. 100 MB Schritten von 6 GB bis runter zu 3 GB. Das macht das Ballooning so lange bis entweder das gesetze Minimum von 3 GB erreicht ist oder bis die RAM-Auslastung des Hostes wieder unter 80% fällt.
Dem Host ist es aber egal ob eine VM den RAM braucht oder nicht, er drosselt einfach immer weiter und die VM muss halt irgendwie dafür sorgen, dass sie mit dem RAM auskommt, welcher der Host ihr noch lässt. Im Idealfall hat die VM da freien RAM, dann muss die VM nichts machen. Hat die VM nicht genug freien RAM oder noch viel "available" RAM, dann ist das auch nicht kritisch, weil die VM einfach schnell mal den Page File Cache wegwirft der ja nicht zwingend benötigt wird. Ist dann höchstens etwas nervig, weil das dann stoßweise zu zu mehr Auslastung der VM führt, weil die VM ja unter druck gesetzt wird und so schnell wie möglich RAM freischaufeln muss. Kritisch wird es aber wenn der Host der VM RAM abzieht aber die VM keinen freien RAM oder "available" RAM mehr besitzt. Dann muss die VM den OOM Killer starten und der killt dann in der VM Prozesse, die man eigentlich nicht beendet haben möchte.

Also mal als Beispiel:

RAM bevor das Ballooning einsetzt:
Host: 25,6 GB von 32 GB benutzt = 80% Auslastung
used RAMfree RAMcache RAMavailable RAM (free+cache)RAM gedrosselt aufballooning (Min RAM Wert)Share Ratio
VM A2 GB2 GB2 GB4 GB6 GB3 GB1000
VM B2 GB3,5 GB0,5 GB4 GB6 GB3 GB1000
VM C5 GB0,5 GB0,5 GB1 GB6 GB3 GB1000
VM D1 GB5 GB0 GB5 GB6 GB3 GB1000
Host ist nicht über 80% RAM-Auslastung also ist Ballooning inaktiv und alle VMs dürfen volle 6 GB RAM nutzen.

Nun braucht der Host plötzlich 3,2 GB mehr RAM und die RAM-Auslastung springt auf 90% weil der Host 28,8 GB von 32 GB benutzt. Ballooning setzt ein und versucht wieder den Host RAM auf unter 80% Auslastung zu drücken, weshalb also 3,2 GB RAM von den VMs abgezogen werden müssen. Dies geschieß gleichmäßig, weil alle VMs das selbe Share Ratio haben. Es wird also jeder VM 0,8 GB RAM abgezogen:
used RAMfree RAMcache RAMavailable RAM (free+cache)RAM gedrosselt aufballooning (Min RAM Wert)Share Ratio
VM A2 GB2 - 0,8 = 1,2 GB2 GB3,2 GB5,2 GB3 GB1000
VM B2 GB3,5 - 0,8 = 2,7 GB0,5 GB3,2 GB5,2 GB3 GB1000
VM C5 GB0,5 - 0,3 = 0,2 GB0,5 - 0,5 = 0 GB0,2 GB5,2 GB3 GB1000
VM D1 GB5 - 0,8 = 4,2 GB0 GB4,2 GB5,2 GB3 GB1000
Soweit alles noch unkritisch. VM A, B und D hatte alle genug "free" RAM und mussten nicht einmal den Cache leeren. VM C ist aber schon echt am Limit und musste den kompletten Cache leeren.

Nun braucht der Host weitere 3,2 GB und die RAM-Auslastung steigt auf 100%. Ballooning muss sich ebenfalls weitere 0,8 GB von jeder VMs zurückholen:
used RAMfree RAMcache RAMavailable RAM (free+cache)RAM gedrosselt aufballooning (Min RAM Wert)Share Ratio
VM A2 GB1,2 - 0,7 = 0,5 GB2 - 0,1 = 1,9 GB2,4 GB4,4 GB3 GB1000
VM B2 GB2,7 - 0,8 = 1,9 GB0,5 GB2,4 GB4,4 GB3 GB1000
VM C5 - 0,6 = 4,4 GB0,2 - 0,2 = 0GB0 GB0,0 GB4,4 GB3 GB1000
VM D1 GB4,2 - 0,8 = 3,4 GB0 GB3,4 GB4,4 GB3 GB1000
VM A musste nur etwas Cache leeren. VM C und D hatten genug freien RAM. VM C hat jetzt aber ein Problem, da nur noch 0,2 GB RAM "available" waren also nirgends mehr freier RAM hergezaubert werden konnte. Es mussten also durch den OOM Killer genug Prozesse gekillt werden, dass da zusätzlich 0,6 GB RAM frei wurden. Was genau an Prozessen gekillt wird entscheidet der Gast. Mit Pech ist es eine wichtige Anwendung auf die man angewiesen ist oder ein wichtiger Systemprozess und die ganze VM stürzt ab. Das ist super ärgerlich, denn gleichzeitig verschwenden die anderen VMs weiterhin RAM. VM A, B und D haben alle weiterhin noch 2,4 oder 3,4 GB RAM zur Verfügung. Anstatt VM C zu zwingen Prozesse zu killen hätte man lieber etwas weniger RAM von VM C weggenommen und dafür etwas mehr von anderen VMs.

Der Host müsste also bei den Gästen nachfragen, wieviel "available" RAM diese haben und dann entscheiden welche VM den RAM am meisten/wenigstens braucht und die RAM-Vergabe dann dynamisch regeln. Ohne beim Gast nachzufragen kann er dies nicht sehen, da er ja nur den phyischen RAM-Verbrauch sieht der ja aber keinen Rückschluss darauf gibt, ob der VM wirklich der RAM ausgeht, da ja für Caching benutzter RAM nicht wirklich von der VM benötigt wird und jederzeit freigemacht werden kann, aber eben doch phyisch RAM belegt. Es können also z.B. 2 VMs beide 90% ihres RAMs benutzen. DAs heißt aber nicht das auch beiden der RAM ausgeht. Vielleicht nutzt die eine nur 10% für Prozesse und 80% für Caching und die andere 80% für Prozesse und nur 10% für Caching. Für den Host sieht das beides gleich aus, aber der einen VM könnt man problemlos ohne NAchteil 50% ihres RAMs wegnehmen während die andere VM dann viele Prozesse killen müsste oder gar crashen würde.

Nach meinen Nachforschungen wurde schon einmal an so etwas direkt von KVM aus gearbeitet, das wurde dann aber verworfen, weil das alles viel zu anfällig und kompliziert umzusetzen war mit einer dynamischen RAM-Verteilung.

Dann ist mir aber eingefallen, dass man das doch mal selbst versuchen könnte.
1.) Im Gegensatz zum "max RAM" kann man den "min RAM" einer VM während ihrer Laufzeit ändern und muss die VM nicht runterfahren, damit der neue Wert übernommen wird. Hier sollte man also dynamisch den "min RAM" je nach Bedarf nach oben oder unten regeln können. Befehl für die CLI wäre qm set <vmid>--balloon <TargetRAMSizeInMB> also z.B. qm set 100 --balloon 7000 wenn man KVM sagen möchte, dass das Ballooning den RAM für die VM 100 bis runter auf 7GB drosseln darf.
2.) Über den qemu-guest-agent kann man vom Host aus abfragen, wieviel RAM eine VM benutzt und wie sie ihn benutzt. Über die CLI läuft das so. Erst muss man über qm monitor <VMID> eine qm Sitzung starten. Dort kann man dann info balloon eingeben und erhält Infos zur RAM-Nutzung. Bei meinem Debian sieht die Rückmeldung z.B. so aus:
Code:
balloon: actual=16324 max_mem=16384 total_mem=15982 free_mem=10239 mem_swapped_in=0 mem_swapped_out=0 major_page_faults=1694 minor_page_faults=5590676 last_update=1632407624
Hier bedeuten die Werte wohl:
actual=16324 -> auf wieviel MB RAM ballooning die VM gerade gedrosselt hat.
max_mem=16384 -> wieviel MB RAM die VM theoretisch maximal nutzen könnte, wenn da Ballooning nicht gedrosselt hätte.
total_mem=15982 -> wieviel MB RAM das OS effektiv nutzen kann?
free_mem=10239 -> wieviel MB RAM das OS "available" hat. Also die Summe aus free+cached.
last_update=1632407624 -> timestamp des letzten Updates der Daten (Daten werden wohl im Sekundentakt aktualisiert)

Wenn man dann ein q sendet verlässt man die Sitzung wieder und kommt in die Konsole.
Ich habe leider keine Ahnung wie man das als ein One-Liner hinbekommt. Oder gar besser asynchron das man in der Sitzung bleiben kann und diese nicht ständig neu starten und verlassen muss. Weiß jemand ob man da irgendwas pipen kann oder so, dass man nur einen Befehl eingeben muss und dann die Rückmeldung angezeigt bekommt? So etwas wie qm monitor 111; echo "info ballon"; echo "q" geht leider nicht.
 
Last edited:
Meine Idee wäre da jetzt ein Bash Script was in etwa sowas macht:
  • im Sekundentakt über qm monitor die RAM-Nutzung abfragen
  • man könnte eine Konfigdatei haben wo man eines von diesen 2 Optionen auswählt
    • KeepAvailableRamPercent -> versucht das immer mindestens soviel Prozent des maximalen RAMs als "avaiable" RAM zur Verfügung stehen. Also hat die VM z.B. 16 GB maximalen RAM, und man setzt KeepAvailableRamPercent=25% dann wird versucht dynamisch den "Min RAM" Wert immer so anzupassen, dass da 4 GB RAM "available" sind.
    • KeepAvailableRamMB -> versucht das immer so viele MB an "available" RAM der VM zur Verfügung stehen. Passt den "Min RAM" Wert dann entsprechend an.
  • Ausrechnen auf was der neue "Min RAM" Wert eingestellt werden soll. Also z.B. so für KeepAvailableRamMB=1000:
    used_mem = total_mem - free_mem
    Neuer "min RAM" Wert = used_ram + KeepAvailableRamMB

    Oder alternativ für KeepAvailableRamPercent=25%:
    used_mem = total_mem - free_mem
    keep_mem = total_mem * 0,25
    Neuer "min RAM" Wert = used_ram + keep_mem
  • Den neuen "min RAM" Wert schreibt man dann mit qm set <vmid>--balloon <TargetRAMSizeInMB>
  • Hat eine VM dann zu viel verfügbaren RAM wird ihr vom Ballooning langsam der RAM entzogen, RAM wird wieder auf dem Host freigegeben und andere VMs (oder der Host selbst) können den RAM stattdessen nutzen. Das wäre dann auch eine Möglichkeit um das Page File Caching von Linux auf einen fixen/prozentualen Wert zu limitieren anstatt dass da Linux einfach immer alles an RAM für Caching verwendet oder man garkein caching hat, weil man per cron ein /proc/sys/vm/drop_caches ausführt.
  • Geht einer VM langsam der RAM aus und ist daher weniger "available" RAM verfügbar als man in der Konfig eingestellt hat, dann wird der "min RAM" Wert für die VM dynamisch erhöht, Ballooning weist der VM mehr RAM vom Host zu.
  • vermutlich sollte man noch so etwas wie Hysteresen haben, damit es zu keiner Feedback-Loop kommen kann
  • und eine dynamische Gewichtung der Share Ratio wäre bestimmt auch nicht schlecht. Das man den VMs dann mehr von dem auf dem Host verfügbaren RAM gibt, wo das GastOS am wenigsten verfügbaren RAM hat. Vielleicht sowas wie:
    used_mem = total_mem - free_mem
    Share Ratio = used_mem / max_mem * 1000
    Dann würden da VMs je mehr von dem am Host verfübaren RAM bekommen, desto weniger "available" RAM ein Gast zur Verfügung hätte.
Das Beispiel von oben würde in dynamisch dann so aussehen:
Jede VM hat "KeepAvailableRamMB=1000" konfiguriert bekommen und 6GB max RAM.
Host: 25,6 GB von 32 GB benutzt = 80% Auslastung
used RAMfree RAMcache RAMavailable RAM (free+cache)RAM gedrosselt aufballooning (Min RAM Wert)Share Ratio
VM A2 GB2 GB2 GB4 GB6 GB3 GB333
VM B2 GB3,5 GB0,5 GB4 GB6 GB3 GB333
VM C5 GB0,5 GB0,5 GB1 GB6 GB6 GB833
VM D1 GB5 GB0 GB5 GB6 GB2 GB167
Host ist nicht über 80% RAM-Auslastung also ist Ballooning inaktiv und alle VMs dürfen volle 6 GB RAM nutzen.

Nun braucht der Host plötzlich 3,2 GB mehr RAM und die RAM-Auslastung springt auf 90% weil der Host 28,8 GB von 32 GB benutzt. Ballooning setzt ein und versucht wieder den Host RAM auf unter 80% Auslastung zu drücken, weshalb also 3,2 GB RAM von den VMs abgezogen werden müssen. Diesmal wird aber nicht von jeder VM stupide 0,8 GB RAM abgezogen. Von der VM C kann garnichts abgezogen werden weil diese schon am Limit ist und der Min RAM Wert dem MAX RAM Wert entspricht.
Kann also nur noch von VM A, B und C etwas abgezogen werden. Wieviel wem abgezogen wird hängt jetzt ausschließlich von der Share Ratio ab. Keiner von den VMs kann jedoch soviel RAM abgezogen werden, dass da der "available" RAM unter 1 GB fallen würde. Die Share Ratio ist daher also eigentlich nicht so wichtig, da Ballooning nie soviel RAM abziehen könnte, dass es da zum OOM kommt. Wenn ich das Rechenbeispiel im Wiki your Share Ratio richtig verstanden habe würde bei den obigen Share Ratios VM A und B je 0,8 GB und VM D 3,4 GB abgezogen werden.
Vielleicht macht es da sogar ohne ein dynamisches Share Ratio mehr Sinn wenn einfach jedem immer gleich viel abgezogen wird.
Da sieht dann so aus:
used RAMfree RAMcache RAMavailable RAM (free+cache) RAM gedrosselt aufballooning (Min RAM Wert)Share Ratio
VM A2 GB2 - 0,8 = 1,2 GB2 GB3,2 GB6 - 0,8 = 5,2 GB3 GB333
VM B2 GB3,5 - 0,8 = 2,7 GB0,5 GB3,2 GB6 - 0,8 = 5,2 GB3 GB333
VM C5 GB0,5 GB0,5 GB1 GB6 GB6 GB833
VM D1 GB5 - 3,4 = 1,6 GB0 GB1,6 GB6 - 3,4 = 2,6 GB2 GB167

Ich habe da aber keine Ahnung ob KVM/PVE/GastOS überhaupt mit so vielen Anfragen klar kommen. Ob die Werte überhaupt schnell genug von KVM übernommen werden können. Ob Ballooning überhaupt RAM auf dem Host wieder freigibt (also der KVM Prozess kleiner wird) wenn man per Ballooning den RAM der VM senkt. Oder ob das Ganze überhaupt schnell genug reagieren kann, wenn da ein Gast ganz plötzlich ganz viel RAM benötigen möchte.

Vermutlich ist das alles viel komplizierter als ich es mir denke (das KVM Team wird das ja nicht ohne Grund aufgegeben haben). Aber ich dachte versuchen kann man das ja vielleicht mal. Viel mehr als ein paar Prozesse in einer VM killen, weil die Erhöhung des RAMs in der VM nicht schnell genug geht, wird ja wohl nicht passieren. Das wär dann ja aber auch nicht schlimmer als wenn mir da das Ballooning die Prozesse killt, weil es einfach statisch einer VM RAM raubt, obwohl die VM schon am Limit ist während aber andere VMs RAM verschwenden.

Achso, wichtig ist noch, dass das z.B. nicht für FreeBSD geht. Die haben eine doofe Version des qemu-guest-agent die keine Infos zur RAM-Nutzung ausgibt. Da gibt es also keinen Weg wie man vom Host aus herausfinden könnte, wieviel der Gast denn gecacht hat und folglich kann man dann auch schlecht dynamisch irgendetwas regeln.

Was meint ihr dazu? Kann sowas klappen?
 
Last edited:
Ok, ich sehe gerade "free_mem=10239" ist wohl wirklich nur "free" RAM und nicht "available". Das macht das ganze dann natürlich schwierig wenn man keinen Zugriff darauf hat wieviel der Gast als "cache" oder "available" hat. :(
Dann würde mir höchstens einfallen per CLI ein Terminal vom Host zur VM zu öffnen um dann über die virtuelle serielle Konsole einen Befehl wie free auszuführen um sich vom Host aus Info über den RAM-Verbrauch vom Gast zu holen.

Gab es da mal Anstrengungen seitens des Proxmox Teams vielleicht einen eigenen guest-agent zu machen? Oder wenigstens den qemu-guest-agent zu modifizieren, dass der mehr Infos über die RAM-Nutzung des Gastes ausspuckt um dann selbst so etwas wie dynamisches Ballooning in PVE integrieren zu können?
 
Last edited:

About

The Proxmox community has been around for many years and offers help and support for Proxmox VE, Proxmox Backup Server, and Proxmox Mail Gateway.
We think our community is one of the best thanks to people like you!

Get your subscription!

The Proxmox team works very hard to make sure you are running the best software and getting stable updates and security enhancements, as well as quick enterprise support. Tens of thousands of happy customers have a Proxmox subscription. Get yours easily in our online shop.

Buy now!