Back to Blog

AWS vs GCP vs Hetzner: Six Clouds, One Kubernetes Benchmark

13 min read
On this page

Yesterday we published UpCloud vs OVH vs DigitalOcean, three identical clusters under one in-cluster suite: k6 HTTP load with SLO thresholds, iperf3 across nodes, fio and sysbench on every worker. The obvious question arrived within hours: fine, but what about the clouds most people actually run on?

So we ran the identical suite on three more clusters: EKS on AWS, GKE on Google Cloud, and k3s on Hetzner, each with two workers in the 2 vCPU / 4 GB class. Same phases, same thresholds, same extraction. Six clouds now sit on one axis, and the axis is not kind to sticker specs.

Cheapest node to pass all 8 SLOs
€5.49/mo
Hetzner cx23, with 30k IOPS of local NVMe underneath
CPU you can actually schedule on GKE e2-medium
187m
of the 2,000m you paid for; system pods reserve the rest
Fastest budget-tier network
4.97 Gbit/s
EKS t3.medium burst, within 8% of UpCloud’s best
Disk gap inside one price class
27x
Hetzner NVMe seq write vs EKS gp3’s 135 MB/s cap

The usual caveat carries over from part one and applies to every number here: one day per provider, two workers each, one size class. Hyperscaler entry tiers are burstable or shared by design where UpCloud and OVH sell dedicated-share tiers, and that asymmetry is inherent to comparing like-priced entry plans. It is also, again, most of the story.

The contenders, rounds one and two

HetznerGKEEKS
Region and planhel1, cx23europe-north1-a, e2-mediumeu-west-1, t3.medium
CPU tiershared vCPUshared coreburstable (unlimited mode)
Storagelocal NVMepd-balancedEBS gp3 baseline
Control planeself-managed k3sGKE, zonalEKS
Worker cost2 x €5.492 x ~$24 + $73 fee2 x ~$34 + $73 fee

Round one, for reference: UpCloud 2xCPU-4GB in fi-hel1, OVH c3-4 in Paris, DigitalOcean s-2vcpu-4gb in fra1, all detailed in the original post.

Hetzner runs the same self-managed k3s shape as round one’s clusters. The two hyperscalers bring managed control planes, which is genuinely worth money, and also bring the management fee that makes their per-node economics worse before the first pod starts.

What you bought vs what you can schedule

The first result arrived before a single benchmark ran. The suite’s stock manifests, which fit trivially on every other cluster in both rounds, would not schedule on GKE at all: podinfo asks for a modest 250 millicores and no e2-medium node had it. The arithmetic: e2-medium exposes 940m allocatable CPU, and GKE’s own system pods request 753m of it.

CPU left for your pods on a 2 vCPU node, millicores, after provider reservations and system pods
Hetzner
~1,800
EKS
~1,700
GKE
187
Hetzner and EKS are close approximations from node allocatable minus system requests; the GKE figure is exact.

We had to fork the manifests down to 50m requests to get the GKE run scheduled at all. Once running, to its credit, it performed: the pods burst fine and the latency below is real. But if you size a GKE entry-class node pool from the spec sheet, Kubernetes will refuse most of what you try to put on it. You are buying a fifth of the node you think you are.

HTTP latency: the budget tier holds the line

All three new clusters passed all eight k6 SLO thresholds with 0.00% error rates, exactly like round one. The percentiles land in a tight band between round one’s extremes:

p95 / p99 in msHetznerGKEEKS
smoke (unloaded)1.89 / 3.671.16 / 2.441.33 / 3.09
baseline, 50 rps2.33 / 4.151.32 / 2.171.53 / 4.33
stress, ramp to 300 rps1.90 / 3.401.27 / 2.251.36 / 3.82
spike, 400 rps1.85 / 3.391.49 / 3.931.30 / 3.66

For calibration: UpCloud and OVH sat below 1 ms at p95 in every scenario, and DigitalOcean’s shared tier climbed to 5.6 / 13.7 under spike. The new trio sits at 1.2 to 2.3 ms at p95 with none of DigitalOcean’s load-dependent tail growth. GKE’s constrained nodes posted the cleanest numbers of the three, which says something good about its network path and something uncomfortable about how little the guaranteed-CPU number correlates with real latency at this load.

Network: EKS crashes the podium

Cross-node pod-to-pod TCP, forward direction, Gbit/s, both rounds
UpCloud
5.40
EKS
4.97
OVH
3.61
Hetzner
1.85
DigitalOcean
1.76
GKE
1.73
Round one results in gray, round two in color.
HetznerGKEEKS
Forward1.85 Gbit/s1.73 Gbit/s4.97 Gbit/s
Reverse1.41 Gbit/s1.82 Gbit/s4.76 Gbit/s
What limits itreceiver CPU at ~70%provider policer, 40k+ retransmitsreceiver CPU at ~48%

EKS is the story here: within 8% of UpCloud’s round-one best, with CPU nowhere near saturated. One honest asterisk: t3.medium’s network is burst-rated. A 30 second benchmark rides the burst window; a sustained streaming workload eventually meets the much lower baseline. GKE shows the same policer signature DigitalOcean did in round one, high retransmit counts with idle CPUs, which means no bigger node fixes it at this tier. Hetzner’s ceiling is its small CPU, the benign kind of limit: buy a bigger node and the pipe widens.

