Skip to content

Configuring Kernel Parameters on OpenShift

Manage NPU node boot parameters through MachineConfig. The settings below were validated on the listed hardware.

Target hardware

Profile Server CPU NPU Validated driver
amd-smci-cr13 Supermicro AS-5126GS-TNRT2 AMD RBLN-CR13 3.5.1
Profile Server CPU NPU Validated driver
amd-smci-ca25 Supermicro AMD RBLN-CA22, RBLN-CA25 3.4.1
amd-gigabyte-ca25 Gigabyte G494-ZB4-AAP2, G294-Z21-AAP2 AMD RBLN-CA22, RBLN-CA25 3.4.1

Kernel parameters

Parameter Purpose Applies to
transparent_hugepage=madvise Use THP for memory regions requested by the application All profiles
pcie_aspm=force Force PCIe Active State Power Management All profiles
pci=pcie_bus_perf Configure PCIe bus performance All profiles
pci=bfsort Sort PCI devices in breadth-first order All profiles
Parameter Purpose Applies to
transparent_hugepage=madvise Use THP for memory regions requested by the application All profiles
pcie_aspm=force Force PCIe Active State Power Management All profiles
pci=pcie_bus_perf Configure PCIe bus performance All profiles
pci=bfsort Sort PCI devices in breadth-first order All profiles
iommu.strict=1 Invalidate IOMMU translations immediately on DMA unmap All profiles

Before applying

You need cluster-admin access and oc. Identify the hardware, inspect the current configuration, and save each target node's /proc/cmdline.

1
2
3
4
5
6
7
oc get nodes
oc get mcp
oc debug node/<NODE_NAME> -- chroot /host dmidecode -s system-manufacturer
oc debug node/<NODE_NAME> -- chroot /host dmidecode -s system-product-name
oc debug node/<NODE_NAME> -- chroot /host lscpu
oc debug node/<NODE_NAME> -- chroot /host lspci -d 1eff: -n
oc debug node/<NODE_NAME> -- chroot /host cat /proc/cmdline

The PCI device ID identifies the card. Select the profile by NPU model even when the server model is the same.

RBLN-CR13 reports the PCI device ID 2130.

RBLN-CA22 reports the PCI device ID 1220, and RBLN-CA25 reports 1250. Both cards use the same ATOM™ profile.

Selecting the target nodes

flowchart LR
    MC["MachineConfig"] -->|"machineConfigSelector"| MCP["MachineConfigPool"]
    MCP -->|"nodeSelector"| N["Target nodes"]

Use a dedicated MCP for a subset of workers. If the cluster has nodes of both product lines, keep them in separate pools because their parameters differ.

Node reboots

Adding or removing kernel parameters causes MCO to drain and reboot the target nodes. Setting a MachineConfig's role to worker can also affect custom pools that inherit worker configuration. Check the target MCP and node count before applying.

Create custom MachineConfigPool

Save this as npu-mcp.yaml. Replace every __MCP_NAME__ with the selected profile name. Retain the worker configuration inheritance and ensure that another custom MCP does not also select these nodes.

npu-mcp.yaml
apiVersion: machineconfiguration.openshift.io/v1
kind: MachineConfigPool
metadata:
  name: __MCP_NAME__
spec:
  machineConfigSelector:
    matchExpressions:
      - key: machineconfiguration.openshift.io/role
        operator: In
        values:
          - worker
          - __MCP_NAME__
  nodeSelector:
    matchLabels:
      node-role.kubernetes.io/__MCP_NAME__: ""
1
2
3
oc apply -f npu-mcp.yaml
oc label node <NODE_NAME> node-role.kubernetes.io/__MCP_NAME__=""
oc get mcp __MCP_NAME__

Confirm that MACHINECOUNT matches the target node count and that the pool is healthy. If using automatic NFD identification, use the profile selector in the next section instead of the role label above.

(Optional) Automatic Identification via NFD NodeFeatureRule

With NFD v0.16+, the system.dmiid.sys_vendor, cpu.model.vendor_id and pci.device features can be combined in a NodeFeatureRule that assigns the profile label automatically, so a node joining the cluster later lands in the right MCP without manual labeling.

