NGINX Ingress Controller for multiple service for branch wise deployment - regex

I my case, I have a branch wise deployment in EKS 1.14 and I want to handle this with "regex" & Nginx ingress.
Scenario:- Let's say I have Branch B1 with service_A(apache service), Similarly under B2 with service_A((apache service) and so on and want to access the service via URL like:- apache-{branch_name}.example.com
Note :- Branch B1/B2 is nothing but unique namespaces where same kind of service is running.
I need single ingress from where I can control all different branch URL
My example file:-
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: regex-ingress
annotations:
kubernetes.io/ingress.class: "nginx"
cert-manager.io/cluster-issuer: "letsencrypt-prod"
spec:
tls:
- hosts:
- '*.k8s.example.com'
secretName: prod-crt
rules:
- host: {service_A-b1}.k8s.acko.in
http:
paths:
- backend:
serviceName: {service_A-b1}
servicePort: 80
- host: {service_A-b2}.k8s.acko.in
http:
paths:
- backend:
serviceName: {service_A-b2}
servicePort: 80

Nginx ingress don't work in this way, is not possible to have regex in serviceName neither host.
From NGINX docs:
Regular expressions and wild cards are not supported in the spec.rules.host field. Full hostnames must be used.
You can use regex only in path field:
The ingress controller supports case insensitive regular expressions in the spec.rules.http.paths.path field. This can be enabled by setting the nginx.ingress.kubernetes.io/use-regex annotation to true (the default is false).
If you need to control your serviceName and host dinamically I strong recommend use some kind of automation (could be jenkins, bash script etc...) or templates by HELM which will modify at deployment time.
References:
https://kubernetes.github.io/ingress-nginx/user-guide/ingress-path-matching/

Related

How to map multiple services to a single ingress using AWS ALB as Ingress Controller?

