This is the multi-page printable view of this section. Click here to print.

Return to the regular view of this page.

Storage I/O Throttle

Limits read/write IOPS and bandwidth on PVC-backed volumes using Linux cgroup I/O controls

    This scenario throttles storage I/O on a PVC-backed volume used by a target pod. It limits read/write IOPS and bandwidth (bytes per second) using Linux cgroup controllers, allowing you to observe how your application behaves under degraded disk performance.

    • cgroups v2: writes to io.max
    • cgroups v1: writes to blkio.throttle.*_device

    The plugin automatically detects the cgroup version, container runtime (CRI-O or containerd), and the block device backing the volume. No manual host configuration is required.

    Why Storage Throttle Scenarios Are Important

    Many production incidents stem from slow or saturated storage, not complete outages. Storage I/O throttling lets you simulate realistic degraded-disk conditions and answer critical questions before they happen in production:

    • Database slowdowns: Will your database handle reduced disk throughput gracefully, or will queries time out and cascade into application-level failures?
    • Write-ahead log (WAL) backpressure: If writes to a WAL-backed volume slow down, does your system queue correctly or lose data?
    • Logging and monitoring pressure: When log volumes become slow, do your applications block on writes or degrade silently?
    • Storage class validation: Verify that your provisioned IOPS and throughput limits match application requirements under real workload conditions.
    • Pod eviction thresholds: Test whether Kubernetes eviction policies trigger correctly when I/O-bound pods consume disproportionate resources.

    How It Works

    The storage throttle scenario follows these steps:

    1. Resolve the target pod — If pvc_name is provided, the plugin looks up which pod has the PVC mounted. Otherwise, it uses the pod_name directly.
    2. Find the PVC volume mount — The plugin identifies the container and mount path for the PVC-backed volume inside the target pod. If mount_path is specified, only that specific mount is targeted.
    3. Discover the block device — The block device major:minor is extracted from /proc/self/mountinfo inside the target container, which is reliable for CSI-provisioned volumes.
    4. Deploy a privileged helper pod — A short-lived privileged pod is deployed on the same node as the target workload. It mounts the host root filesystem and uses chroot to access host cgroup files.
    5. Detect the cgroup version — The helper pod checks whether the node uses cgroups v1 or v2.
    6. Discover the cgroup path — The plugin finds the real host cgroup path for the target container by its container ID, excluding CRI-O conmon (container monitor) paths.
    7. Apply I/O throttle — IOPS and/or bandwidth limits are written to the appropriate cgroup files.
    8. Hold for duration — The throttle remains active for the configured duration, with progress logged every 30 seconds.
    9. Remove throttle — Limits are reset to their default (unlimited) values.
    10. Cleanup — The privileged helper pod is deleted.

    Configuration Parameters

    ParameterDescriptionTypeDefault
    pvc_nameTarget PVC name. If set, the pod is auto-resolved from the PVC.string""
    pod_nameTarget pod name. Ignored if pvc_name is set.string""
    namespaceNamespace of the target PVC or pod. Required.string""
    mount_pathSpecific mount path to throttle. If empty, the first PVC mount is used.string""
    throttle_typeType of throttle to apply: iops, bandwidth, or both.stringbandwidth
    read_iopsMaximum read IOPS. Used when throttle_type is iops or both.integer100
    write_iopsMaximum write IOPS. Used when throttle_type is iops or both.integer50
    read_bpsMaximum read bytes per second. Used when throttle_type is bandwidth or both. Supports unit suffixes.string/integer1Mi (1,048,576)
    write_bpsMaximum write bytes per second. Used when throttle_type is bandwidth or both. Supports unit suffixes.string/integer512Ki (524,288)
    durationHow long to hold the throttle. Supports duration suffixes.string/integer60 (seconds)
    imageContainer image for the privileged helper pod.stringquay.io/krkn-chaos/krkn:tools

    Parameter Dependencies

    • pvc_name vs pod_name: At least one is required. If both are set, pvc_name takes precedence and the pod is auto-resolved from the PVC.
    • throttle_type controls which limits apply:
      • iops — only read_iops and write_iops are applied
      • bandwidth — only read_bps and write_bps are applied
      • both — all four limits are applied simultaneously

    Supported Unit Suffixes

    Byte values (read_bps, write_bps) accept Kubernetes-style unit suffixes:

    SuffixTypeMultiplierExample
    KiBinary (kibibyte)1,024512Ki = 524,288 bytes/s
    MiBinary (mebibyte)1,048,5761Mi = 1,048,576 bytes/s
    GiBinary (gibibyte)1,073,741,8241Gi = 1,073,741,824 bytes/s
    KDecimal (kilobyte)1,000500K = 500,000 bytes/s
    MDecimal (megabyte)1,000,0005M = 5,000,000 bytes/s
    GDecimal (gigabyte)1,000,000,0001G = 1,000,000,000 bytes/s
    (none)Raw bytes11048576 = 1,048,576 bytes/s

    Duration values (duration) accept time suffixes:

    SuffixUnitExample
    sSeconds30s = 30 seconds
    mMinutes2m = 120 seconds
    hHours1h = 3,600 seconds
    (none)Seconds120 = 120 seconds

    Prerequisites

    • The target PVC must be in Bound state and mounted to a running pod.
    • The privileged helper image (quay.io/krkn-chaos/krkn:tools by default) must be pullable on worker nodes.
    • The cluster must allow privileged pods (required for writing to host cgroup files).
    • Supported container runtimes: CRI-O and containerd.
    • Supported cgroup versions: v1 and v2.

    How to Run Storage I/O Throttle Scenarios

    Choose your preferred method to run storage I/O throttle scenarios:

    Example scenario files:

    Sample scenario config
    storage_throttle_scenario:
      pvc_name: ""                    # Target PVC name. If set, pod_name is auto-resolved from PVC.
      pod_name: my-app-pod            # Target pod name. Ignored if pvc_name is set.
      namespace: default              # Namespace of the target PVC/pod (required)
      mount_path: ""                  # Specific mount path to throttle. If empty, first PVC mount is used.
      throttle_type: bandwidth        # "iops", "bandwidth", or "both"
      read_iops: 100                  # Max read IOPS (used when throttle_type is "iops" or "both")
      write_iops: 50                  # Max write IOPS (used when throttle_type is "iops" or "both")
      read_bps: 1Mi                   # Max read bytes/sec (used when throttle_type is "bandwidth" or "both")
      write_bps: 512Ki                # Max write bytes/sec (used when throttle_type is "bandwidth" or "both")
      duration: 1m                    # How long to hold the throttle (supports suffixes: 30s, 2m, 1h)
      # image: quay.io/krkn-chaos/krkn:tools  # (optional) override helper pod image
    
    Throttle type examples

    Bandwidth only (default) — cap read/write throughput:

    storage_throttle_scenario:
      pvc_name: my-data-pvc
      namespace: production
      throttle_type: bandwidth
      read_bps: 1Mi                   # 1 MiB/s read limit
      write_bps: 512Ki                # 512 KiB/s write limit
      duration: 2m
    

    IOPS only — cap read/write operations per second:

    storage_throttle_scenario:
      pod_name: postgres-0
      namespace: database
      throttle_type: iops
      read_iops: 50
      write_iops: 25
      duration: 90s
    

    Both — apply IOPS and bandwidth limits simultaneously:

    storage_throttle_scenario:
      pvc_name: wal-pvc
      namespace: database
      throttle_type: both
      read_iops: 100
      write_iops: 50
      read_bps: 5Mi
      write_bps: 2Mi
      duration: 3m
    

    How to Use Plugin Name

    Add the plugin name to the chaos_scenarios section in config/config.yaml:

    kraken:
        kubeconfig_path: ~/.kube/config
        ..
        chaos_scenarios:
            - storage_throttle_scenarios:
                - scenarios/kube/storage_throttle.yaml
    

    Run

    python run_kraken.py --config config/config.yaml
    

    Storage Throttle scenario

    This scenario applies storage I/O limits (IOPS and/or bandwidth) on a PVC-backed workload by using Linux cgroup controls through a privileged helper pod on the target node.

    Run

    If enabling Cerberus to monitor the cluster and pass/fail the scenario post chaos, refer docs. Make sure to start it before injecting the chaos and set CERBERUS_ENABLED environment variable for the chaos injection container to autoconnect.

    $ podman run --name=<container_name> \
      --net=host \
      --pull=always \
      --env-host=true \
      -v <path-to-kube-config>:/home/krkn/.kube/config:Z \
      -e PVC_NAME=<target_pvc_name> \
      -e NAMESPACE=<target_namespace> \
      -e THROTTLE_TYPE=bandwidth \
      -e READ_BPS=1Mi \
      -e WRITE_BPS=512Ki \
      -e DURATION=1m \
      -d containers.krkn-chaos.dev/krkn-chaos/krkn-hub:storage-throttle
    
    $ podman logs -f <container_name or container_id>
    
    $ podman inspect <container-name or container-id> \
      --format "{{.State.ExitCode}}"
    
    $ docker run $(./get_docker_params.sh) \
      --name=<container_name> \
      --net=host \
      --pull=always \
      -v <path-to-kube-config>:/home/krkn/.kube/config:Z \
      -e PVC_NAME=<target_pvc_name> \
      -e NAMESPACE=<target_namespace> \
      -e THROTTLE_TYPE=bandwidth \
      -e READ_BPS=1Mi \
      -e WRITE_BPS=512Ki \
      -e DURATION=1m \
      -d containers.krkn-chaos.dev/krkn-chaos/krkn-hub:storage-throttle
    
    $ docker logs -f <container_name or container_id>
    
    $ docker inspect <container-name or container-id> \
      --format "{{.State.ExitCode}}"
    

    TIP: Because the container runs with a non-root user, ensure the kube config is globally readable before mounting it in the container. You can achieve this with the following commands:

    kubectl config view --flatten > ~/kubeconfig && \
    chmod 444 ~/kubeconfig && \
    docker run $(./get_docker_params.sh) \
      --name=<container_name> \
      --net=host \
      --pull=always \
      -v ~/kubeconfig:/home/krkn/.kube/config:Z \
      -d containers.krkn-chaos.dev/krkn-chaos/krkn-hub:storage-throttle
    

    Supported parameters

    The following environment variables can be set on the host running the container to tweak the scenario/faults being injected:

    Example if –env-host is used:

    export <parameter_name>=<value>
    

    OR on the command line like example:

    -e <VARIABLE>=<value>
    

    See list of variables that apply to all scenarios here that can be used/set in addition to these scenario specific variables

    ParameterDescriptionTypeDefault
    PVC_NAMETarget PVC name. If set, POD_NAME is auto-resolved from PVCstring
    POD_NAMETarget pod name. Ignored if PVC_NAME is setstring
    NAMESPACENamespace of the target pod/PVCstringdefault
    MOUNT_PATHSpecific mount path to throttle (absolute path, example: /data)string
    THROTTLE_TYPEThrottle mode to apply (bandwidth, iops, both)stringbandwidth
    READ_IOPSMaximum read IOPS (used for iops/both)number100
    WRITE_IOPSMaximum write IOPS (used for iops/both)number50
    READ_BPSMaximum read bytes/sec (example: 1Mi, 512Ki, 1000000)string1Mi
    WRITE_BPSMaximum write bytes/sec (example: 512Ki, 1Mi, 500000)string512Ki
    DURATIONDuration to hold throttling (example: 30s, 1m, 120)string1m
    IMAGEImage used for privileged helper pod that writes cgroup valuesstringquay.io/krkn-chaos/krkn:tools

    Parameter dependencies

    • At least one of PVC_NAME or POD_NAME should be set.
    • If both are set, PVC_NAME takes precedence and POD_NAME is ignored.

    NOTE In case of using custom metrics profile or alerts profile when CAPTURE_METRICS or ENABLE_ALERTS is enabled, mount the metrics profile from the host on which the container is run using podman/docker under /home/krkn/kraken/config/metrics-aggregated.yaml and /home/krkn/kraken/config/alerts. For example:

    $ podman run \
      --name=<container_name> \
      --net=host \
      --pull=always \
      --env-host=true \
      -v <path-to-custom-metrics-profile>:/home/krkn/kraken/config/metrics-aggregated.yaml \
      -v <path-to-custom-alerts-profile>:/home/krkn/kraken/config/alerts \
      -v <path-to-kube-config>:/home/krkn/.kube/config:Z \
      -d containers.krkn-chaos.dev/krkn-chaos/krkn-hub:storage-throttle
    
    krknctl run storage-throttle [--<parameter> <value>]
    

    Can also set any global variable listed here

    Scenario specific parameters:

    ParameterDescriptionTypeRequiredDefault
    --pvc-nameTarget PVC name. If set, --pod-name is auto-resolved from PVCstringNo
    --pod-nameTarget pod name. Ignored if --pvc-name is setstringNo
    --namespaceNamespace of the target pod/PVCstringYesdefault
    --mount-pathSpecific mount path to throttle (absolute path, example: /data)stringNo
    --throttle-typeThrottle mode to apply (bandwidth, iops, both)enumNobandwidth
    --read-iopsMaximum read IOPS (used for iops/both)numberNo100
    --write-iopsMaximum write IOPS (used for iops/both)numberNo50
    --read-bpsMaximum read bytes/sec (example: 1Mi, 512Ki, 1000000)stringNo1Mi
    --write-bpsMaximum write bytes/sec (example: 512Ki, 1Mi, 500000)stringNo512Ki
    --durationDuration to hold throttling (example: 30s, 1m, 120)stringNo1m
    --imageImage used for privileged helper pod that writes cgroup valuesstringNoquay.io/krkn-chaos/krkn:tools

    Parameter dependencies

    • At least one of --pvc-name or --pod-name should be set.
    • If both are set, --pvc-name takes precedence and --pod-name is ignored.

    To see all available scenario options

    krknctl run storage-throttle --help