Note

NFD does not automatically create labels for system.dmiid. A NodeFeatureRule must be defined.

A label outside the default NFD label namespaces is dropped unless the namespace is allowed on nfd-master with --extra-label-ns=rebellions.io.

Create a NodeFeatureRule

Each rule lists several features and matchFeatures requires all of them to match. The server vendor and the CPU vendor cannot tell the two product lines apart on the same server, so the rules also match the device id under pci.device. If the cluster has nodes of both product lines, put the rules from both tabs in one NodeFeatureRule.

apiVersion: nfd.k8s-sigs.io/v1alpha1
kind: NodeFeatureRule
metadata:
  name: rbln-hardware-detection
spec:
  rules:
    - name: "amd-smci-cr13"
      labels:
        rebellions.io/profile: "amd-smci-cr13"
      matchFeatures:
        - feature: system.dmiid
          matchExpressions:
            sys_vendor: {op: In, value: ["Supermicro"]}
        - feature: cpu.model
          matchExpressions:
            vendor_id: {op: In, value: ["AMD"]}
        - feature: pci.device
          matchExpressions:
            vendor: {op: In, value: ["1eff"]}
            device: {op: In, value: ["2130"]}
apiVersion: nfd.k8s-sigs.io/v1alpha1
kind: NodeFeatureRule
metadata:
  name: rbln-hardware-detection
spec:
  rules:
    - name: "amd-smci-ca25"
      labels:
        rebellions.io/profile: "amd-smci-ca25"
      matchFeatures:
        - feature: system.dmiid
          matchExpressions:
            sys_vendor: {op: In, value: ["Supermicro"]}
        - feature: cpu.model
          matchExpressions:
            vendor_id: {op: In, value: ["AMD"]}
        - feature: pci.device
          matchExpressions:
            vendor: {op: In, value: ["1eff"]}
            device: {op: NotIn, value: ["2130"]}
    - name: "amd-gigabyte-ca25"
      labels:
        rebellions.io/profile: "amd-gigabyte-ca25"
      matchFeatures:
        - feature: system.dmiid
          matchExpressions:
            sys_vendor: {op: In, value: ["Giga Computing"]}
        - feature: cpu.model
          matchExpressions:
            vendor_id: {op: In, value: ["AMD"]}
        - feature: pci.device
          matchExpressions:
            vendor: {op: In, value: ["1eff"]}
            device: {op: NotIn, value: ["2130"]}
oc apply -f <NFR_YAML_FILE>

Verify Labels

After applying, confirm that the profile label is assigned to the target node:

oc get node <NODE_NAME> -o jsonpath='{.metadata.labels}' | python3 -m json.tool | grep rebellions.io/profile

Expected output on a Supermicro AMD node:

"rebellions.io/profile": "amd-smci-cr13",

Expected output on a Supermicro AMD node:

"rebellions.io/profile": "amd-smci-ca25",

A Gigabyte AMD node receives amd-gigabyte-ca25.

Before creating the rule, verify the CPU vendor using the built-in NFD label feature.node.kubernetes.io/cpu-model.vendor_id=AMD, which NFD assigns without a NodeFeatureRule.

Use NFD Labels as MCP nodeSelector

Once NFD has assigned the profile label, it can be used directly in the MCP nodeSelector without manual labeling. Update the nodeSelector in the MCP YAML in Create Custom MachineConfigPool as follows.

1
2
3
  nodeSelector:
    matchLabels:
      rebellions.io/profile: __MCP_NAME__

Selecting a MachineConfig

Save one manifest matching the hardware profile as npu-kargs.yaml. Replace __MCP_NAME__ with the target MCP name. Defining the same parameter in multiple configurations for a pool duplicates it on the kernel command line.

Supermicro AMD + RBLN-CR13

apiVersion: machineconfiguration.openshift.io/v1
kind: MachineConfig
metadata:
  name: 99-grub-kargs-amd-smci-cr13
  labels:
    machineconfiguration.openshift.io/role: __MCP_NAME__
    rebellions.io/component: grub-kargs
    rebellions.io/profile: amd-smci-cr13
    rebellions.io/cpu-vendor: amd
    rebellions.io/server-vendor: supermicro
    rebellions.io/accelerator: cr13
