I’ve recently being learning about Kubernetes and I have deployed a service which contains a .NET Core 7 REST API into a pod. This pod/service is configured with it’s ClusterIP and with NGINX port as well.
Whenever I would want to access the static files which is stored under this path in this screenshot:
The path will be "app>wwwroot>icons>svg>anyimagesname.svg".
My localhost address for 127.0.0.1 has been configured to have a DNS of www.chorebear.com hence the complete URL to access the static file will be http://chorebear.com/icons/svg/afghanistan_adobe_express.xml
But everytime I hit this URL, it says "NGINX 404 Not Found". Is there any issue with the service itself? Any help would help in this. Thanks!.
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
var sqlConnectionBuilder = new SqlConnectionStringBuilder();
if (builder.Environment.IsDevelopment())
{
sqlConnectionBuilder.ConnectionString = builder.Configuration.GetConnectionString("Chorebear_Connection");
sqlConnectionBuilder.UserID = builder.Configuration["UserId"];
sqlConnectionBuilder.Password = builder.Configuration["Password"];
} else if (builder.Environment.IsProduction())
{
sqlConnectionBuilder.ConnectionString = builder.Configuration.GetConnectionString("Chorebear_Connection");
// sqlConnectionBuilder.UserID = builder.Configuration["UserId"];
// sqlConnectionBuilder.Password = builder.Configuration["Password"];
}
builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddDbContext<ChoreBearContext>(options => options.UseSqlServer(sqlConnectionBuilder.ConnectionString));
//Registering services and classes which are dependency injection
builder.Services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies());
builder.Services.AddIdentity<User, UserRole>().AddDefaultTokenProviders();
builder.Services.Configure<IdentityOptions>(options =>
{
options.User.RequireUniqueEmail = true;
options.Password.RequiredLength = 8;
options.SignIn.RequireConfirmedEmail = true;
});
builder.Services.AddScoped<IUserStore<User>, UserStore>();
builder.Services.AddTransient<IRoleStore<UserRole>, RoleStore>();
builder.Services.AddScoped<ICategoryOfTaskRepo, CategoryOfTaskRepo>();
builder.Services.AddScoped<ITaskRepo, TaskRepo>();
builder.Services.AddScoped<IAccountRepo, AccountRepo>();
//Registering utility classes which are dependency injection
builder.Services.AddScoped<IEmailUtility, EmailUtility>();
builder.Services.AddScoped<IPasswordHasher<User>, PasswordHasher<User>>();
builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.UseStaticFiles();
PrepDb.PrepPopulation(app, builder.Environment.IsProduction());
app.Run();
2
Answers
I've solved the issue by my own. Let me explain step-by-step on how I found the bug and how I solve it.
Currently, my architecture of my Kubernetes contains the following:
Now my .NET Core REST API had an issue, with first the middleware position especially which is the middleware called
app.UseStaticFiles()
. The position previously was right beforeapp.Run()
hence when a HTTP request is initiated to the REST API service in Kubernetes, the static files which I saved underwww/icons/svg
folder was being served quite late. So quick shoutout to @GuruStron for spotting this and providing the links to the documentation which helped me understanding it. I'll provide the links below:But it's not the full solution to the problem. The problem relies in the Ingress Service and in this case my
ingress-depl.yaml
file. Let me show you the previous YAML file and the update file.Previous Ingress Service YAML file
Updated Ingress YAML file
The difference between both files were the configuration property called
path: /api
. This property rewrites the URL domain for the .NET Core REST API pod container to "http://chorebear.com/api". Any HTTP request to any endpoint will be like this --> http://chorebear.com/api/[any-endpoint-you-create-in-your-controller]Now since my controllers in my REST API contains
[Route("api/[controller]")]
, the "api" portion of the "Route" gets re-written by thepath: /api
of the YAML file for Ingress. This then allows me to call any endpoint created in my controllers with the domain URL in my YAML file but for the static files, it cannot be served on that same re-written URL domain which is "chorebear.com/api" simply because theapp.UseStaticFiles
middleware needs the "api" path from the HTTP request which is not configured/set in the middleware itself and hence the ultimate dead-end of "404 Error Not Found NGINX".To solve it, I simple re-type the
path: /api
topath: /
in my Ingress Service YAML File and it works. For the endpoints I define in my controllers, I can still call as usual with "api" addition like http://chorebear.com/api/[any-endpoint-you-create-in-your-controller] since my controllers are decorated with[Route("api/[controller]")]
which has the "api" on it. So now, my static files are served and accessible on my domain URL set in my Ingress Service YAML File http://chorebear.com/icons/svg/afghanistan_adobe_express.xmlI hope this helps!
Middleware order is very important, your
app.UseStaticFiles
is too late move it closer to the start of the pipeline:Read more: