Skip to main content
Choose UpCloud when you want Kubernetes on UpCloud servers in an account you own, with private nodes behind a managed NAT gateway and, if you need it, a cluster stretched across several UpCloud zones. Ankra creates the router, private network, NAT gateway, bastion and servers, installs Kubernetes and the UpCloud cloud integration, and then operates the cluster for you - this is an Ankra Managed cluster. UpCloud bills you directly for the servers.

Before you start

  • An UpCloud API token with permission to manage servers, networking, storage and Kubernetes, stored as an UpCloud credential.
  • An SSH key credential - your own public key, or one Ankra generates. See SSH Key Credentials.
  • Room in your account’s limits for the servers, networks, routers and IP addresses. Check them in the UpCloud Control Panel; UpCloud support raises them.

Create the cluster

1

Open the create dialog

Go to Clusters, click Create cluster and pick UpCloud under Ankra Managed.
2

Credential & Zone

Pick the UpCloud credential and the SSH key (or add either inline), and the zone, for example Helsinki, Frankfurt, Chicago or Amsterdam.
3

Network & Compute

Keep or change the private network range, then pick the bastion plan, the control plane count and plan, and the worker plan and count, with optional autoscaling bounds. The wizard shows each plan’s vCPUs, RAM and monthly price. Add more node groups once the cluster is running.
4

Kubernetes

Keep kubeadm (the default, with Cilium) or pick k3s, and optionally the version. See Choices fixed at create time for the CNI and etcd options.
5

GitOps

Optionally connect a Git repository; Ankra commits the cluster’s stacks to it. Two checkboxes are on by default:
  • Include Networking Stack - Traefik, cert-manager and a Let’s Encrypt ClusterIssuer, with Traefik behind an UpCloud load balancer.
  • Include Public DNS - a delegated subdomain on ankra.cc with external-dns wired, so an ingress hostname under it gets its DNS record and TLS certificate automatically.
6

Details

Name the cluster, set its environment, and click Create cluster. A progress view follows the router, network, gateway, bastion, servers, Kubernetes installation and Ankra Agent.

Verify

  1. The cluster moves from Provisioning to Online in the clusters list once the Ankra Agent has connected.
  2. Point kubectl at it through Ankra (this needs a Cluster Access grant) and check the nodes:
    Every control plane and worker should be Ready. See Accessing Clusters with kubectl.

What Ankra created in your account

  • An SDN router and a private network with DHCP handing out the default route. Nodes have no public interface.
  • A managed NAT gateway on the router - the egress path for all node traffic.
  • A bastion - the only server with a public IP. It is an SSH jump host only: Ankra reaches the nodes through it to provision, upgrade and reconcile, and no workload or egress traffic flows through it.
  • Control plane and worker servers, and your SSH key on every server.
  • The upcloud-cloud-provider stack - the UpCloud cloud controller manager and CSI driver, for LoadBalancer Services and persistent storage, using your credential.
On a multi-zone cluster, every additional zone gets its own router, private network and NAT gateway, and the nodes are joined by a WireGuard mesh. The UpCloud Reference has the diagram.

UpCloud specifics

  • Plan changes go one way. A node group moves to a larger plan only; each node is powered off, resized and powered on, with brief downtime for its workloads. For smaller nodes, create a new group and delete the old one.
  • Stop. A stop releases the node servers, the bastion and the NAT gateway, and keeps the networking definition and SSH keys. The CSI storage volumes are kept and billed while the cluster is stopped.
  • Terminate deletes the servers, networks, routers, gateways and SSH keys. The storage volumes Ankra deletes, once you accept it, are exactly the ones it recorded for this cluster - never other disks in the account.

Multi-zone clusters

UpCloud has no multi-zone region: every private SDN network, router and managed load balancer lives in one zone, so a cluster is single-zone by construction. Ankra can stretch a cluster across a zone pool instead - one private network and NAT gateway per zone, the nodes joined by a platform-managed kernel WireGuard mesh over UpCloud’s account-wide utility network, and Kubernetes advertising the overlay address on every node. Losing a zone then costs capacity, not the cluster.
Multi-zone placement needs the kubeadm distribution (the default).
Two rules shape everything below. A pool has at least three zones and three control planes - one per zone - so etcd keeps quorum when any one zone is lost; a two-zone pool is refused. And the mesh is decided at create: a cluster created without it cannot be stretched later, so a single-zone cluster that may grow is created with network_mode: wireguard_mesh.

