Traefik ingress does not work with cluster IP - kubernetes

I am using minikube for developing an application on Kubernetes and I am using Traefik as the ingress controller.
I am able to connect and use my application services when I use the url of the host which I defined in the ingress ("streambridge.local") and I set up in the linux hosts ("/etc/hosts"). But when I use the exact same ip address that I used for the dns I am not able to connect to any of the services and I receive "404 page not found". I have to mention that I am using the IP address of the minikube which I got by: $(minikube ip). Below is my ingress config and the commnads that I used for the dns.
How I can connect and use my application services with the IP?
Ingress config:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: my-ingress
annotations:
kubernetes.io/ingress.class: "traefik"
traefik.frontend.rule.type: PathPrefixStrip
traefik.frontend.passHostHeader: "true"
traefik.backend.loadbalancer.sticky: "true"
traefik.wss.protocol: http
traefik.wss.protocol: https
spec:
rules:
- host: streambridge.local
http:
paths:
- path: /dashboard
backend:
serviceName: dashboard
servicePort: 9009
- path: /rdb
backend:
serviceName: rethinkdb
servicePort: 8085
My /etc/hosts:
127.0.0.1 localhost
192.168.99.100 traefik-ui.minikube
192.168.99.100 streambridge.local
This works: http://streambridge.local/rdb
But this does not work: http://192.168.99.100/rdb and returns 404 page not found

You have created ingress routes that evaluate the host header of the http request. So while you are actually connecting to the same ip, it is once with host:streambridge.local and once with "192.168.99.100" for which you did not add a rule in traefik. This is therefore working exactly as configured.

Related

Can I get response of curl through POD IP address (instead of host address) while using nginx ingress

I am using nginx ingress controller below is the ingress rule file for 2 services:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-ingress
namespace: kube-system
annotations:
kubernetes.io/ingress.class: nginx
kubernetes.io/ingress.allow-http: "false"
nginx.ingress.kubernetes.io/ssl-redirect: "false"
nginx.ingress.kubernetes.io/use-regex: "true"
nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
tls:
- hosts:
- rewrite.bar.com.com
secretName: ingress-tls
rules:
- host: rewrite.bar.com.com
- http:
paths:
- path: /my-service-1/(.*)
pathType: Prefix
backend:
service:
name: my-service-1
port:
number: 36995
- path: /my-service-2/(.*)
pathType: Prefix
backend:
service:
name: my-service-2
port:
number: 32243
Now using below command through shell of service-2 I can curl to the service-1 api endpoint, here I need to pass host ('wire.com') which is TLS enabled as well,
curl --resolve wire.com:443:10.22.148.179 https://wire.com:32243/GetData
Above curl using host address give me response successfully, no issue here!
Now I am using IP address of the POD instead of host address, but this won't give me response, it's always give error like curl: (52) Empty reply from server. Here 10.22.148.179 is my ingress public IP address and 10.2.0.58 is my POD IP address.
curl --resolve enabledservices-dev-aks.honeywell.com:443:10.22.148.179 http//10.2.0.58:32243/GetData
My goal to hit the POD/service api end point through IP address, is this possible with context of Ingress integrated?
Moving this from comments to answer.
The issue was curl request and HTTP protocol used while the server is serving by HTTPS. This is the reason of (52) Empty reply from server error.
Request by curl should be done by specifying the protocol like:
curl https://test.example.com:8888
Ingress is used as a single entry point to the cluster so all inside services can be exposed internally in the cluster using cluster-ip service type - see kubernetes service types.
If any inside service/pod is required to be tested from inside the cluster, request should be executed from the cluster to be able to hit a cluster-ip since cluster-ip is only accessible within the cluster.

Kubernetes Ingress with external Reverse Proxy

I'm trying to make the kubernetes dashboard externally accessible.
For this i installed nginx-ingress as ingress controller in my kubernetes cluster which is accessible on port 32012 on the kubernetes node IP.
Now i want to make it accessible via a domain like k8s.xxx.xx. For that I'd create a TLS certificate from Lets Encrypt to secure the whole thing via HTTPS.
Now we have a Apache2 reverse proxy which handles the requests going to k8s.xxx.xx and proxies them to port 32012, but here I'm getting a error from nginx-ingress:
The plain HTTP request was sent to HTTPS port
The connection chain is:
User -> https://k8s.xxx.xx/ > Apache2 reverse proxy redirecting to port 32012 on kubernetes node and handles Lets Encrypt certificate > ingress controller > kubernetes-dashboard pod.
My kubernetes ingress component looks like the following:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: kubernetes-dashboard-ingress
namespace: kubernetes-dashboard
annotations:
nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
spec:
rules:
- host: k8s.xxx.xx
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: kubernetes-dashboard
port:
number: 443

Minikube change address of ingress addon

When I deploy ingress using ingress addon (minikube addons enable ingress) it address sets to 192.168.49.2:
NAME CLASS HOSTS ADDRESS PORTS AGE
some-ingress <none> application.com 192.168.49.2 80, 443 86s
How do I change it to 127.0.0.1 (or external ip) to be able to receive requests from outside?
UPD:
Using vm_driver=docker; minikube ip returns 192.168.49.2.
UPD2: Ingress config:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: application-ingress
annotations:
ingress.kubernetes.io/ssl-redirect: "true"
kubernetes.io/ingress.class: nginx
spec:
tls:
- hosts:
- application.com
secretName: tls-secret
rules:
- host: application.com
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: application-back
port:
number: 80
Actually, you don't have to change it in order to receive external requests.
The rules: part of your configuration:
spec:
rules:
- host: application.com
expects a DNS record with application.com name. Later in the guide you can see:
Add the following line to the bottom of the /etc/hosts file.
Note: If you are running Minikube locally, use minikube ip to get the
external IP. The IP address displayed within the ingress list will be
the internal IP.
172.17.0.15 hello-world.info
This sends requests from hello-world.info to Minikube.
That entry points to your ingress IP or Minikube IP. Of course you need to adjust your IP and DNS name.
If you would like to curl the IP instead of DNS name you can do so by removing the host rule from your ingress. For example:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: application-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- http:
paths:
- path: "/"
backend:
serviceName: application-back
servicePort: 80
After that you should be able to curl -Lk by IP with no issues.

