How do I block paths in my (k8s) ingress? - kubernetes

I have a subset of paths that I expose with an ingress.
I'd like to block them for anyone coming through the ingress.
I'm trying this with a GCE Ingress
Adding a rule like:
- host: my.example.com
http:
paths:
- backend:
serviceName: dead-end-backend
servicePort: 80
path: /private
This backend is designated dead-end using Nginx default backend deployment/service but it's not working well.
I'm not asking how to use the default-backend (but it solve it).
I'm asking for a proper way to do this.

I'm not sure it's the best thing to do but what I did was use a "default-backend" service which returns error for anything.
Then I added each route I wanted to block to get to that default backend.
Like the saying - if it's silly, but it's working, then it's not silly.

Related

How to use ingress so that services can talk to each other?

On AWS EKS, I have three pods in a cluster each of which have been exposed by services. The problem is the services can not communicate with each other as discussed here Error while doing inter pod communication on EKS. It has not been answered yet but further search said that it can be done through Ingress. I am having confusion as to how to do it? Can anybody help ?
Code:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
namespace: test
name: ingress-test
annotations:
alb.ingress.kubernetes.io/scheme: internet-facing
alb.ingress.kubernetes.io/target-type: ip
spec:
ingressClassName: alb
rules:
- http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: server-service
port:
number: 8000
My server-service has APIs like /api/v1/getAll, /api/v1/updateAll, etc.
So, what should I write in path and for a database service what should I do??
And say in future I make another microservice and open another service which has APIs like /api/v1/showImage, /api/v1/deleteImage will I have to write all paths in ingress or is their another way for it to work?
A Ingress is a really good solution to expose both a frontend and a backend at the same domain with different paths (but reading your other question, it will be of no help in exposing the database)
With this said, you don't have to write all the paths in the Ingress (unless you want to) as you can instead use pathType: Prefix as it is already in your example.
Let me link you to the documentation Examples which explain how it works really well. Basically, you can add a rule with:
path: /api
pathType: Prefix
In order to expose your backend under /api and all the child paths.
The case where you put a second backend, which wants to be exposed under /api as the first one, is way more complex instead. If two Pods wants to be exposed at the same paths, you will probably need to list all the subpaths in a way that differentiate them.
For example:
Backed A
/api/v1/foo/listAll
/api/v1/foo/save
/api/v1/foo/delete
Backend B
/api/v1/bar/listAll
/api/v1/bar/save
/api/v1/bar/delete
Then you could expose one under subPath /api/v1/foo (Prefix) and the other under /api/v1/bar (Prefix).
As another alternative, you may want to expose the backends at different paths from what they actually expect using a rewrite target rule.

k8s nginx ingress TLS rules: cert vs. paths

I am struggling to get my nginx ingress (on AWS EKS) working with path rules and TLS.
The ingress is from
here
A snippet from the Ingress looks like:
spec:
tls:
- hosts:
- example.com
secretName: ingress-tls
rules:
- host: example.com
- http:
paths:
- path: /api
pathType: Prefix
backend:
service:
name: api-service
port:
number: 443
This ingress creates the AWS network load balancer, with a URL like
https://xyz.elb.us-west-1.amazonaws.com/
I am updating the
ingress-tls
secret with a certificate using
cert-manager.
When I access the ingress using the NLB URL
https://xyz.elb.us-west-1.amazonaws.com/api, I get
GOOD: Correct routing based on the path rules from the ingress definition (i.e. it ​goes to my
api-service as expected)
BAD: Certificate errors since I'm not accessing the ingress with the domain that the certificate is for.
When I access the ingress using the correct domain e.g.
https://example.com/api which is what I want to do, I get:
BAD:
404, it doesn't respect my path rules, and goes to
upstream-default-backend instead.
GOOD: certificate all good, it’s the one for
example.com that
cert-manager configured.
I tried removing the
host: example.com from the
rules:, which gives me:
GOOD: Correct routing based on the path rules from the ingress definition
BAD: Certificate errors, it serves up the default ingress “Fake” certificate instead of the one for
example.com, I guess since the
host is missing from the rules, though not sure of the exact reason.
Can someone please help me get
GOOD
GOOD
I’m at a loss here.
After staring at this for several more hours, and digging through the nasty chunk of lua that is the
nginx.conf for this, I found it! Maybe someday someone will have this problem, and might find this useful.
The problem was:
rules:
- host: example.com
- http:
This is defining (I think) a
host with no forwarding rules, then then some
http forwarding rules without a host. What I had intended was obviously that the forwarding rules would be for the host.
And that would be:
rules:
- host: example.com
http:
I have to say that I'm now even less of a fan of YAML than I was previously, if that's even possible.

