Monitoring a Kubernetes-hosted .NET application often starts with a simple question: how much CPU and memory is each Pod using?
Developers commonly answer that question with:
kubectl top pods
Behind this command is the Kubernetes resource metrics API, exposed through the metrics.k8s.io API group.
Kubernetes 1.37 promotes the Resource Metrics API to stable, providing a more mature API surface for accessing CPU and memory usage for Nodes and Pods. The API is served by the Metrics Server rather than directly by the Kubernetes API server.
For .NET teams, this matters when building dashboards, autoscaling workflows, deployment diagnostics, or internal tools that need Kubernetes resource-usage information without depending on the human-readable output of kubectl top.
What Is the metrics.k8s.io API?
The Resource Metrics API provides resource usage information for Kubernetes Nodes and Pods.
Its API group is:
metrics.k8s.io
The two primary resources are:
nodes
pods
A simplified architecture looks like this:
.NET Application
|
v
Pod
|
v
Metrics Server
|
v
metrics.k8s.io API
|
v
Kubernetes clients / HPA
The API provides CPU and memory metrics, which are useful for short-term resource usage information. It is not intended to replace a full monitoring system for long-term historical metrics.
Why This Matters for .NET Developers
A .NET application's resource behavior can change significantly under different workloads.
For example:
Low traffic
↓
CPU: 50m
Memory: 180Mi
High traffic
↓
CPU: 700m
Memory: 420Mi
If the Pod has:
resources:
requests:
cpu: "250m"
memory: "256Mi"
limits:
cpu: "1"
memory: "512Mi"
the actual usage can be compared with the configured requests and limits.
This helps answer questions such as:
Is the Pod regularly exceeding its CPU request?
Is memory usage approaching its limit?
Are replicas balanced?
Is the application under resource pressure?
Is an HPA receiving resource metrics?
The Resource Metrics Pipeline
It is important to understand where the numbers come from.
A simplified Kubernetes resource-metrics pipeline is:
Kubelet
|
| Resource usage
v
Metrics Server
|
| Aggregated metrics API
v
metrics.k8s.io
|
+--> kubectl top
|
+--> HPA
|
+--> Custom clients
Metrics Server collects resource metrics from Kubelets and exposes them through the Kubernetes API aggregation layer.
This distinction is important when troubleshooting.
If:
kubectl top pods
does not return data, the .NET application may be completely healthy. The problem could instead be in Metrics Server, Kubelet metrics collection, API aggregation, authentication, or networking.
Checking Pod Metrics
The easiest way to inspect resource metrics is:
kubectl top pods
For a specific namespace:
kubectl top pods -n production
You may see output similar to:
NAME CPU(cores) MEMORY(bytes)
orders-api-7c8f7b9d5f-a1b2c 120m 220Mi
orders-api-7c8f7b9d5f-c3d4e 135m 235Mi
These values provide a current resource-usage view.
For a production monitoring system, however, do not treat kubectl top as your historical monitoring solution.
Accessing the API Directly
The Resource Metrics API can be queried through the Kubernetes API server.
For example:
kubectl get --raw \
"/apis/metrics.k8s.io/v1beta1/namespaces/default/pods"
The API version available in a particular cluster should be checked rather than hardcoded into tooling.
The important point is that applications can consume structured API responses instead of parsing CLI output.
A response contains resource usage for Pods, including CPU and memory information.
Calling Kubernetes Metrics From .NET
A .NET service that has appropriate Kubernetes API permissions can query the resource metrics API.
A simple approach is to use HttpClient against the Kubernetes API server.
For example:
using System.Net.Http.Headers;
public sealed class KubernetesMetricsClient
{
private readonly HttpClient _httpClient;
public KubernetesMetricsClient(HttpClient httpClient)
{
_httpClient = httpClient;
}
public async Task<string> GetPodMetricsAsync(
string namespaceName,
CancellationToken cancellationToken)
{
var path =
$"/apis/metrics.k8s.io/v1beta1/" +
$"namespaces/{namespaceName}/pods";
using var response =
await _httpClient.GetAsync(
path,
cancellationToken);
response.EnsureSuccessStatusCode();
return await response.Content.ReadAsStringAsync(
cancellationToken);
}
}
In a real application, the client should deserialize the response into typed models rather than returning a raw string.
More importantly, the application needs Kubernetes authentication and authorization configured correctly.
Do Not Give Applications Excessive Kubernetes Permissions
A monitoring application should follow the principle of least privilege.
For example, if it only needs to read Pod metrics, its Kubernetes permissions should not include unrelated operations such as:
create deployments
delete pods
update secrets
patch nodes
A minimal read-only permission model is preferable.
A conceptual RBAC configuration might look like:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: pod-metrics-reader
rules:
- apiGroups:
- metrics.k8s.io
resources:
- pods
verbs:
- get
- list
The exact RBAC scope should be reduced further when namespace-level access is sufficient.
Metrics API vs .NET Application Metrics
One of the most important distinctions is that metrics.k8s.io and .NET application metrics measure different things.
Join the conversation! Your thoughts help the community grow.