Unverified Commit 183fdd30 authored by Luca De Petrillo's avatar Luca De Petrillo Committed by GitHub
Browse files

feat: Add memory ballooning support (#1012)

parent 721b214d
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -42,7 +42,10 @@ RUN set -eu && \
        inotify-tools \
        netcat-openbsd \
        ca-certificates \
        qemu-system-x86 && \
        qemu-system-x86 \
        python3 \
        python3-pip && \
    pip3 install --no-cache-dir --break-system-packages qemu.qmp==0.0.6 && \
    wget "https://github.com/qemus/passt/releases/download/v${VERSION_PASST}/passt_${VERSION_PASST}_${TARGETARCH}.deb" -O /tmp/passt.deb -q && \
    dpkg -i /tmp/passt.deb && \
    apt-get clean && \

src/balloon.py

0 → 100644
+758 −0

File added.

Preview size limit exceeded, changes collapsed.

src/balloon.sh

0 → 100644
+62 −0
Original line number Diff line number Diff line
#!/usr/bin/env bash
set -Eeuo pipefail

[[ "${BALLOONING:-}" != [Yy1]* ]] && return 0

# By default, the VM is allocated the full amount of RAM configured via RAM_SIZE for its entire lifetime, but if you want
# the container to dynamically reclaim unused guest RAM based on host memory pressure, you can enable memory ballooning.
# It is also used to prevent the guest from exceeding the container's memory limit, even when the limit is changed at runtime.

# The following optional variables allow you to tune the ballooning behaviour:

# BALLOONING	                     N	          Set to Y to enable dynamic memory ballooning
# BALLOONING_MIN_MEM	             33%	      Minimum balloon target, as a percentage of guest max memory (e.g. 33%) or absolute size (e.g. 2G)
# BALLOONING_RAM_THRESHOLD.  	     80.0	      Target host RAM usage percentage; the PI controller aims to keep host usage at or below this value
# BALLOONING_RAM_THRESHOLD_HARD	     90.0	      Host RAM usage percentage above which the balloon target may drop below guest RAM usage, inducing guest memory pressure
# BALLOONING_PSI_PRESSURE	         10.0	      Host PSI avg10 stall percentage at which the PSI ceiling begins to lower the balloon target
# BALLOONING_PSI_PRESSURE_MAX	     50.0	      Host PSI avg10 stall percentage at which the PSI ceiling reaches the configured minimum balloon target
# BALLOONING_HYSTERESIS	             128M	      Minimum balloon target change required before a resize is applied, as a percentage (e.g. 2%) or absolute size (e.g. 256M)
# BALLOONING_KP.             	     0.5	      PI controller proportional gain; higher values react faster but may oscillate
# BALLOONING_KI.            	     0.05	      PI controller integral gain; higher values correct steady-state error faster but risk overshoot
# BALLOONING_INTERVAL.      	     5	          Polling interval in seconds

# Note: memory ballooning uses Linux PSI (/proc/pressure/memory) for progressive pressure detection. Between BALLOONING_PSI_PRESSURE and 
# BALLOONING_PSI_PRESSURE_MAX the PSI ceiling linearly lowers the maximum balloon target from guest max memory down to the configured minimum.
# If PSI is unavailable (kernel lacks CONFIG_PSI), both thresholds are silently skipped and ballooning continues using host memory usage alone.

# Warning: if the container memory limit is reduced at runtime below the guest VM's current memory usage, the container
# may be killed by the OOM killer if the ballooning driver cannot reclaim memory from the guest fast enough.

ballooning() {

    # Wait for qemu PID file to be created
    while [ ! -f "$QEMU_PID" ]; do
        sleep 1
    done

    BALLOON_ARGS=()
    [[ -n "${BALLOONING_MIN_MEM:-}" ]] && BALLOON_ARGS+=(--min-mem "$BALLOONING_MIN_MEM")
    [[ -n "${BALLOONING_PSI_PRESSURE:-}" ]] && BALLOON_ARGS+=(--psi-pressure "$BALLOONING_PSI_PRESSURE")
    [[ -n "${BALLOONING_PSI_PRESSURE_MAX:-}" ]] && BALLOON_ARGS+=(--psi-pressure-max "$BALLOONING_PSI_PRESSURE_MAX")
    [[ -n "${BALLOONING_RAM_THRESHOLD:-}" ]] && BALLOON_ARGS+=(--ram-threshold "$BALLOONING_RAM_THRESHOLD")
    [[ -n "${BALLOONING_RAM_THRESHOLD_HARD:-}" ]] && BALLOON_ARGS+=(--ram-threshold-hard "$BALLOONING_RAM_THRESHOLD_HARD")
    [[ -n "${BALLOONING_HYSTERESIS:-}" ]] && BALLOON_ARGS+=(--hysteresis "$BALLOONING_HYSTERESIS")
    [[ -n "${BALLOONING_KP:-}" ]] && BALLOON_ARGS+=(--kp "$BALLOONING_KP")
    [[ -n "${BALLOONING_KI:-}" ]] && BALLOON_ARGS+=(--ki "$BALLOONING_KI")
    [[ -n "${BALLOONING_INTERVAL:-}" ]] && BALLOON_ARGS+=(--interval "$BALLOONING_INTERVAL")
    local _ballooning_debug="${BALLOONING_DEBUG:-${DEBUG:-}}"
    if [[ "$_ballooning_debug" == [Yy1]* ]]; then
        BALLOON_ARGS+=(--debug)
    elif [[ -n "$_ballooning_debug" && "$_ballooning_debug" != [Nn0]* ]]; then
        BALLOON_ARGS+=(--debug "$_ballooning_debug")
    fi

    python3 ./balloon.py --qmp-sock "$QEMU_DIR/qemu-qmp-ballooning.sock" --qemu-pid-file "$QEMU_PID" "${BALLOON_ARGS[@]}"
}

msg="Starting memory ballooning monitor..."
info "$msg"

( ballooning ) &

return 0
+4 −3
Original line number Diff line number Diff line
@@ -18,7 +18,7 @@ DEF_OPTS="-nodefaults"
SERIAL_OPTS="-serial $SERIAL"
CPU_OPTS="-cpu $CPU_FLAGS -smp $SMP"
RAM_OPTS=$(echo "-m ${RAM_SIZE^^}" | sed 's/MB/M/g;s/GB/G/g;s/TB/T/g')
MON_OPTS="-monitor $MONITOR -name $PROCESS,process=$PROCESS,debug-threads=on"
MON_OPTS="-monitor $MONITOR -name $PROCESS,process=$PROCESS,debug-threads=on -pidfile $QEMU_PID"
MAC_OPTS="-machine type=${MACHINE},smm=${SECURE},graphics=off,vmport=${VMPORT},dump-guest-core=off,hpet=${HPET}${KVM_OPTS}"

[ -n "$UUID" ] && MAC_OPTS+=" -uuid $UUID"
@@ -27,8 +27,9 @@ MAC_OPTS="-machine type=${MACHINE},smm=${SECURE},graphics=off,vmport=${VMPORT},d
if [[ "${MACHINE,,}" != "pc"* ]]; then
  DEV_OPTS="-object rng-random,id=objrng0,filename=/dev/urandom"
  DEV_OPTS+=" -device virtio-rng-pci,rng=objrng0,id=rng0,bus=pcie.0"
  if [[ "${BOOT_MODE,,}" != "windows"* ]]; then
    DEV_OPTS+=" -device virtio-balloon-pci,id=balloon0,bus=pcie.0"
  if [[ "${BOOT_MODE,,}" != "windows"* || "${BALLOONING:-}" == [Yy1]* ]]; then
    [[ "${BALLOONING:-}" == [Yy1]* ]] && MON_OPTS+=" -qmp unix:${QEMU_DIR}/qemu-qmp-ballooning.sock,server,nowait"
    DEV_OPTS+=" -device virtio-balloon-pci,free-page-reporting=on,guest-stats-polling-interval=1,id=balloon0,bus=pcie.0"
  fi
fi

+1 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ cd /run
. boot.sh       # Configure boot
. proc.sh       # Initialize processor
. memory.sh     # Check available memory
. balloon.sh    # Initialize ballooning
. config.sh     # Configure arguments
. finish.sh     # Finish initialization

Loading