istio virtualservice rewrite not working properly - amazon-eks

I've setup EKS + istio ingress gateway following https://aws.amazon.com/blogs/containers/secure-end-to-end-traffic-on-amazon-eks-using-tls-certificate-in-acm-alb-and-istio/ and it works fine. I want to add uri prefix in virtualservice such that http://domain.tld/vote needs to be displaying vote app created in another namespace in the cluster.
I've used the following istio virtualservice. https://domain.tld works fine however https://domain.tld/vote shows broken layout. screenshot: https://i.is.cc/1ah4YkVU.png
This is the voting app I used for vote service - https://github.com/dockersamples/example-voting-app which use multiple containers. Can someone shed some light on this please?
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: yelb-gateway
spec:
selector:
istio: ingressgateway
servers:
- port:
number: 443
name: https-443
protocol: HTTPS
tls:
mode: SIMPLE
credentialName: "tls-secret"
hosts:
- "*"
---
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: vote
spec:
hosts:
- "*"
gateways:
- yelb-gateway
http:
- match:
- uri:
prefix: /vote
rewrite:
uri: "/"
route:
- destination:
host: vote.vote2.svc.cluster.local
---
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: yelb-ui
spec:
hosts:
- "*"
gateways:
- yelb-gateway
http:
- route:
- destination:
host: yelb-ui
port:
number: 80
match:
- uri:
prefix: /
without a rewrite rule, http://domain.tld/vote was showing 404 errors. with the above rewrite rule,the url is loading but the layout is broken.

You can use one single virtual service like below instead of two. As the port number defined in service 5000 you can mention the same in virutal service. Also in service definition you can use type as "ClusterIP" instead of NodePort. And add "protocol: TCP" in your service definition.
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: vote
spec:
hosts:
- "*"
gateways:
- yelb-gateway
http:
- match:
- uri:
prefix: /vote
route:
- destination:
host: vote.vote2.svc.cluster.local
port:
number: 5000
- uri:
prefix: /
route:
- destination:
host: yelb-ui.default.svc.cluster.local
port:
number: <yelb-service-port-number>

Related

Ingress unable to find backend service in Kubernetes v1.21.5

I am using Kubernetes v1.21.5 on docker. The following is my ingress YAML file
kind: Ingress
metadata:
name: ingress-service
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/use-regex: "true"
spec:
rules:
- host: triver.dev
http:
paths:
- path: /service/account/?(.*)
pathType: Prefix
backend:
service:
name: auth-srv
port:
number: 3000
I am running an auth srv image and the following is its YAML file
kind: Deployment
metadata:
name: auth-depl
spec:
replicas: 1
selector:
matchLabels:
app: auth
template:
metadata:
labels:
app: auth
spec:
containers:
- name: auth
image: triver/auth
env:
- name: MONGO_URI
value: 'mongodb://mongo-srv:27017/auth'
- name: JWT_KEY
valueFrom:
secretKeyRef:
name: jwt-secret
key: JWT_KEY
---
apiVersion: v1
kind: Service
metadata:
name: auth-srv
spec:
selector:
app: auth
ports:
- name: auth
protocol: TCP
port: 3000
targetPort: 3000
but when I try to send a request to any route that I created in auth service for example I created a triver.dev/service/account/signup post express router for a user to signup. When I try to send a post request to the route through Postman it gives an error (404) of ECONNRefused. Couldn't send a request. Why is it happening? (My postman is working fine. It's not an issue on the postman end.)
What am I doing wrong
The app works but I just can't access the route. It's definitely an ingress issue. Can someone help me, please? This is a very important project.
This is what show up when I use the command 'kubectl get ingress'
Everything works fine when I run the application using skaffold dev.
it's due to you have not mentioned the hostname into the ingress, also make sure your ingress controller is running
example ingress
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: example-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
rules:
- host: hello-world.info
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: web
port:
number: 8080
host: hello-world.info
Reference : https://kubernetes.io/docs/tasks/access-application-cluster/ingress-minikube/
you can also checkout : https://kubernetes.io/docs/concepts/services-networking/ingress/
if you have set default backend set in ingress and host is not issue
make sure you are sending the request on HTTP instead of HTTPS
nginx.ingress.kubernetes.io/ssl-redirect: "false"
as you are not using the certificate SSL/TLS so please try the URL with HTTP

Nginx ingress with oauth proxy and CORS

I have two services in Kubernetes which are exposed through nginx controller. Service a wants to invoke content on domain b but at the same time both services need to be authenticated through Google using the oauth-proxy service.
So I have managed to enable CORS and a can invoke b without any issues. But the problem is when I include the authentication as well, I am constantly getting:
Access to manifest at 'https://accounts.google.com/o/oauth2/auth?access_type=offline&approval_prompt=force&client_id=<obscured>.apps.googleusercontent.com&redirect_uri=https%3A%2F%2Fa.example.com%2Foauth2%2Fcallback&response_type=code&scope=profile+email&state=<obscured>manifest.json' (redirected from 'https://a.example.com/manifest.json') from origin 'https://a.example.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
Here are the ingresses:
Service a
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: nginx
kubernetes.io/tls-acme: "true"
nginx.ingress.kubernetes.io/auth-url: "https://$host/oauth2/auth"
nginx.ingress.kubernetes.io/auth-signin: "https://$host/oauth2/start?rd=$escaped_request_uri"
nginx.ingress.kubernetes.io/whitelist-source-range: 0.0.0.0/0
name: a
spec:
rules:
- host: a.example.com
http:
paths:
- backend:
service:
name: a-svc
port:
number: 8080
path: /
pathType: Prefix
tls:
- hosts:
- a.example.com
secretName: a-tls
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/whitelist-source-range: 0.0.0.0/0
labels:
k8s-app: oauth2-proxy
name: a-oauth
spec:
rules:
- host: a.example.com
http:
paths:
- backend:
service:
name: oauth2-proxy
port:
number: 4180
path: /oauth2
pathType: Prefix
tls:
- hosts:
- a.example.com
secretName: a-oauth-tls
Service b
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: nginx
kubernetes.io/tls-acme: "true"
nginx.ingress.kubernetes.io/auth-url: "https://$host/oauth2/auth"
nginx.ingress.kubernetes.io/auth-signin: "https://$host/oauth2/start?rd=$escaped_request_uri"
nginx.ingress.kubernetes.io/enable-cors: "true"
nginx.ingress.kubernetes.io/whitelist-source-range: 0.0.0.0/0
name: b
spec:
rules:
- host: b.example.com
http:
paths:
- backend:
service:
name: b-svc
port:
number: 8080
path: /
pathType: Prefix
tls:
- hosts:
- b.example.com
secretName: b-tls
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/enable-cors: "true"
nginx.ingress.kubernetes.io/auth-url: "https://$host/oauth2/auth"
nginx.ingress.kubernetes.io/auth-signin: "https://$host/oauth2/start?rd=$escaped_request_uri"
nginx.ingress.kubernetes.io/whitelist-source-range: 0.0.0.0/0
labels:
k8s-app: oauth2-proxy
name: b-oauth
spec:
rules:
- host: b.example.com
http:
paths:
- backend:
service:
name: oauth2-proxy
port:
number: 4180
path: /oauth2
pathType: Prefix
tls:
- hosts:
- b.example.com
secretName: b-oauth-tls
Obviously, there is only one difference between these two and that is the cors annotations nginx.ingress.kubernetes.io/enable-cors: "true" in the service b ingresses.
I am not sure of what is causing the issue but I am guessing that the authentication done against Google in service a is not being passed to the CORS request so that the service b can also be authenticate with the same token/credentials.
What am I doing wrong and how can I resolve this?
Based on the documentation, it looks like you lack of annotations for using HTTP.
Try to add fragment like this in service configuration file:
nginx.ingress.kubernetes.io/enable-cors: "true"
nginx.ingress.kubernetes.io/cors-allow-methods: "PUT, GET, POST, OPTIONS"
nginx.ingress.kubernetes.io/cors-allow-credentials: "true"
nginx.ingress.kubernetes.io/configuration-snippet: |
more_set_headers "Access-Control-Allow-Origin: $http_origin";
But it can be a problem with CORS. In such case you should add the following line:
--cors-allowed-origins=["http://*"]
to /etc/default/kube-apiserver or /etc/kubernetes/manifests/kube-apiserver.yaml file (depending on the location your kube-apiserver configuration file).
After that restart kube-apiserver.
See also this similar question.
So, it turns out that the whole Kubernetes and Nginx config was correct, so the solution was implementing the usage of the saved cookie on client side when invoking a CORS request to the second service.
Essentially, this was already answered here: Set cookies for cross origin requests
Excerpt from the answer:
Front-end (client): Set the XMLHttpRequest.withCredentials flag to
true, this can be achieved in different ways depending on the
request-response library used:
jQuery 1.5.1 xhrFields: {withCredentials: true}
ES6 fetch() credentials: 'include'
axios: withCredentials: true