How to get two ingress ports accessible for single service using NGINX kubernetes controller

We have one service which has two exposed ports- one is for server and second is for management. Kubernetes cluster have NGINX controller running. Is there any way to expose both the ports of service in Ingress YAML file?
Details:
Service server Port : 8081
Service Management Port: 8082
We tried with two "backends" in Ingress YAML file but it works only for default port which is 80 and fail for any other port.
ingress.yml file is as below:
kind: Ingress
apiVersion: extensions/v1beta1
metadata:
name: bw-ingress
annotations:
kubernetes.io/ingress.class: "nginx"
spec:
rules:
- host: my.host.net
http:
paths:
- path: "/controller/"
backend:
serviceName: bw-svc1
servicePort: 80
- path: "/actuator/"
backend:
serviceName: bw-svc2
servicePort: 5612
The indentation level of both paths is not equal in your config sample.
Other than that your config looks correct and should result in the following behavior:
All traffic coming to the cluster via my.host.net/controller will be sent to service bw-svc1:80
All traffic coming to the cluster via my.host.net/actuator will be sent to service bw-svc2:5612
If this is not what you'd like to achieve, could you please re-phrase your question?

kubernetes: access Ingress within a Pod

I have an Ingress object set up to route traffic to the appropriate Service based on the Url path. I would like to access/expose this Ingress object within another Pod. I'm wondering if this is possible?
I tried to set up a Service on the Ingress but that didn't seem to work.
So, for whatever reason (ssr, lots of microservices, etc) you want to access k8s resources using their ingress path mapping, instead of calling each service by its internal name.
For example, you have an ingress config like that:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: ingress-service
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/use-regex: 'true'
spec:
rules:
- host: example.com
http:
paths:
- path: /api/users/?(.*)
backend:
serviceName: auth-service
servicePort: 80
- path: /api/cart/?(.*)
backend:
serviceName: cart-service
servicePort: 80
and you want to access auth-service using http://example.com/api/auth instead of http://auth-service.
All you have to do is replace domain part (example.com in our case) with ingress service url. It depends on your configuration and environment, but usually it looks like http://[SERVICE_NAME].[NAMESPACE], for example:
GCP - http://ingress-nginx-controller.ingress-nginx
Helm ingress nginx - http://my-release-ingress-nginx-controller (here we are
using only service name part, because helm installs ingress in
default namespace)
Minikube - if you are using minikube ingress
addon, then you might run into problem where you cannot access
ingress, then just use helm version. (dont disable ingress addon - just install helm version alongside of it)
Get namespaces: kubectl get namespaces
Get service names inside namespace kubectl get services -n [NAMESPACE].
If you have assigned a host name, you also have to provide the domain name and IP address of the cluster to the /etc/hosts file. When you access a service via Ingress from outside the cluster, this is the file that is consulted for host name resolution.
However, a pod running inside a cluster does not have access to this /etc/hosts file. It has its own /etc/hosts file. To use ingress, the pod needs to have the same domain name and IP address entry in it's own /etc/hosts file.
To achieve this, you have to use hostAliases. Here's a sample of how that works:
apiVersion: v1
kind: Pod
metadata:
...
spec:
hostAliases:
- ip:<IP address>
hostnames:
- <host name>
For more detail on hostAliases, go to this link
I have spend so much time on this issue. I found very simple solution. I am using Mac Docker Desktop 3.3.1.
My Kubernetes Version: 1.19.7
I am trying to access UI URL from another pod running in the cluster.
My UI Service
apiVersion: v1
kind: Service
metadata:
name: my-ui-service
spec:
type: LoadBalancer
selector:
app: my-ui
ports:
- protocol: TCP
port: 8080
targetPort: 8080
Ingress for the service
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-ingress
spec:
rules:
- host: my-site.com
http:
paths:
- pathType: Prefix
path: /
backend:
service:
name: my-ui-service
port:
number: 8080
I have used NGINX Ingress Controller.
Command to run the Ingress Controller:
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v0.48.1/deploy/static/provider/cloud/deploy.yaml
Once the controller is ready run the command to see the status of ingress.
kubectl get ingress
Now see the description of the ingress:
kubectl describe ingress my-ingress
Here you will find
Rules:
Host Path Backends
---- ---- --------
my-site.com
/ my-ui-service:8080 (10.1.2.198:8080)
In any pod in the cluster you can access the domain my-site.com by using my-ui-service:8080.
Inside your cluster your pods use services to reach other pods.
From outside the cluster a client may use ingress to reach services.
Ingress resource allows connection to services.
So your pod need to be reachable by a service (my-svc-N in the following example), which you're going to use in your ingress definition.
Take a look at this example:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: example-ing
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
backend:
serviceName: default-http-backend
servicePort: 80
rules:
- host: my-kube.info
http:
paths:
- path: /
backend:
serviceName: my-svc-1
servicePort: 80
- host: cheeses.all
http:
paths:
- path: /aaa
backend:
serviceName: my-svc-2
servicePort: 80
- path: /bbb
backend:
serviceName: my-svc-3
servicePort: 80