How add nginx-ingress custom health check behind a nginx reverse proxy - nginx

I have a nginx server outside kubernetes. nginx -> nginx ingress. I want know how add a custom health check path /health/status to nginx ingress.

This question is almost certainly solving the wrong problem, but in the spirit of answering what was asked:
You can expose the Ingress /healthz to the outside world:
kind: Service
metadata:
name: ingress-nginx-health
spec:
type: ClusterIP
selector: # whatever
ports:
- name: healthz
port: 80
targetPort: 10254
---
kind: Ingress
spec:
rules:
- host: elb-1234.example.com
http:
path: /healthz
backend:
serviceName: ingress-nginx-health
servicePort: healthz
Because if your Ingress controller falls over, it will for sure stop answering its own healthz check

Related

nginx ingress redirect traffic

I deployed nginx ingress controller and randomApp to minikube cluster.
I have 2 requirements:
All traffic for "random/.*" should go to the random service
Other paths should go to the nginx.
This configuration is correct?
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: path-rule-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
defaultBackend:
service:
name: ingress-nginx-controller
port:
number: 80
rules:
- host: random.localdev.me
http:
paths:
- path: /random/(.*)
backend:
service:
name: random
port:
number: 8000
pathType: Prefix
You also need to add metadata.annotations: kubernetes.io/ingress.class: "nginx" or spec.ingressClassName: nginx to allow nginx-ingress-controller to discover the ingress.
Also you shouldn't define default backend service as ingress-nginx-controller. Because you will get 503 Service Temporarily Unavailable since nginx-ingress-controller's nginx.conf didn't be configured for this. You can give another nginx server's service for it.

NGINX Ingress Routing based on Header

I have an nginx-ingress calling a custom auth-service before sending requests to the backend service, using this simple ConfigMap and Ingress:
apiVersion: v1
kind: ConfigMap
metadata:
...
data:
global-auth-url: auth-service-url:8080/authenticate
global-auth-method: GET
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: "nginx"
...
spec:
rules:
- host: host1
http:
paths:
- backend:
serviceName: backend-service
servicePort: 8080
Now I need something different.
How can I send requests, all with the same "Host" header, through different flows, one with auth-service and connected to backend-service1 and the other without any authentication and connecting to backend-service2?
To be clear, and using the custom header "Example-header: test"
If "Example-header" is "test", authenticate via my auth-service before sending to backend-service, as it's done now.
If "Example-header" is not defined, I want to send requests to a different backend service and do not use auth-service in the process.
I tried a couple of things, namely having 2 Ingresses, one with global-auth-url and the other with nginx.ingress.kubernetes.io/enable-global-auth: "false" but the auth-service is always called.
Can I do this with NGINX, or do I have to use Istio or Ambassador?
One way you can achieve this behavior is by abusing the canary feature.
For your backend-service, create a normal Ingress, e. g.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-backend
spec:
ingressClassName: nginx
rules:
- host: localhost
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: backend-service
port:
number: 80
Create a second Ingress for you auth-service with enabled canary and set the header name and value, e. g.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-auth
annotations:
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-by-header: Example-header
nginx.ingress.kubernetes.io/canary-by-header-value: test
spec:
ingressClassName: nginx
rules:
- host: localhost
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: auth-service
port:
number: 80
Now, every request with Example-header: test routes to auth-service. Any other value, e. g. Example-header: some-value, will not route to auth-service but rather go to your backend-service.

nginx ingress controller routing doesn't work as expected

I have a kubernetes cluster with an application (deployment + ClusterIp service), nginx ingress controller, cert manager and letsencrypt issuer.
Here the service
apiVersion: v1
kind: Service
metadata:
name: myapp-service
namespace: mynamespace
spec:
selector:
app: myapp
ports:
- protocol: TCP
port: 80
targetPort: 80
type: ClusterIP
This is the the ingress yaml:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: myapp-ingress
namespace: mynamespace
annotations:
kubernetes.io/ingress.class: nginx
cert-manager.io/cluster-issuer: letsencrypt
spec:
tls:
- hosts:
- <myapp>.<myregion>.cloudapp.azure.com
secretName: tls-secret
rules:
- host: <myapp>.<myregion>.cloudapp.azure.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: myapp-service
port:
number: 80
It works correctly, responding to the url https://<myapp>.<myregion>.cloudapp.azure.com.
Now I need to change the path like in :
spec:
tls:
- hosts:
- <myapp>.<myregion>.cloudapp.azure.com
secretName: tls-secret
rules:
- host: <myapp>.<myregion>.cloudapp.azure.com
http:
paths:
- path: /sub
pathType: Prefix
backend:
service:
name: myapp-service
port:
number: 80
I would expect to browse my app at https://<myapp>.<myregion>.cloudapp.azure.com/sub.
Instead I get
This <myapp>.<myregion>.cloudapp.azure.com page can’t be found
What I am doing wrong?
I tried to find examples online, but couldn't find any that helped me understand what's wrong.
EDIT
What happens behind the scenes (dev tools) is:
The browser sends a request to /sub
The ingress routes to the correct service, rewriting the url to /
The application receives the request correctly
The application wants to redirect the browser to a login url (e.g. /login)
The browser receives a redirect (302) to /login and executes it
The ingress doesn't see the /sub in the redirect url, so it doesn't know what to do
I guess the redirect url should be /sub/login, not simply /login.
There should be an easy way to configure the ingress to fix this trivial issue. Can someone point me to the right direction?

