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

# Connect to a managed Kubernetes cluster

> Launch a managed Kubernetes cluster on your reserved Ornn GPUs, download the namespace-scoped kubeconfig, and run your first GPU workload.

A managed Kubernetes cluster turns the GPU nodes you already reserved into a Kubernetes cluster you reach with a namespace-scoped kubeconfig. Ornn runs the control plane; you get full control inside your own namespace. You launch the cluster from the console, download a kubeconfig, and connect with `kubectl`.

## When to use Kubernetes

* You run containerized training or inference and want orchestration, not a single host.
* You want to schedule multiple GPU jobs across your reserved nodes.
* You already have Kubernetes manifests, Helm charts, or operators to deploy.

<Note>
  For a single machine you SSH into, [VM access](/guides/vm-access) or [Bare Metal access](/guides/bare-metal-access) is simpler. Choose Kubernetes when you want a cluster.
</Note>

## Prerequisites

* The bid is promoted to a confirmed reservation that is visible in your portfolio.
* **Checkout and payment** for the reservation are complete.
* You have `kubectl` installed locally.

## Launch the cluster

<Steps>
  <Step title="Open Clusters">
    From the console, go to **Clusters** (`/clusters`) and start a new cluster, or open your reservation in [Portfolio](/guides/portfolio-overview) and choose the **Kubernetes** access mode.
  </Step>

  <Step title="Choose Kubernetes and a network mode">
    Pick **Kubernetes**, then a network mode:

    * **Public** — the API is reachable over the internet.
    * **Private** — the API is reachable only over your reservation's WireGuard VPN (nothing is exposed publicly).
  </Step>

  <Step title="Launch">
    Launch the cluster. The first launch after an enrollment takes a few extra minutes while the GPU images download. The manage page shows live progress and, once the cluster is active, a **Download kubeconfig** action plus a **Need help connecting?** link to this guide.
  </Step>
</Steps>

## Connect with kubeconfig

<Steps>
  <Step title="Download the kubeconfig">
    On the cluster panel, click **Download kubeconfig**. It contains a short-lived, namespace-scoped token and the API endpoint.
  </Step>

  <Step title="Point kubectl at it">
    ```bash theme={null}
    export KUBECONFIG="$HOME/Downloads/ornn-<reservation-id>-kubeconfig.yaml"
    ```
  </Step>

  <Step title="Confirm the connection">
    Your access is scoped to your namespace, so namespace commands work:

    ```bash theme={null}
    kubectl get ns tenant-<id>
    kubectl get pods
    ```
  </Step>
</Steps>

<Note>
  Cluster-wide commands like `kubectl get nodes` and `kubectl cluster-info` return `Forbidden`. That is the security boundary working as intended — your token is scoped to your namespace — not a connection failure.
</Note>

## Run a GPU smoke test

Your GPU node is dedicated to your reservation, so every pod must select it (`nodeSelector`), tolerate its reservation taint, and request `nvidia.com/gpu`. This pod runs `nvidia-smi` and cleans up after itself:

```bash theme={null}
kubectl apply -f - <<'EOF'
apiVersion: v1
kind: Pod
metadata:
  name: ornn-smoke
  namespace: tenant-<id>
spec:
  restartPolicy: Never
  nodeSelector:
    ornn.ai/reservation: "<reservation-id>"
  tolerations:
    - key: ornn.ai/reservation
      operator: Equal
      value: "<reservation-id>"
      effect: NoSchedule
  containers:
    - name: smoke
      image: nvidia/cuda:12.4.1-base-ubuntu22.04
      command: ["nvidia-smi"]
      resources:
        limits:
          nvidia.com/gpu: 1
EOF

kubectl wait --for=jsonpath='{.status.phase}'=Succeeded pod/ornn-smoke --timeout=300s || true
kubectl logs ornn-smoke || true
kubectl delete pod ornn-smoke --ignore-not-found
```

You should see your allocated GPU in the `nvidia-smi` table. Apply the same `nodeSelector`, `tolerations`, and `nvidia.com/gpu` request to your real workloads.

## Private clusters: bring up WireGuard first

Private clusters expose nothing publicly — the API is reachable only over your reservation's WireGuard tunnel. Set it up once:

```bash theme={null}
# 1. Generate a WireGuard keypair locally.
wg genkey | tee privatekey | wg pubkey

# 2. Paste the printed PUBLIC key into the cluster panel's Connect section and
#    generate a config.
# 3. Save the returned config (fill in your private key) and bring the tunnel up.
sudo wg-quick up ./ornn-wg.conf
```

Once the tunnel is up, the downloaded kubeconfig reaches the API and the steps above are unchanged.

## Tear down

Tearing down drains all workers, revokes the kubeconfig, and returns the GPU nodes to your reservation. A torn-down or failed cluster relaunches in place.

<Warning>
  Teardown interrupts running workloads and can't be undone. Persist checkpoints and data to your own object storage first.
</Warning>

## Troubleshooting

<AccordionGroup>
  <Accordion title="`kubectl get nodes` is Forbidden">
    Expected. Your token is namespace-scoped, so cluster-wide reads (`get nodes`, `cluster-info`, other namespaces) are denied by design. Use namespace-scoped commands like `kubectl get pods`.
  </Accordion>

  <Accordion title="Commands return Unauthorized">
    The kubeconfig token is short-lived. Download a fresh kubeconfig from the cluster panel and re-export `KUBECONFIG`.
  </Accordion>

  <Accordion title="My pod is stuck Pending">
    The node is dedicated to your reservation. Confirm the pod has the `nodeSelector`, the matching `ornn.ai/reservation` toleration, and a `nvidia.com/gpu` request, as shown in the smoke test.
  </Accordion>

  <Accordion title="A private cluster won't connect">
    Make sure the WireGuard tunnel is up (`sudo wg show`) before using the kubeconfig. Re-generate the peer config from the Connect section if your public key changed.
  </Accordion>
</AccordionGroup>

## What's next

<CardGroup cols={2}>
  <Card title="Slurm access" img="https://mintcdn.com/ornn/fNQRwmmR9H-yzza5/images/banners/access.jpg?fit=max&auto=format&n=fNQRwmmR9H-yzza5&q=85&s=d7f78f5776720abf9eadfbb2519503c6" href="/guides/slurm-access" width="1200" height="800" data-path="images/banners/access.jpg">
    Prefer batch scheduling? Run a managed Slurm cluster on your reserved GPUs instead.
  </Card>

  <Card title="Access overview" img="https://mintcdn.com/ornn/fNQRwmmR9H-yzza5/images/banners/access.jpg?fit=max&auto=format&n=fNQRwmmR9H-yzza5&q=85&s=d7f78f5776720abf9eadfbb2519503c6" href="/guides/access-overview" width="1200" height="800" data-path="images/banners/access.jpg">
    Compare the ways to access your reserved Ornn compute.
  </Card>
</CardGroup>