Storage: one of these things is not like the others

Round one taught us to read twin numbers as fingerprints: caps produce identical values, physics produces merely close ones. Round two has both, and a ringer.

fdatasync p99 per provider, slower worker, ms. The vertical rule is etcd’s 10 ms bar.
OVH
0.43
UpCloud
1.09
Hetzner
2.47
GKE
3.46
EKS
3.52
DigitalOcean
11.86
DigitalOcean remains the only breach across all six clouds. Round one in gray, round two in color.

The full per-worker table for round two:

Per workerHZ w0HZ w1GKE w0GKE w1EKS w0EKS w1
Seq write MB/s3,6092,452175175135135
Seq read MB/s2,7422,853176177132132
4k rand read IOPS35,76933,7423,7693,7593,0993,099
4k rand write IOPS29,48928,6123,5723,5583,0333,034
fsync ops/s1,5351,547468466483481
fdatasync p99 ms2.212.473.393.463.523.52

GKE’s 175 next to 175 and EKS’s 3,099 next to 3,099 are the cap fingerprint again: pd-balanced and gp3 baseline doing exactly what their documentation says, no more, ever. Predictable, plannable, and roughly a tenth of what round one’s budget IOPS leader delivered.

Then there is the Hetzner column. €5.49 buys local NVMe posting 2.5 to 3.6 GB/s sequential, 30k random IOPS, and a 2.5 ms fsync p99, on the cheapest node in either round by a factor of four. It is instance-local storage, so as with OVH in round one, durability is your replication story, and the k3s cluster running it is self-managed. But as raw price-per-performance, nothing else in this test is on the same chart.

CPU: two classes, clearly labeled

sysbench CPU events per second, slower worker of each pair
UpCloud
9,616
OVH
7,970
EKS
1,350
DigitalOcean
1,342
Hetzner
1,106
GKE
1,069
Round one in gray, round two in color. The gap between the tiers is 6x to 9x.

Every shared or burstable tier in both rounds lands between 1,069 and 1,370 events per second; every dedicated-share tier lands between 7,970 and 9,666. There is no middle. The spec sheets all say “2 vCPU”; the benchmark says there are two products with a 7x gap wearing the same label. EKS’s t3.medium tops the budget class thanks to unlimited-mode bursting, and it also posts the best memory bandwidth of the trio at 4.9 GB/s, but remember that sustained bursting on t3 bills you for the privilege.

One difference from round one worth celebrating: all three round-two pairs are twins. Hetzner’s workers differ by 5%, GKE’s by 2%, EKS’s by 1%. Nobody drew DigitalOcean’s 2.8x lottery this time.

What to place where, six clouds edition

UpCloud keeps the overall crown from round one: the IOPS headroom, the network ceiling that scales with node size, and dedicated-class CPU still make it our pick for control planes and stateful workloads.

OVH still owns everything latency-shaped: its 0.43 ms fsync p99 is one nothing in round two came within 5x of.

Hetzner is the value verdict of round two. It gives up two thirds of the network and the dedicated CPU class, and in exchange costs a quarter of anything else here while carrying storage that embarrasses nodes six times its price. For dev clusters, CI runners, batch work, or any replicated data layer where you control durability, it is the obvious answer. Do the math against the price-hike post before assuming, but at these numbers the math is short.

EKS is the best hyperscaler showing: budget-class-best network and CPU, honest caps on disk, tight twins, and a managed control plane. The fee and the burst-billing asterisks are the price of admission, and its provisioning was the rockiest of the six (more on that below).

GKE performed better than its scheduling story deserves: cleanest budget-tier latency, perfectly consistent disks. But 187 schedulable millicores on a 2 vCPU node makes the entry class a demo tier, not a workload tier. Size up a class or plan around the reservation.

DigitalOcean keeps its round-one verdict: smoothest onboarding, honest SLO passes, and the only etcd-bar breach plus the twin-node lottery at the entry tier.

Full disclosure: the sweep found our bugs too

A benchmark that exercises real provisioning paths finds real bugs, and three of them were ours. Running the AWS leg surfaced a missing credential mount in our scheduler deployment, a missing iam:GetRole in the CloudFormation template we hand to customers for EKS onboarding, and a subnet configuration case our preflight should have caught before AWS did. All three fixes shipped before this post did, which is exactly the argument for benchmarking through the same path your users take.

Run it yourself

The suite is unchanged from the methodology post: three Kubernetes Jobs and a target deployment, about fifteen minutes per cluster, mechanical pass/fail verdicts. The six-cloud loop was the same Ankra motion as round one: declare the same cluster shape per provider, deploy the suite as a stack, collect logs, tear down. The marginal cost of adding a cloud to the comparison was one YAML declaration and a coffee. When a spec sheet and a benchmark disagree, believe the benchmark, especially about what “2 vCPU” means.


Get started: Create a free account on Ankra.

Join our community: Slack

Follow us on: LinkedIn | GitHub

Contact us: [email protected]

ShareXLinkedInHN

Get the next post in your inbox

Platform engineering guides and product updates. No spam, unsubscribe anytime.

Related Posts