Traefik 2.2 http to https redirect

I'm following the guide and I'm able to access my website via HTTP and HTTPs however redirect is not working for me, any ideas on what might be wrong?
# IngresRoute
---
kind: IngressRoute
apiVersion: traefik.containo.us/v1alpha1
metadata:
name: whoami
namespace: default
spec:
entryPoints:
web:
address: :80
http:
redirections:
entryPoint:
to: websecure
scheme: https
permanent: true
websecure:
address: :443
routes:
- match: Host(`hello.mydomain.io`)
kind: Rule
services:
- name: whoami
port: 80
tls: {}
I use Docker compose, so might not be spot on for you. But suggestion is to add a scheme redirect middleware to your dynamic config file.
http:
middlewares:
https_redirect:
redirectScheme:
scheme: https
permanent: true
Or just add the middleware to your service if you don't have access to the Traefik configs.
I prefer the dynamic config, because then you can register it on any service as required using https_redirect#file.
You do need a router per entrypoint though, using this method. And register the middleware on only the http router.
I'm sure there are other, better ways. But if you need some apps automatically redirecting and some not this is the best solution I've found thusfar.
I have a working configuration which uses Ingress objects instead of IngressRoute , but I hope this will help some people :
Thus, here is a working configuration :
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: redirect
namespace: some_namespace
spec:
redirectScheme:
scheme: https
permanent: true
and
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: wordpress
namespace: your_app_namespace
annotations:
kubernetes.io/ingress.class: traefik
traefik.ingress.kubernetes.io/router.middlewares: some_namespace-redirect#kubernetescrd
spec:
tls:
- secretName: your_certificate
hosts:
- www.your_website.com
rules:
- host: www.your_website.com
http:
paths:
- path: /
backend:
service:
name: your_service
port:
number: 80
pathType: ImplementationSpecific
So the trick is to :
define a Middleware object (in any namespace you want, but that may be in the same one as your app)
reference it in traefik.ingress.kubernetes.io/router.middlewares with the syntax <NAMESPACE>-<NAME>#kubernetescrd (where NAMESPACE and NAME are those of the Middleware object)

how to config traefik 2.2 forward url and remove keywords

I want to forward my request using treafik 2.2 and config my ingress like this:
kind: Ingress
apiVersion: extensions/v1beta1
metadata:
name: soa-illidan-forward
namespace: dabai-pro
selfLink: /apis/extensions/v1beta1/namespaces/dabai-pro/ingresses/soa-illidan-forward
uid: b0778435-4fff-4e78-b85f-a534833b73e0
resourceVersion: '322554'
generation: 1
creationTimestamp: '2020-06-07T11:04:43Z'
spec:
rules:
- host: manage.example.net
http:
paths:
- path: /service
backend:
serviceName: zuul-service
servicePort: 8088
status:
loadBalancer: {}
but the forward still using the key word service and forward to backend, how to remove the keywards service when forward request? I also tried this:
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: pro-manage-route
namespace: dabai-pro
spec:
entryPoints:
- web
routes:
- match: Host(`manage.example.net`)
kind: Rule
services:
- name: be-illidan-frontend
port: 80
- match: Host(`manage.example.net`) && PathPrefix(`/service`)
kind: Rule
services:
- name: zuul-service
port: 8088
but still not work. and this is my request path:
https://manage.example.net/service/illidan/report/user/captcha
and I want forward to backend zuul-service's url is /illidan/report/user/captcha. not /service/illidan/report/user/captcha.
just using traefik StripPrefix middleware, for example:
http:
middlewares:
test-stripprefix:
stripPrefix:
prefixes:
- "/foobar"
- "/fiibar"
for more detail, read the traefik docs.

Trouble at configuring http(s) for an nginx-ingress

Im currently trying to create an ingress, following the ssl-termination approach, which allows me to connect to a service both via http and https.
I managed to create a working ingress for http, partly for https, but not both together..
heres my config
Ingress Controller: Deployment & Service
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: nginx-ingress-controller
spec:
replicas: 1
revisionHistoryLimit: 3
template:
metadata:
labels:
k8s-app: nginx-ingress-lb
spec:
containers:
- args:
- /nginx-ingress-controller
- "--default-backend-service=$(POD_NAMESPACE)/default-http-backend"
env:
<!-- default-config ommitted -->
image: "quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.9.0-beta.17"
imagePullPolicy: Always
livenessProbe:
<!-- omitted -->
name: nginx-ingress-controller
ports:
- containerPort: 80
name: http
protocol: TCP
- containerPort: 443
name: https
protocol: TCP
volumeMounts:
- mountPath: /etc/nginx-ssl/tls
name: tls-vol
terminationGracePeriodSeconds: 60
volumes:
- name: tls-vol
secret:
secretName: tls-test-project-secret
---
apiVersion: v1
kind: Service
metadata:
name: nginx-ingress
spec:
type: NodePort
ports:
- name: http
port: 80
targetPort: http
nodePort: 31115
- name: https
port: 443
targetPort: https
nodePort: 31116
selector:
k8s-app: nginx-ingress-lb
Ingress
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: nginx-ingress
annotations:
kubernetes.io/ingress.class: "nginx"
ingress.kubernetes.io/secure-backends: "false"
# modified this to false for http & https-scenario
ingress.kubernetes.io/ssl-redirect: "true"
# modified this to false for http & https-scenario
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
ingress.kubernetes.io/add-base-url: "true"
spec:
tls:
- hosts:
- author.k8s-test
secretName: tls-test-project-secret
rules:
- host: author.k8s-test
http:
paths:
- path: /
backend:
serviceName: cms-author
servicePort: 8080
Backend - Service
apiVersion: v1
kind: Service
metadata:
name: cms-author
spec:
selector:
run: cms-author
ports:
- name: http
protocol: TCP
port: 8080
targetPort: 8080
Backend-Deployment:
apiVersion: apps/v1
kind: Deployment
metadata:
name: cms-author
spec:
selector:
matchLabels:
run: cms-author
replicas: 1
template:
metadata:
labels:
run: cms-author
spec:
containers:
- name: cms-author
image: <someDockerRegistryUrl>/magnolia:kube-dev
imagePullPolicy: Always
ports:
- containerPort: 8080
I have several issues, when follwing the https only scenario, i can reach the application via the ingress https nodePort, but cant login, as the follwing request goes via http instead of https.. If i put manually https before the url in browser, it is working again and any further request goes via https., but I dont know why :(
The final setting (supporting http and https) is completely not working, as if I try to access the app via http-nodePort of Ingress, it always redirects to ssl, but in this scenario, I configured to ssl-redirect to false, but still not working.
I have read many posts on github, dealing with that, but none of them worked for me
I've changed the nginx-controller images from gce_containers to quay.io, also not working
I've tried some older versions, also not working.
Deploy the nginx ingress controller from the official kubernetes charts repo https://github.com/kubernetes/charts/tree/master/stable/nginx-ingress by setting the helm arguments controller.service.targetPorts.https and controller.service.nodePorts.https. Once they are set, the appropriate NodePort (443) will be configured by helm.
Helm uses the YAML files in https://github.com/kubernetes/charts/tree/master/stable/nginx-ingress/templates.
Along with the nginx ingress controller, you'll need an ingress resource too. Refer https://github.com/nginxinc/kubernetes-ingress/tree/master/examples/complete-example for examples.