> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mixpeek.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Qualification

> What Mixpeek checks on your cluster before deploying anything, and how to read the report

Qualification runs before any Mixpeek workload is deployed. It answers one
question: can Mixpeek be attached to this cluster safely, and if not, which part
is the problem.

You get the report. It is plain text, one line per check.

## Two reports, at two different times

There are two suites, and the difference is when they can run.

|                             | Substrate qualification                                                       | Ray qualification                                                        |
| --------------------------- | ----------------------------------------------------------------------------- | ------------------------------------------------------------------------ |
| **Asks**                    | Can the Mixpeek plane be installed here, and what does it cost in permissions | Does Mixpeek behave correctly here, and did it disturb anything of yours |
| **Runs**                    | Before anything of ours exists                                                | After the plane is installed                                             |
| **Needs**                   | A kubeconfig                                                                  | A running Ray cluster                                                    |
| **You can run it yourself** | Yes, read-only                                                                | Not until we are installed                                               |

Start with the substrate report. Everything it asks has an answer that should
stop an install rather than be discovered halfway through one.

### Substrate checks

| Check                | What it establishes                                                                                                                                                                              |
| -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `k8s-reachable`      | The API server answers, and which cluster this is                                                                                                                                                |
| `k8s-version`        | Whether your version is one we test against. Below it is untested rather than known-broken, so this warns rather than fails                                                                      |
| `kuberay`            | Whether KubeRay is present and at least 1.1. Absent is fine and expected before an install                                                                                                       |
| `storage-class`      | A class exists that can provision volumes, with its binding mode, expansion and reclaim policy written out                                                                                       |
| `pvc-durability`     | **Data written by one pod is readable by another after the first is gone.** This is what MVS needs from your storage and it is the row worth reading first                                       |
| `storage-throughput` | Sequential write and read throughput on that class. Informational unless you give us a floor, because it measures burst on a fresh volume, once, sequentially, and MVS serves small random reads |
| `crd-install-grant`  | Who holds the cluster-scoped grant that installing KubeRay needs. Never fails; both answers are supported                                                                                        |
| `namespace-grant`    | The identity can create what the install creates, so a missing grant is named now rather than partway through                                                                                    |
| `workload-identity`  | Whether a ServiceAccount here is bound to a cloud identity, so we reach your object storage as ourselves rather than with static keys you hand us                                                |
| `pod-security`       | Whether PodSecurity admission on the namespace will reject our pods, and what to tell us so it does not                                                                                          |
| `node-capacity`      | Enough **untainted** allocatable capacity for what we asked for. Tainted and cordoned nodes are excluded and listed                                                                              |
| `gpu-nodes`          | Whether any node advertises a GPU                                                                                                                                                                |
| `namespace-census`   | What your cluster held before we touched it, for comparison afterwards                                                                                                                           |

<Note>
  `pvc-durability` and `storage-throughput` are the only rows that write anything.
  Between them they create two small PersistentVolumeClaims and three short-lived
  pods, and delete all of it. Both are opt-in behind `--allow-provision`; everything
  else in the substrate report is read-only.

  It is worth understanding why it goes to that trouble. A pod that writes to its
  mount and reads the value back passes on an `emptyDir`, which persists nothing.
  So the row writes a marker unique to that run, deletes the pod, and requires a
  second pod on the same claim to read that exact marker back. A volume returning
  some other marker fails as loudly as an empty one: a claim quietly carrying
  another workload's data is the worse finding of the two.
</Note>

## What the Ray suite checks

Twenty checks in five groups. Every one is a claim about *your* cluster, not
about Mixpeek.

### Cluster

| Check           | What it establishes                                                |
| --------------- | ------------------------------------------------------------------ |
| `ray-reachable` | The Ray dashboard answers, and reports its version and node count  |
| `fingerprint`   | The cluster the suite is talking to is the cluster you think it is |
| `kuberay`       | The KubeRay CRDs are served, at a version whose fields we emit     |

### Security

| Check               | What it establishes                                                                                                            |
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------ |
| `rbac-minimal-sa`   | The submitter ServiceAccount can do what it needs and **cannot** do what it must not. Five required verbs, five forbidden ones |
| `rayjob-cr-secrets` | Whether credentials are readable from RayJob specs in your namespace                                                           |
| `dashboard-secrets` | Whether credential-shaped values are exposed through the Ray dashboard                                                         |
| `network-policy`    | Whether any NetworkPolicy governs the namespace, so a deliberate choice and an oversight stop looking identical                |
| `canary-secret`     | A planted value is not readable where it should not be                                                                         |

### Connectivity

Every one of these asks *can the cluster reach it*, not *can this laptop reach
it*. They run as jobs inside your cluster and report from there, because those
differ in exactly the cases that matter: a private endpoint, a workload identity,
an egress policy.

