# vpctl cluster command

> Validate that your Kubernetes cluster meets the deployment prerequisites before you deploy.

Use the `cluster` command group to validate your Kubernetes cluster before you deploy.

## Check the cluster prerequisites

The `cluster check` command validates your manifest, and then verifies that the cluster your current kubeconfig context points at meets the deployment prerequisites.

```sh
vpctl cluster check
```

The command requires a manifest, because it reads the target namespace, the storage class names, and the deployment method from it. It doesn't require a pulled release, so you can run it before you download the release package. For more information, refer to [Global flags](./_index.md#global-flags).

The command is read-only by default: it runs only `kubectl get` commands.

### Cluster check reference

The following table lists each check the command runs and the condition it verifies.

| Check                        | What it verifies                                                                                                               |
| ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------ |
| `kubectl available`          | The `kubectl` binary is on your `PATH`.                                                                                        |
| `cluster reachable`          | The current kubeconfig context can reach the Kubernetes API.                                                                   |
| `kubernetes version`         | The cluster runs Kubernetes 1.33 or later.                                                                                     |
| `general worker nodes`       | At least three nodes you can schedule, or one node if the manifest sets `configuration.infrastructure.singleNode: true`.       |
| `transformations pool`       | A node pool labeled `aks-node-pool=argocpu` exists.                                                                            |
| `large transformations pool` | A node pool labeled `aks-node-pool=argocpu-large` exists and carries the `aks-node-pool=argocpu-large:NoSchedule` taint.       |
| `default storage class`      | The default storage class your manifest names exists, or the cluster has a class marked as default.                            |
| `rwx storage class`          | The `ReadWriteMany` storage class your manifest names exists.                                                                  |
| `namespace`                  | The target namespace already exists. The deployment doesn't create it.                                                         |
| `metrics api`                | The `metrics.k8s.io` API is registered and available. Horizontal pod autoscaling requires it.                                  |
| `argocd application crd`     | The ArgoCD `Application` custom resource definition (CRD) is installed. This check runs only for the ArgoCD deployment format. |
| `argocd controller`          | An ArgoCD application controller pod is running and ready. This check runs only for the ArgoCD deployment format.              |
| `node ipv6 addresses`        | The nodes report IPv6 addresses. This check runs only if the manifest sets `configuration.networking.ipFamily: ipv6`.          |

If a node pool has no running node, the command looks for a matching Karpenter `NodePool` instead. Clusters that scale transformation capacity from zero therefore pass the node pool checks even when no node is running. If Karpenter isn't installed, or your credentials can't read its resources, the command ignores the lookup, because Karpenter is optional.

### Read the results

Each check reports one of these statuses:

| Symbol | Status  | Effect on the exit code                  |
| ------ | ------- | ---------------------------------------- |
| `✔`    | Pass    | None.                                    |
| `⚠`    | Warning | None.                                    |
| `✘`    | Failure | The command exits with a nonzero status. |
| `-`    | Skipped | None.                                    |

Failed and warning checks also print a remediation hint. Because the command exits with a nonzero status when any check fails, you can use it to gate a CI pipeline before the deployment steps.

The output looks like the following example:

```text
Context: my-cluster (https://kubernetes.example.com)
Manifest: platform onprem, namespace asset-solutions

✔ kubectl available              client v1.34.1
✔ cluster reachable              server v1.34.1
✔ kubernetes version             1.34 ≥ 1.33 required
✔ general worker nodes           3 schedulable node(s) (need ≥ 3): node-1, node-2, node-3
✔ transformations pool           2 node(s) labeled aks-node-pool=argocpu: node-4, node-5
✔ large transformations pool     no node at rest; provisioned on demand by Karpenter NodePool transformations-large (taint declared)
✔ default storage class          gp3 exists (named in manifest)
✔ rwx storage class              efs-sc exists (RWX capability verified only with --probe-storage)
✔ namespace                      asset-solutions exists
✔ metrics api                    v1beta1.metrics.k8s.io available
✔ argocd application crd         applications.argoproj.io installed
✔ argocd controller              pod/argocd-application-controller-0 is Ready
- node ipv6 addresses            manifest ipFamily is ipv4 (default)

Summary: 12 passed, 0 warning, 0 failed, 1 skipped
```

## Parameters for cluster check

The `cluster check` command accepts the following parameters:

| Parameter         | Description                                                                                                                                    | Default                                                                         |
| ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- |
| `--probe-storage` | Provisions and deletes a temporary 1-GiB test volume for each configured storage class to verify that provisioning works. Mutates the cluster. | `false`                                                                         |
| `--probe-timeout` | Time to wait for a probe volume to bind.                                                                                                       | `60s`                                                                           |
| `--dry-run`       | Prints the command plan without executing anything.                                                                                            | `false`                                                                         |
| `--format`        | Deployment format to validate for: `argocd` or `helm`.                                                                                         | `argocd` if the manifest contains a `deployment.argocd` block, otherwise `helm` |

## Verify that storage provisioning works

> **Important:**
>
> `--probe-storage` creates and deletes resources in your cluster. Every other `cluster check` option is read-only.

Add `--probe-storage` to verify that each configured storage class can provision a volume, including `ReadWriteMany` support:

```sh
vpctl cluster check --probe-storage
```

This is the only option that changes anything in your cluster. For each configured storage class, the command creates a temporary 1-GiB `PersistentVolumeClaim` labeled `vpctl.unity.com/cluster-check=true` in the target namespace, waits for it to bind, and then deletes it. If a probe fails to bind, the command reads the events in that namespace to report why.

The command skips, rather than probes, storage classes that use `volumeBindingMode: WaitForFirstConsumer`, because binding such a class requires a scheduled pod. Skipped checks don't affect the exit code.

## Preview the commands without contacting the cluster

Add `--dry-run` to print every `kubectl` command that the checks will run. The command executes nothing and doesn't contact the cluster, so you can use `--dry-run` for a security review:

```sh
vpctl cluster check --dry-run
```

## Select the deployment format

By default, the command runs the ArgoCD checks if your manifest contains a `deployment.argocd` block, and the Helm checks otherwise. To override that inference, pass `--format`:

```sh
vpctl cluster check --format argocd
```

## Additional resources

* [Global flags](./_index.md#global-flags)
* [vpctl manifest commands](manifest)
* [Manifest reference](./manifest.md)
