feat: Add metrics-server for pod/node resource metrics

Enables CPU/memory visibility in k9s and kubectl top by deploying
the Kubernetes metrics-server via the metrics.k8s.io API.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Felix Wolf 2026-04-04 14:28:42 +02:00
parent 167fc62b92
commit 8af1321177
18 changed files with 364 additions and 0 deletions

View file

@ -13,3 +13,4 @@ environment:
- proto: node-exporter - proto: node-exporter
- proto: hcloud-csi - proto: hcloud-csi
- proto: cloudnative-pg - proto: cloudnative-pg
- proto: metrics-server

View file

@ -0,0 +1,5 @@
#@data/values-schema
---
#@overlay/match-child-defaults missing_ok=True
application:
namespace: kube-system

View file

@ -0,0 +1,15 @@
---
args:
- --kubelet-insecure-tls
resources:
requests:
cpu: 10m
memory: 32Mi
limits:
memory: 64Mi
tolerations:
- key: node-role.kubernetes.io/control-plane
operator: Exists
effect: NoSchedule

View file

@ -0,0 +1,16 @@
#@ load("@ytt:data", "data")
#@ app = data.values.application
---
apiVersion: vendir.k14s.io/v1alpha1
kind: Config
directories:
- path: #@ "charts/" + app.name
contents:
- path: .
helmChart:
name: #@ app.name
version: #@ app.version
repository:
url: #@ app.url
lazy: true

View file

@ -0,0 +1,8 @@
#@data/values-schema
---
#@overlay/match-child-defaults missing_ok=True
application:
#! renovate: datasource=helm
name: metrics-server
url: https://kubernetes-sigs.github.io/metrics-server/
version: 3.12.2

View file

@ -0,0 +1,10 @@
#@ load("@ytt:data", "data")
#@ load("@ytt:overlay", "overlay")
#@ ns = data.values.application.namespace
#@overlay/match by=overlay.subset({"kind": "APIService"})
---
spec:
service:
namespace: #@ ns

View file

@ -0,0 +1,10 @@
#@ load("@ytt:data", "data")
#@ load("@ytt:overlay", "overlay")
#@ ns = data.values.application.namespace
#@overlay/match by=overlay.subset({"kind": "ClusterRoleBinding"}), expects="1+"
---
subjects:
#@overlay/match by=overlay.all, expects="1+"
- namespace: #@ ns

View file

@ -0,0 +1,10 @@
#@ load("@ytt:data", "data")
#@ load("@ytt:overlay", "overlay")
#@ ns = data.values.application.namespace
#@overlay/match by=overlay.all, expects="1+"
---
metadata:
#@overlay/match missing_ok=True
namespace: #@ ns

View file

@ -0,0 +1,25 @@
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
annotations:
myks.dev/environment: production
finalizers:
- resources-finalizer.argocd.argoproj.io
name: app-production-metrics-server
namespace: argocd
spec:
destination:
namespace: metrics-server
server: https://kubernetes.default.svc
project: env-production
source:
path: rendered/envs/production/metrics-server
repoURL: ssh://git@git.tr1ceracop.de:222/gitea_admin/k8s-and-chill.git
targetRevision: main
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true
- ServerSideApply=true

View file

@ -0,0 +1,23 @@
apiVersion: apiregistration.k8s.io/v1
kind: APIService
metadata:
annotations:
a8r.io/repository: ssh://git@git.tr1ceracop.de:222/gitea_admin/k8s-and-chill.git
labels:
app.kubernetes.io/instance: metrics-server
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/name: metrics-server
app.kubernetes.io/version: 0.7.2
helm.sh/chart: metrics-server-3.12.2
name: v1beta1.metrics.k8s.io
namespace: kube-system
spec:
group: metrics.k8s.io
groupPriorityMinimum: 100
insecureSkipTLSVerify: true
service:
name: metrics-server
namespace: kube-system
port: 443
version: v1beta1
versionPriority: 100

View file

@ -0,0 +1,26 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
annotations:
a8r.io/repository: ssh://git@git.tr1ceracop.de:222/gitea_admin/k8s-and-chill.git
labels:
app.kubernetes.io/instance: metrics-server
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/name: metrics-server
app.kubernetes.io/version: 0.7.2
helm.sh/chart: metrics-server-3.12.2
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:metrics-server-aggregated-reader
namespace: kube-system
rules:
- apiGroups:
- metrics.k8s.io
resources:
- pods
- nodes
verbs:
- get
- list
- watch

View file

