I have setup as below:
One kubernetes cluster with nginx ingress for deployment A. Ingress to deployment has configuration for host example.com. I want abc.com to point to example.comusing CNAME but its always throwing SSL error.
If I understand you correctly you need to use Rewrite annotations.
See the example below:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$2
name: rewrite
namespace: default
spec:
rules:
- host: rewrite.bar.com
http:
paths:
- backend:
serviceName: http-svc
servicePort: 80
path: /something(/|$)(.*)
In this ingress definition, any characters captured by (.*) will be
assigned to the placeholder $2, which is then used as a parameter in
the rewrite-target annotation. For example, the ingress definition
above will result in the following rewrites:
- rewrite.bar.com/something rewrites to rewrite.bar.com/
- rewrite.bar.com/something/ rewrites to rewrite.bar.com/
- rewrite.bar.com/something/new rewrites to rewrite.bar.com/new
Please let me know if that helped.
EDIT:
More options:
create additional Ingresses
use HTTP (80) and generate SSL certificates
Related
I have a pod that exposes an HTTP service.
This pod has some HTTP endpoints which are available under /accounts.
My goal is to access this sub-path via accounts.example.com.
For example if the url accounts.example.com/test is requested, the nginx ingress should route the request to /accounts/test on my pod.
In the nginx ingress documentation I cannot find a use-case with examples like this.
You should use rewrite to accomplish your request.
https://kubernetes.github.io/ingress-nginx/examples/rewrite/
Here is an example:
Focus on this line: path: /something(/|$)(.*)
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$2
name: rewrite
namespace: default
spec:
rules:
- host: rewrite.bar.com
http:
paths:
- backend:
serviceName: http-svc
servicePort: 80
path: /something(/|$)(.*)
Look on the different annotations for the re-write:
When I use nginx as ingress controller for my k8s cluster, specifying an ingress rule automatically creates corresponding configurations in the /etc/nginx/conf.d/ files of nginx pod.
So, it configures proxy_pass directive there to relevant upstream/backend service. And it is http.
For this ingress rule for my service:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: my-ingress
# annotations:
# nginx.org/redirect-to-https: "false"
# #nginx.ingress.kubernetes.io/ssl-passthrough: "true"
spec:
ingressClassName: nginx
tls:
- hosts:
- test.myapp.com
secretName: test-tls-secret
rules:
- host: test.myapp.com
http:
paths:
- backend:
serviceName: myui
servicePort: 80
- path: /api/
backend:
serviceName: myapp
servicePort: 88
By default, it automatically creates this directive for backend in nginx configuration:
proxy_pass http://default-my-ingress-test.myapp.com-myapp-88;
But instead, i need it to be https like this:
proxy_pass https://default-my-ingress-test.myapp.com-myapp-88;
Then only my application will work as that backend accepts https requests only.
Is there any way to modify that proxy_pass directive for a particular backend service for this purpose, using any annotations or something like that via Ingress resource?
EDIT:
Is there any annotation like that available?
Or Is there any option that I could handle it with a sidecar container in the same pod with the actual myapp container?
I had a similar requirement very recently where the backend pods expected the request on https.
What you'd need is ssl-passthrough feature of nginx controller. You need to start the nginx ingress controller with flag --enable-ssl-passthrough. This can be passed as a command line argument to the nginx deployment.
Thereafter, the ingress resource needs to be deployed with the following annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
nginx.ingress.kubernetes.io/secure-backends: "true"
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/ssl-passthrough: "true"
to instruct the controller to send TLS connections directly to the backend.
how do I achieve something similar to this.
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: nginx
ingress.kubernetes.io/rewrite-target: /c/{word-maching-wildcard}
name: some-route
namespace: prod
spec:
rules:
- host: "*.example.com" # {hello}.example.com -> hello.example.com/hello
http:
paths:
- backend:
serviceName: svc
servicePort: 8080
path: /
Is there any way to capture the matching word in the subdomain and append it in the path before routing to the upstream service.
From the official doc:
Regular expressions and wild cards are not supported in the
spec.rules.host field. Full hostnames must be used.
See: nginx-ingress-matching.
However I have found similar problem which advice to write your own controller that writes out an nginx config that uses $http_host in the appropriate proxy_pass or redirect lines.
Read more: wildcard-url-mapping.
I'd like to split incoming traffic in Kubernetes Nginx in the following way:
Client --> Nginx --> {Service A, Service B}
The problem I am facing is Service A is an internal service and does not support HTTPS therefore SSL should be terminated for Service A. On the other hand, Service B is an external service (hosted on example.com) and only works over HTTPS.
I cannot manage to get this work easily with Kubernetes Nginx. Here is what I have come with:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: ingress-proxy
annotations:
nginx.ingress.kubernetes.io/backend-protocol: HTTPS
nginx.ingress.kubernetes.io/upstream-vhost: example.com
spec:
tls:
- hosts:
- proxy.com
secretName: secret
rules:
- host: proxy.com
http:
paths:
- path: /api/v1/endpoint
backend:
serviceName: service-a
servicePort: 8080
- path: /
backend:
serviceName: service-b
servicePort: 443
kind: Service
apiVersion: v1
metadata:
name: service-b
namespace: default
spec:
type: ExternalName
externalName: service-b.external
ports:
- port: 443
I have got a route for service-b.external:443 to point to example.com.
This solution only works if service-b is over HTTPS, but in my case, I cannot change to HTTPS for this service because of some other internal dependencies.
My problem is the backend-protocol annotation works for the whole kind and I cannot define it per path.
P.S: I am using AWS provider
Following the suggested solution and question from comments.
Yes, like mentioned below it is possible to have two ingress items. In your case
only one should have backend-protocol in it.
According to nginx ingress documentation:
Basic usage - host based routingĀ¶
ingress-nginx can be used for many use cases, inside various cloud provider and supports a lot of configurations. In this section you can find a common usage scenario where a single load balancer powered by ingress-nginx will route traffic to 2 different HTTP backend services based on the host name.
First of all follow the instructions to install ingress-nginx. Then imagine that you need to expose 2 HTTP services already installed: myServiceA, myServiceB. Let's say that you want to expose the first at myServiceA.foo.org and the second at myServiceB.foo.org. One possible solution is to create two ingress resources:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: ingress-myservicea
annotations:
# use the shared ingress-nginx
kubernetes.io/ingress.class: "nginx"
spec:
rules:
- host: myservicea.foo.org
http:
paths:
- path: /
backend:
serviceName: myservicea
servicePort: 80
---
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: ingress-myserviceb
annotations:
# use the shared ingress-nginx
kubernetes.io/ingress.class: "nginx"
spec:
rules:
- host: myserviceb.foo.org
http:
paths:
- path: /
backend:
serviceName: myserviceb
servicePort: 80
When you apply this yaml, 2 ingress resources will be created managed by the ingress-nginx instance. Nginx is configured to automatically discover all ingress with the kubernetes.io/ingress.class: "nginx" annotation. Please note that the ingress resource should be placed inside the same namespace of the backend resource.
On many cloud providers ingress-nginx will also create the corresponding Load Balancer resource. All you have to do is get the external IP and add a DNS A record inside your DNS provider that point myServiceA.foo.org and myServiceB.foo.org to the nginx external IP. Get the external IP by running:
kubectl get services -n ingress-nginx
It is also possible to have separate nginx classes as mentioned here.
Due to some legacy application that relies on Host header to function correctly, I need to have an Ingress (proxy, etc) that capable of rewrite Host header and pass that to downstream (backend). Is there any Ingress Controller that supports this functionality?
Example:
End user access our website through foo.com/a for backend a and foo.com/b for backend b. But since a and b are legacy app, it only accept:
a accepts connection when Host: a.foo.com
b accepts connection when Host: b.foo.com
This can be done using this annotation: nginx.ingress.kubernetes.io/upstream-vhost: host.example.com
I'm not sure whether you can find appropriate annotation within NGINX Ingress Controller for Host header modification to match your requirement as well. However, you can consider using nginx.ingress.kubernetes.io/configuration-snippet annotation in order to append configuration snippet to the location block inside nginx.conf of the particular Nginx controller pod:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/configuration-snippet: |
proxy_set_header Host www.example-host.com;
name: my-app
spec:
rules:
- host: my-app.example.com
http:
paths:
- backend:
path: /app
serviceName: my-app
servicePort: http
We set here Host header www.example-host.com for target URL my-app.example.com.
I want to add my finding to this question of mine.
Although my solution is not using k8s Ingress Controller, our cluster is using Istio and Istio's VirtualService supports rewrite the uri and authority (Host header) as documented in this link: https://istio.io/docs/reference/config/istio.networking.v1alpha3/#HTTPRewrite
To know how I implement that in my case, you can take a look at this link: https://github.com/istio/istio/issues/11668
you can use ingress nginx controller on Kubernetes and set head and also transfer to backend and manage services connection from ingress objects.
here sharing link for rewrite target from header: https://kubernetes.github.io/ingress-nginx/examples/rewrite/
ingress nginx will be also good with SSL cert manager you can add it.
manage other thing using annotations of ingress.
check this out for ingress SSL setup you can modify it and per your need: https://www.digitalocean.com/community/tutorials/how-to-set-up-an-nginx-ingress-with-cert-manager-on-digitalocean-kubernetes
ingress will be like at last
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: ingress
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
tls:
- hosts:
- myapp.abc.com
secretName: ingress-tls
rules:
- host: myapp.abc.com
http:
paths:
- path: /my-service
backend:
serviceName: my-backend
servicePort: 80