Friday, April 9, 2021

Azure AKS- Scale out to ACI through virtual nodes

One of the nice features of AKS(Azure Kubernetes Service) is that you can create a virtual nodes that can be used to scale out to ACI.

This feature is really useful in following scenario’s:

  • Temporary burst of capacity
  • On-demand processing, e.g. batch jobs
  • Isolated processing for untrusted code

The virtual nodes feature is build on top of the Virtual Kubelet technology.

To enable this feature you need to extend the deployment yaml with the configuration below. This configuration will first try to schedule the pod on the default node pools. If not enough resources are available, the pod will be scheduled on the virtual node:

A good introduction can be found here:


Remark: Virtual nodes only supports Linux pods at the moment of writing

Thursday, April 8, 2021

Application Insights–Report browser usage

I was looking at a way to report browser usage statistics through Application Insights.

Here are the required steps:

  • Browse to the Application Insights resource in the Azure Portal
  • Go to the Monitoring section and click on Logs

  • Click on Get Started on the Welcome screen

  • Close the queries screen

  • Enter the following query and click on Run
    • pageViews | summarize count() by client_Browser

  • Check the results


Wednesday, April 7, 2021

AutoRest- Duplicate operation detected

I was trying to use AutoRest to generate a client SDK for one of my API’s. This turned out not to be the success I was hoping for.

Yesterday I explained that I got into trouble because an OperationId was missing. But after adding it, it still didn’t work. Instead I got the following error message:

Duplicate operation detected

Here was the API controller I was using:

AutoRest uses the OpenAPI generated through Swashbuckle. When I took  a look at the OpenAPI file, I noticed that indeed the same OperationId was used:

This is because I was using the ActionName as the OperationId. As I have multiple Action methods with the same name they all result in the same OperationIe

To fix it, you can do 2 things:

  • Using the [SwaggerOperation] attribute
  • Using the Name property on the Http attribute ([HttpGet], [HttpPost],…)

Using the [SwaggerOperation] attribute

By adding a [SwaggerOperation] attribute to the controller action method, you can control the generated OperationId:

Using the Name property

An alternative solution is to use the Name property on the HTTP routing attributes:

Tuesday, April 6, 2021

AutoRest–OperationId is required for all operations

I was trying to use AutoRest to generate a client SDK for one of my API’s. This turned out not to be the success I was hoping for. I downloaded the swagger.json file for my API and executed AutoRest through the following command:

autorest --csharp --input-file=swagger.json

This command failed with the following exception message:

FATAL: OperationId is required for all operations.

Here was the API controller I was using:

And here is an extract of the generated swagger.json:

As you can see, there is indeed no OperationId specified in the swagger.json. The swagger documentation has the following to tell about the OperationId:

operationId is an optional unique string used to identify an operation. If provided, these IDs must be unique among all operations described in your API.

Some common use cases for operationId are:

  • Some code generators use this value to name the corresponding methods in code.
  • Links can refer to the linked operations by operationId.

AutoRest uses the OperationId to identify each method. Unfortunately as the OperationId is optional, it is not generated by Swashbuckle automatically.

To change this, you can add an extra line in your Swashbuckle configuration;

This will use the ActionName as the OperationId. Of course you can also use a different naming strategy.

Monday, April 5, 2021

AutoRest–Generate a client library for your REST API

I was investigating some ways to generate a C# client library based on the OpenAPI definition of my REST API. One of the solutions I found was AutoRest.

AutoRest is an open source tool created by Microsoft so that Azure service teams could start producing generated client libraries from new Swagger and OpenAPI 2.0 specifications.

Install AutoRest

To install AutoRest, you can use NPM:

# Depending on your configuration you may need to be elevated or root to run this. (on OSX/Linux use 'sudo' )
npm install -g autorest

# run using command 'autorest' to check if installation worked
autorest – --help

Generate a C# client

To generate a C# client, you first need to have your OpenAPI file available. When you are using Swashbuckle in ASP.NET Core, you can browse to the swagger endpoint and download the swagger.json.

Next step is to invoke AutoRest:

autorest --input-file=swagger.json – --csharp

This will generate a C# project with a REST API client.

Friday, March 26, 2021

Kubernetes–Working with multiple namespaces

Kubernetes has the concept of namespaces to logically seperate different parts of your cluster.

To simplify working with different namespaces, it is recommend to create a separate context:

kubectl config set-context <contexname> --namespace=<namespace> --cluster=<clustername> --user=<clusteruser>

After a new context is created, you can switch to this new context using:

kubectl config use-context <contextname>

All commands you execute afterwards will apply to this context.

You can verify your current context by doing the following:

kubectl config current-context

To view all the contexts:

kubectl config view

Thursday, March 25, 2021

Kubernetes - Reload your ASP.NET Core configuration when a configmap changes

Yesterday I blogged about configmaps and how changing the configmap is not picked up by ASP.NET Core. In this post I want to dig deeper in why this is the case and suggest a possible solution.

The CreateDefaultBuilder() method in ASP.NET Core will load your appsettings.json file and monitor it for changes (see the reloadOnChange: true):

Behind the scenes the reloadOnChange setting will monitor the config file for changes based on the last modified date. Seems logical…

Let’s continue to find out why this doesn’t work with Kubernetes. In Kubernetes a config map is mounted as a symlink:

kubectl exec -it <pod-name> -- bash
root@example-deployment-839f6c6546-c783b:/appg# ls -la
rwxrwxrwx 3 root root 4096 Mar 25  10:01 .
drwxr-xr-x 1 root root 4096 Mar 25 10:47 ..
drwxr-xr-x 2 root root 4096 Mar 25 10:01 ..2021_03_25_10_01_16.386067924
lrwxrwxrwx 1 root root 31 Mar 25 10:01 -> ..2021_03_25_10_01_16.386067924
lrwxrwxrwx 1 root root 53 Mar 25 10:47 appsettings.json ->

Unfortunately when you update the config map, the last modified date doesn’t change, although the file reference itself is updated. This is a known issue as discussed here.

One suggested workaround for this problem is to use a a configuration provider that understand symlinks(notice that this solution only works on linux):

Another possible solution is mentioned by Francisco Beltrao and uses the content itself to detect changes instead of the last modified date:

The code required for this solution can be found in this GitHub repo: