Node Tuning Helper Scripts
Detailed instructions for invoking the helper utilities that back /node-tuning commands:
generate_tuned_profile.py renders Tuned manifests (tuned.openshift.io/v1).
analyze_node_tuning.py inspects live nodes or sosreports for tuning gaps.
When to Use These Scripts
- Translate structured command inputs into Tuned manifests for the Node Tuning Operator.
- Iterate on generated YAML outside the assistant or integrate the generator into automation.
- Analyze CPU isolation, IRQ affinity, huge pages, sysctl values, and networking counters from live clusters or archived sosreports.
Prerequisites
- Python 3.8 or newer (
python3 --version).
- Repository checkout so the scripts under
plugins/node-tuning/skills/scripts/ are accessible.
- Optional:
oc CLI when validating or applying manifests.
- Optional: Extracted sosreport directory when running the analysis script offline.
- Optional (remote analysis):
oc CLI access plus a valid KUBECONFIG when capturing /proc//sys or sosreport via oc debug node/<name>. The sosreport workflow pulls the registry.redhat.io/rhel9/support-tools image (override with --toolbox-image or TOOLBOX_IMAGE) and requires registry access. HTTP(S) proxy env vars from the host are forwarded automatically when present, but using a proxy is optional.
Script: generate_tuned_profile.py
Implementation Steps
Collect Inputs
--profile-name: Tuned resource name.
--summary: [main] section summary.
- Repeatable options:
--include, --main-option, --variable, --sysctl, --section (SECTION:KEY=VALUE).
- Target selectors:
--machine-config-label key=value, --match-label key[=value].
- Optional:
--priority (default 20), --namespace, --output, --dry-run.
- Use
--list-nodes/--node-selector to inspect nodes and --label-node NODE:KEY[=VALUE] (plus --overwrite-labels) to tag machines.
Inspect or Label Nodes (optional)
# List all worker nodes
python3 plugins/node-tuning/skills/scripts/generate_tuned_profile.py --list-nodes --node-selector "node-role.kubernetes.io/worker" --skip-manifest
# Label a specific node for the worker-hp pool
python3 plugins/node-tuning/skills/scripts/generate_tuned_profile.py \
--label-node ip-10-0-1-23.ec2.internal:node-role.kubernetes.io/worker-hp= \
--overwrite-labels \
--skip-manifest
Render the Manifest
python3 plugins/node-tuning/skills/scripts/generate_tuned_profile.py \
--profile-name "$PROFILE" \
--summary "$SUMMARY" \
--sysctl net.core.netdev_max_backlog=16384 \
--match-label tuned.openshift.io/custom-net \
--output .work/node-tuning/$PROFILE/tuned.yaml
- Omit
--output to write <profile-name>.yaml in the current directory.
- Add
--dry-run to print the manifest to stdout.
Review Output
- Inspect the generated YAML for accuracy.
- Optionally format with
yq or open in an editor for readability.
Validate and Apply
- Dry-run:
oc apply --server-dry-run=client -f <manifest>.
- Apply:
oc apply -f <manifest>.
Error Handling
- Missing required options raise
ValueError with descriptive messages.
- The script exits non-zero when no target selectors (
--machine-config-label or --match-label) are supplied.
- Invalid key/value or section inputs identify the failing argument explicitly.
Examples
python3 plugins/node-tuning/skills/scripts/generate_tuned_profile.py \
--profile-name realtime-worker \
--summary "Realtime tuned profile" \
--include openshift-node --include realtime \
--variable isolated_cores=1 \
--section bootloader:cmdline_ocp_realtime=+systemd.cpu_affinity=${not_isolated_cores_expanded} \
--machine-config-label machineconfiguration.openshift.io/role=worker-rt \
--priority 25 \
--output .work/node-tuning/realtime-worker/tuned.yaml
python3 plugins/node-tuning/skills/scripts/generate_tuned_profile.py \
--profile-name openshift-node-hugepages \
--summary "Boot time configuration for hugepages" \
--include openshift-node \
--section bootloader:cmdline_openshift_node_hugepages="hugepagesz=2M hugepages=50" \
--machine-config-label machineconfiguration.openshift.io/role=worker-hp \
--priority 30 \
--output .work/node-tuning/openshift-node-hugepages/hugepages-tuned-boottime.yaml
Script: analyze_node_tuning.py
Purpose
Inspect either a live node (/proc, /sys) or an extracted sosreport snapshot for tuning signals (CPU isolation, IRQ affinity, huge pages, sysctl state, networking counters) and emit actionable recommendations.
Usage Patterns
- Live node analysis
python3 plugins/node-tuning/skills/scripts/analyze_node_tuning.py --format markdown
- Remote analysis via oc debug
python3 plugins/node-tuning/skills/scripts/analyze_node_tuning.py \
--node worker-rt-0 \
--kubeconfig ~/.kube/prod \
--format markdown
- Collect sosreport via oc debug and analyze locally
python3 plugins/node-tuning/skills/scripts/analyze_node_tuning.py \
--node worker-rt-0 \
--toolbox-image registry.example.com/support-tools:latest \
--sosreport-arg "--case-id=01234567" \
--sosreport-output .work/node-tuning/sosreports \
--format json
- Offline sosreport analysis
python3 plugins/node-tuning/skills/scripts/analyze_node_tuning.py \
--sosreport /path/to/sosreport-2025-10-20
- Automation-friendly JSON
python3 plugins/node-tuning/skills/scripts/analyze_node_tuning.py \
--sosreport /path/to/sosreport \
--format json --output .work/node-tuning/node-analysis.json
Implementation Steps
- Select data source
- Provide
--node <name> (with optional --kubeconfig / --oc-binary). By default the helper runs sosreport remotely from inside the RHCOS toolbox container (registry.redhat.io/rhel9/support-tools). Override the image with --toolbox-image, extend the sosreport command with --sosreport-arg, or disable the curated OpenShift flags via --skip-default-sosreport-flags. Pass --no-collect-sosreport to fall back to the direct /proc snapshot mode.
- Provide
--sosreport <dir> for archived diagnostics; detection finds embedded proc/ and sys/.
- Omit both switches to query the live filesystem (defaults to
/proc and /sys).
- Override paths with
--proc-root or --sys-root when the layout differs.
- Run analysis
- The script parses
cpuinfo, kernel cmdline parameters (isolcpus, nohz_full, tuned.non_isolcpus), default IRQ affinities, huge page counters, sysctl values (net, vm, kernel), transparent hugepage settings, netstat/sockstat counters, and ps snapshots (when available in sosreport).
- Review the report
- Markdown output groups findings by section (System Overview, CPU & Isolation, Huge Pages, Sysctl Highlights, Network Signals, IRQ Affinity, Process Snapshot) and lists recommendations.
- JSON output contains the same information in structured form for pipelines or dashboards.
- Act on recommendations
- Apply Tuned profiles, MachineConfig updates, or manual sysctl/irqbalance adjustments.
- Feed actionable items back into
/node-tuning:generate-tuned-profile to codify desired state.
Error Handling
- Missing
proc/ or sys/ directories trigger descriptive errors.
- Unreadable files are skipped without raising an error and noted in observations where relevant.
- Non-numeric sysctl values are flagged for manual investigation.
Example Output (Markdown excerpt)
# Node Tuning Analysis
## System Overview
- Hostname: worker-rt-1
- Kernel: 4.18.0-477.el8
- NUMA nodes: 2
- Kernel cmdline: `BOOT_IMAGE=... isolcpus=2-15 tuned.non_isolcpus=0-1`
## CPU & Isolation
- Logical CPUs: 32
- Physical cores: 16 across 2 socket(s)
- SMT detected: yes
- Isolated CPUs: 2-15
...
## Recommended Actions
- Configure net.core.netdev_max_backlog (>=32768) to accommodate bursty NIC traffic.
- Transparent Hugepages are not disabled (`[never]` not selected). Consider setting to `never` for latency-sensitive workloads.
- 4 IRQs overlap isolated CPUs. Relocate interrupt affinities using tuned profiles or irqbalance.
Follow-up Automation Ideas
- Persist JSON results in
.work/node-tuning/<host>/analysis.json for historical tracing.
- Gate upgrades by comparing recommendations across nodes.
- Integrate with CI jobs that validate cluster tuning post-change.
1---2name: scripts3description: Generate tuned manifests and evaluate node tuning snapshots4---56# Node Tuning Helper Scripts78Detailed instructions for invoking the helper utilities that back `/node-tuning` commands:9- `generate_tuned_profile.py` renders Tuned manifests (`tuned.openshift.io/v1`).10- `analyze_node_tuning.py` inspects live nodes or sosreports for tuning gaps.1112## When to Use These Scripts13- Translate structured command inputs into Tuned manifests for the Node Tuning Operator.14- Iterate on generated YAML outside the assistant or integrate the generator into automation.15- Analyze CPU isolation, IRQ affinity, huge pages, sysctl values, and networking counters from live clusters or archived sosreports.1617## Prerequisites18- Python 3.8 or newer (`python3 --version`).19- Repository checkout so the scripts under `plugins/node-tuning/skills/scripts/` are accessible.20- Optional: `oc` CLI when validating or applying manifests.21- Optional: Extracted sosreport directory when running the analysis script offline.22- Optional (remote analysis): `oc` CLI access plus a valid `KUBECONFIG` when capturing `/proc`/`/sys` or sosreport via `oc debug node/<name>`. The sosreport workflow pulls the `registry.redhat.io/rhel9/support-tools` image (override with `--toolbox-image` or `TOOLBOX_IMAGE`) and requires registry access. HTTP(S) proxy env vars from the host are forwarded automatically when present, but using a proxy is optional.2324---2526## Script: `generate_tuned_profile.py`2728### Implementation Steps291. **Collect Inputs**30 - `--profile-name`: Tuned resource name.31 - `--summary`: `[main]` section summary.32 - Repeatable options: `--include`, `--main-option`, `--variable`, `--sysctl`, `--section` (`SECTION:KEY=VALUE`).33 - Target selectors: `--machine-config-label key=value`, `--match-label key[=value]`.34 - Optional: `--priority` (default 20), `--namespace`, `--output`, `--dry-run`.35 - Use `--list-nodes`/`--node-selector` to inspect nodes and `--label-node NODE:KEY[=VALUE]` (plus `--overwrite-labels`) to tag machines.36372. **Inspect or Label Nodes (optional)**38 ```bash39 # List all worker nodes40 python3 plugins/node-tuning/skills/scripts/generate_tuned_profile.py --list-nodes --node-selector "node-role.kubernetes.io/worker" --skip-manifest4142 # Label a specific node for the worker-hp pool43 python3 plugins/node-tuning/skills/scripts/generate_tuned_profile.py \44 --label-node ip-10-0-1-23.ec2.internal:node-role.kubernetes.io/worker-hp= \45 --overwrite-labels \46 --skip-manifest47 ```48493. **Render the Manifest**50 ```bash51 python3 plugins/node-tuning/skills/scripts/generate_tuned_profile.py \52 --profile-name "$PROFILE" \53 --summary "$SUMMARY" \54 --sysctl net.core.netdev_max_backlog=16384 \55 --match-label tuned.openshift.io/custom-net \56 --output .work/node-tuning/$PROFILE/tuned.yaml57 ```58 - Omit `--output` to write `<profile-name>.yaml` in the current directory.59 - Add `--dry-run` to print the manifest to stdout.60614. **Review Output**62 - Inspect the generated YAML for accuracy.63 - Optionally format with `yq` or open in an editor for readability.64655. **Validate and Apply**66 - Dry-run: `oc apply --server-dry-run=client -f <manifest>`.67 - Apply: `oc apply -f <manifest>`.6869### Error Handling70- Missing required options raise `ValueError` with descriptive messages.71- The script exits non-zero when no target selectors (`--machine-config-label` or `--match-label`) are supplied.72- Invalid key/value or section inputs identify the failing argument explicitly.7374### Examples75```bash76python3 plugins/node-tuning/skills/scripts/generate_tuned_profile.py \77 --profile-name realtime-worker \78 --summary "Realtime tuned profile" \79 --include openshift-node --include realtime \80 --variable isolated_cores=1 \81 --section bootloader:cmdline_ocp_realtime=+systemd.cpu_affinity=${not_isolated_cores_expanded} \82 --machine-config-label machineconfiguration.openshift.io/role=worker-rt \83 --priority 25 \84 --output .work/node-tuning/realtime-worker/tuned.yaml85```86```bash87python3 plugins/node-tuning/skills/scripts/generate_tuned_profile.py \88 --profile-name openshift-node-hugepages \89 --summary "Boot time configuration for hugepages" \90 --include openshift-node \91 --section bootloader:cmdline_openshift_node_hugepages="hugepagesz=2M hugepages=50" \92 --machine-config-label machineconfiguration.openshift.io/role=worker-hp \93 --priority 30 \94 --output .work/node-tuning/openshift-node-hugepages/hugepages-tuned-boottime.yaml95```9697---9899## Script: `analyze_node_tuning.py`100101### Purpose102Inspect either a live node (`/proc`, `/sys`) or an extracted sosreport snapshot for tuning signals (CPU isolation, IRQ affinity, huge pages, sysctl state, networking counters) and emit actionable recommendations.103104### Usage Patterns105- **Live node analysis**106 ```bash107 python3 plugins/node-tuning/skills/scripts/analyze_node_tuning.py --format markdown108 ```109- **Remote analysis via oc debug**110 ```bash111 python3 plugins/node-tuning/skills/scripts/analyze_node_tuning.py \112 --node worker-rt-0 \113 --kubeconfig ~/.kube/prod \114 --format markdown115 ```116- **Collect sosreport via oc debug and analyze locally**117 ```bash118 python3 plugins/node-tuning/skills/scripts/analyze_node_tuning.py \119 --node worker-rt-0 \120 --toolbox-image registry.example.com/support-tools:latest \121 --sosreport-arg "--case-id=01234567" \122 --sosreport-output .work/node-tuning/sosreports \123 --format json124 ```125- **Offline sosreport analysis**126 ```bash127 python3 plugins/node-tuning/skills/scripts/analyze_node_tuning.py \128 --sosreport /path/to/sosreport-2025-10-20129 ```130- **Automation-friendly JSON**131 ```bash132 python3 plugins/node-tuning/skills/scripts/analyze_node_tuning.py \133 --sosreport /path/to/sosreport \134 --format json --output .work/node-tuning/node-analysis.json135 ```136137### Implementation Steps1381. **Select data source**139 - Provide `--node <name>` (with optional `--kubeconfig` / `--oc-binary`). By default the helper runs `sosreport` remotely from inside the RHCOS toolbox container (`registry.redhat.io/rhel9/support-tools`). Override the image with `--toolbox-image`, extend the sosreport command with `--sosreport-arg`, or disable the curated OpenShift flags via `--skip-default-sosreport-flags`. Pass `--no-collect-sosreport` to fall back to the direct `/proc` snapshot mode.140 - Provide `--sosreport <dir>` for archived diagnostics; detection finds embedded `proc/` and `sys/`.141 - Omit both switches to query the live filesystem (defaults to `/proc` and `/sys`).142 - Override paths with `--proc-root` or `--sys-root` when the layout differs.1432. **Run analysis**144 - The script parses `cpuinfo`, kernel cmdline parameters (`isolcpus`, `nohz_full`, `tuned.non_isolcpus`), default IRQ affinities, huge page counters, sysctl values (net, vm, kernel), transparent hugepage settings, `netstat`/`sockstat` counters, and `ps` snapshots (when available in sosreport).1453. **Review the report**146 - Markdown output groups findings by section (System Overview, CPU & Isolation, Huge Pages, Sysctl Highlights, Network Signals, IRQ Affinity, Process Snapshot) and lists recommendations.147 - JSON output contains the same information in structured form for pipelines or dashboards.1484. **Act on recommendations**149 - Apply Tuned profiles, MachineConfig updates, or manual sysctl/irqbalance adjustments.150 - Feed actionable items back into `/node-tuning:generate-tuned-profile` to codify desired state.151152### Error Handling153- Missing `proc/` or `sys/` directories trigger descriptive errors.154- Unreadable files are skipped without raising an error and noted in observations where relevant.155- Non-numeric sysctl values are flagged for manual investigation.156157### Example Output (Markdown excerpt)158```159# Node Tuning Analysis160161## System Overview162- Hostname: worker-rt-1163- Kernel: 4.18.0-477.el8164- NUMA nodes: 2165- Kernel cmdline: `BOOT_IMAGE=... isolcpus=2-15 tuned.non_isolcpus=0-1`166167## CPU & Isolation168- Logical CPUs: 32169- Physical cores: 16 across 2 socket(s)170- SMT detected: yes171- Isolated CPUs: 2-15172...173174## Recommended Actions175- Configure net.core.netdev_max_backlog (>=32768) to accommodate bursty NIC traffic.176- Transparent Hugepages are not disabled (`[never]` not selected). Consider setting to `never` for latency-sensitive workloads.177- 4 IRQs overlap isolated CPUs. Relocate interrupt affinities using tuned profiles or irqbalance.178```179180### Follow-up Automation Ideas181- Persist JSON results in `.work/node-tuning/<host>/analysis.json` for historical tracing.182- Gate upgrades by comparing recommendations across nodes.183- Integrate with CI jobs that validate cluster tuning post-change.