Sometimes you just want one specific node gone.

⚠️ Anti-Pattern Alert!

Yeah, yeah — “cattle, not pets”. In theory you shouldn’t care. In reality, especially in enterprise setups, sometimes you do.

Here’s how to do it properly in a Cluster API (CAPI) cluster without it coming back.


The catch

CAPI is declarative.

If your cluster says:

“I want N nodes”

…it will keep N nodes.

So if you just do:

1
kubectl delete node <node>

It’ll come back.


The rule (don’t skip this)

1
2
Annotate first.
Then reduce capacity.

Are you using autoscaler?

Quick check:

1
kubectl get machinedeployments -A

Pick your MachineDeployment name, then:

1
kubectl get machinedeployment <md-name> -o yaml | grep autoscaler

If you see:

1
2
cluster.x-k8s.io/cluster-api-autoscaler-node-group-min-size
cluster.x-k8s.io/cluster-api-autoscaler-node-group-max-size

👉 You’re using Cluster Autoscaler.

Or:

1
kubectl get pods -A | grep -i autoscaler

If you see a cluster-autoscaler pod, same thing.

💡 On platforms like Nutanix Kubernetes Platform, autoscaler is typically enabled.


The flow

  flowchart TD
  A[Find node] --> B[Find Machine + MachineDeployment]
  B --> C[Annotate Machine]
  C --> D{Autoscaler?}

  D -->|Yes| E[Update min/max]
  D -->|No| F[Scale replicas]

Step 1 — Find your node

List nodes:

1
kubectl get nodes

Pick the node you want to remove.


Step 2 — Find the Machine and MachineDeployment

Get all Machines:

1
kubectl get machines -A

Find the Machine that matches your node using:

1
machine.status.nodeRef.name

To get more details (including owner MachineDeployment):

1
kubectl get machine <machine-name> -n <namespace> -o yaml

Look for:

1
ownerReferences → kind: MachineSet

Then:

1
kubectl get machineset <machineset-name> -n <namespace> -o yaml

From there you’ll find the MachineDeployment name.


Step 3 — Annotate the Machine

1
2
kubectl annotate machine <machine-name> -n <namespace> \
  cluster.x-k8s.io/delete-machine="true"

This tells CAPI:

“When you scale down, delete this one.”


Step 4 — Reduce capacity

No autoscaler

Scale the MachineDeployment:

1
kubectl scale machinedeployment <md-name> -n <namespace> --replicas=<new-count>

With autoscaler

Update min/max instead:

1
2
3
4
kubectl annotate machinedeployment <md-name> -n <namespace> \
  cluster.x-k8s.io/cluster-api-autoscaler-node-group-min-size="<new-min>" \
  cluster.x-k8s.io/cluster-api-autoscaler-node-group-max-size="<new-max>" \
  --overwrite

If you’re testing this on Nutanix Kubernetes Platform, this is the path you’ll use.


Verify

1
2
kubectl get machines -A
kubectl get nodes

TL;DR

1
2
3
4
5
6
7
1. kubectl get nodes
2. kubectl get machines -A
3. Find Machine + namespace
4. Annotate Machine
5. Then:
   - No autoscaler → scale MachineDeployment
   - Autoscaler → update min/max

That’s it—no guessing, no missing steps.