How to programmatically consume the Kubernetes API in Azure

.NET Azure Kubernetes
Kubernetes provides you the capability to create true microservices architecture by spinning up short running pods that are managed by a central management service. Each pod is a self-contained instance of an operating system (for example, Linux) which starts with a set of directives, executing applications (for example a Python or PHP script) with the desired input parameters or environment variables.

NOTE: This post assumes that you already have some experience working with Azure and Kubernetes.

What we will do



In this post, we will go through the steps for how to consume the API in your Azure Kubernetes Cluster programmatically, with C#.

Simplified, we will:

  1. Create a service principal

  2. Use the Azure Management SDK to authenticate

  3. Use the Azure Manager to fetch the Administrator token from Kubernetes

  4. Execute a HTTP request against the Kubernetes API


Ready? Let's do it!

Create a service principal



Open your browser and go to portal.azure.com

In the Portal, open the Active Directory blade.

Go to App registrations.

Click + New registration and follow the wizard to create your service principal.

The Service Principal (App Registration) will be the "user" you will use to access Kubernetes via the Azure Management SDK.

Take a careful note of your Application (client) ID and Directory (tenant) ID.

Under Manage in the menu, open Certificates & secrets.

Click + New client secret to add a new client secret and make a careful note of the Value once it has been created!

Grant access to the service principal in Kubernetes



Go to the portal home again and open the Kubernetes services blade.

Open your desired Kubernetes serice and click Access control (IAM) in the menu.

Here, we need to grant permission to the service principal (app registration) we just created, so that we can later retrieve the administrator token for the cluster.

In the usual way, grant a role assignment for the service principal. The role "Contributor" should be OK.

When you've done that, let's open up Visual Studio and get ready to code!

Authenticate with the Azure Management SDK



I'm going to be programming this in a Console Application, but really, this technique applies to any platform, be it a desktop application, Web API, Azure Function, etc.

When you've got your project set up, you'll need to install a NuGet package.

Open the package manager and install Microsoft.Azure.Management.Fluent

When that's installed, find a suitable place to write your C# code. We'll be using await, so make sure you are working in an async Task method.

Add these using directives to the top of the file:


using Microsoft.Azure.Management.ResourceManager.Fluent;
using Microsoft.Azure.Management.Fluent;
using System.Text;
using System.Text.RegularExpressions;
using System.Net.Http;


Since we want to use the Azure management SDK, we better start off by creating the credentials. For this, we use the Azure Credentials Factory in the SDK Context.


var credentials = SdkContext.AzureCredentialsFactory
.FromServicePrincipal(
clientId: APPLICATION_ID,
clientSecret: CLIENT_SECRET,
tenantId: DIRECTORY_ID,
environment: AzureEnvironment.AzureGlobalCloud);


Obviously, you need to replace the constants (in capital letters) with the values that you carefully made a note of earlier 🤓

The next thing to do is create an instance of an implemented IAzure interface by using the Fluent API.


IAzure azure = Azure
.Configure()
.Authenticate(credentials)
.WithSubscription(SUBSCRIPTION_ID);


The SUBSCRIPTION_ID should be the GUID which is found in the portal on the Overview of your Kubernetes service.

Get the Kubernetes admin config



Next, we need to get the administrator configuration for Kubernetes:


var bytes = await azure.KubernetesClusters.GetAdminKubeConfigContentsAsync(
resourceGroupName: RESOURCE_GROUP,
kubernetesClusterName: CLUSTER_NAME);


This is a bit strange, as it actually returns an array of bytes, which is not exactly intuitive from an SDK-perspective.

To convert these bytes to a string, use:


var str = Encoding.UTF8.GetString(bytes);


The payload received is actually a YAML file, not JSON.

Extract the token



We need to extract the token from this YAML string. The token is effectively a SHA-512 hash (128 character hex), so we can use regex to accomplish this.


var regex = new Regex("[ ]{4}token: ([0-9a-f]{128})([ ]|$)");

var match = regex.Match(str);

string token;

if (match.Success)
{
token = match.Groups[1].Value;
}
else throw new Exception("Unable to extract token!");


Now we've got the token, we can use this as a Bearer token for the Kubernetes API request.

This document describes how to use Bearer tokens for OAuth in detail:
tools.ietf.org

Kubernetes API targeting



Back in the portal, you need to determine the link to your Kubernetes API.

This is found under your Kubernetes service Overview, under API server address. This typically ends in .azmk8s.io

Make a note of this host name, you'll use it in the next step...

Create a message request



You can use the HttpRequestMessage class to create the request message.

The URL you want to target is:
https:// mykubernetescluster.azmk8s.io /api/v1/namespaces/my-namespace/pods

Replace the host with your actual Kubernetes API server address.

Replace my-namespace with your desired Kubernetes namespace.

See the Kubernetes documentation:
kubernetes.io

You may use some code similar to this:


var builder = new UriBuilder("https", API_SERVER_ADDRESS);
builder.Path = "/api/v1/namespaces/default/pods";

var message = new HttpRequestMessage();
message.Method = new HttpMethod("GET");
message.RequestUri = builder.Uri;
message.Headers.Add("Authorization", "Bearer " + token);


See the Kubernetes API reference:
kubernetes.io

Send the request message



Be aware, that in some case, you may experience SSL errors when targeting the Kubernetes API error in Azure. If this happens, you can use a Http client handler with a custom certificate validation callback function. I've included this in the example below.


var client = new HttpClient(new HttpClientHandler()
{
ServerCertificateCustomValidationCallback = (w, x, y, z) => true
});

var response = await client.SendAsync(message);

var content = await response.Content.ReadAsStringAsync();


And that's it! The content string will usually be some sort of JSON representing the object returned by the server.

Summary



A service principal must have permissions granted to it for the Kubernetes cluster. Use the Azure Management SDK to fetch the Adminstrator token. Use HTTP requests to target the API and execute GET or POST requests.

Happy coding! Please support me by leaving a comment and sharing this article 👍
Hey you! I need your help!

Thanks for reading! All the content on this site is free, but I need your help to spread the word. Please support me by:

  1. Sharing my page on Facebook
  2. Tweeting my page on Twitter
  3. Posting my page on LinkedIn
  4. Bookmarking this site and returning in the near future
Thank you!