istio: use service registry to make internal HTTPS request - linux

we are using kubernetes (1.17.14-gke.1600) and istio (1.7.4)
we have several deployments that need to make each other HTTPS requests using the public DNS record (mydomain.com). The goal here is to make internal HTTPS request instead of going public and then come back.
we cannot change the host with the "internal" dns (ex my-svc.my-namespace.svc.cluster-domain.example ) because sometimes the same host is returned to the client to make HTTP request from the client browser
Our services are exposed in HTTP so I understand that if we want to use HTTPS scheme we need to pass through the istio gateway
Here is my VirtualService, adding the mesh gateway I'm able to make internal HTTP request with the public DNS, but this doesn't work with HTTPS
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: myservice
spec:
gateways:
- istio-system/gateway
- mesh
hosts:
- myservice.mydomain.com
http:
- match:
- uri:
prefix: /
route:
- destination:
host: myservice
port:
number: 3000
subset: v1
Here is the gateway:
apiVersion: v1
items:
- apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
name: gateway
namespace: istio-system
spec:
selector:
istio: ingressgateway
servers:
- hosts:
- '*'
port:
name: http
number: 80
protocol: HTTP
tls:
httpsRedirect: true
- hosts:
- '*'
port:
name: https
number: 443
protocol: HTTPS
tls:
credentialName: ingress-cert
mode: SIMPLE
I've figured out one workaround to solve the problem is to use a Service Entry like this:
apiVersion: networking.istio.io/v1beta1
kind: ServiceEntry
metadata:
name: internal-https-redirect
spec:
endpoints:
- address: 10.43.2.170 # istio-ingressgateway ClusterIP
hosts:
- '*.mydomain.com'
location: MESH_INTERNAL
ports:
- name: internal-redirect
number: 443
protocol: HTTPS
resolution: STATIC
But I'm not sure if the right way to do it or if that is considered a bad practice.
Thank you

Related

Ingress Nginx external IP set not working

I'm trying to make Ingress use external IP i have created in Azure
First I have created an IP in the portal and added my AKS service as network contributor, then added it in the values file used by HELM
# -- List of IP addresses at which the controller services are available
## Ref: https://kubernetes.io/docs/user-guide/services/#external-ips
##
externalIPs: ["20.124.63.xxx"]
# -- Used by cloud providers to connect the resulting `LoadBalancer` to a pre-existing static IP according to https://kubernetes.io/docs/concepts/services-networking/service/#loadbalancer
loadBalancerIP: ""
loadBalancerSourceRanges: []
enableHttp: true
enableHttps: true
But after deployment, my ingress gets two external IPs, and the one set by me does not work at all, only automatically generated works:
My config looks like this, so I think running this as loadbalancer is not exactly possible:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: hello-world-ingress
namespace: default
annotations:
nginx.ingress.kubernetes.io/ssl-redirect: "false"
nginx.ingress.kubernetes.io/use-regex: "true"
nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
ingressClassName: nginx
rules:
- host: xxx.com
http:
paths:
- path: /(.*)
pathType: Prefix
backend:
service:
name: aks-one
port:
number: 80
- host: xxx.com
http:
paths:
- path: /(.*)
pathType: Prefix
backend:
service:
name: aks-two
port:
number: 80
I would like to use static IP I have created to access my Ingress, what should I do to achieve that?
Exposing the Service of your ingress controller with your public ip can be done like this:
apiVersion: v1
kind: Service
metadata:
annotations:
service.beta.kubernetes.io/azure-load-balancer-resource-group: myResourceGroup # only needed if the LB is in another RG
name: ingress-nginx-controller
spec:
loadBalancerIP: <YOUR_STATIC_IP>
type: LoadBalancer
Azure now will spin-up a LoadBalancer with your public IP.
The Ingress Controller then will route incoming traffic to your apps with an Ingress resource:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: minimal-ingress
spec:
ingressClassName: nginx # ingress-nginx specifix
rules:
- http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: test
port:
number: 80

Rewrite rule or server snippet in Nginx ingress with query parameter

I have a cluster with Nginx ingress. I receive an API request, for example:
/api/v1/user?json={query}
I want to redirect this request with ingress to my service. I want to modify it like this:
/api/v2/user/{query}
Assuming your domain name is example.com, and you have a service called example-service exposing port 80, you can achieve this task by defining the following ingress rule.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/configuration-snippet: |
if ($arg_json) {
return 302 https://example.com/api/v2/user/$arg_json;
}
nginx.ingress.kubernetes.io/use-regex: 'true'
name: ingress-rule
namespace: default
spec:
rules:
- host: example.com
http:
paths:
- backend:
service:
name: example-service
port:
number: 80
path: /api/v1/user(.*)
pathType: Prefix

Is it safe to have an internal ClusterIp backend service using HTTP behind an Ngynx Ingress controller accessible via HTTPS?

