Kubernetes internal CORS issues between services

5/11/2019

1

Im trying to make a http request from my frontend deployment/pods (Angular 7 app running inside NGINX) to my backend service (NET Core WEB API).

The URL, as indicated in the diagram, is http://k8s-demo-api:8080/api/data.

//environment.prod.ts in Angular App

export const environment = {
  production: true,
  api_url: "http://k8s-demo-api:8080/api"
};

I have CORS enabled in my API:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using K8SDockerCoreWebApi.Contexts;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;

namespace K8SDockerCoreWebApi
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddCors();
            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
            services.Add(new ServiceDescriptor(typeof(K8SDemoContext), new K8SDemoContext(Configuration.GetConnectionString("DefaultConnection"))));
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseHsts();
            }

            app.UseCors( options => options.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader());
            app.UseMvc();
        }
    }
}

So here come the issue, when I make the request I get the following console error on the Angular side:

2

If there are any issues with the image above the error basically reads:

Access to XMLHttpRequest at 'k8s-demo-api:8080/api/data' from origin 'http://192.168.99.100:4200' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, https.

Points to note:

  • All the other services within the cluster can communicate fine (i.e. WEB API with MySQL using the same approach)
  • These two containers can speak to each other when I run them locally
  • Both of these services run 100% when I access them individually

I'm thinking of implementing an ingress on the API, but my understanding of what that will accomplish is limited.

Any help will be appreciated. Thanks.

EDIT

I am using the following headers as part of my Angular request:

headers: new HttpHeaders({
  'Content-Type': 'application/json',
  'X-Requested-With': 'XMLHttpRequest',
  'Access-Control-Allow-Origin' : '*'
})
-- Barend
angular
angular7
asp.net-core-webapi
kubernetes
nginx

1 Answer

5/12/2019

While looking simple at the first look there are many ways to solve your issues. First some background on CORS: The browser automatically adds the X-Requested-With header, no need to add it in your Angular request. The browser will look for Access-Control-Allow-Origin in the response headers - otherwise you could tell the browser to trust anything, exactly what CORS prevents. (The server side has to decide if requests are allowed) So, if you want to have CORS enabled, you need to configure that in your asp.net application, which you did

        app.UseCors( options => options.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader());

But you don't need CORS - your setup is carefully constructed to avoid the need: CORS will only become active when your make a cross-origin request. You configured the nginx reverse proxy in that way, that you can request the API from the same origin, where you loaded the Angular app.

The reason this is not working, is that your browser is unable to connect to the internal kubernetes hostname k8s-demo-api since that is an internal name in the kubernetes cluster.

I assume that you added a hostPort to the container of your frontend pod and that nginx is running on port 4200 serving the Angular app on the root path and the reverse proxy path is /api.

Easiest solution, given that the rest of your setup is working: Change the URL for the API to use the created reverse proxy path

 api_url: "http://192.168.99.100:4200/api"

From the screenshot it looks like you are trying to request the api without a proper protocol (http:// in this case), make sure the Angular HttpClient is configured correctly.

-- Thomas
Source: StackOverflow