Create a cluster across zones

zone stays the primary zone - bastion, first control plane and default network - and must be in zones. Control planes spread one per zone; workers spread per node group unless a group is pinned.
network_mode is derived - wireguard_mesh for a pool, private_network otherwise - and can be set to wireguard_mesh on a single-zone cluster to make it mesh-capable:

Grow the pool

Zones can be added to a wireguard_mesh cluster, never removed. Pass the full desired pool, primary zone first; every new zone gets its router, private network and NAT gateway, and later node groups spread across the grown pool.

Pin a node group to one zone

Pin the group that runs zonal storage: an UpCloud volume cannot attach from another zone.
Day-2 growth follows the stored pool: node group add, node group scale, worker scale, autoscaling and control plane growth balance new servers around where the existing ones are. A group whose nodes all share one zone is treated as pinned and grows there; a spread group keeps spreading. Control planes cannot be scaled below three on a multi-zone pool. ankra cluster node-group list ends each line with zones= and the zones the group’s nodes were placed in (zones on the node-group listing API).

Node topology labels

Every node carries topology.kubernetes.io/zone (the UpCloud zone, e.g. fi-hel2) and topology.kubernetes.io/region (the zone without its index, e.g. fi-hel), so topologySpreadConstraints and zone-aware scheduling work without extra configuration.

Node addressing on a meshed cluster

Every node advertises its overlay address to Kubernetes, so that is what kubectl get nodes -o wide reports as INTERNAL-IP - not the node’s private SDN address. Overlay addresses are allocated per cluster from a range Ankra manages (172.30.0.0/16 by default) and stay stable for the life of a node, so anything keyed on a node IP - monitoring targets, NO_PROXY lists, allow-lists - should use the overlay address:
Each zone in the pool also takes its own consecutive /24 from the cluster’s private range: with the default range, fi-hel1 gets 10.166.78.0/24, fi-hel2 10.166.79.0/24, and so on. Pick network_ip_range with room for every zone you expect to add.

LoadBalancer Services on a meshed cluster

A meshed cluster advertises each node’s overlay address as its Kubernetes InternalIP. An UpCloud load balancer is not part of the WireGuard mesh, so a backend registered at that address would be unreachable. Ankra runs a cloud controller manager on meshed clusters that takes each backend member’s address from the node’s address on the private network the load balancer is attached to, rather than from the InternalIP. That is the one address a load balancer can always reach, so LoadBalancer Services - including the Traefik ingress the networking stack installs - work normally. You do not need to configure anything.
This is worth knowing if you compare a meshed cluster against a stock UpCloud CCM: the address behaviour is a deliberate difference, and the controller runs with its node controller disabled, because the overlay address it would otherwise reject is the whole point of a meshed cluster. Ankra applies the topology.kubernetes.io/* and node.kubernetes.io/instance-type labels itself instead.

What stays in the primary zone

UpCloud block storage is zone-local, and the cluster’s CSI is scoped to the primary zone:
  • PersistentVolumeClaims are provisioned in the primary zone. Run stateful workloads there, or use replicated storage such as Longhorn for the other zones.
  • The bastion is in the primary zone: if that zone is lost, workloads keep running in the others, but provisioning and node management pause until it returns.
  • The cloud controller manager cannot match a node’s overlay address to an address UpCloud reports for the server, so it does not maintain node addresses on a meshed cluster. Ankra runs the CCM with its node controller disabled there and stamps the topology.kubernetes.io/* and node.kubernetes.io/instance-type labels itself; nodes register, stay Ready and keep their providerID.
Pod MTU is 1370 inside the mesh (WireGuard and VXLAN overheads), and Cilium’s own WireGuard encryption is refused on a meshed cluster - the overlay already encrypts every node-to-node byte.

Operate it

Day-2 tasks work the same way on every Ankra Managed provider, with the CLI name upcloud:

Troubleshooting