//------------------------------------------------------------------- //-------------------------------------------------------------------
fix Kubernetes VPS Performance Issues

Why Kubernetes Struggles on VPS: The Core Bottlenecks

Running Kubernetes on a Virtual Private Server (VPS) is the most cost-effective way to learn and deploy clusters, but it often comes with a hidden cost, which is unpredictable Kubernetes VPS performance. Many developers deploy a cluster that works perfectly in a local environment, only to face unexplained timeouts, CrashLoopBackOff errors, and sluggish API responses once deployed to a VPS.

The problem usually isn’t your configuration; it’s the virtualization layer. Unlike bare metal servers, a VPS shares physical resources with other noisy neighbors. This environment introduces specific bottlenecks that Kubernetes is not designed to handle, specifically CPU Steal Time, Disk I/O latency, and Network Packet (PPS) limits.

In this guide, from PerLod Hosting, we want to explain why these issues occur and learn the best methods to mitigate CPU steal, disk I/O latency, and network limits.

Kubernetes VPS Performance Bottlenecks

When you run Kubernetes on a VPS server, you are sharing physical hardware with noisy neighbors. The hypervisor, the software managing the VMs, enforces strict limits that Kubernetes is often unaware of, which leads to three primary bottlenecks:

1. CPU Steal: In a VPS environment, your vCPU is just a time slice of a physical CPU core. If other VMs on the same host are busy, the hypervisor might delay giving CPU time to your VM. This delay is called Steal Time.

This affects K8s because Kubernetes needs immediate processing power. If it asks for the CPU and gets delayed, it assumes something is broken and starts restarting your containers unnecessarily.

You can check for CPU steal time by using the vmstat command:

vmstat 1 5

You must look at the st column; if it is consistently above 5 to 10%, your VPS is being throttled by the host.

Or, you can use the top command and watch for the %st value in the CPU row.

2. Disk I/O Latency: VPS hard drives are often shared, and speed is limited by your provider. This is a major problem for Kubernetes because its database (etcd) requires fast write speeds. If the disk is too slow to save data instantly, the database panics and freezes the entire cluster.

You can use the iotop command to check real-time usage:

# Install iotop if missing
sudo apt install iotop -y  # Ubuntu/Debian
sudo dnf install iotop -y  # CentOS/AlmaLinux

# Run it to see what processes are eating your IO
sudo iotop

3. Network Packet Limits: VPS providers often limit PPS (Packets Per Second), not just the total bandwidth. Kubernetes sends thousands of tiny messages between apps. Even if you have plenty of bandwidth, you can hit this packet limit, which causes traffic to get dropped.

Kubernetes VPS Performance Tuning

As you must know, we can not fix the hardware limits, so we can optimize the kernel parameters to handle these limitations without crashing.

1. Mitigate CPU Steal via Scheduler Tuning

We can tell Linux to switch between tasks less frequently, which reduces the lag caused by the shared CPU. You can create a sysctl configuration file to tune the scheduler:

# Create the tuning file
sudo tee /etc/sysctl.d/99-k8s-vps-cpu.conf <<EOF
# Increase the time a task runs before being preempted (reduces context switching overhead)
kernel.sched_min_granularity_ns = 10000000
kernel.sched_wakeup_granularity_ns = 15000000
EOF

# Apply the changes immediately
sudo sysctl --system

Note: This setting adds a tiny latency but improves throughput and stability under high steal time.​

2. Prevent Etcd Crashes by Prioritizing Disk I/O

To prevent etcd from crashing during heavy disk usage, you should give it a higher I/O priority over other processes like logging or container builds.

First, you must find the Process ID (PID) of etcd, usually inside a container:

pgrep -f etcd

Then, use the ionice to set the priority for it. Give this process the highest possible priority (0) within the standard ‘Best Effort’ group:

sudo ionice -c2 -n0 -p <PID>

To make this change permanent, you must add it to your etcd systemd service configuration file.

3. Sysctl Tuning for Kubernetes Networking

At this point, you can optimize the network settings so the server can handle high connections in Kubernetes without hitting connection tracking limits. To do this, you can use the commands below:

sudo tee /etc/sysctl.d/99-k8s-vps-net.conf <<EOF
# Increase the maximum number of backlog connections
net.core.somaxconn = 4096

# Allow reusing sockets in TIME_WAIT state (essential for high pod-to-pod requests)
net.ipv4.tcp_tw_reuse = 1

# Increase the range of ephemeral ports for outgoing connections
net.ipv4.ip_local_port_range = 1024 65535
EOF

# Apply changes
sudo sysctl --system

These settings prevent your VPS from running out of sockets when many pods communicate simultaneously.

For detailed information on maximizing throughput and BBR congestion control, check out our guide on Linux Kernel Network Tuning.

Kubernetes VPS Performance Validation

After implementing optimizations, you must validate that the improvements take effect.

1. Validate Disk Performance with Kubestr: Kubestr is a tool specifically designed to test if your storage is fast enough for Kubernetes.

First, download the Kubestr tool with the commands below:

wget https://github.com/kastenhq/kubestr/releases/download/v0.4.31/kubestr_0.4.31_linux_amd64.tar.gz
tar -xvf kubestr_0.4.31_linux_amd64.tar.gz
chmod +x kubestr

Then, run a disk benchmark (FIO) on your storage class:

# Replace 'local-path' with your storage class name (e.g., standard, gp2)
./kubestr fio -s local-path

You must look for IOPS higher than 500 for a healthy etcd cluster.

2. Validate Network Performance with iPerf3: Test the actual speed between two pods to ensure your sysctl tuning worked.

Deploy an iPerf3 server (receiver) with the commands below:

kubectl create deployment iperf-server --image=networkstatic/iperf3
kubectl expose deployment iperf-server --port=5201

Run a client pod to test the speed:

# Get the ClusterIP of the server
kubectl get svc iperf-server

# Run a test (replace <CLUSTER-IP> with the IP from above)
kubectl run iperf-client --rm -it --image=networkstatic/iperf3 -- -c <CLUSTER-IP>

Check the Retr (Retransmits) column in the output. High retransmits represent packet loss due to VPS limits.

3. Validate CPU and Steal Stability: You can perform a stress test while monitoring steal time to see if the system remains responsive:

# Install stress-ng
sudo apt-get install stress-ng -y

# Run a 60-second CPU stress test on 2 cores
stress-ng --cpu 2 --timeout 60s &

# Watch vmstat while the test runs
watch -n 1 vmstat 1

If your tuning worked, the system should remain responsive even if st (steal) increases.

FAQs

How do I know if CPU Steal is the actual cause of my Kubernetes VPS performance?

Run vmstat 1. If the st number is above 5, your provider is limiting you. If st is low but us hits 100, your app just needs a stronger CPU.

Is ionice safe to run on a production database?

Yes, it’s safe. This command doesn’t block other apps; it just puts etcd at the front of the line so your database doesn’t wait behind less important tasks.

Why is my network slow even though I have a 1Gbps connection?

You might be hitting a packet count limit, not a speed limit. Kubernetes sends thousands of tiny messages that can overload the VPS. Implement the tuning; if it doesn’t fix it, you need a dedicated server plan that has higher PPS allowances.​

Conclusion

Running Kubernetes on a VPS means fighting hidden hardware limits. Since you can’t upgrade the physical machine, your only defense is tuning the software. By adjusting Linux to handle CPU steal and giving priority to etcd, you can stop your cluster from crashing under load. Just remember to test regularly with tools like Kubestr and iPerf3.

We hope you enjoy this guide. Subscribe to our X and Facebook channels to get the latest updates and articles.

If your VPS has less than 4GB of RAM, standard Kubernetes might be too heavy. We recommend switching to K3s on Ubuntu, which is a production-ready version that uses half the memory.

Post Your Comment

PerLod delivers high-performance hosting with real-time support and unmatched reliability.

Contact us

Payment methods

payment gateway
Perlod Logo
Privacy Overview

This website uses cookies so that we can provide you with the best user experience possible. Cookie information is stored in your browser and performs functions such as recognising you when you return to our website and helping our team to understand which sections of the website you find most interesting and useful.