<p>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.</p>
<p>Whenever I would want to access the static files which is stored under this path in this screenshot:
<a href="https://i.stack.imgur.com/DZwZz.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/DZwZz.png" alt="first folder which is &quot;app&quot;" /></a>
<a href="https://i.stack.imgur.com/JTD9q.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/JTD9q.png" alt="wwwroot folder where the static files are" /></a></p>
<p>The path will be &quot;app&gt;wwwroot&gt;icons&gt;svg&gt;anyimagesname.svg&quot;.</p>
<p>My localhost address for 127.0.0.1 has been configured to have a DNS of <a href="http://www.chorebear.com" rel="nofollow noreferrer">www.chorebear.com</a> hence the complete URL to access the static file will be <a href="http://chorebear.com/icons/svg/afghanistan_adobe_express.xml" rel="nofollow noreferrer">http://chorebear.com/icons/svg/afghanistan_adobe_express.xml</a></p>
<p>But everytime I hit this URL, it says &quot;NGINX 404 Not Found&quot;. Is there any issue with the service itself? Any help would help in this. Thanks!.</p>
<p><a href="https://i.stack.imgur.com/Mh5De.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/Mh5De.png" alt="Not found 404 Error" /></a></p>
<pre><code>var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
var sqlConnectionBuilder = new SqlConnectionStringBuilder();
if (builder.Environment.IsDevelopment())
{
    sqlConnectionBuilder.ConnectionString = builder.Configuration.GetConnectionString(&quot;Chorebear_Connection&quot;);
    sqlConnectionBuilder.UserID = builder.Configuration[&quot;UserId&quot;];
    sqlConnectionBuilder.Password = builder.Configuration[&quot;Password&quot;];
} else if (builder.Environment.IsProduction()) 
{
    sqlConnectionBuilder.ConnectionString = builder.Configuration.GetConnectionString(&quot;Chorebear_Connection&quot;);
    // sqlConnectionBuilder.UserID = builder.Configuration[&quot;UserId&quot;];
    // sqlConnectionBuilder.Password = builder.Configuration[&quot;Password&quot;];
}

builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddDbContext&lt;ChoreBearContext&gt;(options =&gt; options.UseSqlServer(sqlConnectionBuilder.ConnectionString));

//Registering services and classes which are dependency injection
builder.Services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies());
builder.Services.AddIdentity&lt;User, UserRole&gt;().AddDefaultTokenProviders();
builder.Services.Configure&lt;IdentityOptions&gt;(options =&gt; 
{
    options.User.RequireUniqueEmail = true;
    options.Password.RequiredLength = 8;
    
    options.SignIn.RequireConfirmedEmail = true;
});
builder.Services.AddScoped&lt;IUserStore&lt;User&gt;, UserStore&gt;();
builder.Services.AddTransient&lt;IRoleStore&lt;UserRole&gt;, RoleStore&gt;();
builder.Services.AddScoped&lt;ICategoryOfTaskRepo, CategoryOfTaskRepo&gt;();
builder.Services.AddScoped&lt;ITaskRepo, TaskRepo&gt;();
builder.Services.AddScoped&lt;IAccountRepo, AccountRepo&gt;();

//Registering utility classes which are dependency injection
builder.Services.AddScoped&lt;IEmailUtility, EmailUtility&gt;();
builder.Services.AddScoped&lt;IPasswordHasher&lt;User&gt;, PasswordHasher&lt;User&gt;&gt;();

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();
</code></pre>

