# Rackspace Spot from zero: a spot-priced Kubernetes cluster with a DevPod dev environment

> Onboard to Rackspace Spot's auction-priced Kubernetes, dodge the four traps every new cloudspace hits, and stand up a devcontainer-based dev environment with DevPod — for as little as $0.001/hr.

- Canonical: https://jedarden.com/guides/rackspace-spot-devpod/
- Published: 2026-07-08
- Last verified: 2026-07-08
- Tags: kubernetes, rackspace-spot, devpod, remote-development

---


Rackspace Spot sells surplus data-center capacity as managed Kubernetes clusters,
priced by open auction with a floor of **$0.001 per hour** — about $0.73 a month
for a node if you win at the floor, which in the less-contested regions you
usually do. That makes it the cheapest way I know of to run a real, persistent
Kubernetes cluster — and a remote dev environment on top of it.

This guide gets you from no account to a working [devcontainer](https://containers.dev/)
dev environment served by [DevPod](https://devpod.sh/), including the handful of
sharp edges that aren't in Rackspace's docs. Everything here comes from running
several Spot clusters in production for over a year; the pitfalls are ones I hit
for real.

## What you'll need

- `kubectl` installed locally
- A Docker Hub account (free) — you'll need a personal access token to dodge a
  rate-limit trap explained below
- Optionally, a repo with a `devcontainer.json` you want to develop in

## Part 1 — A working Spot cluster

### 1. Sign up and create a cloudspace

Create an account at [spot.rackspace.com](https://spot.rackspace.com), then
create a **cloudspace** — Rackspace's name for a managed Kubernetes cluster. The
control plane is free on the standard tier; you pay only for the nodes you bid on.

**Region choice matters more than anything else on your bill.** Auction prices
vary a lot between regions: the US regions around Ashburn (IAD) and Chicago (ORD)
have historically had classes sitting at or near the $0.001/hr floor for long
stretches, while others clear meaningfully higher. Check the
[live pricing table](/spot-pricing/) before you pick — it reads Rackspace's
public pricing feed and shows the current market price plus percentiles for every
server class in every region.

### 2. Add a spot node pool — and bid with the percentiles

Add a node pool to your cloudspace. Two decisions here:

- **Server class.** A general-purpose class (e.g. `gp.vs1.medium` in your chosen
  region — 4 vCPU / 8 GB) is plenty for a dev environment.
- **Bid price.** Your bid is the *maximum* you'll pay; you're charged the current
  market price as long as it's at or below your bid. When the market rises above
  your bid, your node is preempted. The [pricing table](/spot-pricing/) shows
  p20/p50/p80 percentiles for each class: bidding at the p80 level would have
  kept your node through roughly 80% of the recent window. Bidding exactly the
  current market price wins now and gets preempted at the next uptick.

Stick to spot pools. On-demand pools exist but cost many times more, which
defeats the reason to be here.

### 3. Download the kubeconfig — then immediately make a better one

The kubeconfig you download from the console authenticates with an OIDC token
that **expires after about three days**. It's fine for bootstrap work, but
anything unattended (CI, a dev-environment launcher, monitoring) will mysteriously
lose access mid-week.

Mint a long-lived ServiceAccount credential right away:

```bash
export KUBECONFIG=~/Downloads/your-cloudspace.yaml

kubectl create serviceaccount admin-sa -n kube-system
kubectl create clusterrolebinding admin-sa \
  --clusterrole=cluster-admin \
  --serviceaccount=kube-system:admin-sa
kubectl create token admin-sa -n kube-system --duration=8760h
```

Build a kubeconfig around that token (same cluster/server block, swap the `user`
for `token: <output>`), keep it somewhere safe, and use it for everything from
here on. Scope it down from `cluster-admin` later if you keep the cluster around.

### 4. Two first-boot fixes every new cloudspace needs

**Calico picks the wrong node IP.** Spot's Calico ships with `firstFound`
autodetection, which on these nodes grabs an unreachable interface — symptoms
range from flaky pod networking to nodes that never go Ready. Point it at the
node's real InternalIP:

```bash
kubectl patch installation default --type=merge \
  -p '{"spec":{"calicoNetwork":{"nodeAddressAutodetectionV4":{"kubernetes":"NodeInternalIP"}}}}'
```

**Anonymous Docker Hub pulls get throttled.** Spot nodes share NAT egress
addresses with other tenants, so Docker Hub's anonymous rate limit
(HTTP 429) is effectively always exhausted. This can break anything pulling from
`docker.io` — I've seen it take down CNI and CSI images after a node was
recreated, leaving the node NotReady. Create an authenticated pull secret in each
namespace you deploy to, using a Docker Hub personal access token:

```bash
kubectl create namespace devpod
kubectl create secret docker-registry docker-hub-registry -n devpod \
  --docker-username=<your-dockerhub-user> \
  --docker-password=<your-dockerhub-PAT>
```

Reference it from your pods' `imagePullSecrets` — or, for DevPod below, it gets
picked up automatically.

### 5. Storage: decide sizes up front

Spot's storage is OpenStack Cinder. Two rules:

- **Always set `storageClassName` explicitly** on every PVC. The default class
  varies by cluster, and on Spot the `sata` class (or `sata-large` for volumes
  over ~100 GB) is the one you want.
- **Volumes cannot be expanded.** The API returns a 403 on resize — a PVC's size
  is a lifetime decision. Size generously; at these prices a too-big volume
  costs cents.

## Part 2 — The dev environment, with DevPod

[DevPod](https://devpod.sh/) is a client-side, open-source tool that creates dev
environments from `devcontainer.json` on any backend — including a bare
Kubernetes cluster. Nothing to install in the cluster ahead of time: each
workspace is a pod plus a PVC, created on demand, and DevPod's *dockerless* mode
builds the devcontainer image **inside the cluster**, so you don't need Docker
locally or a registry.

### 6. Install the CLI

```bash
curl -L -o devpod "https://github.com/loft-sh/devpod/releases/latest/download/devpod-linux-amd64" \
  && sudo install -c -m 0755 devpod /usr/local/bin && rm -f devpod
```

(There's also a desktop app, and builds for macOS/Windows — see
[devpod.sh](https://devpod.sh/).)

### 7. Configure the Kubernetes provider once

This is where every Spot lesson from Part 1 gets encoded as a default:

```bash
devpod provider add kubernetes
devpod provider set-options kubernetes \
  -o KUBERNETES_CONFIG=$HOME/.kube/spot.kubeconfig \
  -o KUBERNETES_NAMESPACE=devpod \
  -o STORAGE_CLASS=sata \
  -o DISK_SIZE=30Gi \
  -o PVC_ACCESS_MODE=RWO \
  -o INACTIVITY_TIMEOUT=2h
```

Why each option matters here:

- `KUBERNETES_CONFIG` — the long-lived kubeconfig from step 3, not the 3-day one.
- `STORAGE_CLASS=sata` — otherwise DevPod uses the cluster default, which may not
  be the class you want (step 5).
- `DISK_SIZE=30Gi` — this PVC is your workspace's persistent home **and it can
  never be expanded**. Pick a size you won't outgrow.
- `INACTIVITY_TIMEOUT=2h` — auto-stops idle workspace pods. The PVC (your work)
  stays; the pod (the compute) goes away until the next `devpod up`.
- Pull secrets: the provider's `KUBERNETES_PULL_SECRETS_ENABLED` defaults to
  `true`, so the `docker-hub-registry` secret from step 4 protects workspace
  image pulls from the 429 trap automatically.

### 8. Launch

```bash
devpod up github.com/your-org/your-repo --provider kubernetes --ide vscode
```

DevPod creates the PVC and workspace pod, builds the devcontainer in-cluster,
and opens VS Code connected through a tunnel — no ingress, no load balancer, no
public exposure of the cluster. Prefer a terminal?

```bash
devpod up github.com/your-org/your-repo --provider kubernetes --ide none
devpod ssh your-repo
```

### 9. Living with preemption

This is spot capacity: when the market price rises above your bid, the node goes
away. What that actually means for a DevPod workspace:

- The **pod dies, the PVC survives** — your checked-out code, build caches, and
  home directory are all on the volume.
- `devpod up <workspace>` re-provisions onto whatever node your bid wins next,
  usually within a couple of minutes of capacity returning.
- Anything running unattended (long builds, servers) dies with the pod. Treat
  the workspace like a laptop that can run out of battery: commit and push often.
- Bidding at the p80 percentile (step 2) makes this rare — at the floor-priced
  classes, preemptions can be weeks apart.

## Caveats worth knowing

- **The 429 trap recurs.** Every time Spot recreates a node, that node pulls its
  system images through the shared NAT. If a fresh node sits NotReady, check for
  `ImagePullBackOff` on CNI/CSI pods before suspecting anything else.
- **Prices move.** The [pricing table](/spot-pricing/) is a snapshot of
  Rackspace's published feed with the fetch time shown — always confirm in the
  console before changing a bid.
- **DevPod's Kubernetes provider needs write access** to one namespace. The
  ServiceAccount options (`SERVICE_ACCOUNT`, `CLUSTER_ROLE`) let you tighten this
  once you're past the bootstrap stage.
- **Check your node pool type occasionally.** Only spot pools; if an on-demand
  pool ever appears (e.g. from console experimentation), delete it — it bills at
  a completely different rate.
