Resource Validation#

After configuring pools, add resource validation rules to prevent workflows from requesting more resources than available on your nodes. Validation acts as a pre-flight check that rejects invalid requests before they reach the scheduler.

Why Use Resource Validation?#

Resource validation provides guardrails that protect your cluster and improve user experience:

✓ Prevent Scheduling Failures

Reject workflows that request more CPU, memory, or GPU than any node can provide, avoiding pods getting stuck in pending state.

✓ Catch Configuration Errors

Detect invalid resource specifications (negative values, zero allocations, incorrect units) before submission.

✓ Provide Clear Feedback

Give users immediate, actionable error messages explaining what’s wrong and how to fix it.

✓ Optimize Resource Utilization

Enforce safety margins and best practices for resource allocation across your cluster.

How It Works#

Validation Flow#

1. Submit Workflow 📝

User requests resources

2. Validate Rules ⚖️

Check against capacity

3. Proceed or Reject ✓✗

Accept or deny

Rule Structure#

Each validation rule has four components:

{
  "operator": "LE",
  "left_operand": "{{USER_CPU}}",
  "right_operand": "{{K8_CPU}}",
  "assert_message": "CPU {{USER_CPU}} exceeds node capacity {{K8_CPU}}"
}
  • operator: Comparison type (EQ, LT, LE, GT, GE)

  • left_operand: User-requested value (e.g., {{USER_CPU}})

  • right_operand: Limit or node capacity (e.g., {{K8_CPU}})

  • assert_message: Error shown when validation fails

Note

For detailed configuration fields and all available variables, see /api/configs/resource_validation in the API reference documentation.

Practical Guide#

Standard Validation Rules#

Create validation templates for common resources: CPU, GPU, memory, and storage.

Step 1: Create Validation Configuration

Define validation rules using variables for user requests ({{USER_*}}) and node capacity ({{K8_*}}):

Available Variables
User Request Variables:
  • {{USER_CPU}} - CPU count requested

  • {{USER_GPU}} - GPU count requested

  • {{USER_MEMORY}} - Memory requested (e.g., “8Gi”)

  • {{USER_STORAGE}} - Storage requested (e.g., “100Gi”)

Note

The values from the user request variables are the same values that are provided in the resource spec of a workflow.

Node Capacity Variables:
  • {{K8_CPU}} - Available CPU on nodes

  • {{K8_GPU}} - Available GPU on nodes

  • {{K8_MEMORY}} - Available memory on nodes

  • {{K8_STORAGE}} - Available storage on nodes

Note

The values from the node capacity variables are the same values that are reported by the Kubernetes API in the allocatable fields. {{K8_MEMORY}} and {{K8_STORAGE}} support units B, Ki, Mi, Gi and Ti.

Note

If the CPU allocatable provided by Kubernetes is in the format of m, {{K8_CPU}} will be an integer value after rounding down the CPU allocatable value.

Operators:
  • EQ (equal)

  • LT (less than)

  • LE (less/equal)

  • GT (greater than)

  • GE (greater/equal)

  • NE (not equal)

For all available variables and detailed configuration fields, see /api/configs/resource_validation.

Step 2: Apply Standard Validation Rules

Create a file with recommended validation templates:

$ cat << EOF > validation_config.json
{
  "default_cpu": [
    {
      "operator": "LE",
      "left_operand": "{{USER_CPU}}",
      "right_operand": "{{K8_CPU}}",
      "assert_message": "CPU {{USER_CPU}} exceeds node capacity {{K8_CPU}}"
    },
    {
      "operator": "GT",
      "left_operand": "{{USER_CPU}}",
      "right_operand": "0",
      "assert_message": "CPU {{USER_CPU}} must be greater than 0"
    }
  ],
  "default_gpu": [
    {
      "operator": "LE",
      "left_operand": "{{USER_GPU}}",
      "right_operand": "{{K8_GPU}}",
      "assert_message": "GPU {{USER_GPU}} exceeds node capacity {{K8_GPU}}"
    },
    {
      "operator": "GE",
      "left_operand": "{{USER_GPU}}",
      "right_operand": "0",
      "assert_message": "GPU {{USER_GPU}} cannot be negative"
    }
  ],
  "default_memory": [
    {
      "operator": "LT",
      "left_operand": "{{USER_MEMORY}}",
      "right_operand": "{{K8_MEMORY}}",
      "assert_message": "Memory {{USER_MEMORY}} exceeds node capacity {{K8_MEMORY}}"
    },
    {
      "operator": "GT",
      "left_operand": "{{USER_MEMORY}}",
      "right_operand": "0",
      "assert_message": "Memory {{USER_MEMORY}} must be greater than 0"
    }
  ],
  "default_storage": [
    {
      "operator": "LT",
      "left_operand": "{{USER_STORAGE}}",
      "right_operand": "{{K8_STORAGE}}",
      "assert_message": "Storage {{USER_STORAGE}} exceeds node capacity {{K8_STORAGE}}"
    },
    {
      "operator": "GT",
      "left_operand": "{{USER_STORAGE}}",
      "right_operand": "0",
      "assert_message": "Storage {{USER_STORAGE}} must be greater than 0"
    }
  ]
}
EOF

$ osmo config update RESOURCE_VALIDATION --file validation_config.json

Step 3: Reference in Pool Configuration

Add validation templates to your pool’s common_resource_validations field:

{
  "name": "my-pool",
  "backend": "default",
  "common_resource_validations": [
    "default_cpu",
    "default_memory",
    "default_storage",
    "default_gpu"
  ]
}

Additional Examples#

Custom GPU Validation - Enforce Minimum GPU Requirements

Create validation for workloads requiring at least 2 GPUs:

{
  "min_2_gpu": [
    {
      "operator": "GE",
      "left_operand": "{{USER_GPU}}",
      "right_operand": "2",
      "assert_message": "This pool requires minimum 2 GPUs, you requested {{USER_GPU}}"
    },
    {
      "operator": "LE",
      "left_operand": "{{USER_GPU}}",
      "right_operand": "{{K8_GPU}}",
      "assert_message": "GPU {{USER_GPU}} exceeds node capacity {{K8_GPU}}"
    }
  ]
}
Memory Safety Margins - Prevent 100% Utilization

Enforce 80% maximum memory usage to leave headroom:

{
  "memory_80_percent": [
    {
      "operator": "LT",
      "left_operand": "{{USER_MEMORY}}",
      "right_operand": "{{K8_MEMORY}} * 0.8",
      "assert_message": "Memory {{USER_MEMORY}} exceeds 80% of node capacity"
    }
  ]
}
Platform-Specific Rules - Different Limits Per Platform

Create different validation rules for different hardware platforms:

{
  "a100_validation": [
    {
      "operator": "LE",
      "left_operand": "{{USER_GPU}}",
      "right_operand": "8",
      "assert_message": "A100 platform supports max 8 GPUs"
    }
  ],
  "h100_validation": [
    {
      "operator": "LE",
      "left_operand": "{{USER_GPU}}",
      "right_operand": "8",
      "assert_message": "H100 platform supports max 8 GPUs"
    }
  ]
}

Troubleshooting#

Validation Always Fails
  • Check Kubernetes nodes are properly labeled and available

  • Verify node variables are populated: kubectl describe nodes

Inconsistent Results
  • Ensure all nodes report resources consistently

  • Check no nodes are in unschedulable state

Unit Conversion Errors
  • Use consistent units between requests and validation (For example, use Gi vs GB)

  • Review variable substitution in error messages

Debugging Tips
  • Start with simple rules and add complexity gradually

  • Test validation with different resource values

  • Examine OSMO service logs for detailed rule evaluation

Tip

Best Practices

  • Don’t allow 100% resource utilization - leave margins for system overhead and unexpected spikes

  • Use LT (less than) instead of LE (less/equal) for memory and storage to ensure safety margins

  • Write clear error messages that include variable values to help users fix issues quickly

  • Test rules with edge cases (minimum values, maximum values, invalid inputs)