spec:
  kernelArguments:
    - transparent_hugepage=madvise
    - pcie_aspm=force
    - pci=pcie_bus_perf
    - pci=bfsort

Supermicro AMD + RBLN-CA22, RBLN-CA25

apiVersion: machineconfiguration.openshift.io/v1
kind: MachineConfig
metadata:
  name: 99-grub-kargs-amd-smci-ca25
  labels:
    machineconfiguration.openshift.io/role: __MCP_NAME__
    rebellions.io/component: grub-kargs
    rebellions.io/profile: amd-smci-ca25
    rebellions.io/cpu-vendor: amd
    rebellions.io/server-vendor: supermicro
    rebellions.io/accelerator: ca25
spec:
  kernelArguments:
    - transparent_hugepage=madvise
    - pcie_aspm=force
    - pci=pcie_bus_perf
    - pci=bfsort
    - iommu.strict=1

Gigabyte AMD + RBLN-CA22, RBLN-CA25

apiVersion: machineconfiguration.openshift.io/v1
kind: MachineConfig
metadata:
  name: 99-grub-kargs-amd-gigabyte-ca25
  labels:
    machineconfiguration.openshift.io/role: __MCP_NAME__
    rebellions.io/component: grub-kargs
    rebellions.io/profile: amd-gigabyte-ca25
    rebellions.io/cpu-vendor: amd
    rebellions.io/server-vendor: gigabyte
    rebellions.io/accelerator: ca25
spec:
  kernelArguments:
    - transparent_hugepage=madvise
    - pcie_aspm=force
    - pci=pcie_bus_perf
    - pci=bfsort
    - iommu.strict=1

Applying and verifying

oc apply -f npu-kargs.yaml
oc get mcp __MCP_NAME__ -w
Example output
$ oc get mcp __MCP_NAME__ \
>   -o 'custom-columns=NAME:.metadata.name,UPDATED:.status.conditions[?(@.type=="Updated")].status,UPDATING:.status.conditions[?(@.type=="Updating")].status,DEGRADED:.status.conditions[?(@.type=="Degraded")].status'
NAME            UPDATED   UPDATING   DEGRADED
amd-smci-ca25   True      False      False

When the pool reports UPDATED=True, UPDATING=False, and DEGRADED=False, inspect the target nodes.

oc debug node/<NODE_NAME> -- chroot /host cat /proc/cmdline
Example output (result line)
$ oc debug node/<NODE_NAME> -- chroot /host cat /sys/kernel/mm/transparent_hugepage/enabled
...
always [madvise] never

All parameters for the selected profile must be present, and the THP output must select [madvise].

Rolling back

Delete the MachineConfig added by this page and wait for the MCP rollout to finish.

oc delete -f npu-kargs.yaml
oc get mcp __MCP_NAME__ -w

Once the pool is healthy, compare /proc/cmdline with the saved baseline. A parameter remains if another MachineConfig still defines it.

Remove the MCP only when no other MachineConfig depends on it. Order: remove node labels → wait for worker-pool return and configuration completion → delete the MCP. For NFD selection, also check the profile-label rules.

oc label node <NODE_NAME> node-role.kubernetes.io/__MCP_NAME__-
oc get mcp worker __MCP_NAME__ -w

After the nodes have moved and finished applying their configuration, run:

oc delete mcp __MCP_NAME__

Troubleshooting an incomplete rollout

1
2
3
oc describe mcp __MCP_NAME__
oc describe node <NODE_NAME>
oc get pods -n openshift-machine-config-operator -o wide

Read the MCP status messages and the affected node's Machine Config Daemon logs. Check node selectors, overlapping custom pools, workloads blocking drain, and missing MachineConfigs. Manually changing a node's currentConfig or desiredConfig annotation can make it disagree with the applied configuration.

See Red Hat's MachineConfig documentation for MCO configuration and recovery.