Blog

  • Aside: Applying Kernel Tunnables quickly (randomize_va_space)

    When a Tuned profile changes a sysctl such as:

    [sysctl]
    kernel.randomize_va_space=0

    You can use TuneD Custom Resource:

    apiVersion: tuned.openshift.io/v1
    kind: Tuned
    metadata:
      name: disable-aslr
      namespace: openshift-cluster-node-tuning-operator
    spec:
      profile:
      - name: disable-aslr-profile
        data: |
          [main]
          summary=Disable ASLR
          include=openshift-node
    
          [sysctl]
          kernel.randomize_va_space=0
    
      recommend:
      - priority: 20
        profile: disable-aslr-profile
        match:
        - label: node-role.kubernetes.io/worker

    The Node Tuning Operator/tuned applies it dynamically via the sysctl interface, so a reboot is typically not required. The new value takes effect immediately on the node after the profile is applied.

    You can verify:

    oc debug node/<node>
    chroot /host
    
    sysctl kernel.randomize_va_space

    or

    cat /proc/sys/kernel/randomize_va_space

    Disabling ASLR through a Tuned object, the setting is applied without a node reboot. You can usually observe the change within seconds after the profile becomes active.

  • Using zstd for Fast and Efficient Compression on OpenShift

    When you need to archive files directly on an OpenShift node, zstd is a great choice because it is already available on the system and provides an excellent balance of compression ratio and performance.

    Access the Target Node

    Start by opening a remote shell to the node:

    oc rsh node/<node-target>

    Maximum Compression

    To prioritize the smallest archive size, use the ultra compression level (-22) with all available CPU threads:

    time tar -I 'zstd -T0 --ultra -22' -cf /tmp/archive.tar.zst /tmp/random_100m.dat

    Example result:

    real    0m30.007s
    user    0m29.346s
    sys     0m0.384s

    Maximum Compression with a Single Thread

    If you want to limit CPU usage, run the same compression level with a single thread:

    time tar -I 'zstd -T1 --ultra -22' -cf /tmp/archive.tar.zst /tmp/random_100m.dat

    Example result:

    real    0m30.677s
    user    0m30.322s
    sys     0m0.275s

    The runtime is similar, making this a viable option when CPU resources are constrained.

    Fast Throughput Compression

    For large files where speed is more important than archive size, use a lower compression level:

    time tar -I 'zstd -T0 -1' -cf /tmp/archive.tar.zst /var/log/random_1000m.dat

    Example result:

    real    0m18.716s
    user    0m14.327s
    sys     0m16.420s

    Fast Compression with One Thread

    You can further reduce CPU consumption by limiting compression to a single thread:

    time tar -I 'zstd -T1 -1' -cf /tmp/archive.tar.zst /var/log/random_1000m.dat

    Example result:

    real    0m19.121s
    user    0m13.434s
    sys     0m14.402s

    Key Takeaways

    • Use --ultra -22 when achieving the highest compression ratio is the primary goal.
    • Use -1 for the fastest archive creation and best throughput.
    • -T0 allows zstd to use all available CPU threads.
    • -T1 limits compression to a single thread and can be useful on busy systems.
    • In these examples, single-threaded and multi-threaded runs showed only minor differences in elapsed time, making thread selection largely a resource-management decision.
  • OpenShift: Adding Public Key to core user

    Post-installation, the supported way to add another SSH public key for the core user on OpenShift/RHCOS nodes is by updating or creating a MachineConfig that contains all desired sshAuthorizedKeys. The Machine Config Operator (MCO) then rolls the change out to the targeted MachineConfigPool.

    Note: OpenShift commonly uses 99-worker-ssh and 99-master-ssh to manage SSH keys for the core user.

    1. Export the existing MachineConfig for worker
    oc get machineconfig 99-worker-ssh -o yaml > 99-worker-ssh.yaml
    1. Add the second public key

    Edit the file and ensure both keys are present under sshAuthorizedKeys.

    Example:

    apiVersion: machineconfiguration.openshift.io/v1
    kind: MachineConfig
    metadata:
      labels:
        machineconfiguration.openshift.io/role: worker
      name: 99-worker-ssh
    spec:
      config:
        ignition:
          version: 3.5.0
        passwd:
          users:
          - name: core
            sshAuthorizedKeys:
            - ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAEXISTINGKEY user1@example
            - ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAANEWKEY user2@example

    Important: The sshAuthorizedKeys list is authoritative. Include the existing key(s) plus the new key. Do not provide only the new key unless you want to remove the old ones. The MCO only supports modifying sshAuthorizedKeys for the core user.

    1. Apply the MachineConfig
    oc apply -f 99-worker-ssh.yaml

    The Machine Config Operator will render a new configuration and update the nodes in the associated MachineConfigPool.

    1. Watch the rollout

    Check the MachineConfigPool:

    oc get mcp

    Watch until the pool reports:

    • UPDATED=True
    • UPDATING=False
    • DEGRADED=False
    1. Verify one of the nodes
    ssh core@<node-ip>

    Using either the original key or the newly added key.

    You can also verify on the node:

    oc debug node/<node-name>
    chroot /host
    cat /home/core/.ssh/authorized_keys

    The file should contain both public keys

    This will add both public keys to the core user on all worker nodes.

    You can repeat for the control plane.

    References: Update SSH Keys

  • IPI PowerVS: Power10 Migration in One Change

    Running an OpenShift IPI cluster on PowerVS? Moving to Power10 can be as simple as updating the machine systemType and letting OpenShift perform a rolling node replacement. The cluster provisions new nodes, migrates workloads, and removes the old VMs automatically. Full details at Christy Norman’s blog. [community.ibm.com]

    Control plane

    oc patch controlplanemachineset cluster \
      -n openshift-machine-api \
      --type=merge \
      -p '{"spec":{"template":{"machines_v1beta1_machine_openshift_io":{"spec":{"providerSpec":{"value":{"systemType":"s1022"}}}}}}}'
    

    Workers

    oc patch machineset <worker-machineset> \
      -n openshift-machine-api \
      --type=merge \
      -p '{"spec":{"template":{"spec":{"providerSpec":{"value":{"systemType":"s1022"}}}}}}'
    

    Credit: Christy Norman, “Migrating an OpenShift IPI Cluster to Power10 on Power Virtual Server.” [community.ibm.com]

  • OpenShift 4.22.0 ClusterImagePolicy Feature enforces signature verification on Release and Payload

    With OpenShift Container Platform 4.22, Red Hat enforces signature verification for the release image and payload (cluster operators and oeprands). The verification is controlled by the ClusterImagePolicy which specifies the Root CA and a scope of quay.io/openshift-release-dev/ocp-release and quay.io/openshift-release-dev/ocp-v4.0-art-dev. When an image is used on a node, the signatures are pulled from the mirror along with the image, and verified before starting a container. This verification expands on the ocp-release scope.

    apiVersion: config.openshift.io/v1
    kind: ClusterImagePolicy
    metadata:
      name: openshift
    spec:
      policy:
        rootOfTrust:
          policyType: PublicKey
          publicKey:
            keyData: ...
      scopes:
      - quay.io/openshift-release-dev/ocp-release
      - quay.io/openshift-release-dev/ocp-v4.0-art-dev
      ...
    

    If you are running a disconnected cluster and the signature is missing from your mirror, you’ll see the following:

    • Install: The bootstrap node hangs and does not install as the signature is not verified.
    • Upgrade: The ClusterImagePolicy enforces signature verification. If the signatures are missing from your mirror, the Cluster Version Operator (CVO) will be blocked, preventing node updates.

    In order to continue, you may do one of the following:

    1. Use oc mirror --v2 to mirror your content. This feature automatically honors signatures … see Mirroring images for a disconnected installation using the oc-mirror plugin
    2. If you are currently using oc adm release mirror, you can copy the sig file for the release payload:
    $ oc image mirror quay.io/openshift-release-dev/ocp-release:${RELEASE_DIGEST}.sig registry.example.com/openshift/whatever:${RELEASE_DIGEST}.sig
    

    You repeat for each image listed in the release.txt

    RELEASE_DIGEST:: Specifies your digest image with the : character replaced by a - character. For example: sha256:884e1ff5effeaa04467fab9725900e7f0ed1daa89a7734644f14783014cebdee becomes sha256-884e1ff5effeaa04467fab9725900e7f0ed1daa89a7734644f14783014cebdee.sig.

    You must switch to using oc mirror --v2.

    Good luck with your disconnected clusters, and ensure image signatures are present in your local mirror using one of the mirroring methods.

    Note: you can use this with your application / deliverable for enhanced security.

    References

    1. Red Hat OpenShift Docs: Chapter 12. Manage secure signatures with sigstore
    2. Red Hat Developer: How to verify container signatures in disconnected OpenShift
    3. Red Hat Developer: Verify Cosign bring-your-own PKI signature on OpenShift
    4. IBM Power Blog Mirroring for OpenShift on IBM Power in Disconnected Environments
    5. IBM Power Blog OpenShift 4.21.0 ClusterImagePolicy Feature enforces signature verification
  • 2026-07: Additions IBM Power Open Source Images on the IBM Container Registry

    The IBM Linux on Power team has released some new open source container images into the IBM Container Registry (ICR). These images are available for no-charge and can be used in your development and production environments.

    Image NameTag NameProject LicensesImage Pull CommandLast Published On
    clickhousev26.3.9.8-ltsApache-2.0podman pull icr.io/ppc64le-oss/clickhouse-ppc64le:v26.3.9.8-ltsJuly 1, 2026
    open-webui0.7.2OpenWebUI Licensepodman pull icr.io/ppc64le-oss/open-webui-ppc64le:0.7.2July 1, 2026
    ollamav0.24.0MITpodman pull icr.io/ppc64le-oss/ollama-ppc64le:v0.24.0July 1, 2026
    agentstack-chat0.4.3Apache-2.0podman pull icr.io/ppc64le-oss/agentstack-chat-ppc64le:0.4.3July 17, 2026
    agentstack-rag0.4.3Apache-2.0podman pull icr.io/ppc64le-oss/agentstack-rag-ppc64le:0.4.3July 17, 2026
    agentstack-form0.4.3Apache-2.0podman pull icr.io/ppc64le-oss/agentstack-form-ppc64le:0.4.3July 17, 2026
    agentstack-server0.4.3Apache-2.0podman pull icr.io/ppc64le-oss/agentstack-server-ppc64le:0.4.3July 17, 2026

    Refer to https://community.ibm.com/community/user/blogs/priya-seth/2023/04/05/open-source-containers-for-power-in-icr for more details.

    If you need opensource software enabled on IBM Power, reach out at https://www.ibm.com/power/resources/isv/enablement-request/

  • How to Manually Extract RHCOS Build Artifacts for OpenShift (ppc64le)

    How to Manually Extract RHCOS Build Artifacts for OpenShift (ppc64le)

    When working with the OpenShift assisted or agent installer, you may find yourself needing to access the underlying Red Hat Enterprise Linux CoreOS (RHCOS) components. Specifically, if you are building custom layers or debugging boot issues on ppc64le architecture, you need a way to programmatically identify and download the exact kernel and rootfs associated with a specific OpenShift release.

    Some people have been hitting:

    Jun 01 1:01:08 my.host.com node-image-pull.sh[6612]: layers already present: 51; layers needed: 2 (164.1 MB)
    Jun 01 1:01:19 my.host.com node-image-pull.sh[6612]: error: Importing: Parsing layer blob sha256:xxxx: error: ostree-tar: Failed to handle file: ostree-tar: Failed to import file: Writing content object: min-free-space-percent '3%' would be exceeded, at least 45.4 MB requested: Processing tar: Failed to commit tar: ExitStatus(unix_wait_status(256))
    

    This happens due to the additional node image pulled down during initial boot, and added to the RAM file system as a second layer.

    Because RHCOS versions are tied to specific build IDs that aren’t always obvious from the version string alone, you have to “dig” into the image metadata.

    Here is the step-by-step process to extract these artifacts.

    Prerequisites

    • Podman installed on your workstation.
    • jq for parsing JSON output.
    • A valid Red Hat pull secret.

    Step 1: Identify the RHCOS Pull Spec

    First, we need to find the current stable image for the target architecture. We can do this by querying the OpenShift mirror and filtering for the rhel-coreos image while excluding extensions and older versions.

    # Fetch the pull spec for ppc64le on stable 4.21
    RHEL_COREOS_PULLSPEC=$(curl -s
    https://mirror.openshift.com/pub/openshift-v4/ppc64le/clients/ocp/stable-4.21/release.txt | grep
    rhel-coreos | grep -v coreos-10 | grep -v rhel-coreos-extensions | awk '{print $2}')
    
    echo $RHEL_COREOS_PULLSPEC
    

    Step 2: Pull the Image

    Once you have the pull spec, use podman to pull the image to your local machine. You will need to provide the path to your pull secret to authenticate with the registry.

    podman pull --authfile=/path/to/your/pull-secret ${RHEL_COREOS_PULLSPEC}
    

    Note the Image ID (SHA) returned after the pull; you’ll need this for the next step.

    Step 3: Extract the Machine-OS Build ID

    The critical piece of information—the DOWNLOAD_ID—is stored as a label within the container image itself. We can use podman inspect combined with jq to extract the io.openshift.build.versions label.

    # Replace <IMAGE_ID> with your actual image SHA
    IMAGE_ID="eeff15d6342fd..."
    MACHINE_OS=$(podman inspect $IMAGE_ID | jq -r '.[].Labels."io.openshift.build.versions"')
    
    # Parse the string (e.g., machine-os=9.6.20260608-0) to get only the ID
    DOWNLOAD_ID="${MACHINE_OS#*=}"
    
    echo "The Build ID is: $DOWNLOAD_ID"
    

    Step 4: Download the OS Artifacts

    Now that we have the DOWNLOAD_ID, we can construct the direct URLs to the RHCOS storage buckets. From here, you can download the live kernel, initramfs, and rootfs images needed for your installation process.

    # Define the base URL for ppc64le
    BASE_URL="https://rhcos.mirror.openshift.com/art/storage/prod/streams/rhel-9.6/builds/${DOWNLOAD_ID}/ppc64leBASE_URL="https://rhcos.mirror.openshift.com/art/storage/prod/streams/rhel-9.6/builds/${DOWNLOAD_ID}/ppc64le"
    
    # Download the artifacts
    curl -O ${BASE_URL}/rhcos-${DOWNLOAD_ID}-live-kernel.ppc64le
    curl -O ${BASE_URL}/rhcos-${DOWNLOAD_ID}-live-initramfs.ppc64le.img
    curl -O ${BASE_URL}/rhcos-${DOWNLOAD_ID}-live-rootfs.ppc64le.img
    

    Summary

    By pulling the RHCOS image and inspecting its labels, we can resolve the exact build ID required to fetch the raw boot artifacts. This is essential for anyone customizing the second layer of an assisted installer or performing low-level architecture validation on PowerPC systems.

  • A Guide to Setting up Internet Egress for PowerVS

    Need to give your private PowerVS instances internet access? Don’t reinvent the wheel. Follow this high-level workflow based on Samuel Matzek’s implementation guide.

    The Architecture: Private VM → Private Network → NAT VM (Dual NIC) → Public Network → Internet

    Implementation Checklist:

    • [ ] Network Setup: Ensure you have both a Public and a Private network created.
    • [ ] The Gateway: Deploy a Linux VM with two Network Interface Cards (NICs)—one connected to the public side, one to the private side.
    • [ ] OS Configuration:
      • Enable net.ipv4.ip_forward = 1 in /etc/sysctl.conf.
      • Configure iptables MASQUERADE rules to handle the traffic translation.
    • [ ] Routing Table: Update the PowerVS Private Network route table so that all 0.0.0.0/0 (default) traffic is pointed toward the NAT VM’s private IP address.

    Pro Tip: This setup is ideal for pulling updates (yum updateapt-get) and connecting to external APIs without needing a full-blown enterprise firewall deployment.

    Full technical details and command snippets can be found here: Simple Internet Egress for PowerVS Private Network.

  • Security Profiles Operator: v1.0.0 is out! 🛡️

    We are thrilled to announce the official v1.0.0 release of the Security Profiles Operator (SPO)! This is a major milestone, marking the transition of the operator from an evolving project to a stable, production-ready tool for managing security profiles in Kubernetes.

    1. Hardened by Design

    Security tools must be the most secure components in the cluster. To ensure this, v1.0.0 was preceded by a rigorous third-party security audit. We are proud to share that zero critical vulnerabilities were found, and all identified hardening areas have been fully addressed in this release. !

    1. Universal Hardware Support (Including ppc64le!)

    We believe security should be accessible regardless of your infrastructure. The Security Profiles Operator is built for diversity. Beyond the standard amd64 and arm64, we provide first-class support for linux/ppc64le. Whether you are running on standard cloud VMs, ARM-based Graviton instances, or IBM Power systems, SPO has you covered.

    1. Meet spoc: The CLI Managing profiles via YAML is great, but sometimes you need a dedicated tool. This release introduces spoc, the official Security Profiles Operator Command Line Interface, making it faster and easier to interact with your security profiles.

    To get started you can install the operator with a single command:

    kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/security-profiles-operator/v1.0.0/deploy/operator.yaml
    

    Security First We highly encourage users to verify the container image signature using cosign before deployment to ensure the integrity of your supply chain.

    Happy Hardening! 🥳👯

    Release page at https://github.com/kubernetes-sigs/security-profiles-operator/releases/tag/v1.0.0

  • Managing NVDIMM Devices with ndctl on OpenShift 4: A Complete Setup Guide

    Managing Non-Volatile Memory devices (like /dev/nmem0) using ndctl from within a container on an OpenShift 4 (RHCOS) cluster presents a unique challenge. Because ndctl interacts directly with the kernel’s NVDIMM Firmware Interface Table (NFIT) and requires raw ioctl access to the devices, standard container sandboxing will block it. Furthermore, Red Hat CoreOS (RHCOS) is an immutable operating system, meaning day-two hardware management requires specific architectural considerations.

    This guide breaks down the exact permissions, mounts, OpenShift constructs, and operational best practices required to configure and maintain this setup reliably.

    Bypassing the Sandbox

    To run a container that can access host hardware, you must configure high-level host privileges and explicit system mounts.

    1. OpenShift Security Context Constraints (SCC) OpenShift enforces strict security by default. The Pod’s ServiceAccount must be granted the privileged SCC. This automatically transitions the pod’s SELinux context to spc_t (Super Privileged Container), which is required to bypass SELinux restrictions when accessing raw host device nodes on RHCOS.

    # Grant the privileged SCC to your ServiceAccount
    oc adm policy add-scc-to-user privileged -z my-ndctl-sa -n my-namespace
    

    2. Pod Security Context Within your Pod deployment YAML, the container must explicitly request privileged execution. This grants the CAP_SYS_ADMIN capability (essential for ndctl hardware ioctls) and disables device cgroup filtering.

    securityContext:
      privileged: true
    

    3. Required Host Mounts The ndctl utility relies heavily on sysfs to discover the NVDIMM topology and /dev to issue commands. You must mount the host’s /dev and /sys directories into the container.

    • /dev: Required to access /dev/nmem0/dev/ndctl0, etc.
    • /sys: Required because ndctl scans /sys/class/nd/ and /sys/bus/nd/ to build the device tree.

    Part 2: Deployment Configuration

    Here is a complete example of how a CentOS 10 container pod would need to be configured to run ndctl successfully on your OpenShift cluster.

    apiVersion: v1
    kind: Pod
    metadata:
      name: ndctl-manager
      namespace: my-namespace
    spec:
      serviceAccountName: my-ndctl-sa
      containers:
      - name: centos10-ndctl
        image: quay.io/centos/centos10:latest
        command: ["/bin/sleep", "infinity"]
        securityContext:
          privileged: true
        volumeMounts:
        - name: host-dev
          mountPath: /dev
        - name: host-sys
          mountPath: /sys
      volumes:
      - name: host-dev
        hostPath:
          path: /dev
          type: Directory
      - name: host-sys
        hostPath:
          path: /sys
          type: Directory
    

    Once it starts, run dnf install -y ndctl in the container.

    Once deployed, you can execute into the container and run your ndctl commands. The OS mismatch between the RHCOS 9 host and the CentOS 10 container is fine, provided the kernel API/ABIs for NVDIMMs remain compatible. Ensure ndctl is installed in your custom image (dnf install ndctl). When running commands (e.g., ndctl create-namespace -f -e namespace0.0 -m fsdax), the utility will now have the necessary hardware visibility and CAP_SYS_ADMIN privileges.

    Operational Best Practices for RHCOS

    Keeping this setup working reliably as your cluster scales and upgrades requires adhering to OpenShift’s declarative nature.

    Managing Kernel Modules via MachineConfig The underlying RHCOS 9 host must have the correct NVDIMM kernel modules loaded to expose /dev/nmem0. OpenShift does not always load NVDIMM/PMEM modules by default. Do not rely on a manual modprobe inside your container, as it will not survive a node reboot. Instead, create a MachineConfig object to drop a configuration file into /etc/modules-load.d/ on the RHCOS nodes for modules like libnvdimmnd_pmem, and dax_pmem.

    The RHCOS Immutability Rule Hardware configurations saved to the physical NVDIMM’s label area via ndctl will survive a reboot. However, if your workflow requires changing host-level OS configurations—such as adding a udev rule for permissions or modifying /etc/fstab—do not do this directly from the container via the /host mount. Deploy host file changes via the Machine Config Operator (MCO) to prevent them from being overwritten during drift-reconciliation cycles.

    Deploying as a DaemonSet with Node Affinity Running a static Pod is a fragile way to manage hardware in a dynamic cluster. To handle node failures and scaling, use the Node Feature Discovery (NFD) Operator to automatically label nodes that physically contain NVDIMM hardware. Then, wrap your management container in a DaemonSet configured with a nodeSelector or nodeAffinity targeting those NFD labels.

    OpenShift Upgrades and ABI Compatibility You are running a CentOS 10 user-space against an RHCOS 9 kernel space. While Linux maintains strong backward compatibility for ioctl calls, there is a slight risk of divergence. During major OpenShift upgrades, test your container image in a non-production environment to verify that ndctl commands still successfully read the NFIT tables without ABI mismatch errors.

    Interaction with Storage Operators Configuring the memory is only step one. If your goal is to let Kubernetes workloads consume the NVDIMM as persistent storage, you will likely need the Local Storage Operator (LSO) or a CSI driver (like the PMEM-CSI driver) to discover the newly formatted device. Ensure your container provisions the namespaces in the exact mode (fsdaxdevdax, or sector) expected by your storage operator.