@ -0,0 +1,31 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
annotations:
a8r.io/repository: ssh://git@git.tr1ceracop.de:222/gitea_admin/k8s-and-chill.git
labels:
app.kubernetes.io/instance: metrics-server
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/name: metrics-server
app.kubernetes.io/version: 0.7.2
helm.sh/chart: metrics-server-3.12.2
name: system:metrics-server
namespace: kube-system
rules:
- apiGroups:
- ""
resources:
- nodes/metrics
verbs:
- get
- apiGroups:
- ""
resources:
- pods
- nodes
- namespaces
- configmaps
verbs:
- get
- list
- watch

View file

@ -0,0 +1,21 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
annotations:
a8r.io/repository: ssh://git@git.tr1ceracop.de:222/gitea_admin/k8s-and-chill.git
labels:
app.kubernetes.io/instance: metrics-server
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/name: metrics-server
app.kubernetes.io/version: 0.7.2
helm.sh/chart: metrics-server-3.12.2
name: metrics-server:system:auth-delegator
namespace: kube-system
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:auth-delegator
subjects:
- kind: ServiceAccount
name: metrics-server
namespace: kube-system

View file

@ -0,0 +1,21 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
annotations:
a8r.io/repository: ssh://git@git.tr1ceracop.de:222/gitea_admin/k8s-and-chill.git
labels:
app.kubernetes.io/instance: metrics-server
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/name: metrics-server
app.kubernetes.io/version: 0.7.2
helm.sh/chart: metrics-server-3.12.2
name: system:metrics-server
namespace: kube-system
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:metrics-server
subjects:
- kind: ServiceAccount
name: metrics-server
namespace: kube-system

View file

@ -0,0 +1,84 @@
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
a8r.io/repository: ssh://git@git.tr1ceracop.de:222/gitea_admin/k8s-and-chill.git
labels:
app.kubernetes.io/instance: metrics-server
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/name: metrics-server
app.kubernetes.io/version: 0.7.2
helm.sh/chart: metrics-server-3.12.2
name: metrics-server
namespace: kube-system
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/instance: metrics-server
app.kubernetes.io/name: metrics-server
template:
metadata:
labels:
app.kubernetes.io/instance: metrics-server
app.kubernetes.io/name: metrics-server
spec:
containers:
- args:
- --secure-port=10250
- --cert-dir=/tmp
- --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname
- --kubelet-use-node-status-port
- --metric-resolution=15s
- --kubelet-insecure-tls
image: registry.k8s.io/metrics-server/metrics-server:v0.7.2
imagePullPolicy: IfNotPresent
livenessProbe:
failureThreshold: 3
httpGet:
path: /livez
port: https
scheme: HTTPS
initialDelaySeconds: 0
periodSeconds: 10
name: metrics-server
ports:
- containerPort: 10250
name: https
protocol: TCP
readinessProbe:
failureThreshold: 3
httpGet:
path: /readyz
port: https
scheme: HTTPS
initialDelaySeconds: 20
periodSeconds: 10
resources:
limits:
memory: 64Mi
requests:
cpu: 10m
memory: 32Mi
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
readOnlyRootFilesystem: true
runAsNonRoot: true
runAsUser: 1000
seccompProfile:
type: RuntimeDefault
volumeMounts:
- mountPath: /tmp
name: tmp
priorityClassName: system-cluster-critical
serviceAccountName: metrics-server
tolerations:
- effect: NoSchedule
key: node-role.kubernetes.io/control-plane
operator: Exists
volumes:
- emptyDir: {}
name: tmp

View file

@ -0,0 +1,21 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
annotations:
a8r.io/repository: ssh://git@git.tr1ceracop.de:222/gitea_admin/k8s-and-chill.git
labels:
app.kubernetes.io/instance: metrics-server
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/name: metrics-server
app.kubernetes.io/version: 0.7.2
helm.sh/chart: metrics-server-3.12.2
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: metrics-server

View file

@ -0,0 +1,24 @@
apiVersion: v1
kind: Service
metadata:
annotations:
a8r.io/repository: ssh://git@git.tr1ceracop.de:222/gitea_admin/k8s-and-chill.git
labels:
app.kubernetes.io/instance: metrics-server
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/name: metrics-server
app.kubernetes.io/version: 0.7.2
helm.sh/chart: metrics-server-3.12.2
name: metrics-server
namespace: kube-system
spec:
ports:
- appProtocol: https
name: https
port: 443
protocol: TCP
targetPort: https
selector:
app.kubernetes.io/instance: metrics-server
app.kubernetes.io/name: metrics-server
type: ClusterIP

View file

@ -0,0 +1,13 @@
apiVersion: v1
kind: ServiceAccount
metadata:
annotations:
a8r.io/repository: ssh://git@git.tr1ceracop.de:222/gitea_admin/k8s-and-chill.git
labels:
app.kubernetes.io/instance: metrics-server
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/name: metrics-server
app.kubernetes.io/version: 0.7.2
helm.sh/chart: metrics-server-3.12.2
name: metrics-server
namespace: kube-system