I am trying to host static files in kubernetes with an nginx container, and expose them on a private network with istio.
I want the root of my server to exist at site.com/foo, as I have other applications existing at site.com/bar, site.com/boo, etc.
My istio virtual service configuration:
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: cluster-foo
namespace: namespace
spec:
gateways:
- cluster-gateway
hosts:
- site.com
http:
- match:
- name: http
port: 80
uri:
prefix: /foo
route:
- destination:
host: app.namespace.svc.cluster.local
port:
number: 80
All of my static files exist in the directory /data on my nginx container. My nginx config:
events {}
http {
server {
root /data;
location /foo {
autoindex on;
}
}
}
Applying this virtual service, and a kube deployment that runs an nginx container with this config, I get a nginx server at site.com/foo that serves all of the static files in /data on the container. All good. The problem is that the autoindexing that nginx does, does not respect the prefix /foo. So all the file links that nginx indexes at site.com/foo, look like this:
site.com/page.html, rather than site.com/foo/page.html. Furthermore, when I put site.com/foo/page.html in my browser manually, site.com/foo/page.html is displayed correctly, So I know that nginx is serving it in the correct location, just the links that it is indexing are incorrect.
Is there any way to configure nginx autoindex with a prefix?
Related
I'm attempting to expose a service from my home network via a sub-url from my domain. This service is running on a Kubernetes (K3s) cluster on a Ubuntu 20.04 server. However there's an issue with proxy_pass in that pod that is giving me the `nginx: [emerg] host not found in upstream in 'webhook.lan' error.
Here's an overview of my setup
.lan DNS entry is setup on my router. I have many other services accessible (locally) that use .lan. I'm confident this is setup correctly.
My Ubuntu server is set up to use my router (192.168.0.1) as a DNS server. I can run dig webhook.lan and it's successful. I can also run wget webhook.lan and it downloads the HTML. So, the server can definitely resolve the address. resolvectl status has 192.168.0.1 as the Current DNS Server. Everything seems okay.
The K3s cluster is using an NGINX Ingress controller. I have two hosts setup. A wildcard host for *.lan addresses, along with a host to handle requests from my sub-url sub.url.com. I'm not attempting any sort of communication within the cluster, as I don't see the point (they're both already exposed separately).
Each container has it's own NGINX configuration to handle / proxy requests.
The .lan config looks like this:
server {
server_name service-a.lan;
listen 80;
listen [::]:80;
location / {
include proxy_params;
proxy_pass http://192.168.0.27:8000;
}
}
server {
server_name service-b.lan;
listen 80;
listen [::]:80;
location / {
include proxy_params;
proxy_pass http://192.168.0.27:3000;
}
}
That's just a sample. There's many more. They all work perfect on my local network.
Here's the config for the pod that is handling requests from the web. I currently use it to serve static files, along with a few basic HTML pages. This is where the proxy_pass issue is coming up:
upstream webhook {
server webhook.lan;
}
server {
server_name genweb;
listen 80;
listen [::]:80;
#basic welcome screen
location / {
alias /srv/web/;
try_files $uri $uri/ /index.html;
}
#static images, music, etc.
location /static {
alias /app/static;
autoindex on;
}
#problem area!!
location /webhook {
#resolver 127.0.0.11;
resolver 192.168.0.1;
include proxy_params;
proxy_pass http://webhook;
}
}
Originally, I just imported proxy_params and used the proxy_pass directive. Since that's all I was doing with the other container. Then, I tried using upstream{}; tried resolver 192.168.0.1 to make it resolve to the router. Finally, tried resolver 127.0.0.11 because that's the docker localhost (apparently).
No dice. Also, I should mention that the pod/deployment doesn't even start. It got that error from kubectl logs. It tries to restart a bunch of times, and eventually gives a status of Failure (I think), and never starts. Commenting out the webhook location in the NGINX config allows it to start right up.
I'm guessing the issue comes down to NGINX in the sub-url's container not being able to resolve 192.168.0.1, but I cannot figure out why.
Here's the Dockerfile (which I basically copied from the other running app) and Service/Deployment yaml file, in case that's where the problem lies:
Dockerfile
FROM nginx:1.21.4
RUN rm /etc/nginx/conf.d/default.conf
COPY web-nginx.conf /etc/nginx/conf.d
COPY proxy_params /etc/nginx
RUN mkdir -p /srv/web/static
COPY index.html /srv/web
ADD static /srv/web/static
web-service.yml
apiVersion: v1
kind: Service
metadata:
name: gen-web-service
spec:
selector:
app: genweb
ports:
- protocol: TCP
port: 8080
targetPort: 80
type: NodePort
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: gen-web-deployment
labels:
app: genweb
spec:
replicas: 1
selector:
matchLabels:
app: genweb
template:
metadata:
labels:
app: genweb
spec:
containers:
- name: genweb
image: genweb:v1.0.16
imagePullPolicy: Never
ports:
- containerPort: 80
volumeMounts:
- name: gen-web-volume
mountPath: /app/static
volumes:
- name: gen-web-volume
hostPath:
path: /srv/web/static
I got the following code that uses ingress-nginx within infra\k8s-dev\ingress-srv.yaml file.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-service
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/use-regex: "true"
spec:
rules:
- host: mysite.local
http:
paths:
- path: /api/users/?(.*)
pathType: Prefix
backend:
service:
name: auth-srv
port:
number: 3000
- path: /?(.*)
pathType: Prefix
backend:
service:
name: client-srv
port:
number: 3000
I searched through the internet and found the following command to install it:
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.4.0/deploy/static/provider/cloud/deploy.yaml
But I am not sure where should I run this command? Is there any ingress-nginx package that I also must install from NPM?
I am using Docker-Desktop on Windows 10 machine.
Command you have mentioned is right
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.4.0/deploy/static/provider/cloud/deploy.yaml
it self will download and apply the YAML config from URL, it will deploy the Nginx controller. Nginx ingress controller will manage the Ingress you are creating above.
Ingress is rule to divert the traffic and controller manages these rules (ingress).
So just running the apply to K8s cluster context will download and start the PODs of the Nginx controller.
as you mentioned in your ingress annotation
kubernetes.io/ingress.class: nginx
that specific ingress rule will get connected or managed by nginx controller.
inside the ingress you have mentioned mysite.local so make sure in local setup host file you are mapping the domain to IP.
Once controller is up and running opening the URL (mysite.local) into the browser will show the site.
I am trying to create an ingress controller that points to a service that I have exposed via NodePort.
Here is the yaml file for the ingress controller (taken from https://kubernetes.io/docs/tasks/access-application-cluster/ingress-minikube/):
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: example-ingress
spec:
rules:
- host: hello-world.info
http:
paths:
- path: /
backend:
serviceName: appName
servicePort: 80
I can connect directly to the node port and the frontend is displayed.
Please note that I am doing this because the frontend app is unable to connect to other deployments that I have created and I read that an ingress controller would be able to solve the issue. Will I still have to add an Nginx reverse proxy? If so how would I do that? I have tried adding this to the nginx config file but with no success.
location /middleware/ {
proxy_pass http://middleware/;
}
You must use a proper hostname to reach the route defined in the Ingress object. Either update your /etc/hosts file or use curl -H "hello-world.info" localhost type command. Alternatively, you can delete the host mapping and redirect all traffic to one default service.
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: example-ingress
spec:
rules:
- http:
paths:
- path: /
backend:
serviceName: appName
servicePort: 80
I have set up a proxy with Nginx which is as follows
server {
listen 80;
server_name localhost;
location /api {
proxy_pass https://api.mydomain.com/;
}
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
my Dockerfile
FROM node:12-alpine as builder
WORKDIR /workspace
COPY ./package.json ./
RUN npm install
COPY . .
RUN npm run build
FROM nginx
COPY ./nginx/default.conf /etc/nginx/conf.d/default.conf
COPY --from=builder /app/www /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
This works fine But wants to replace Nginx with Traefik for the above proxy settings. Any help would be much appreciated since I'm very new to traefik.
With Traefik 2+, you need to configure 2 routers:
- One for the API
- One for the webapp
For the API proxy, you will have a rule like:
rule = "Host(`example.com`) && Path(`/api`)"
And the webapp will juste have the host as rule
rule = "Host(`example.com`)"
For kubernetes, you can do it in an ingress like that:
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: simpleingressroute
namespace: default
spec:
entryPoints:
- web
routes:
- match: Host(`example.com`) && PathPrefix(`/api`)
kind: Rule
services:
- name: mywebapp-svc
port: 80
- match: Host(`example.com`)
Kind: Rule
services:
- name: myapi-svc
port: 80
If the API is not inside the kubernetes cluster, you can define the rule tu use an externalService like that:
---
apiVersion: v1
kind: Service
metadata:
name: myapi-svc
namespace: default
spec:
externalName: api.mydomain.com
type: ExternalName
if you want to step up from that manual configuration, you may use Traefik as described here. Watch how he uses docker labels to define how to route HTTP traffic.
I personally use caddy docker proxy in docker (swarm, but not required) which I find easier to understand and use
I'm currently trying to configure a Kubernetes environment.
Currently I have a Docker image which serves my compiled Angular application via Nginx.
The default.conf of the Nginx is:
server {
listen 80;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri $uri/ /index.html =404;
}
}
Ingress configuration (mapped to Google Cloud Load Balancer since I'm using Kubernetes Cluster)
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: fullstack-ingress
annotations:
ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- http:
paths:
- path: /app
backend:
serviceName: frontend-main
servicePort: 80
- path: /app/*
backend:
serviceName: frontend-main
servicePort: 80
- path: /core
backend:
serviceName: backend-core
servicePort: 80
Whenever I request my front-end using http://[loadbalancerip]/app/, all request sent to my angular docker are GET /app/inline.js when they should be GET /inline.js in order to work.
I tried directly in my cluster with curl and the file works. I only need to get rid of the "/app". How can I do that? Is that in the Nginx configuration or in the Ingress file?
I would rather fix it in the Ingress file, since I will probably have the same issue when I will be deploying my back-end which are .NET Core and Kestrel.