How to access metrics in Kubernetes
First, let me say that there are multiple solutions to achieve the same outcome. One of the simplest ones is to install Kubernetes Dashboard and call it good. That said, though, while the dashboard is an effective way to quickly get insight into your cluster, perhaps you want to grab the metrics and feed them into our own data pipeline for more serious cluster performance monitoring.
The case I want to present today is somewhere between the Dashboard and the Data Pipeline. In these next few articles, we'll use a .NET Core library called KubeClient to retrieve metrics from the cluster's API and print them to console. In the example code, we'll write a simple .NET Core console application in preparation for turning into a cron job in a future article. Let's get started.
You can create a new project via dotnet new console
and add the KubeClient package I linked above. I created a new directory called KubeMetricScraper to house this project.
mkdir KubeMetricScraper
cd KubeMetricScraper
dotnet new console
dotnet add package KubeClient
You should see in your KubeMetricScraper.csproj file the following:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="KubeClient" Version="2.3.11" />
</ItemGroup>
</Project>
Obviously if you're doing this months from now when .NET Core is version 17.8 or whatever, you'll see a different target framework. You'll have to make sure that KubeClient can run in the version of netcore you're targeting.
Let's add a couple more packages:
dotnet add package microsoft.extensions.logging
dotnet add package microsoft.extensions.logging.console
dotnet add package newtonsoft.json
Open up the project using whatever editor you like and let's take a look at what KubeClient can do. First, let's add the logger:
class Program
{
static async Task Main(string[] args)
{
ILoggerFactory loggers = new LoggerFactory();
loggers.AddConsole();
}
}
You'll notice I swapped the default void
for async Task
. This is a feature of C# 7.1 so if you're running something older than that, you'll need to stick to void
and use GetAwaiter()
in the code whenever asynchronous code shows up. Hopefully you're on 7.1 though, because that's ugly.
Below the loggers let's instantiate the KubeCpiClient:
var client = KubeApiClient.Create("http://localhost:8001", loggers);
Above code requires that you're running kube proxy
and have proxy access to the cluster. To set that up, you need kubectl installed and an SSH key registered with the cluster. For more information, the official docs are actually not bad. Assuming you have all that set up, let's continue on with C#.
var nodes = await client.NodesV1().List();
var serializedNodes = JsonConvert.SerializeObject(nodes);
Console.WriteLine(serializedNodes, Formatting.Indented);
This should print out a list of nodes in your cluster. Great! Try this:
var pods = await client.PodsV1().List(null, "default");
When querying pods, you can provide the label and the namespace. If you don't provide the namespace, the default
namespace is used. If you've been following my past articles, you can replace "default"
with "integration"
to get a list of pods in there.
You can also retrieve namespaces, services, jobs and more using the same syntax. Unfortunately, with the basic KubeClient, you cannot retrieve metrics. But wait... how then? The title of this article promised me...
One of KubeClient's chief perks is its extensibility. The library exposes the underlying ResourceClient and lets you build your own API queries on top of it. Anything the base KubeClient doesn't cover, you can build yourself. That's exactly what we're going to do in the next article.
Your code by the end of this article should look like this:
class Program
{
static async Task Main(string[] args)
{
ILoggerFactory loggers = new LoggerFactory();
loggers.AddConsole();
var nodes = await client.NodesV1().List();
var serializedNodes = JsonConvert.SerializeObject(nodes);
Console.WriteLine(serializedNodes, Formatting.Indented);
var pods = await client.PodsV1().List(null, "default");
var serializedPods = JsonConvert.SerializeObject(pods);
Console.WriteLine(serializedPods, Formatting.Indented);
Console.ReadLine();
}
}
I encourage you to see what else KubeClient has to offer. In the next article we'll build a KubeClient extension and get us some metrics.