Add config exmaples to README for resource reservations on node level

Fixes: #373
This commit is contained in:
gyptazy
2025-12-23 15:24:02 +01:00
parent 2ce3d73262
commit 89ad425243
6 changed files with 23 additions and 33 deletions

View File

@@ -0,0 +1,2 @@
added:
- Add resource reservation support for PVE nodes (@Chipmonk2). [#373]

4
.gitignore vendored
View File

@@ -5,7 +5,3 @@ build/
dist/
*.egg-info/
proxlb_dev.yaml
log.log
proxlb/log.log
proxlb.yaml
proxlb_reservation.yaml

View File

@@ -290,6 +290,7 @@ The following options can be set in the configuration file `proxlb.yaml`:
| | method | | memory | `Str` | The balancing method that should be used. [values: `memory` (default), `cpu`, `disk`]|
| | mode | | used | `Str` | The balancing mode that should be used. [values: `used` (default), `assigned`, `psi` (pressure)] |
| | balance_larger_guests_first | | False | `Bool` | Option to prefer larger/smaller guests first |
| | node_resource_reserve | | { default: { memory: 4 }, { node01: { memory: 6 }} } | `Dict` | A dict of pool names and their type for creating affinity/anti-affinity rules |
| | psi | | { nodes: { memory: { pressure_full: 0.20, pressure_some: 0.20, pressure_spikes: 1.00 }}} | `Dict` | A dict of PSI based thresholds for nodes and guests |
| | pools | | pools: { dev: { type: affinity }, de-nbg01-db: { type: anti-affinity }} | `Dict` | A dict of pool names and their type for creating affinity/anti-affinity rules |
| `service` | | | | | |
@@ -338,6 +339,11 @@ balancing:
method: memory
mode: used
balance_larger_guests_first: False
node_resource_reserve:
defaults:
memory: 4
node01:
memory: 6
# # PSI thresholds only apply when using mode 'psi'
# # PSI based balancing is currently in beta and req. PVE >= 9
# psi:
@@ -530,7 +536,7 @@ Connect with us in our dedicated chat room for immediate support and live intera
| Support Channel | Link |
|------|:------:|
| Matrix | [#proxlb:gyptazy.com](https://matrix.to/#/#proxlb:gyptazy.com) |
| Discord | [Discord](https://discord.gg/JemGu7WbfQ) |
| Discord | [Discord](https://discord.gg/JemGu7WbfQ) |
| GitHub Community | [GitHub Community](https://github.com/gyptazy/ProxLB/discussions/)
| GitHub | [ProxLB GitHub](https://github.com/gyptazy/ProxLB/issues) |

View File

@@ -33,6 +33,11 @@ balancing:
method: memory # 'memory' | 'cpu' | 'disk'
mode: used # 'assigned' | 'used' | 'psi'
balance_larger_guests_first: False # Option to prioritize balancing of larger or smaller guests first
node_resource_reserve: # Optional: Define resource reservations for nodes (in GB)
defaults: # Default reservation values applying to all nodes (unless explicitly overridden)
memory: 4 # Default: 4 GB memory reserved per node
node01: # Specific node reservation override for node 'node01'
memory: 6 # Specific: 6 GB memory reserved for node 'node01'
# # PSI thresholds only apply when using mode 'psi'
# psi:
# nodes:
@@ -69,15 +74,6 @@ balancing:
pin: # Define a pinning og guests to specific node(s)
- virt66
- virt77
# reserve some ressource for proxmox and / or other application on the nodes
node_resource_reserve:
# defaults - cpu in %, memory in GB, disk in %
defaults:
cpu: 10
memory: 4
disk: 20
node1:
memory: 4
service:
daemon: True

View File

@@ -256,7 +256,6 @@ class Nodes:
logger.debug("Finished: get_node_pve_version.")
return version["version"]
@staticmethod
def apply_resource_reservation(node_name, proxlb_config: Dict[str, Any], node_data: Dict[str, Any]) -> None:
"""
@@ -264,24 +263,19 @@ class Nodes:
Checks for a node specific config first, then if there is any configured default and if neither then nothing is reserved.
Reservations are applied by directly modifying the data gathered from the nodes.
Args:
node_name: (str) the name of the node
Args:
node_name: (str) the name of the node
proxlb_config (Dict[str, Any]): A dictionary containing the ProxLB configuration.
node_data: (Dict[str, Any]): Dict containing the current nodes data
Returns: none
"""
logger.debug(f"Starting: Resource reservation")
logger.debug(f"Processing resource reservation for node {node_name}")
# load the balancing section from the config dict, will create an empty dict if there isnt anything
logger.debug(f"Starting: apply_resource_reservation")
balancing_cfg = proxlb_config.get("balancing", {})
# get the reservation dict from the previously loaded dict , will create an empty dict if there isnt anything
reserve_cfg = balancing_cfg.get("node_resource_reserve", {})
# try to get the reserved memory for the node
reserve_cfg = balancing_cfg.get("node_resource_reserve", {})
reserved_memory_gb_node = reserve_cfg.get(node_name, {}).get("memory")
# try to load the default reserved memory - will set to 0 if there isn't anything
reserved_memory_gb_default = reserve_cfg.get("defaults", {}).get("memory", 0)
# make sure the reservation is a numeric value - check for both, default and node specific
# Make sure the reservation is a numeric value - check for both, default and node specific
if not isinstance(reserved_memory_gb_default, (int, float)):
if reserved_memory_gb_default is not None:
logger.info("Invalid default memory reservation: Found a string while expecting a numeric value - skipping default reservation")
@@ -292,16 +286,16 @@ class Nodes:
logger.info(f"Invalid memory reservation: Found a string while expecting a numeric value - applying current default of {reserved_memory_gb_default} Bytes")
reserved_memory_gb_node = reserved_memory_gb_default
# make sure the reservation is positive
# Make sure the reservation is positive
if reserved_memory_gb_node < 0:
logger.info(f"{nodes['nodes'][node['node']]['name']}: Invalid assigned memory reservation, applying defaults")
reserved_memory_gb_node = reserved_memory_gb_default
# convert the reservation from GB to Bytes, get the current nodes physical memory
# Convert the reservation from GB to Bytes, get the current nodes physical memory
reserved_memory_node = int(round(reserved_memory_gb_node * 1024 ** 3))
total_mem = node_data.get("memory_total")
# check if the reservation doesnt exceed the nodes total memory
# Check if the reservation doesnt exceed the nodes total memory
if reserved_memory_node > total_mem:
logger.debug(f"Reservation of {reserved_memory_node} Bytes exceeds available memory of {total_mem} Bytes- skipping reservation")
reserved_memory_node = 0
@@ -310,7 +304,4 @@ class Nodes:
logger.debug(f"Reserved Memory: {reserved_memory_gb_node} GB ({reserved_memory_node} Bytes)")
node_data["memory_total"] -= reserved_memory_node
Helper.update_node_resource_percentages(node_data)
logger.debug(f"End: Resource reservation")
return
logger.debug(f"Finished: apply_resource_reservation")

View File

@@ -362,4 +362,3 @@ class Helper:
logger.debug(f"node data: {node_data}")
logger.debug(f"End: Update resource percentages")
return