Kubernetes nginx ingress service cannot serve static files - kubernetes

We have created service and ingress files for our deployment below.
However, when we try to reach our app through the ingress controller, we have seen that our static files such as JS and CSS cannot be loaded on the website. Aside from this, when we try to reach with NodePort, we have seen that the app was loaded perfectly.
service.yaml:
---
apiVersion: v1
kind: Service
metadata:
name: karel-service-1
labels:
app: karel-deployment-1
spec:
selector:
app: karel-deployment-1
type: NodePort
ports:
- port: 3000
targetPort: 3000
nodePort:
ingress.yaml:
---
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: karel-ingress-1
annotations:
nginx.ingress.kubernetes.io/add-base-url: 'true'
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/rewrite-target: "/"
spec:
rules:
- host: www.kareldeployment.com
http:
paths:
- path: "/1"
backend:
serviceName: karel-service-1
servicePort: 3000
How can we reach all static content of the website by using the ingress controller?

It looks like the ingress controller listens on port 80 (and that's why HTML pages are loaded) but they have links that point to port 3000 (and that's why everything works with NodePort). In other words, I suspect that you have to modify the pages to not use hardcoded port.

Related

Blazor server through k8s ingress controller

I've written a small Blazor application which looks to work all well when containerized and when accessed through k3s port forwarding, but struggling to find a guideline on how that application needs to be correctly exposed via a ingress controller. To show this:
If I run the Blazor application and access via port-forwarding (blazor routing works perfectly well etc.):
kubectl port-forward deployment/ 8000:80
and page routing working as expected
However, when I add a clusterIP service to the deployment and connect to it through Traefik ingress controller, I get:
and changing the route will give a 404 page not found error
My Ingress serviceIp and ingress controller setup:
ClusterIP:
apiVersion: v1
kind: Service
metadata:
name: driverpassthrough
spec:
selector:
app: driverpassthrough
ports:
- name: ui
protocol: TCP
port: 8010
targetPort: 80
ingress
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: ingress-test
annotations:
kubernetes.io/ingress.class: "traefik"
traefik.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- http:
paths:
- path: /passthrough
backend:
serviceName: driverpassthrough
servicePort: 8010
so in my case, I use k3s and traefik. I also have 3 replicas of my blazor server app. To make it work, I had to enable sticky session (in annotations) on the cluster ip like so:
Service
apiVersion: v1
kind: Service
metadata:
name: qscale-healthcheck-service
annotations:
traefik.ingress.kubernetes.io/affinity: "true"
labels:
name: qscale-healthcheck-service
spec:
type: ClusterIP
selector:
app: healthcheck
ports:
- name: http
port: 80
targetPort: 80
Ingress
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: traefik-ingress
annotations:
kubernetes.io/ingress.class: "traefik"
spec:
rules:
- http:
paths:
- path: /
backend:
serviceName: qscale-healthcheck-service
servicePort: 80
This is the link where I found the annotation: Traefik Doc

How to manage 'link forwarding' for a website inside a kubernetes cluster

I have a website that uses relative href links (eg. the link directs to "/login", rather than "http://somesite.com/login"). This works A-OK in a normal server but I'd like to use the website inside a docker container as part of a kubernetes cluster. My goal is to have multiple replicas of the website to manage high load times, defaulting to two nodes with dynamic scaling.
I set us the service as a 'loadbalancer' as follows:
apiVersion: v1
kind: Service
metadata:
name: websiteservice
spec:
selector:
app: websiteapp
type: LoadBalancer
ports:
- protocol: TCP
port: 80
targetPort: 80
The issue here is that if I navigate to the URL of the load balancer (that's automatically created at my host - digital ocean) then although the homepage of the website loads, any other pages give me a 404 because rather than loading the "/login" page of the container it loads the "/login" page of the load balancer which doesn't exist. How can I configure my cluster or load balancer to forward all subdirectories (anything after the .com) to the webserver?
EDIT 1
In comments I was advised to set up ingress. I think I've done so with this change to my yaml:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: test-ingress
annotations:
kubernetes.io/ingress.class: nginx
spec:
rules:
- host: somesite.co.uk
http:
paths:
- backend:
serviceName: websiteservice
servicePort: 80
---
apiVersion: v1
kind: Service
metadata:
name: websiteservice
spec:
selector:
app: websiteapp
type: ClusterIP
ports:
- protocol: TCP
port: 80
targetPort: 80
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: websiteapp
spec:
replicas: 2
selector:
matchLabels:
app: websiteapp
template:
metadata:
labels:
app: websiteapp
spec:
containers:
- name: websiteapp
image: mydocker.co.uk/websiteimg
imagePullSecrets:
- name: regcred
nodeSelector:
beta.kubernetes.io/instance-type: s-2vcpu-4gb
But I'm still not able to navigate beyond the home page of my website.
Your Ingress file should look like this:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: test-ingress
annotations:
kubernetes.io/ingress.class: nginx
spec:
rules:
- host: somesite.co.uk
http:
paths:
- path: /*
backend:
serviceName: websiteservice
servicePort: 80
Simply you have add path to redirect traffic.
Take a look: host-path-routing, ingress-path-matching.

Not able to access multiple services from ingress controller hosted on different ports

I have two services hosted on different ports and I have created a ingress resource which looks like this
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: ingress
namespace: mynamespace
annotations:
kubernetes.io/ingress.class: "nginx"
spec:
rules:
- http:
paths:
- path: /svc1/
backend:
serviceName: app1-svc
servicePort: 3000
- path: /svc2/
backend:
serviceName: app2-svc
servicePort: 8080
on top of this I have created a NodePort type ingress controller.
apiVersion: v1
kind: Service
metadata:
labels:
app: nginx-ingress
name: controller-nginx-ingress-controller
spec:
clusterIP: 10.88.18.191
externalTrafficPolicy: Cluster
ports:
- name: http
nodePort: 30080
port: 80
protocol: TCP
targetPort: http
- name: https
nodePort: 31442
port: 443
protocol: TCP
targetPort: https
selector:
app: nginx-ingress
component: controller
release: controller
And finally, setup a cloud load balancer to access application running on my K8S cluster.
Problem:
I couldn't able to access any of my application using URL routing
http://load-balancer-ip/svc1/
http://load-balancer-ip/svc2/
Can anyone please let me know what incorrect I'm doing? And how to resolve this issue?
From what you mentioned in comments I am pretty sure the problem can be solved with path rewrites.
Now, when you are sending a request to /svc1/ with path: /svc1/ then the request is forwarded to app1-svc with path set to /svc1/ and you are receiving 404 errors as there is no such path in app1. From what you mentioned, you can most probably solve the issue using rewrite. You can achieve it using nginx.ingress.kubernetes.io/rewrite-target annotation, so your ingress would look like following:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: ingress
namespace: mynamespace
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$2
kubernetes.io/ingress.class: "nginx"
spec:
rules:
- http:
paths:
- path: /svc1(/|$)(.*)
backend:
serviceName: app1-svc
servicePort: 3000
- path: /svc2(/|$)(.*)
backend:
serviceName: app2-svc
servicePort: 8080
In this case when sending request with path set to /svc1/something the request will be forwarded to app1 with path rewritten to /something.
Also take a look in ingress docs for more explanation.
Let me know if it solved you issue.

Ingress without ip address

I create a ingress to expose my internal service.
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: app-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: example.com
http:
paths:
- path: /app
backend:
serviceName: my-app
servicePort: 80
But when I try to get this ingress, it show it has not ip address.
NAME HOSTS ADDRESS PORTS AGE
app-ingress example.com 80 10h
The service show under below.
apiVersion: v1
kind: Service
metadata:
name: my-app
spec:
selector:
app: my-app
ports:
- name: my-app
nodePort: 32000
port: 3000
targetPort: 3000
type: NodePort
Note: I'm guessing because of the other question you asked that you are trying to create an ingress on a manually created cluster with kubeadm.
As described in the docs, in order for ingress to work, you need to install ingress controller first. An ingress object itself is merely a configuration slice for the installed ingress controller.
Nginx based controller is one of the most popular choice. Similarly to services, in order to get a single failover-enabled VIP for your ingress, you need to use MetalLB. Otherwise you can deploy ingress-nginx over a node port: see details here
Finally, servicePort in your ingress object should be 3000, same as port of your service.

externally access the application using hostname/subdomain in ingress resource

Need to access the application from external using Ingress hostname/sub-domain for the application that is specified in the below code. eg. test-app.dev-cluster-poc.company.domain.
cat app-ingress.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
namespace: ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
name: app-ingress
spec:
rules:
- host: test-app.dev-cluster-poc.company.domain
http:
paths:
- backend:
serviceName: appsvc1
servicePort: 80
path: /app1
- backend:
serviceName: appsvc2
servicePort: 80
path: /app2
While troubleshooting using steps in the url, I found that there is no ADDRESS in the "kubectl get ingress" output. expecting an ip address like below.
but, I am seeing like below, 3rd column is empty.
what are the necessary configuration required to externally access the application like registering the hostname(test-app.dev-cluster-poc.company.domain) or adding A-record or running any dns service in the kubernetes cluster.
what is causing the ADDRESS column empty in "kubectl get ingress" command.
[EDIT]
apiVersion: v1
kind: Service
metadata:
name: appsvc1
namespace: ingress
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
app: app1
Nginx controller service like below.
cat nginx-ingress-controller-service.yaml
apiVersion: v1
kind: Service
metadata:
name: nginx-ingress
namespace: ingress
spec:
type: NodePort
ports:
- port: 80
nodePort: 30000
name: http
- port: 18080
nodePort: 32000
name: http-mgmt
selector:
app: nginx-ingress-lb
1.you can deploy an ingress deployment
2.expose your ingress deployment through port 80
kubectl expose deploy your-deployment-name --port 80
source
3.you can add ingressClassName in your deploy
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: nginx-ingress
namespace: ingress
spec:
ingressClassName: nginx
ingress configuration sample