Tutorial: Learn how to quickly install the Metrics Server in minikube in five easy steps! 🧊
This instructional explains how to install the Metrics Server in Kubernetes (k8s, see also the Kubernetes page on Wikipedia) specifically using minikube; we’ll also explore how to solve the “cannot validate certificate for” x509 IP SANs Error as well, which appears with some frequency during the installation process.
Install minikube Metrics Server TOC
Learn How To Solve The "cannot validate certificate for" x509 IP SANs Error in minikube Metrics Server
The following practice question for the Certified Kubernetes Application Developer (CKAD) exam came up this weekend while reviewing the observability exercises available on Dimitris-Ilias Gkanatsios’ CKAD Exercises project page:
Get CPU/memory utilization for nodes (metrics-server must be running)
Configuring the Metrics Server in Minikube can be helpful when managing microservices in Kubernetes as it monitors CPU and memory usage data.
Installing the Kubernetes (K8s) Metrics Server appears to be a straightforward one-liner from the command line (CLI) however I ran into problems while using minikube on both Ubuntu and OSX.
Below I have the full details of the issue along with a full example of a working solution (the issue on GitHub includes the correct command however it doesn’t indicate where exactly it needs to be placed — we cover this below).
In this example, we rely on Kubectl version v1.19.4, Kubernetes version v1.17.3, and Docker version v19.03.6.
This article was updated on May 27, 2025.
The Problem: Unexpected x509 certificate validation errors
Step One: Install the minikube Metrics Server from components.yaml
According to the kubernetes-sigs / metrics-server page we should be able to install the Metrics Server in minikube with a single line (step one):
kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
This results in the following, which looks promising:
creationTimestamp: “2020-11-29T22:07:21Z”
serviceaccount/metrics-server created
clusterrole.rbac.authorization.k8s.io/system:aggregated-metrics-reader created
clusterrole.rbac.authorization.k8s.io/system:metrics-server created
rolebinding.rbac.authorization.k8s.io/metrics-server-auth-reader created
clusterrolebinding.rbac.authorization.k8s.io/metrics-server:system:auth-delegator created
clusterrolebinding.rbac.authorization.k8s.io/system:metrics-server created
service/metrics-server created
deployment.apps/metrics-server created
apiservice.apiregistration.k8s.io/v1beta1.metrics.k8s.io created
— however on closer inspection, we can see that the Metrics-Server isn’t working — for example, executing the top command as follows:
kubectl top nodes
returns:
Error from server (ServiceUnavailable): the server is currently unable to handle the request (get nodes.metrics.k8s.io)
and executing:
kubectl get deployment metrics-server -n kube-system
returns:
NAME READY UP-TO-DATE AVAILABLE AGE
metrics-server 0/1 1 0 105s
— which is also wrong.
I’ve included an image below with blue arrows that point to the command and several orange arrows that direct your attention to the output that shows that the Metrics Server is unavailable.
The block in orange is directly related to the issue on Github entitled “metrics-server error because it doesn’t contain any IP SANs” — buried in the conversation is one suggested solution that works and we’ll cover that next.
I’ve included the kubectl logs command, which appears in the orange box, below.
kubectl logs -n kube-system deploy/metrics-server
Do you need to hire an Interim CTO?
The Solution: Add commands to the minikube Metrics Server
Step Two: Modify The components.yaml File
In order to fix this we need to add the following command to the components.yaml file:
command:
- /metrics-server
- --kubelet-insecure-tls
- --kubelet-preferred-address-types=InternalIP
Below we have the complete file with notes, see lines 141 to 215, specifically as this is where the change needs to be applied.
#
# https://gist.github.com/thospfuller/d0d918e0b9fdb719a34d3d355b0886bb
#
# Jump to line ~ 141 to ~ 215 for the command that pertains to this change.
#
apiVersion: v1
kind: ServiceAccount
metadata:
labels:
k8s-app: metrics-server
name: metrics-server
namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
labels:
k8s-app: metrics-server
rbac.authorization.k8s.io/aggregate-to-admin: "true"
rbac.authorization.k8s.io/aggregate-to-edit: "true"
rbac.authorization.k8s.io/aggregate-to-view: "true"
name: system:aggregated-metrics-reader
rules:
- apiGroups:
- metrics.k8s.io
resources:
- pods
- nodes
verbs:
- get
- list
- watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
labels:
k8s-app: metrics-server
name: system:metrics-server
rules:
- apiGroups:
- ""
resources:
- pods
- nodes
- nodes/stats
- namespaces
- configmaps
verbs:
- get
- list
- watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
labels:
k8s-app: metrics-server
name: metrics-server-auth-reader
namespace: kube-system
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: extension-apiserver-authentication-reader
subjects:
- kind: ServiceAccount
name: metrics-server
namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
labels:
k8s-app: metrics-server
name: metrics-server:system:auth-delegator
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:auth-delegator
subjects:
- kind: ServiceAccount
name: metrics-server
namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
labels:
k8s-app: metrics-server
name: system:metrics-server
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:metrics-server
subjects:
- kind: ServiceAccount
name: metrics-server
namespace: kube-system
---
apiVersion: v1
kind: Service
metadata:
labels:
k8s-app: metrics-server
name: metrics-server
namespace: kube-system
spec:
ports:
- name: https
port: 443
protocol: TCP
targetPort: https
selector:
k8s-app: metrics-server
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
k8s-app: metrics-server
name: metrics-server
namespace: kube-system
spec:
selector:
matchLabels:
k8s-app: metrics-server
strategy:
rollingUpdate:
maxUnavailable: 0
template:
metadata:
labels:
k8s-app: metrics-server
spec:
containers:
- args:
- --cert-dir=/tmp
- --secure-port=4443
- --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname
- --kubelet-use-node-status-port
image: k8s.gcr.io/metrics-server/metrics-server:v0.4.1
imagePullPolicy: IfNotPresent
#
# Precondition: Metrics Server installation attempted on Minikube (on Ubuntu) as per:
#
# https://github.com/kubernetes-sigs/metrics-server
#
# Specifically, the instructions suggest running the following in order to install the Metrics Server:
#
# kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
#
# and running:
#
# kubectl top nodes
#
# results in:
#
# "Error from server (ServiceUnavailable): the server is currently unable to handle the request (get nodes.metrics.k8s.io)"
#
# and running:
#
# kubectl get deployment metrics-server -n kube-system
#
# results in something that looks like:
#
# NAME READY UP-TO-DATE AVAILABLE AGE
# metrics-server 1/1 1 0 6m
#
# -----
#
# We can see in the log that there's a problem:
#
# kubectl logs -n kube-system deploy/metrics-server
#
# E1129 22:08:56.736988 1 server.go:132] unable to fully scrape metrics: [unable to fully scrape metrics from node minikube: unable to fetch metrics from node minikube: Get "https://192.168.99.100:10250/stats/summary?only_cpu_and_memory=true": x509: cannot validate certificate for 192.168.99.100 because it doesn't contain any IP SANs, unable to fully scrape metrics from node m01: unable to fetch metrics from node m01: Get "https://192.168.99.100:10250/stats/summary?only_cpu_and_memory=true": x509: cannot validate certificate for 192.168.99.100 because it doesn't contain any IP SANs]
# I1129 22:08:56.748352 1 requestheader_controller.go:169] Starting RequestHeaderAuthRequestController
# I1129 22:08:56.748378 1 shared_informer.go:240] Waiting for caches to sync for RequestHeaderAuthRequestController
# I1129 22:08:56.748400 1 configmap_cafile_content.go:202] Starting client-ca::kube-system::extension-apiserver-authentication::client-ca-file
# I1129 22:08:56.748404 1 shared_informer.go:240] Waiting for caches to sync for client-ca::kube-system::extension-apiserver-authentication::client-ca-file
# I1129 22:08:56.748414 1 configmap_cafile_content.go:202] Starting client-ca::kube-system::extension-apiserver-authentication::requestheader-client-ca-file
# I1129 22:08:56.748417 1 shared_informer.go:240] Waiting for caches to sync for client-ca::kube-system::extension-apiserver-authentication::requestheader-client-ca-file
# I1129 22:08:56.749024 1 secure_serving.go:197] Serving securely on [::]:4443
# I1129 22:08:56.749096 1 dynamic_serving_content.go:130] Starting serving-cert::/tmp/apiserver.crt::/tmp/apiserver.key
# I1129 22:08:56.749163 1 tlsconfig.go:240] Starting DynamicServingCertificateController
# I1129 22:08:56.848729 1 shared_informer.go:247] Caches are synced for client-ca::kube-system::extension-apiserver-authentication::requestheader-client-ca-file
# I1129 22:08:56.848758 1 shared_informer.go:247] Caches are synced for client-ca::kube-system::extension-apiserver-authentication::client-ca-file
# I1129 22:08:56.849090 1 shared_informer.go:247] Caches are synced for RequestHeaderAuthRequestController
#
# -----
#
# The solution at the link below will remedy this issue:
#
# https://github.com/kubernetes-sigs/metrics-server/issues/196#issuecomment-451061841
#
# And we'll need to either modify the component.yaml file with the command below and
# apply the file or we can edit the current configuration using:
#
# kubectl edit deployment -n kube-system metrics-server
#
# Then execute:
#
# minikube stop
# minikube start
#
# and try "kubectl top nodes" again and the Metrics Server should be working now.
#
# See also:
# * https://github.com/kubernetes-sigs/metrics-server/issues/196
# * https://github.com/juan-vg/metrics-server/commit/264f9c551abdeedc575d36e74da40671c51cb747
#
command:
- /metrics-server
- --kubelet-insecure-tls
- --kubelet-preferred-address-types=InternalIP
#
# Changes end.
#
livenessProbe:
failureThreshold: 3
httpGet:
path: /livez
port: https
scheme: HTTPS
periodSeconds: 10
name: metrics-server
ports:
- containerPort: 4443
name: https
protocol: TCP
readinessProbe:
failureThreshold: 3
httpGet:
path: /readyz
port: https
scheme: HTTPS
periodSeconds: 10
securityContext:
readOnlyRootFilesystem: true
runAsNonRoot: true
runAsUser: 1000
volumeMounts:
- mountPath: /tmp
name: tmp-dir
nodeSelector:
kubernetes.io/os: linux
priorityClassName: system-cluster-critical
serviceAccountName: metrics-server
volumes:
- emptyDir: {}
name: tmp-dir
---
apiVersion: apiregistration.k8s.io/v1
kind: APIService
metadata:
labels:
k8s-app: metrics-server
name: v1beta1.metrics.k8s.io
spec:
group: metrics.k8s.io
groupPriorityMinimum: 100
insecureSkipTLSVerify: true
service:
name: metrics-server
namespace: kube-system
version: v1beta1
versionPriority: 100
Step Three: Apply the components.yaml file to your local minikube metrics server deployment
Once we’ve edited the configuration directly, we can restart minikube and we should see something that looks like what we have below.
Note that the green arrows point to output that indicates that the Metrics Server is now running correctly — you should see something similar to this.
You can edit your components.yaml file however you’ll need to apply the configuration file once the change has been added — so either (step three):
kubectl edit deployment -n kube-system metrics-server
and add this text to the appropriate place
or
modify the components.yaml file and then run:
kubectl apply -f ./components.yaml
Step Four: Stop minikube
In the next step we’ll stop minikube as follows:
minikube stop
See the first blue arrow below:
Step Five: Start minikube
Finally, we’ll start minikube as follows:
minikube start
See the second blue arrow below and also note that the green arrows indicate that the metrics API is now running correctly.
As the minikube Metrics Server is now installed correctly, this issue has been resolved.
Step Six (optional): Configure the minikube Metrics-Server to allow for anonymous access
At this point the Metrics-Server is running in minikube however in order to access it locally we’ll need to execute several additional steps.
The first step is to map the Metrics Server port from 443 to 8080 — we can do this using the following command:
kubectl port-forward -n kube-system service/metrics-server 8080:443
We can see the result of executing this command successfully below.
We can use the following command to curl the k8s Metrics Server nodes endpoint:
curl -k https://localhost:8080/apis/metrics.k8s.io/v1beta1/nodes
however when we attempt to curl the this endpoint we’ll encounter the following error:
nodes.metrics.k8s.io is forbidden: User “system:anonymous” cannot list resource “nodes” in API group “metrics.k8s.io” at the cluster scope
— this is demonstrated in the image below:
Likewise, we can also use the following command to curl the k8s Metrics Server pods endpoint:
curl -k https://localhost:8080/apis/metrics.k8s.io/v1beta1/pods
and, in this case, a similar error is encountered:
pods.metrics.k8s.io is forbidden: User “system:anonymous” cannot list resource “pods” in API group “metrics.k8s.io” at the cluster scope
— this is also demonstrated in the image below:
In order to address this issue we need to apply the anonymous-metrics-server-access.yaml file, which grants temporary access to the Metrics Server API for anonymous users.
This file, which has been included below, allows anonymous users the ability to retrieve node and pod metrics without encountering “forbidden” errors due to insufficient permissions.
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: metrics-reader
rules:
- apiGroups: ["metrics.k8s.io"]
resources: ["pods", "nodes"]
verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: metrics-reader-binding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: metrics-reader
subjects:
- kind: User
name: "system:anonymous"
apiGroup: rbac.authorization.k8s.io
WARNING: This file is appropriate for working locally with minikube.
This file is not appropriate for use in production or any environment where security is a concern, as it grants broad access to metrics data to anonymous users thereby potentially exposing sensitive information about resource usage in your cluster.
In security-sensitive environments, it is best to grant access to specific authenticated users or service accounts with appropriate permissions.
We can apply these settings by using the following command:
kubectl apply -f anonymous-metrics-server-access.yaml
An example of this command being successfully executed can be seen here:
Once we’ve successfully applied the anonymous-metrics-server-access.yaml file we’ll be able to curl the /nodes endpoint with the following command:
curl -k https://localhost:8080/apis/metrics.k8s.io/v1beta1/nodes
and we should receive a response that looks something like this:
We’ll also be able to curl the /pods endpoint as follows:
curl -k https://localhost:8080/apis/metrics.k8s.io/v1beta1/pods
and we should receive a response that looks similar to the following:
This concludes this section — the article conclusion follows.
If you found this guide to be helpful you may also like the article I wrote that explores five mock CKAD sample questions including answers and verification that the provided solutions work.
Questions and comments are welcomed.
Frequently Asked Questions (FAQ)
The Metrics Server in Kubernetes (k8s) is a scalable, efficient, and Kubernetes-native solution for aggregating resource usage data, such as CPU and memory, from each node and pod in a Kubernetes cluster. The k8s Metrics Server serves as a backend for the Kubernetes Horizontal Pod Autoscaler, which automatically scales the number of pod replicas based on observed CPU and memory usage. The Metrics Server collects this data at regular intervals, processes it, and then exposes it via the Kubernetes API, making it accessible for various use cases like autoscaling or capacity planning.
Learn how to install the Kubernetes Metrics Server in minikube in five steps here.
The Kubernetes Metrics Server has been released under the Apache License 2.0 license. The Apache License 2.0 license is a permissive free software license written by the Apache Software Foundation that allows users considerable freedom in using the software for any purpose, including commercial and proprietary uses.
See Also
- RBAC Minikube
- Learn how to use kubectl to get the cluster name in this guide.