| Check              | What it establishes                                                                                        |
| ------------------ | ---------------------------------------------------------------------------------------------------------- |
| `registry-pull`    | Your **nodes** can pull the Mixpeek engine image                                                           |
| `object-storage`   | The cluster can reach your object storage, and whether it did so with its own identity or with static keys |
| `control-plane`    | The cluster can reach the endpoints the engine needs                                                       |
| `api-health`       | The Mixpeek API is reachable                                                                               |
| `engine-on-target` | The engine you reached is running on the cluster under test, not a different one                           |

### Workloads

| Check              | What it establishes                                                                                                                                                                                                           |
| ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `scheduling`       | Your node pool, taint and quota bind. A pod with the right toleration lands; the same pod without it is refused and the reason names the taint; an impossible selector is refused; an oversized pod is rejected by your quota |
| `autoscaling`      | Worker count rises under load and falls after, never past your `maxReplicas`                                                                                                                                                  |
| `failure-recovery` | Different infrastructure faults produce **different, named** diagnoses through the API                                                                                                                                        |
| `serve-lifecycle`  | One named Serve application can be deployed, scaled and removed without moving yours                                                                                                                                          |
| `golden-e2e`       | A real document flows through ingestion to retrieval                                                                                                                                                                          |

### Isolation

| Check                      | What it establishes                                                                                              |
| -------------------------- | ---------------------------------------------------------------------------------------------------------------- |
| `non-interference`         | Every foreign application, job and actor is unchanged after Mixpeek runs                                         |
| `cleanup`                  | No Mixpeek residue after uninstall                                                                               |
| `serve-full-config-hazard` | A destructive positive control, opt-in and throwaway-only, that proves the hazard the deploy path avoids is real |

## Fault handling, and where the boundary of the suite sits

The suite reports on your cluster. Some platform behaviour is a property of the
software and holds on any cluster, so it is stated here rather than measured per
install.

| Behaviour                                                                                                                    | Where it is established                                                                     |
| ---------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- |
| Different infrastructure faults produce different, named diagnoses through the API                                           | `failure-recovery`, on your cluster                                                         |
| A batch orphaned by node death, preemption or SIGTERM is resubmitted automatically, bounded; one orphaned by a deploy is not | Platform behaviour, identical on every install                                              |
| Removing and recreating the `RayCluster` costs a cold start and the work in flight, and nothing durable                      | Platform behaviour; `upgradeStrategy: NewCluster` makes recreation the routine upgrade path |
| A Serve application of ours can be deployed, scaled and removed without moving yours                                         | `serve-lifecycle`, on your cluster                                                          |

The distinction matters when you read a report. A row that passed is a statement
about your cluster. A behaviour in the second group is a statement about Mixpeek,
and a green report does not re-derive it.

## Reading a verdict

```
RESULT: QUALIFIED       every required check passed
RESULT: NOT QUALIFIED   a required check failed. The row names which
RESULT: INCOMPLETE      nothing failed, but not everything ran
RESULT: UNREACHABLE     the cluster did not answer at all
```

`INCOMPLETE` is the one worth understanding. It means no check contradicted
anything and some checks could not run: a missing credential, a permission the
running identity lacks, or a check that could not run. The row names which. It is
not a pass, and it is
not a failure. Treating it as either is the mistake the verdict exists to
prevent.

## Rows that skip, and why that is deliberate

A skipped row states what it could not do:

```
scheduling  SKIP | this identity cannot create pods, so scheduling policy
                   cannot be measured from here. That is the submitter Role
                   working as intended (it grants rayjobs.ray.io and nothing
                   on pods); run this row as an identity that can create pods.
```

This matters more than it looks. The alternative is a check that reports a
failure of *your* cluster when the truth is that our probe lacked a permission,
and a report that blames the customer for the auditor's access is worse than no
report.

The same discipline applies to absence. `network-policy` will tell you it could
not read your NetworkPolicies rather than telling you there are none. `kuberay`
distinguishes "not installed" from "could not read whether it is installed", and
only the first is a statement about your cluster.

## Running it yourself

The substrate suite is the one you can run before granting us anything. It needs
a kubeconfig, `kubectl`, and the `python3` already on your machine. No Ray, no
Mixpeek, no dependencies to install.

```bash theme={null}
# read-only
python3 substrate_e2e.py --namespace mixpeek

# with the storage probe, which creates one 1Gi PVC and two pods and deletes them
python3 substrate_e2e.py --namespace mixpeek --allow-provision \
  --require-cpu 8 --require-memory 32Gi
```

`--require-cpu` and `--require-memory` are the capacity the install needs; ask us
for the numbers for your configuration. Without them the capacity row skips
rather than guessing, because a check that capacity exceeds the capacity it just
observed cannot fail.

The one-liner that checks the most important RBAC claim needs nothing at all:

```bash theme={null}
kubectl auth can-i --list \
  --as=system:serviceaccount:mixpeek:mixpeek-submitter -n mixpeek
```

Both suites live in the Mixpeek repository. Ask us to run them against your
cluster and send you the reports, or ask for the suites and run them yourself.

<Note>
  The compatibility matrix of Ray, KubeRay and Kubernetes versions we publish as
  supported is generated from CI results rather than written by hand. See
  [Compatibility](/docs/customer-hosted/compatibility).
</Note>
