[{"data":1,"prerenderedAt":564},["ShallowReactive",2],{"blog-en-k3s-metrics-server-default-kubeadm-hpa-kubectl-top":3,"blog-related-en-k3s-metrics-server-default-kubeadm-hpa-kubectl-top":519,"blog-en-k3s-metrics-server-default-kubeadm-hpa-kubectl-top-alt":509},{"id":4,"title":5,"author":6,"body":7,"date":503,"description":504,"extension":505,"image":506,"locale":507,"meta":508,"navigation":509,"path":510,"seo":511,"stem":512,"tags":513,"__hash__":518},"blog\u002Fblog\u002Fen\u002Fk3s-metrics-server-default-kubeadm-hpa-kubectl-top.md","`kubectl top` Returned Nothing. The Cause Was a Missing metrics-server — K3s Never Has That Problem","Kubo Team",{"type":8,"value":9,"toc":494},"minimark",[10,18,31,39,45,56,67,73,80,84,90,98,117,137,155,159,165,172,180,185,197,210,239,247,251,257,260,268,277,406,409,413,419,436,446,454,458,469,481,490],[11,12,13],"p",{},[14,15],"img",{"alt":16,"src":17},"section01","https:\u002F\u002Fcdn.kubo.hexabase.io\u002Fimages\u002Fblog\u002Fen\u002Fk3s-metrics-server-default-kubeadm-hpa-kubectl-top\u002Fsection01.webp",[11,19,20,21,25,26,30],{},"You took a Horizontal Pod Autoscaler (HPA) manifest you'd validated on K3s and applied it, unchanged, to a standard Kubernetes cluster bootstrapped with kubeadm. ",[22,23,24],"code",{},"kubectl top"," returned nothing, and HPA never scaled a single replica. Plenty of infrastructure engineers have hit exactly this wall. The cause is usually something surprisingly basic: ",[27,28,29],"strong",{},"whether metrics-server is present at all",". Something that just worked on K3s simply doesn't exist yet on standard Kubernetes. This article walks through why that gap exists, backed by official documentation, and how to diagnose it.",[32,33,35,36,38],"h2",{"id":34},"_1-the-day-kubectl-top-went-silent","1. The Day ",[22,37,24],{}," Went Silent",[11,40,41],{},[14,42],{"alt":43,"src":44},"section02","https:\u002F\u002Fcdn.kubo.hexabase.io\u002Fimages\u002Fblog\u002Fen\u002Fk3s-metrics-server-default-kubeadm-hpa-kubectl-top\u002Fsection02.webp",[11,46,47,48,51,52,55],{},"The story is simple enough. A Deployment with HPA attached, built and tested on a K3s environment, gets moved to a production-equivalent standard Kubernetes cluster bootstrapped with kubeadm. The manifest itself hasn't changed. But ",[22,49,50],{},"kubectl top pods"," returns nothing, and the HPA status sits stuck at ",[22,53,54],{},"unknown",".",[11,57,58,59,66],{},"The ",[60,61,65],"a",{"href":62,"rel":63},"https:\u002F\u002Fkubernetes.io\u002Fdocs\u002Ftasks\u002Frun-application\u002Fhorizontal-pod-autoscale-walkthrough\u002F",[64],"nofollow","official Kubernetes HPA walkthrough"," spells out the prerequisite plainly:",[68,69,70],"blockquote",{},[11,71,72],{},"To follow this walkthrough, you also need to use a cluster that has a Metrics Server deployed and configured.",[11,74,75,76,79],{},"In other words, using HPA requires ",[27,77,78],{},"Metrics Server to be deployed and correctly configured"," as a baseline assumption. On K3s, that assumption was already satisfied, so nobody ever had to think about it. On standard Kubernetes, it's a condition you have to satisfy yourself.",[32,81,83],{"id":82},"_2-why-k3s-ships-metrics-server-by-default","2. Why K3s Ships metrics-server by Default",[11,85,86],{},[14,87],{"alt":88,"src":89},"section03","https:\u002F\u002Fcdn.kubo.hexabase.io\u002Fimages\u002Fblog\u002Fen\u002Fk3s-metrics-server-default-kubeadm-hpa-kubectl-top\u002Fsection03.webp",[11,91,58,92,97],{},[60,93,96],{"href":94,"rel":95},"https:\u002F\u002Fdocs.k3s.io\u002Finstallation\u002Fpackaged-components",[64],"official K3s \"Packaged Components\" documentation"," spells out exactly which addons K3s bundles by default:",[68,99,100],{},[11,101,102,103,106,107,106,110,113,114,55],{},"K3s comes with a number of packaged components that are deployed as AddOns via the manifests directory: ",[22,104,105],{},"coredns",", ",[22,108,109],{},"traefik",[22,111,112],{},"local-storage",", and ",[22,115,116],{},"metrics-server",[11,118,119,120,123,124,127,128,131,132,55],{},"Alongside coredns (DNS), traefik (Ingress), and local-storage (local volume provisioning), ",[27,121,122],{},"metrics-server is explicitly listed as one of the standard components",". These manifests are placed automatically under ",[22,125,126],{},"\u002Fvar\u002Flib\u002Francher\u002Fk3s\u002Fserver\u002Fmanifests"," and get deployed the moment K3s starts, in a process similar to ",[22,129,130],{},"kubectl apply",". The same fact is confirmed in ",[60,133,136],{"href":134,"rel":135},"https:\u002F\u002Fdocumentation.suse.com\u002Fcloudnative\u002Fk3s\u002Flatest\u002Fen\u002Finstallation\u002Fpackaged-components.html",[64],"SUSE's official documentation",[11,138,139,140,145,146,148,149,154],{},"K3s is designed around the goal of \"running Kubernetes from a lightweight single binary,\" and that design philosophy extends to bundling the minimum set of addons needed for real operation. The existence of ",[60,141,144],{"href":142,"rel":143},"https:\u002F\u002Foneuptime.com\u002Fblog\u002Fpost\u002F2026-03-20-k3s-disable-metrics-server\u002Fview",[64],"documented steps to disable metrics-server"," is itself proof that it's enabled by default. Both ",[22,147,24],{}," and HPA work the moment the cluster comes up. ",[60,150,153],{"href":151,"rel":152},"https:\u002F\u002Fkubo.hexabase.io\u002F",[64],"Kubo",", a managed service built on K3s, inherits this same bundling policy.",[32,156,158],{"id":157},"_3-why-standard-kubernetes-kubeadm-doesnt-include-metrics-server","3. Why Standard Kubernetes (kubeadm) Doesn't Include metrics-server",[11,160,161],{},[14,162],{"alt":163,"src":164},"section04","https:\u002F\u002Fcdn.kubo.hexabase.io\u002Fimages\u002Fblog\u002Fen\u002Fk3s-metrics-server-default-kubeadm-hpa-kubectl-top\u002Fsection04.webp",[11,166,167,168,171],{},"kubeadm, on the other hand, is a tool focused on providing a ",[27,169,170],{},"minimal control plane",". CNI, an Ingress Controller, and metrics-server are all addons that fall outside what kubeadm installs.",[11,173,58,174,179],{},[60,175,178],{"href":176,"rel":177},"https:\u002F\u002Fkubernetes.io\u002Fdocs\u002Ftasks\u002Fdebug\u002Fdebug-cluster\u002Fresource-metrics-pipeline\u002F",[64],"official Kubernetes \"Resource metrics pipeline\" documentation"," states this directly:",[68,181,182],{},[11,183,184],{},"You must deploy the metrics-server or alternative adapter that serves the Metrics API to be able to access it.",[11,186,187,188,190,191,55],{},"The same page positions metrics-server as a \"cluster addon component\" and explains that HPA, VPA, and ",[22,189,24],{}," all depend on the Metrics API it provides. In short: ",[27,192,193,194,196],{},"just because you created a cluster with kubeadm doesn't mean HPA, VPA, or ",[22,195,24],{}," will work out of the box",[11,198,199,200,203,204,209],{},"Installing it isn't hard. You can apply the ",[22,201,202],{},"components.yaml"," manifest from the ",[60,205,208],{"href":206,"rel":207},"https:\u002F\u002Fgithub.com\u002Fkubernetes-sigs\u002Fmetrics-server",[64],"official metrics-server repository"," with a single command:",[211,212,217],"pre",{"className":213,"code":214,"language":215,"meta":216,"style":216},"language-bash shiki shiki-themes tokyo-night","kubectl apply -f https:\u002F\u002Fgithub.com\u002Fkubernetes-sigs\u002Fmetrics-server\u002Freleases\u002Flatest\u002Fdownload\u002Fcomponents.yaml\n","bash","",[22,218,219],{"__ignoreMap":216},[220,221,224,228,232,236],"span",{"class":222,"line":223},"line",1,[220,225,227],{"class":226},"sE3pS","kubectl",[220,229,231],{"class":230},"sPY7s"," apply",[220,233,235],{"class":234},"sT800"," -f",[220,237,238],{"class":230}," https:\u002F\u002Fgithub.com\u002Fkubernetes-sigs\u002Fmetrics-server\u002Freleases\u002Flatest\u002Fdownload\u002Fcomponents.yaml\n",[11,240,241,242,246],{},"The problem is that teams migrating from K3s are the ones most likely to forget — or never know — this step existed in the first place. A step nobody on K3s ever had to think about becomes a mandatory extra task on standard Kubernetes. Even managed services built on standard Kubernetes, like EKS or AKS, often leave this kind of addon installation as the customer's responsibility. ",[60,243,245],{"href":151,"rel":244},[64],"Kubo Cloud"," is built on K3s and delivers Pure Kubernetes, so this initial setup burden never arises in the first place.",[32,248,250],{"id":249},"_4-what-breaks-when-metrics-server-is-missing","4. What Breaks When metrics-server Is Missing",[11,252,253],{},[14,254],{"alt":255,"src":256},"section05","https:\u002F\u002Fcdn.kubo.hexabase.io\u002Fimages\u002Fblog\u002Fen\u002Fk3s-metrics-server-default-kubeadm-hpa-kubectl-top\u002Fsection05.webp",[11,258,259],{},"When metrics-server is absent, or its Pod isn't running, trying to run HPA typically produces an error like this:",[211,261,266],{"className":262,"code":264,"language":265},[263],"language-text","failed to get cpu utilization: unable to get metrics for resource cpu: no metrics returned from resource metrics API\n","text",[22,267,264],{"__ignoreMap":216},[11,269,270,271,276],{},"A ",[60,272,275],{"href":273,"rel":274},"https:\u002F\u002Foneuptime.com\u002Fblog\u002Fpost\u002F2026-02-09-hpa-not-scaling-missing-metrics\u002Fview",[64],"troubleshooting guide aimed at on-call engineers"," lays out a diagnostic sequence for exactly this error:",[278,279,280,331,364],"ol",{},[281,282,283,286],"li",{},[27,284,285],{},"Confirm metrics-server exists",[211,287,289],{"className":213,"code":288,"language":215,"meta":216,"style":216},"kubectl get deployment metrics-server -n kube-system\nkubectl get pods -n kube-system -l k8s-app=metrics-server\n",[22,290,291,310],{"__ignoreMap":216},[220,292,293,295,298,301,304,307],{"class":222,"line":223},[220,294,227],{"class":226},[220,296,297],{"class":230}," get",[220,299,300],{"class":230}," deployment",[220,302,303],{"class":230}," metrics-server",[220,305,306],{"class":234}," -n",[220,308,309],{"class":230}," kube-system\n",[220,311,313,315,317,320,322,325,328],{"class":222,"line":312},2,[220,314,227],{"class":226},[220,316,297],{"class":230},[220,318,319],{"class":230}," pods",[220,321,306],{"class":234},[220,323,324],{"class":230}," kube-system",[220,326,327],{"class":234}," -l",[220,329,330],{"class":230}," k8s-app=metrics-server\n",[281,332,333,336],{},[27,334,335],{},"Confirm metrics are actually being returned",[211,337,339],{"className":213,"code":338,"language":215,"meta":216,"style":216},"kubectl top nodes\nkubectl top pods -n default\n",[22,340,341,351],{"__ignoreMap":216},[220,342,343,345,348],{"class":222,"line":223},[220,344,227],{"class":226},[220,346,347],{"class":230}," top",[220,349,350],{"class":230}," nodes\n",[220,352,353,355,357,359,361],{"class":222,"line":312},[220,354,227],{"class":226},[220,356,347],{"class":230},[220,358,319],{"class":230},[220,360,306],{"class":234},[220,362,363],{"class":230}," default\n",[281,365,366,369,393,394,397,398,401,402,405],{},[27,367,368],{},"Confirm the API service registration",[211,370,372],{"className":213,"code":371,"language":215,"meta":216,"style":216},"kubectl get apiservices | grep metrics\n",[22,373,374],{"__ignoreMap":216},[220,375,376,378,380,383,387,390],{"class":222,"line":223},[220,377,227],{"class":226},[220,379,297],{"class":230},[220,381,382],{"class":230}," apiservices",[220,384,386],{"class":385},"sAklC"," |",[220,388,389],{"class":226}," grep",[220,391,392],{"class":230}," metrics\n","\nCheck whether ",[22,395,396],{},"v1beta1.metrics.k8s.io"," shows a Status of ",[22,399,400],{},"True",". If it's ",[22,403,404],{},"False",", metrics-server itself likely has a startup problem.",[11,407,408],{},"Working through these three steps immediately tells you whether you're looking at an HPA misconfiguration or a missing metrics-server altogether. Teams that have only ever worked with K3s often don't even know this diagnostic sequence exists.",[32,410,412],{"id":411},"_5-bundled-and-self-installed-metrics-server-dont-always-behave-the-same","5. Bundled and Self-Installed metrics-server Don't Always Behave the Same",[11,414,415],{},[14,416],{"alt":417,"src":418},"section06","https:\u002F\u002Fcdn.kubo.hexabase.io\u002Fimages\u002Fblog\u002Fen\u002Fk3s-metrics-server-default-kubeadm-hpa-kubectl-top\u002Fsection06.webp",[11,420,421,422,427,428,431,432,435],{},"There's one more wrinkle worth watching for: \"I installed metrics-server, but it behaves differently than it did on K3s.\" According to ",[60,423,426],{"href":424,"rel":425},"https:\u002F\u002Foneuptime.com\u002Fblog\u002Fpost\u002F2026-02-09-monitor-pod-resource-usage-metrics-server\u002Fview",[64],"an article explaining metrics-server resource monitoring",", the binary's own default for ",[22,429,430],{},"--metric-resolution"," is 60 seconds, but the official manifest sets it to ",[22,433,434],{},"--metric-resolution=15s",". Which value is actually running changes how fresh the metrics are that HPA uses to make scaling decisions.",[11,437,438,439,442,443,445],{},"On top of that, flags like ",[22,440,441],{},"--kubelet-insecure-tls",", used to tolerate kubelets with self-signed certificates, can be enabled or disabled differently depending on the distribution and install method. The configuration bundled with K3s and the configuration you get from applying ",[22,444,202],{}," yourself are not guaranteed to match. If HPA feels like it's reacting at a different speed than it used to \"on the same metrics-server,\" this configuration gap is the first thing to suspect.",[11,447,448,449,453],{},"On small clusters, it's also worth paying attention to metrics-server's own resource footprint. Typical startup requirements are cited at around ",[60,450,452],{"href":206,"rel":451},[64],"100m CPU \u002F 200Mi memory in requests",", and that overhead isn't negligible on nodes already under resource pressure.",[32,455,457],{"id":456},"conclusion-on-a-k3s-foundation-this-problem-never-comes-up","Conclusion: On a K3s Foundation, This Problem Never Comes Up",[11,459,460,461,463,464,468],{},"Most cases where HPA or ",[22,462,24],{}," don't work aren't misconfigurations — they're a missing prerequisite: metrics-server. K3s ",[60,465,467],{"href":94,"rel":466},[64],"bundles it by default",", so this problem simply doesn't occur. If you're running standard Kubernetes (kubeadm) yourself, you need to turn metrics-server installation and flag configuration into a checklist you run every time.",[11,470,471,472,475,476,480],{},"The difference between \"it just works\" and \"you run a checklist every time\" quietly adds up as operational cost. ",[60,473,153],{"href":151,"rel":474},[64]," is a managed Kubernetes service built on K3s, where standard addons including metrics-server work from the moment the cluster is up. If you're spending this kind of setup effort on AWS EKS or Azure AKS, you can try the same ",[60,477,479],{"href":151,"rel":478},[64],"Pure Kubernetes setup"," starting at ¥48,000\u002Fmonth.",[11,482,483,484,489],{},"This kind of \"invisible gap in default assumptions\" when migrating clusters shows up far beyond just HPA and metrics-server. If you're carrying similar overhead running standard Kubernetes on your own, feel free to ",[60,485,488],{"href":486,"rel":487},"https:\u002F\u002Fwww.hexabase.com\u002Fcontact-us\u002F",[64],"get in touch"," to talk through what a Kubo setup would look like.",[491,492,493],"style",{},"html pre.shiki code .sE3pS, html code.shiki .sE3pS{--shiki-default:#C0CAF5}html pre.shiki code .sPY7s, html code.shiki .sPY7s{--shiki-default:#9ECE6A}html pre.shiki code .sT800, html code.shiki .sT800{--shiki-default:#E0AF68}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .sAklC, html code.shiki .sAklC{--shiki-default:#89DDFF}",{"title":216,"searchDepth":312,"depth":312,"links":495},[496,498,499,500,501,502],{"id":34,"depth":312,"text":497},"1. The Day kubectl top Went Silent",{"id":82,"depth":312,"text":83},{"id":157,"depth":312,"text":158},{"id":249,"depth":312,"text":250},{"id":411,"depth":312,"text":412},{"id":456,"depth":312,"text":457},"2026-10-24","When kubectl top or HPA suddenly stops working, the first thing to suspect is metrics-server. Here's why K3s ships it by default, why standard Kubernetes (kubeadm) always requires a manual install, and how to diagnose the gap.","md","https:\u002F\u002Fcdn.kubo.hexabase.io\u002Fimages\u002Fblog\u002Fen\u002Fk3s-metrics-server-default-kubeadm-hpa-kubectl-top\u002Ftitle.webp","en",{},true,"\u002Fblog\u002Fen\u002Fk3s-metrics-server-default-kubeadm-hpa-kubectl-top",{"title":5,"description":504},"blog\u002Fen\u002Fk3s-metrics-server-default-kubeadm-hpa-kubectl-top",[514,515,116,516,517],"k3s","kubernetes","hpa","kubeadm","cCTw1eG2Bx9fY9dKGHDAZfGAXSeMllBifRCkM-FWNjg",[520,528,534,542,550,558],{"path":521,"title":522,"description":523,"date":524,"tags":525},"\u002Fblog\u002Fen\u002Fk3s-hpa-not-scaling-metrics-unknown-vpa-death-spiral","Your HPA Config Is Correct. So Why Won't Pods Scale? The Real Cause of 'Unknown Metrics' in K3s and the HPA\u002FVPA Death Spiral","You set up an HPA in K3s and Pods still won't scale. The usual culprits are unset resource requests silently disabling metrics, and a self-reinforcing HPA\u002FVPA feedback loop. Here's how to diagnose and fix it.","2026-09-02",[514,515,516,526,527,116],"vpa","autoscaling",{"path":529,"title":530,"description":531,"date":532,"tags":533},"\u002Fblog\u002Fen\u002Fhpa-vpa-aep-5342-multidimensional-pod-autoscaler","HPA and VPA Conflicts in Kubernetes: How AEP-5342 Aims to Fix What GKE's MPA Couldn't","Running HPA and VPA together has long been considered risky in Kubernetes. GKE's Multidimensional Pod Autoscaler and the upstream AEP-5342 proposal point toward a resolution. Here's what K3s and Kubo users can do today.","2026-10-27",[514,515,516,526,527],{"path":535,"title":536,"description":537,"date":538,"tags":539},"\u002Fblog\u002Fen\u002Fk3s-hpa-containerresource-sidecar-utilization-dilution","HPA Was Scaling on the Sidecar's Share Too. The ContainerResource Blind Spot in Kubernetes","Kubernetes HPA sums resource usage across every container in a Pod, so Istio sidecars and logging agents dilute the scaling decision. Here's how the ContainerResource metric fixes it, in a K3s\u002FKubo context.","2026-10-21",[514,515,516,540,527,541],"containerresource","service-mesh",{"path":543,"title":544,"description":545,"date":546,"tags":547},"\u002Fblog\u002Fen\u002Fk3s-hpa-prometheus-adapter-discovery-interval-stale-metrics","Question Your discoveryInterval: Why K3s HPA Keeps Scaling on Stale Metrics from Prometheus Adapter","K3s HPA won't scale even though CPU usage looks normal. The culprit is a mismatch between Prometheus Adapter's metrics-relist-interval\u002Fmetrics-max-age and the HPA sync-period. Here's the three-layer delay chain and how to diagnose it.","2026-10-12",[514,515,516,548,527,549],"prometheus-adapter","observability",{"path":551,"title":552,"description":553,"date":554,"tags":555},"\u002Fblog\u002Fen\u002Fk3s-kubeadm-ha-etcd-failover-rto-gap","Your RTO Said 30 Seconds. It Took 3 Minutes. Why K3s and kubeadm HA Specs Don't Match Reality","How long does failover really take with K3s embedded etcd versus kubeadm stacked\u002Fexternal etcd? We examine the gap between official RTO targets and real-world recovery times, and how failure domains and node counts differ.","2026-10-09",[514,515,556,557,517],"etcd","high-availability",{"path":559,"title":560,"description":561,"date":562,"tags":563},"\u002Fblog\u002Fen\u002Fkubernetes-hpa-vpa-autoscaling-conflict-design","\"Running Both Feels Safer\" Is the Trap. Why Combining HPA and VPA in Kubernetes Can Send Autoscaling Into a Spiral","Enabling both HPA and VPA in Kubernetes can make two well-intentioned automations fight each other, sending autoscaling into an endless spiral. Here's why the conflict happens, and how to combine them safely with updateMode and metric separation.","2026-10-07",[514,515,516,526,527],1793798724021]