Kubernetes service - How to differentiate identical target ports

I have two different deployments creating two different pods that spins up two different containers serves different purposes. but as a coincidence the port being exposed by both of those containers is 8080.
I created a single service with two ports 8080 and 8081(type=LoadBalancer) to expose both of those deployments. when I hit the LoadBalancer url I get back response from container 1 and after hitting refresh few times I get back the response from container 2. This behavior is same on both ports.
I know that changing the port exposed on the dockerfile of one of those containers would solve this problem. but just out of curiosity as a newbie to the kubernetes, is there any different approach to handle this scenario?
You could use Ingress. Here is an example.
Instead of creating one Service for both pods. Create one Service per pod. Make sure the selector labels are different for both. Set type to NodePort. Then create an Ingress with rules like.
spec:
rules:
- host: cafe.example.com
http:
paths:
- path: /tea
backend:
serviceName: tea-svc
servicePort: 80
- path: /coffee
backend:
serviceName: coffee-svc
servicePort: 80
Now there are many ingress solutions out there. Ingress in k8s is just a networking spec. All it is, is a data model that represents your networking logic. The various ingress controllers take that spec and implement the logic with their given solution. Here is a link to the docs for nginx ingress controller. https://www.nginx.com/products/nginx/kubernetes-ingress-controller/

Is there an order to how an Ingress rule is chosen?

Is there an order to Ingress rule specification i.e. will the first qualifying rule be honored?
The intention of following spec is to route all requests that do not have headers Host: foo.com and Host: bar.com and route them to service3. I am not sure if the spec is syntactically correct and more so, if it will serve the desired purpose?
spec:
rules:
- host: foo.com
http:
paths:
- backend:
serviceName: service1
servicePort: http
path: /
- host: bar.com
http:
paths:
- backend:
serviceName: service2
servicePort: http
path: /a/b/c
- http:
paths:
- path: /a/b/c
backend:
serviceName: service3
servicePort: http
Don't think it matters, but I am using the Contour Ingress controller.
I am not familar with Contour, I just quickly browse the doc.
How Contour works with Ingress rule is not clear from its document. I think Contour perfer using its CRD IngressRoute to specify how request rule works.
So I infer your Ingress behavior from offical kubernetes ingress rule:
Request with host: foo.com will route to service1 or service3
Request with host: bar.com will route to service2 or service3
Other request will route to service3
What you have created in syntactically correct and should route http://*/a/b/c and http://*/a/b/c/* to service3 in most ingress controllers.
An Ingress definition is just data that is supplied to an ingress controller though. The implementation of converting that data into config is ingress controller specific.
Code
Contours route config looks to be rooted by a "virtualhost" name. In the route.go code I can't see any handling of the "no virtualhost" case.
From the route.go tests it looks like a virtualhost of * is how the default host is handled.
This sorting of virtualhosts would hopefully always put * in the right place for contour to default as you describe but then I think there is also an interface for this config to be applied to envoy, the actual proxy process.
So it would appear (without testing) that no matter what order you put the Ingress definition in, contour will sort out the default host routes for you as '*'
This kind of makes sense when you consider contour also supports a custom resource definition of IngressRoute which only allows one virtualhost per definition. These CRDs as a group have no specific ordering so the sort is required.

Ingress rule for multiple paths not working as expected

here is the situation: I have 2 deployments running for sonarqube (for different use cases) linked to 2 different services and I am redirecting traffic through Ingress path based routing.
metadata:
annotations:
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
name: sonarqube
namespace: sonar-namespace
spec:
rules:
- host: sonar.example.com
http:
paths:
- backend:
serviceName: sonar-service-1
servicePort: 80
path: /sonarqube/
- backend:
serviceName: sonar-service-2
servicePort: 80
path: /sonarqube-two/
I am able to access UI page under /sonarqube and under /sonarqube-two/ as well but whenever I am trying to take any action (say installing new plugins, creating new user etc) it's redirecting me to login page every single time. Could someone please help me this? Let me know if any information is required from my side.
You need to tell Sonarqube the path in which it is running, if you're not using the default path /.
You can set that by setting
sonar.web.context=/sonarqube
in $SONARQUBE-HOME/conf/sonar.properties
Taken from the official documentation: https://docs.sonarqube.org/latest/setup/install-server/ (Starting the Web Server)
An alternative approach would be to use subdomains instead of paths to host it (e.g. sonar1.example.com and sonar2.example.com). Then you wouldn't need to modify your configuration.
Never thought that issue would be with cache and cookies! Opened a new browser(firefox) and cleared all the history, cache, and cookies and after that, all started working. Now being able to open and take POST actions on both the URLs. Thanks Harsh and Pampy for taking out time and helping me out.