Skip to content

Troubleshooting

Most problems show up as a machine landing in FAILED (read last_error via Get) or an UpCloud API error in the logs/metrics. Work from those two signals.

The provider won’t start

SymptomCauseFix
UPCLOUD_USERNAME and UPCLOUD_PASSWORD (an API sub-account) are required for the upcloud backendReal backend with no credentials.Set UPCLOUD_USERNAME/UPCLOUD_PASSWORD (or --username/--password), or use --upcloud-backend=fake for dev.
--zone is required for the upcloud backendReal backend with no zone.Set --zone (e.g. fi-hel1).
--template (an OS template storage UUID) is required for the upcloud backendReal backend with no template.Pass --template with a valid UpCloud OS-template storage UUID.
both --tls-cert and --tls-key are required / --tls-ca set without --tls-cert/--tls-keyHalf-configured gRPC TLS.Provide cert and key (and a CA for mTLS), or none.
capacity_type ... is not offered by UpCloud (on-demand cloud servers only)A spot/reserved/bare_metal capacity_type in offerings.Remove it — UpCloud has only on-demand cloud servers.

Provider boots in fake mode unexpectedly

If the log shows “using the IN-MEMORY fake UpCloud backend”, auto resolved to fake because credentials or --zone were missing. The real backend needs both UPCLOUD_USERNAME/UPCLOUD_PASSWORD and --zone; set all three (and --template) to opt into the real backend. This is by design — a credential-free run defaults to the simulator so it can never accidentally touch a real account.

A machine reaches FAILED

Get the machine and read last_error:

last_error mentionsCauseFix
create server …CreateServer failed (bad plan/template/zone, account limit, credentials).Check the plan/zone exist and the --template UUID is correct and visible to the sub-account; check the account’s server limit.
wait for server … to startCreate timed out waiting for started.Check UpCloud status; the zone may be temporarily out of capacity; the machine goes FAILED.
host key mismatch: pinned … presented …The server’s SSH host key did not match the fingerprint pinned at Create — a possible MITM, hard-failed.Investigate the path to the server; do not disable verification. If the server was legitimately rebuilt out-of-band, delete the slot and let the provider re-create it (which re-pins).
ssh dial … / ssh command on … failedConfigure/Drain couldn’t reach the server or the hook failed.Confirm the provider can reach the server over SSH (--ssh-user, port 22); confirm the image ships --bootstrap-hook and it consumes the blob; confirm --ssh-pubkey matches --ssh-key.
SSH delivery disabled (set --ssh-key)Configure with no SSH key configured.Set --ssh-key (and --ssh-pubkey); without it Configure cannot deliver the blob.
transition interrupted by a provider restartThe process was killed mid-transition.Expected after a kill without graceful drain; the shard re-drives on a fresh slot. Enable --state so fence marks/bindings survive.

A FAILED machine is terminal-pending-cleanup: the shard recovers on a different slot, never in place. Don’t re-issue mutations against it.

A server was stopped out-of-band

If someone stops a server in the UpCloud console while it still owns a slot, the provider does not fail Configure/Drain on it: EnsureRunning powers the server back on (and waits for started) before delivering the SSH bootstrap or drain. You’ll see a EnsureRunning API call in the metrics. No action needed — but out-of-band stops add latency, so avoid them on managed servers.

Delete leaves no orphaned storage

UpCloud storage (the OS disk) is a separate, separately-billed resource from the server: deleting only the server would leak the disk. The provider’s Delete stops the server, then calls DeleteServerAndStorages, removing both in one shot. It is idempotent — an already-gone server (404) is treated as success. If you ever delete servers by hand, use the equivalent “delete with storages” path so you don’t accumulate orphaned disks.

UpCloud API errors

SymptomCauseFix
api_calls_total{outcome="error"} rising; logs show 401/403Bad, disabled, or under-scoped API sub-account.Verify UPCLOUD_USERNAME/UPCLOUD_PASSWORD are current and the sub-account has API + server/storage permission; rotate if needed.
Errors spike under loadUpCloud API rate limiting / transient errors.Back off; reduce churn; the kit retries idempotently. Spread creates if you run many zones off one account.
pricing: no pinned price for plan; reporting 0The offered plan isn’t in the pinned EUR table and has no override.Add the plan to the pinned table or set price_usd_per_hour on the offering. A 0 price is valid but skews the engine’s cost ranking.

Placement / packing looks wrong

SymptomCauseFix
Pods won’t schedule on a plan that should fitresources set to the plan’s hardware total, forcing density = 1.resources is the per-replica request (e.g. {cpu:"1"}); leave allocatable to the provider (derived from the plan via the Plans API). See Configuration.
allocatable is 0/nil for a planThe plan is neither in the pinned table nor resolvable from the Plans API.Confirm the plan name is exactly an UpCloud plan; add it to the pinned table if UpCloud can’t return it. A nil allocatable is treated as allocatable == resources.
topology.kubernetes.io/zone selectors don’t matchZone not surfaced as zone.The provider sets zone from the server’s zone automatically; confirm the offering’s zone matches the one you select on (and this process’s --zone).

Fencing alerts

A spike of FailedPrecondition on bigfleet_upcloud_grpc_requests_total{code="FailedPrecondition"} means a zombie shard (an old shard process) is being correctly rejected. This is the provider doing its job — investigate the shard side (a restart that didn’t take over cleanly), not the provider. FailedPrecondition is reserved for fencing; any other rejection uses a different code.

Useful commands

Terminal window
# What state is a machine in, and why?
grpcurl -plaintext -d '{"id":"<machine-id>"}' localhost:9000 \
bigfleet.v1alpha1.CapacityProvider/Get
# Inventory by state.
grpcurl -plaintext -d '{}' localhost:9000 \
bigfleet.v1alpha1.CapacityProvider/List
# Probes and metrics.
curl localhost:9090/healthz
curl localhost:9090/readyz
curl -s localhost:9090/metrics | grep bigfleet_upcloud_