I have a Service configured to be accessible via HTTP.
kind: Service
apiVersion: v1
metadata:
name: myservice
spec:
ports:
- name: http
protocol: TCP
port: 80
targetPort: 8080
type: ClusterIP
And an Ngynx Ingress configured to make that internal service accessible from a specific secure subdomain.domain
kind: Ingress
apiVersion: extensions/v1beta1
metadata:
name: myservice-ingress
selfLink: /apis/extensions/v1beta1/namespaces/default/ingresses/myservice-ingress
annotations:
certmanager.k8s.io/issuer: letsencrypt-prod
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/backend-protocol: HTTP
spec:
tls:
- hosts:
- myservice.mydomain.com
secretName: myservice-ingress-secret-tls
rules:
- host: myservice.mydomain.com
http:
paths:
- path: /
backend:
serviceName: myservice
servicePort: 80
status:
loadBalancer:
ingress:
- {}
So when I reach https://myservice.mydomain.com I can access to my service through HTTPS.
Is it safe enough or should I configure my service and pods to communicate only through HTTPS?
It's expected behaviour since you've set TLS in your Ingress.
Note that by default the controller redirects (308) to HTTPS if TLS is enabled for that ingress. If you want to disable this behavior globally, you can use ssl-redirect: "false" in the NGINX ConfigMap.
To configure this feature for specific ingress resources, you can use the nginx.ingress.kubernetes.io/ssl-redirect: "false" annotation in the particular resource.
About your question: "Is it safe enough.." - it's opinion based question, so I can answer to use better HTTPS, rather than HTTP, but it's just my opinion. You can always find the difference between HTTP and HTTPS

k8s expose virtual service with istio

I’ve download the Prometheus helm chart
https://github.com/helm/charts/tree/master/stable/prometheus
and deploy it to our cluster as-is and I was able to access prom ui via port-forwarding.
As we are using istio I want to configure it to access with host (lik external IP ) and I configure the following but it doesn’t work for me.
I mean if I put the host I don’t get anything in the browser, any idea what could be missing here ?
I dont see any exteranal-ip when running kubectl get svc -n mon ,
just internal-ip which doesnt help to our needs.
gateway.yaml
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: http-gateway
namespace: mon
spec:
selector:
istio: ingressgateway
servers:
- hosts: mo-gateway.web-system.svc.cluster.local
port:
name: https-monitoring
number: 443
protocol: HTTPS
tls:
mode: SIMPLE
privateKey: /etc/istio/sa-tls/tls.key
serverCertificate: /etc/istio/sa-tls/tls.crt
virtual_service.yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: prom-virtualservice
namespace: mon
spec:
hosts:
- mo-gateway.web-system.svc.cluster.locall
gateways:
- http-gateway
http:
- match:
- uri:
prefix: /prometheus
route:
- destination:
host: prometheus-server
port:
number: 80
Any idea why it doesnt works ?
Btw, If I just change the type of Prometheus to use LoadBalancer it work, I was able to get external-ip and use it but not on istio
istio is up-and-running ...

Invalid host header and default backend 404 with Kubernetes ingress controller

Accessing my nodejs/react site using the URL displays "Invalid Host header". Accessing it through the public IP displays "default backend - 404".
I am using Kubernetes nginx controller with Azure cloud and load balancer.
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: myrule
namespace: mynamespace
annotations:
kubernetes.io/ingress.class: nginx
certmanager.k8s.io/cluster-issuer: letsencrypt-staging
nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
tls:
- hosts:
- mysite.uknorth.cloudapp.azure.com
secretName: tls-secret
rules:
- host: mysite.uknorth.cloudapp.azure.com
http:
paths:
- backend:
serviceName: service-ui
servicePort: 8080
path: /
- backend:
serviceName: service-api
servicePort: 8999
path: /api
Any guidance appreciated.
So let's assume the SSL part is ok (link) since you can reach the nginx ingress controller.
Your rewrite annotation is not necessary for what you need. Take a look at these rules:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: myrule
namespace: mynamespace
annotations:
kubernetes.io/ingress.class: nginx
certmanager.k8s.io/cluster-issuer: letsencrypt-staging
spec:
tls:
- hosts:
- mysite.uknorth.cloudapp.azure.com
secretName: tls-secret
rules:
- host: mysite.uknorth.cloudapp.azure.com
http:
paths:
- backend:
serviceName: service-ui
servicePort: 8080
path: /
- backend:
serviceName: service-api
servicePort: 8999
path: /api
Whatever you send to /api/.* will be redirected to service-api. And whatever you send to / will be send to service-ui.
Thanks for your feedback. It turns out the problem was not with the ingress rule above. The service-ui was running the incorrect command parameters thus not acknowledging the request. I missed the fact that the service-api was responding correctly.
In short, check the endpoints and running services are configured correctly - more a lesson for me than anyone else. I received a response by curling the service locally but that didn't mean it could handle https requests over ingress as the service was configured incorrectly.
Also, another lesson for me, ask the developers if the correct image is being used for the build. And ask them again if they say yes.

Resources