How to configure an ASP.NET Core multi microservice application and Azure AKS ingress routes so that it doesn't break resources in the wwwroot folder

9/19/2018

I have two ASP.NET Core apps. One is a Headless CMS (API), and the other one is a Razor Pages blog front-end (with a REST client that communicates with the Headless CMS/API).

I then have an Azure AKS cluster. In it I have an ingress resource with the following routes (as per the instructions from the following AKS docs: https://docs.microsoft.com/en-us/azure/aks/ingress-tls#create-an-ingress-route ). Each route is mapped to each of the apps/services mentioned above:

spec:
  rules:
  - host: mydomain.westeurope.cloudapp.azure.com
    http:
      paths:
      - backend:
          serviceName: headless-cms-svc
          servicePort: 80
        path: /
      - backend:
          serviceName: blog-svc
          servicePort: 80
        path: /blog

When I now navigate to the first route, mydomain.westeurope.cloudapp.azure.com, the headless CMS app works as expected but when I navigate to the second route , mydomain.westeurope.cloudapp.azure.com/blog, I get a bunch of 404:s because the blog apps root path is now relative to the /blog ingress route which in turn breaks all the resources (css, javascript, images etc) in the wwwroot folder.

How should I configure my ASP.NET Core blog app and/or my ingress object?

404:s

https://mydomain.westeurope.cloudapp.azure.com/css/site.min.css?v=kHvJwvVAK1eJLN4w8xygUR3nbvlLmRwi5yr-OuAO90E

https://mydomain.westeurope.cloudapp.azure.com/images/banner1.svg

https://mydomain.westeurope.cloudapp.azure.com/images/banner2.svg

https://mydomain.westeurope.cloudapp.azure.com/js/site.min.js?v=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU

If I add the URL segment /blog the resources get served properly. https://mydomain.westeurope.cloudapp.azure.com/blog/images/banner1.svg <- works

And here is a regular img tag in the Index.cshtml Razor page (from a default ASP.NET Core 2.1 Razor Pages web application). I haven't changed anything in the code.

<img src="~/images/banner1.svg" alt="ASP.NET" class="img-responsive" />
-- PussInBoots
asp.net-core
azure-aks
kubernetes
razor-pages

3 Answers

9/20/2018

You want to annotate your Ingress with nginx.ingress.kubernetes.io/rewrite-target. For example:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: test-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - host: mydnsname.westeurope.cloudapp.azure.com
    http:
      paths:
      - backend:
          serviceName: headless-cms-svc
          servicePort: 80
        path: /
      - backend:
          serviceName: blog-svc
          servicePort: 80
        path: /blog

Hope it helps!

-- Rico
Source: StackOverflow

7/26/2019

Follow these steps to run your code:

  1. deployment: pass environment variable with path base in k8s-yaml-file
apiVersion: apps/v1
kind: Deployment
# ..
spec:
  # ..
  template:
    # ..
    spec:
      # ..
      containers:
        - name: test01
          image: test.io/test:dev
          # ...
          env:
            # define custom Path Base (it should be the same as 'path' in Ingress-service)
            - name: API_PATH_BASE # <---
              value: "blog"
  1. program: enable loading environment params in Program.cs
var builder = new WebHostBuilder()
    .UseContentRoot(Directory.GetCurrentDirectory())
    // ..
    .ConfigureAppConfiguration((hostingContext, config) =>
    {
        // ..  
        config.AddEnvironmentVariables(); // <---
        // ..
    })
    // ..
  1. startup: apply UsePathBaseMiddleware in Startup.cs
public class Startup
{
    public Startup(IConfiguration configuration)
    {
        _configuration = configuration;
    }

    private readonly IConfiguration _configuration;

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        var pathBase = _configuration["API_PATH_BASE"]; // <---

        if (!string.IsNullOrWhiteSpace(pathBase))
        {
            app.UsePathBase(
quot;/
{pathBase.TrimStart('/')}"); } app.UseStaticFiles(); // <-- StaticFilesMiddleware must follow UsePathBaseMiddleware // .. app.UseMvc(); } // .. }
-- vladimir
Source: StackOverflow

9/21/2018

Problem

It seems that your proxy rewrites the path.

  • Before proxy: /blog/images/banner1.png
  • After proxy: /images/banner1.png

Asp generates absolute (host relative) links (path only, but starting with a slash "/"). That means, we have to tell the framework that it must prefix all URLs with "/blog".

Solution

Do this (for asp.net core 2.1) by inserting the following snipped in your Startup class:

app.Use((context, next) =>
{
    context.Request.PathBase = new PathString("/blog");
    return next();
});

Code sample from: https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/proxy-load-balancer?view=aspnetcore-2.1

Insert this snipped before any other middleware in your Configure method.

You can test this on your local machine too. All generated links should be prefixed with "/blog" - so they will be broken on your dev machine.

Use Configuration

You will need to make it configurable e.g. like so:

        var basePath = Configuration.GetSection("BASE_PATH").Value;
        if (basePath != null)
        {
            Console.WriteLine($"Using base path '{basePath}'");
            // app.Use().. goes here
        }

(Assuming you read configuration from env vars in your startup.)

… and provide this env var in your kubernetes depoyment:

...
 containers:
  - name: myapp
    image: myappimage
    env:
      - name: BASE_PATH
        value: "/blog"
-- Christoph Lütjen
Source: StackOverflow