kubernetes-how to subdomain localhost using nginx ingress controller?

I want to have 2 apps running on kubernetes, I wonder if I can do 2 subdomains using nginx ingress controller.
For example: app1.localhost:8181/cxf and app2.localhost:8181/cxf
each one of those will have diferent services.
How can I do that?
Some more context here:
EDIT:
Note:mysql is working fine so im not posting the yaml's here so it doesn't get too long.
Note too that im using karaf with a kar.(that will be my app)
I was thinking that maybe I should have 2 nodes? one with mysql and app1 and the other one with mysql and app2? so in one I could access app1.localhost/cxf services and in the other app2.localhost/cxf services... maybe doesn't make much sense... and I was reading that I need kubeadm for that, and there is no way to install it on windows. I think I must use minikube for that instead?
These are my yaml's:
The load balancer:
apiVersion: v1
kind: Service
metadata:
name: lb-service
spec:
type: LoadBalancer
selector:
app: app1
ports:
- protocol: TCP
name: app1
port: 3306
targetPort: 3306
- protocol: TCP
name: app1-8080
port: 8080
targetPort: 8080
- protocol: TCP
name: app1-8101
port: 8101
targetPort: 8101
- protocol: TCP
name: app1-8181
port: 8181
targetPort: 8181
status:
loadBalancer:
ingress:
- hostname: localhost
app1:
apiVersion: v1
kind: Service
metadata:
name: app1-service
spec:
ports:
- port: 8101
selector:
app: app1
clusterIP: None
---
apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2
kind: Deployment
metadata:
name: app1-deployment
spec:
selector:
matchLabels:
app: app1
replicas: 1
template:
metadata:
labels:
app: app1
spec:
containers:
- name: app1
image: app1:latest
app2: is the same as app1 but in a diferent version(older services)
ingress-resource:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: apps-ingress
#annotations:
#nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
rules:
- host: app1.localhost # tried app1.127-0-0-1.sslip.io ass answered below too.
http:
paths:
- path: /
backend:
serviceName: app1-service
servicePort: 8181
- host: app2.localhost
http:
paths:
- path: /
backend:
serviceName: app2-service
servicePort: 8181
I should be able to access app1 version in app1.localhost:8181/cxf, and app2 version in app2.localhost:8181/cxf
There is another doubt I have, shouldn't I be able to create another loadBalancer? I wanted to, so the selector would be app2 in that loadBalancer, but since I already have one, the new one just stays <pending> until I remove the first one.
That would make some sense, since if I have 2 replicas if app1, and 2 replicas of app2, there should be a loadBalancer for each app right?
Note that I installed the nginx ingress-controller using helm too, since the ingress-resource would not work otherwise, at least thats what I have read.
By installing that, it installed nginx load balancer too, and this one didnt go to pending. Do I need to use nginx loadBalancer? or can I delete it and use kubernetes type loadBalancer?
Huum, im missing something here...
Thanks for your time!
I want to have 2 apps running on kubernetes, I wonder if I can do 2 subdomains using nginx ingress controller.
Yes, you just need any number of DNS records which point to your Ingress controller's IP (you used 127.0.0.1, so that's what I'll use for these examples, but you can substitute whatever IP is relevant). That's the whole point of an Ingress resource: to use the host: header to dispatch requests into the cluster
I found a list of wildcard DNS providers of which I confirmed that app1.127-0-0-1.sslip.io and app2.127-0-0-1.sslip.io do as expected
Thus:
kind: Ingress
metadata:
name: app1-and-2
spec:
rules:
- host: app1.127-0-0-1.sslip.io
http:
paths:
- path: /
backend:
serviceName: app1-backend
servicePort: 8181 # <-- or whatever your Service port is
# then you can repeat that for as many hosts as you wish
- host: app2.127-0-0-1.sslip.io
http:
paths:
- path: /
backend:
serviceName: app2-backend
servicePort: 8181

Kubernetes Services Architecture

I'm trying to connect have NGINX direct traffic to different parts of my app through the config file, but I can't figure it out for the life of me. Here is my current setup:
http-service (loadbalancer)
NGINX (port 80)
website-service (10.27.246.107, port 8000, targetPort 8000, selector 'run: website')
website (label 'run: website', containerPort 8000)
NGINX Conf
upstream website{
server 10.27.246.107:8000
}
This is a normal nginx pod using containerPort 80 at the moment.
Am I going about this the right way?
The best way to rout traffic to different part of your application is using Ingress. In Ingress, you can describe all your paths into all parts of your application. It will look like:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: test
annotations:
ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: foo.bar.com
http:
paths:
- path: /foo
backend:
serviceName: website1
servicePort: 80
- path: /bar
backend:
serviceName: website2
servicePort: 3368
Actually, Ingress-controller is based on Nginx, but anyway you can choose another engine, for example, HAproxy.
Ingress was designed for using in Kubernetes and it has more features in Kubernetes. For example, your website upstream should be described as a service in Kubernetes:
kind: Service
apiVersion: v1
metadata:
name: website1
spec:
selector:
app: python-web-site
ports:
- protocol: TCP
port: 80
targetPort: 8080
Anyway, you can route traffic by Nginx and expose it to the world, but the best practice is to uses Ingress in Kubernetes.

Resources