AWS Load Balancer Controller. Ingress with Custom Fixed response 503 - amazon-web-services

maybe someone can help me with this.
I have deployed AWS Load Balancer Controller to EKS.
When I created such ingress:
ingressClassName: alb
rules:
- host: myhost.com
http:
paths:
- backend:
service:
name: frontned
port:
number: 80
path: /*
pathType: ImplementationSpecific
In AWS it looks like this:
Load Balancer Rule in
The question Is that I want to change this default Fixed response 503 message. How can I do it?
I know that I can create something like this in annotations:
alb.ingress.kubernetes.io/actions.response-503: |
{"type":"fixed-response","fixedResponseConfig":{"contentType":"text/plain","statusCode":"503","messageBody":" ERROR ..."}}
And specify a rule for this:
- host: myhost.com
http:
paths:
- backend:
service:
name: response-503
port:
name: use-annotation
path: /*
pathType: ImplementationSpecific
But in this case, all of the traffic will go to this rule, If I specify 2 rules, 1 which will lead to annotation, and another one that will lead to the correct service, only one rule will work.
So I'm looking for a solution that can help me create 1 rule with the condition: if success - > route traffic to the pod, if not -> show custom 503 message.
I will be grateful for your help, thanks in advance!

Related

Exposing a service on EKS using NGINX ingress and issues with load balancer

I am trying to set up a service and expose it externally on EKS. I have already done it on GKE pretty easily but now AWS is giving me a hard time.
My NGINX yaml looks something like that:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: myapp-ingress
annotations:
kubernetes.io/ingress.class: "nginx"
cert-manager.io/cluster-issuer: "letsencrypt-prod"
spec:
tls:
- hosts:
- app.mydomain.com
secretName: myapp-tls
rules:
- host: app.mydomain.com
http:
paths:
- path: /
backend:
serviceName: myapp-service
servicePort: 80
And then I have my domain app.mydomain.com on Google Domains pointing at the ingress external address. There is also a cert-manager service running in order to support HTTPS.
However, while basically the same setup worked completely out of the box on GKE, EKS gives me a hard time.
From what I understand it has something to do with EKS default LoadBalancer being layer 4 in comparison to Google's layer 7 (Which explains HTTPS not working) but there is also issues with redirections of the domain as it just resolves as the ingress address instead of my desired address and thus my app doesn't show up.
The domain is registered over Google Domains and I'm creating Synthetic Records (for my subdomain) that points to my ingress external address on EKS. The same scheme works perfectly fine on GKE but here it resolves the address as the ingress address instead of my domain which results in 404 on the ingress side.
I was wondering if someone could please point me to how to properly set it up? Should I give up on nginx ingress on EKS and move onto ALB? and how to properly associate the domain?
Thank you very much in advance!
Edit:
output of kubectl describe ingress myapp-ingress:
Name: myapp-ingress
Namespace: default
Address: ********************************-****************.elb.eu-west-1.amazonaws.com
Default backend: default-http-backend:80 (<error: endpoints "default-http-backend" not found>)
TLS:
myapp-tls terminates app.mydomain.com
Rules:
Host Path Backends
---- ---- --------
app.mydomain.com
/ myapp-service:80 (172.31.2.238:8000)
Annotations: cert-manager.io/cluster-issuer: myapp-letsencrypt-prod
kubernetes.io/ingress.class: nginx
Events: <none>
Should I give up on nginx ingress on EKS and move onto ALB
No. NGinX ingress controllers work perfectly well on EKS. It is possible to configure them as either layer 4 or layer 7; we use it in layer 7 mode.
Can you update your question with the output of
kubectl get ingress myapp-ingress
I think your ingress path is also incorrect. Unless I'm mistaken that's just routing the root of your app, not all uris. We use the scheme
spec:
rules:
- host: service.d.tld
http:
paths:
- path: /?(.*) # <---
backend:
serviceName: my-service
servicePort: http
Are you seeing errors in the nginx ingress controller's logs? That + kubectl events are both useful for debugging purposes.
I'd disable TLS everywhere and get your service working on http, then work stepwise on getting TLS enabled on the ingress controller.
Edit: Based on your response above,
curl -H "Host: app.mydomain.com" http://<elb-address>:80
SHOULD call through to your service behind the ingress.
How is app.mydomain.com defined? Is it a CNAME to the dns entry?

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.

NGINX Ingress Controller for multiple service for branch wise deployment

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/

eks http https redirect using ingress

This is my ingress file , what I need is how to add https redirection settings here in ingress file , I did it using service file and it works but after to reduce costs I decided to use SINGLE ingress file which manage multiple services with SINGLE AWS CLASSIC load balancer.
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
generation: 4
name: brain-xx
namespace: xx
spec:
rules:
- host: app.xx.com
http:
paths:
- backend:
serviceName: xx-frontend-service
servicePort: 443
path: /
status:
loadBalancer:
ingress:
- ip: xx.xx.xx.xx
I have managed to create http to https redirection on GKE. Let me know if this solution will work for your case on AWS:
Steps to reproduce
Apply Ingress definitions
Configure basic HTTP ingress resource
Create SSL certificate
Replace old Ingress resource with HTTPS enabled one.
Apply Ingress definitions
Follow this Ingress link to check if there are any needed prerequisites before installing NGINX Ingress controller on your AWS infrastructure and install it.
Configure basic HTTP ingress resource and test it
Example below is Ingress configuration with HTTP traffic only.
It will act as starting point:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: ingress-http
annotations:
kubernetes.io/ingress.class: "nginx"
spec:
rules:
- host: xx.yy.zz
http:
paths:
- path: /
backend:
serviceName: hello-service
servicePort: hello-port
- path: /v2/
backend:
serviceName: goodbye-service
servicePort: goodbye-port
Please change this file to reflect configuration appropriate to your case.
Create SSL certificate
For this to work without browser's security warnings you will need valid SSL certificate and a domain name.
To create this certificate you can use for example: Linode create Let's Encrypt SSL certificates.
Let's Encrypt will create files which will be used later.
Configure HTTPS ingress resource and test it
By default Nginx Ingress will create a self-signed certificate if he's not provided one. To provide him one you will need to add it as a secret to your Kubernetes cluster.
As I said earlier the files (cert.pem privkey.pem) that Let's Encrypt created will be added to Kubernetes to configure HTTPS.
Below command will use this files to create secret for Ingress:
$ kubectl create secret tls ssl-certificate --cert cert.pem --key privkey.pem
This Ingress configuration support HTTPS as well as redirects all the traffic to it:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: ingress-https
annotations:
kubernetes.io/ingress.class: "nginx"
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
spec:
tls:
- secretName: ssl-certificate
rules:
- host: xx.yy.zz
http:
paths:
- path: /
backend:
serviceName: hello-service
servicePort: hello-port
- path: /v2/
backend:
serviceName: goodbye-service
servicePort: goodbye-port
Please change this file to reflect configuration appropriate to your case.
Take a look at this fragment which will enable HTTPS and redirect all the traffic to it:
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
spec:
tls:
- secretName: ssl-certificate
Apply this configuration and check if it worked for you.
Below is part of curl output which shows that connecting to http://xx.yy.zz gives redirection to https://xx.yy.zz
< HTTP/1.1 308 Permanent Redirect
< Server: openresty/1.15.8.2
< Date: Fri, 20 Dec 2019 15:06:57 GMT
< Content-Type: text/html
< Content-Length: 177
< Connection: keep-alive
< Location: https://xx.yy.zz/

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