I have a single ingress (example, www.a.com). I have mapped the root to a service, like so:
- backend:
serviceName: ui-svc
servicePort: 80
path: /
This routes to the correct service when go to www.a.com. I want to mount another service on /api, like so:
- backend:
serviceName: api-svc
servicePort: 80
path: /api
The routing to www.a.com/api works fine, however any trailing endpoints get 404'd (etc www.a.com/api/swagger, even though this endpoint is mounted in the application itself (spring application)). Previously, using Traefik, I've used the rewriteTarget: / annotation to remedy this, however ALB does not support this. Is there a kubernetes native way that I can solve this problem?
I am using kubernetes 1.17 and EKS as my kubernetes platform.
You can use regular expressions to match the path
- backend:
serviceName: api-svc
servicePort: 80
path: /api/.*
This can be enabled by setting this annotation in your ingress deployment:
nginx.ingress.kubernetes.io/use-regex: "true"
more info https://kubernetes.github.io/ingress-nginx/user-guide/ingress-path-matching/
This has since been remedied by adding
server.servlet.context-path=/*relvantPathName*
As an environment variable to the containers. This is a spring specific thing, where it needs to rewrite the root in order to work.

Kubernetes Ingress Controller GPC GKE can't reach the site

Kubernetes Ingress Controller can't reach the site
Hi, this is the first time I am trying to deploy an application with kubernetes. The problem I am facing is I want to be able link subdomains with my svc, but when I try to navigate to the links I get
This site can’t be reached
I will explain the steps I made for these, probably I something is wrong or missing
I installed ingress-controller on google cloud platform
In GCP -> Networking Services -> Cloud DNS
a. I pointed testcompany.com with google dns
b. I created an A record pointing the public IP from the previous step "ingress-nginx-controller"
my svc manifest
apiVersion: v1
kind: Service
metadata:
namespace: staging
name: testcompany-svc
labels:
app: testcompany-svc
spec:
type: NodePort
ports:
- name: test-http
port: 80
protocol: TCP
targetPort: 3001
selector:
app: testcompany
my ingress manifest
apiVersion: networking.k8s.io/v1beta1
- host: api.testcompany.com
http:
paths:
- backend:
serviceName: testcompany-svc
servicePort: test-http
Everything is green and it seems to be working, but when I try to reach the url I get the This site can’t be reached
Update 1
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
namespace: staging
name: ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: front.stagingtestcompany.com
http:
paths:
- backend:
serviceName: testcompanyfront-svc
servicePort: testcompanyfront-http
- host: api.stagingtestcompanysrl.com
http:
paths:
- backend:
serviceName: testcompanynodeapi-svc
servicePort: testcompanyapi-http
You should check this, in order:
your Service, Pod, Ingress are in the same namespace: kubectl get all -n staging
your Pod is listening on port 3001: run it locally if you can, or use kubectl port-forward pods/[pod-name] -n staging 3001:3001 and try it locally with http://localhost:3001/...
your Service is reaching your Pod correctly: use kubectl port-forward service/testcompany-svc -n staging 3001:3001 and try it locally with http://localhost:3001/...
check any other Ingress spec rules before the one you posted
check for firewall rules in your VPC network, they should allow traffic from Google LBs

Ingress controller does not show external IP

I have been trying to create a kubernetes cluster on Google kubernetes Engine. My pods are sucessfully running but the problem is with the ingress controller. The ingress conroller is not showing the external IP to access the application.
And the YAML file for nginx ingress controller looks like this :
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: http-ingress
labels:
app: ingress
annotations:
kubernetes.io/ingress.class: addon-http-application-routing
nginx.ingress.kubernetes.io/ssl-redirect: "false"
nginx.ingress.kubernetes.io/rewrite-target: /
nginx.ingress.kubernetes.io/proxy-send-timeout: "3600"
nginx.ingress.kubernetes.io/proxy-read-timeout: "3600"
spec:
rules:
- http:
paths:
- path: /
backend:
serviceName: nodeapp1svc
servicePort: 80
- path: /app1
backend:
serviceName: nodeapp2svc
servicePort: 80
- path: /app2
backend:
serviceName: nodeapp2svc
servicePort: 80
What can I do next?
It looks like the problem is related with your annotations, specifically with this one:
kubernetes.io/ingress.class: addon-http-application-routing
The ingress.class you're trying to use is something specific to Azure AKS so definitely you cannot use it on your GKE Cluster.
Note that you can omit kubernetes.io/ingress.class annotation at all if you want your default GKE Ingress controller - ingress-gce to be used.
I tested it on my GKE cluster and without the mentioned above annotation it works just fine.
As to your specific setup, I noticed one more problem, namely your nodeapp[1-3]svc Services are of a type ClusterIP and they need to be either NodePort or LoadBalancer.
If you run:
kubectl describe ingress http-ingress
and take a look at the events section, you may encounter the error message like the one below:
loadbalancer-controller error while evaluating the ingress spec: service "default/nodeapp1svc" is type "ClusterIP", expected "NodePort" or "LoadBalancer"
Summary:
use the correct ingress.class i.e. omit this annotation at all and the default ingress controller will be used.
make sure your backends are exposed via NodePort rather than ClusterIP.

How to hide Django Admin from the public on Azure Kubernetes Service while keeping access via backdoor

I'm running a Django app on Azure Kubernetes Service and, for security purposes, would like to do the following:
Completely block off the admin portal from the public (e.g. average Joe cannot reach mysite.com/admin)
Allow access through some backdoor (e.g. a private network, jump host, etc.)
One scenario would be to run two completely separate services: 1) the main API part of the app which is just the primary codebase with the admin disabled. This is served publicly. and 2) Private site behind some firewall which has admin enabled. Each could be on a different cluster with a different FQDN but all connect to the same datastore. This is definitely overkill - there must be a way to keep everything within the cluster.
I'm think there might be a way to configure the Azure networking layer to block/allow traffic from specific IP ranges, and do it on a per-endpoint basis (e.g. mysite.com/admin versus mysite.com/api/1/test). Alternatively, maybe this is doable on a per-subdomain level (e.g. api.mysite.com/anything versus admin.mysite.com/anything).
This might also be doable at the Kubernetes ingress layer but I can't figure out how.
What is the easiest way to satisfy the 2 requirements?
You can manage restriction at ingress level :
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
nginx.ingress.kubernetes.io/whitelist-source-range: "192.168.0.XXX, 192.175.2.XXX"
name: staging-ingress
namespace: default
spec:
rules:
- host: test.example.io
http:
paths:
- backend:
serviceName: service-name
servicePort: 80
tls:
- hosts:
- test.example.io
secretName: tls-cert
You can white list the IP address for allowing specific path to resolve your backdoor issue. For other you can create another ingress rule with removing annotation for public accesss.
For a particular path :
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
nginx.ingress.kubernetes.io/whitelist-source-range: "192.168.0.XXX, 192.175.2.XXX"
name: staging-ingress
namespace: default
spec:
rules:
- host: test.example.io
http:
paths:
- path : /admin
backend:
serviceName: service-name
servicePort: 80
tls:
- hosts:
- test.example.io
secretName: tls-cert
test.example.io/admin will only be accessible through source-range.

how to add more than one service to ingress with url maps?

Hi I have four microservices running and i want to use one ingress lb for all of those.
Problem here is my ingress is working for only one microservice. but my application has some url like index.html. which means I have to access http:///index.html
If I access http:/// (it shows white label page error)
when I am using url-maps with path as path1 and I am trying to access http:///path1 (it shows white label page error). which means backend are working.But when I am try to access http:///path1/index.html it shows backend not found.
I need to know how to use url-maps in this case. Kindly help me out
Here is an example extracted from the Kubernetes documentation [1] that creates 1 ingress load balancer that points to diferent backend services:
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: s1
servicePort: 80
- path: /bar
backend:
serviceName: s2
servicePort: 80
You can add as many back end services as you need.
[1] https://kubernetes.io/docs/concepts/services-networking/ingress/#simple-fanout