Adrian Joseph
<p>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.</p>
<p>Currently, my architecture of my Kubernetes contains the following:</p>
<ol>
<li>.NET Core REST API service [With a ClusterIP service exposed to port 80] in a pod</li>
<li>Node Port Service for .NET Core REST API [only for development purposes]</li>
<li>Ingress NGINX Service which is configured to connect or rewrite the ClusterIP of .NET Core REST API to a domain URL instead of &quot;localhost&quot; IP address. [Used as production standard environment]</li>
<li>MS SQL Server Instance Database service [With a ClusterIP service exposed to port 1433 and LoadBalancer exposed to 1433 to allow the service to be accessed by Microsoft SQL Server Management Studio]</li>
<li>Persistent Volume Claim to persist data saved in MS SQL Server Instance Database service directly into the hardware of the host (in this case my PC)</li>
</ol>
<p>Now my .NET Core REST API had an issue, with first the middleware position especially which is the middleware called <code>app.UseStaticFiles()</code>. The position previously was right before <code>app.Run()</code> hence when a HTTP request is initiated to the REST API service in Kubernetes, the static files which I saved under <code>www/icons/svg</code> 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:</p>
<ol>
<li><a href="https://learn.microsoft.com/en-us/aspnet/core/fundamentals/middleware/?view=aspnetcore-7.0" rel="nofollow noreferrer">ASP.NET Core Middleware</a></li>
<li><a href="https://learn.microsoft.com/en-us/aspnet/core/fundamentals/static-files?view=aspnetcore-7.0" rel="nofollow noreferrer">Static Files in ASP.NET Core</a></li>
</ol>
<p>But it's not the full solution to the problem. The problem relies in the Ingress Service and in this case my <code>ingress-depl.yaml</code> file. Let me show you the previous YAML file and the update file.</p>
<p><em><strong>Previous Ingress Service YAML file</strong></em></p>
<pre><code>apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-srv
  annotations:
   kubernetes.io/ingress.class: nginx
   nginx.ingress.kubernetes.io/use-regex: 'true'
spec:
 rules:
  - host: chorebear.com
    http:
    paths:
      - path: /api
        pathType: Prefix
        backend:
          service:
            name: chorebear-clusterip-srv
            port:
              number: 80
</code></pre>
<p><em><strong>Updated Ingress YAML file</strong></em></p>
<pre><code>apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-srv
  annotations:
   kubernetes.io/ingress.class: nginx
   nginx.ingress.kubernetes.io/use-regex: 'true'
spec:
 rules:
  - host: chorebear.com
    http:
    paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: chorebear-clusterip-srv
            port:
              number: 80
</code></pre>
<p>The difference between both files were the configuration property called <code>path: /api</code>. This property rewrites the URL domain for the .NET Core REST API pod container to &quot;http://chorebear.com/api&quot;. Any HTTP request to any endpoint will be like this --&gt; <a href="http://chorebear.com/api/%5Bany-endpoint-you-create-in-your-controller%5D" rel="nofollow noreferrer">http://chorebear.com/api/[any-endpoint-you-create-in-your-controller]</a></p>
<p>Now since my controllers in my REST API contains <code>[Route(&quot;api/[controller]&quot;)]</code>, the &quot;api&quot; portion of the &quot;Route&quot; gets re-written by the <code>path: /api</code> 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 &quot;chorebear.com/api&quot; simply because the <code>app.UseStaticFiles</code> middleware needs the &quot;api&quot; path from the HTTP request which is not configured/set in the middleware itself and hence the ultimate dead-end of &quot;404 Error Not Found NGINX&quot;.</p>
<p>To solve it, I simple re-type the <code>path: /api</code> to <code>path: /</code> in my Ingress Service YAML File and it works. For the endpoints I define in my controllers, I can still call as usual with &quot;api&quot; addition like <a href="http://chorebear.com/api/%5Bany-endpoint-you-create-in-your-controller%5D" rel="nofollow noreferrer">http://chorebear.com/api/[any-endpoint-you-create-in-your-controller]</a> since my controllers are decorated with <code>[Route(&quot;api/[controller]&quot;)]</code> which has the &quot;api&quot; on it. So now, my static files are served and accessible on my domain URL set in my Ingress Service YAML File <a href="http://chorebear.com/icons/svg/afghanistan_adobe_express.xml" rel="nofollow noreferrer">http://chorebear.com/icons/svg/afghanistan_adobe_express.xml</a></p>
<p><a href="https://i.stack.imgur.com/cctV4.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/cctV4.png" alt="The static files now being served under the Ingress Service Domain URL" /></a></p>
<p><a href="https://i.stack.imgur.com/9DGJX.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/9DGJX.png" alt="The API HTTP Request now being served under the Ingress Service Domain URL" /></a></p>
<p>I hope this helps!</p>
