Kubernetes Ingress not accessible (localhost) - kubernetes

I am setting up a minimal Kubernetes cluster on localhost on a Linux machine (starting with hack/local-up-cluster from the checked out repo). In my deployment file I defined an ingress, which should make the services, which are deployed in the cluster, accessible from the outside. Deployment.yml:
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: foo-service-deployment
spec:
replicas: 2
template:
metadata:
labels:
app: foo-service
spec:
containers:
- name: foo-service
image: images/fooservice
imagePullPolicy: IfNotPresent
ports:
- containerPort: 7778
---
apiVersion: v1
kind: Service
metadata:
name: foo-service-service
spec:
ports:
- port: 7778
selector:
app: foo-service
type: NodePort
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: api-gateway-ingress
spec:
rules:
- host:
http:
paths:
- path: /foo
backend:
serviceName: foo-service-service
servicePort: 7779
- path: /bar
backend:
serviceName: bar-service-service
servicePort: 7776
I can not access the services. kubectl describe shows the following for my ingress:
Name: api-gateway-ingress
Namespace: default
Address:
Default backend: default-http-backend:80 (<none>)
Rules:
Host Path Backends
---- ---- --------
*
/foo foo-service-service:7779 (<none>)
/bar bar-service-service:7776 (<none>)
Annotations:
Events: <none>
Is it because there is not address set for my ingress, that it is not visible to outside world yet?

An Ingress resource is just a definition for your cluster how to handle ingress traffic. It needs an Ingress Controller to actually process these definitions; creating an Ingress resource without having deployed an Ingress controller will not have any effect.
From the documentation:
In order for the Ingress resource to work, the cluster must have an Ingress controller running. This is unlike other types of controllers, which typically run as part of the kube-controller-manager binary, and which are typically started automatically as part of cluster creation. You need to choose the ingress controller implementation that is the best fit for your cluster, or implement one.
There are several Ingress controllers available that you can deploy by yourself (typically, via a Deployment resource), like for example the NGINX ingress controller (which is part of the Kubernetes project) or third-party ingress controllers like Traefik, Envoy or Voyager.

Related

endpoints “default-http-backend” not found in Ingress resource

When I am trying to create an ingress resource for my Kubernetes cluster(ingress controller is already created), Ingress resource/rules are creating and I am able to see in the kubectl get ing.
But when I do kubectl describe, I am seeing a error:
Default backend: default-http-backend:80 (<error: endpoints
“default-http-backend” not found>)
Is this expected?? I am not even able to connect to my application using the DNS name (hotel.example.com) which I defined in Ingress resource. Is it due to this http-backend error?
If not, any suggestions to make the application connect!!
[dockuser#hostname]$ kubectl describe ing hotel-ingress -n hotel
Name: hotel-ingress
Namespace: hotel
Address:
Default backend: default-http-backend:80 (<error: endpoints "default-http-backend" not found>)
Rules:
Host Path Backends
---- ---- --------
hotel.example.com
/ hotel-svc:80 (10.36.0.2:80,10.44.0.2:80)
Annotations:
Events:
deployment files:
namespaces.yaml
apiVersion: v1
kind: Namespace
metadata:
name: hotel
ingress.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: hotel-ingress
namespace: hotel
spec:
rules:
- host: hotel.example.com
http:
paths:
- path: /
backend:
serviceName: hotel-svc
servicePort: 80
deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: hotel
namespace: hotel
spec:
replicas: 2
selector:
matchLabels:
app: hotel
template:
metadata:
labels:
app: hotel
spec:
containers:
- name: hotel
image: nginxdemos/hello:plain-text
ports:
- containerPort: 80
service.yaml
apiVersion: v1
kind: Service
metadata:
name: hotel-svc
namespace: hotel
spec:
selector:
app: hotel
ports:
- port: 80
targetPort: 80
You may want add defaultBackend as a part of your Ingress definition like so
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: default-backend-ingress-example
spec:
defaultBackend:
service:
name: hotel-svc
port:
number: 80
Environment
minikube version: v1.21.0
kubectl version: v1.20.7
I realize this was answered (adding for posterity,) however in my case I had already ran
minikube addons enable ingress
but system was still missing default-http-backend.
I suspect that at the time there had been a conflicting use of a port or some such and the default-http-backend silently failed to be created.
After many attempts to correct the issue I finally discovered that executing the following commands fixed the issue for me:
[update 2021-12-15]
original resources no longer available, sorry
If I had to do this again today I would probably try to apply a deployment directly from the ingress-nginx project:
kubectl apply -f https://github.com/kubernetes/ingress-nginx/tree/main/deploy/static/provider/baremetal/deploy.yaml
(not tested)
PS: Note that there already were configmaps present for nginx-load-balancer-conf so I didn't add those.
PPS: Secondly, this was just for education on a local laptop so take its trustworthiness with a grain of salt.
If you are using Minikube, it may be because you haven't enabled ingress.
Please try the command below:
minikube addons enable ingress
or
minikube addons enable ingress --alsologtostderr
The answer in my case was found here, which is that the ingress rule needs to be created in the same namespace as the service rule(s) its referencing. Or else, as discussed in the same thread, one must find a way to include the namespace as part of the reference to that service.
Instead of creating the ingress your-ingress-name in ingress-nginx namespace you should create it in the namespace where you have the service...
Possible solution if you're getting this result:
kubectl describe ingress your-ingress-name
...
Default backend: default-http-backend:80 (<error: endpoints "default-http-backend" not found>)
I tried following this doc steps and it worked fine:
https://kubernetes.io/docs/tasks/access-application-cluster/ingress-minikube/
I think missing default backend can be ignored. At least it is not required for Openshift-style routes with load-balancing work under k8s, as described in this answer.
Create default-http-backend service in kube-system namespace and error will be gone.
See more: ngress-nginx-troubleshooting.

Multiple external IP (load balancers) for ingress-nginx

How can I configure multiple external IPs within a single cluster using ingress-nginx?
I can see that ingress-nginx creates a load balancer service with external IP. I assume I would need to create another load balancer service? How I would indicate in ingress which load balancer to use?
PS I am using GKE.
Create multiple ingress controller. In new controller define a class name, (Here nginx-internal)
spec:
template:
spec:
containers:
- name: nginx-ingress-internal-controller
args:
- /nginx-ingress-controller
- '--election-id=ingress-controller-leader-internal'
- '--ingress-class=nginx-internal'
- '--configmap=ingress/nginx-ingress-internal-controller'
Then Create a Ingress with
kubernetes.io/ingress.class: "nginx-internal" annotation.
For example, creating a hello-world ingress with following yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: hello-world
annotations:
kubernetes.io/ingress.class: "nginx-internal"
spec:
tls:
- secretName: tls-secret
rules:
- http:
paths:
- backend:
serviceName: hello-world-svc
servicePort: 8000
Click here for official documentation

Kubernetes Cross Namespace Ingress Network

I have a simple ingress network, I want to access services at different namespaces, from this ingress network.
How I can do this?
My ingress network yaml file:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: ingress
spec:
rules:
- host: api.myhost.com
http:
paths:
- backend:
serviceName: bookapi-2
servicePort: 8080
path: /booking-service/
I've set the ExternalNames service type to the yaml file:
apiVersion: v1
kind: Service
metadata:
name: bookapi-2
namespace: booking-namespace
spec:
type: ExternalName
externalName: bookapi-2
ports:
- name: app
protocol: TCP
port: 8080
targetPort: 8080
selector:
app: bookapi-2
tier: backend-2
An ExternalName service is a special case of service that does not
have selectors and uses DNS names instead.
You can find out more about ExternalName service from the official Kubernetes documentation:
When you want to access a service from a different namespace, your yaml could, for example, look like this:
kind: Service
apiVersion: v1
metadata:
name: test-service-1
namespace: namespace-a
spec:
type: ExternalName
externalName: test-service-2.namespace-b.svc.cluster.local
ports:
- port: 80
As to your Ingress yaml file, please recheck it and make sure it is compliant with the official examples, for example this one as it contains some inconsistency:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: my-ingress
spec:
rules:
- host: www.mysite.com
http:
paths:
- backend:
serviceName: website
servicePort: 80
- host: forums.mysite.com
http:
paths:
- path:
backend:
serviceName: forums
servicePort: 80
Please also recheck ExternalName yaml as it has TargetPorts and selectors which are not used in this type of Service and make sure that:
ExternalName Services are available only with kube-dns version 1.7
and later.
In case you will not succeed, please share the kind of problem you have meet.
create namespace service-ns
create a service of type ClusterIP ( which is default ) named nginx-service listening on port 80 in namespace service-ns
create nginx deployment in service-ns
create namespace ingress-ns
create a service in ingress-ns of type ExternalName and pointing to FQDN of nginx-service pointing it as nginx-internal.service-ns.svc.cluster.local
create ingress rules
NOTE: Demo code not to be running in production. Just wanted to give an idea of how it would work cross-namespaces
---
#1
apiVersion: v1
kind: Namespace
metadata:
name: service-ns
---
#2
apiVersion: v1
kind: Service
metadata:
labels:
app: nginx
name: nginx-internal
namespace: service-ns
spec:
ports:
- name: "80"
port: 80
targetPort: 80
selector:
app: nginx
---
#3
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: nginx
name: nginx
namespace: service-ns
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
image: nginx
name: nginx
ports:
- containerPort: 80
restartPolicy: Always
---
#4
apiVersion: v1
kind: Namespace
metadata:
name: ingress-ns
---
#5
kind: Service
apiVersion: v1
metadata:
name: nginx
namespace: ingress-ns
spec:
type: ExternalName
externalName: nginx-internal.service-ns.svc.cluster.local
ports:
- port: 80
---
#6
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: main-ingress
annotations:
kubernetes.io/ingress.class: nginx
namespace: ingress-ns
spec:
rules:
- host: whatever.domain.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: nginx
port:
number: 80
Outside traffic comes through ingress controller service that is responsible for routing the traffic based on the defined routing rules or what we call ingress rules in k8s world.
In other words, ingress resources are just routing rules (think of it in away that's similar to DNS records) so when you define an ingress resource you just defined a rule for ingress controller to work on and route traffic based on such defined rules.
Solution:
Since Ingress are nothing but routing rules, you could define such rules anywhere in the cluster (in any namespace) and controller should pick them up as it monitors creation of such resources and react accordingly.
Here's how to create ingress easily using kubectl
Create an ingress
kubectl create ingress <name> -n namespaceName --rule="host/prefix=serviceName:portNumber"
Note: Add --dry-run=client -oyaml to generate yaml manifest file
Or you may create a service of type ExternalName in the same namespace where you have defined your ingress. such external service can point to any URL (a service that lives outside namespace or even k8s cluster)
Here's an example:
Create an ExternalName service
kubectl create service externalname ingress-ns -n namespaceName --external-name=serviceName.namespace.svc.cluster.local --tcp=80:80
Note: Add --dry-run=client -oyaml to generate yaml manifest file
kind: Service
apiVersion: v1
metadata:
name: nginx
namespace: ingress-ns
spec:
type: ExternalName
externalName: serviceName.namespace.svc.cluster.local #or any external svc
ports:
- port: 80 #specify the port of service you want to expose
targetPort: 80 #port of external service
As described above, create an ingress as below:
kubectl create ingress <name> -n namespaceName --rule="host/prefix=serviceName:portNumber"
Note: Add --dry-run=client -oyaml to generate yaml manifest file
ExternaNames service should be created without any selector options. So create the ExternaNames service in the namespace where your ingress resource is created and point the external name service to resolve the name of your application hosted in different namespace.

Kubernetes Ingress Path only works with /

I have configured a kubernetes ingress service but it only works when the path is /
I have tried all manner of different values for the path including:
/*
/servicea
/servicea/
/servicea/*
This is my ingress configuration (that works)
- apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: boardingservice
annotations:
ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: my.url.com
http:
paths:
- path: /
backend:
serviceName: servicea-nodeport
servicePort: 80
This is my nodeport service
- apiVersion: v1
kind: Service
metadata:
name: servicea-nodeport
spec:
type: NodePort
ports:
- port: 80
targetPort: 8081
nodePort: 30124
selector:
app: servicea
And this is my deployment
- apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: servicea
spec:
replicas: 1
template:
metadata:
name: ervicea
labels:
app: servicea
spec:
containers:
- image: 350329402011.dkr.ecr.eu-west-2.amazonaws.com/servicea
name: servicea
ports:
- containerPort: 8080
protocol: TCP
- image: 350329402011.dkr.ecr.eu-west-2.amazonaws.com/serviceb
name: serviceab
ports:
- containerPort: 8081
protocol: TCP
If the path is / then I can do this http://my.url.com/api/ping
but as I will have multiple services I want to do this: http://my.url.com/servicea/api/ping but when I set the path to /servicea I get a 404.
I am running kubernetes on AWS with an ingress-nginx ingress controller
Any idea?
You are not using kubernetes Pods as they are intended to be used. A Pod
it contains one or more application containers which are relatively tightly coupled — in a pre-container world, they would have executed on the same physical or virtual machine.
If you have two applications, servicea and serviceb, they should be running on different Pods: one pod for servicea and another one for serviceb. This has many benefits: you can deploy them separately, scale them independently, etc.
As the docs say
A Pod represents a unit of deployment: a single instance of an application in Kubernetes, which might consist of either a single container or a small number of containers that are tightly coupled and that share resources.
These Pods can be created using Deployments, as you were already doing. That's fine and recommended.
Once you have the Deployments running, you'd create a different Service that would balance traffic between all the Pods for a given Deployment.
And finally, you want to hit servicea or serviceb depending on the request URL. That can be done with Ingress, as you were trying, but mapping each path to different services. For example
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: test
annotations:
ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: my.url.com
http:
paths:
- path: /servicea
backend:
serviceName: servicea
servicePort: 80
- path: /serviceb
backend:
serviceName: serviceb
servicePort: 80
That way, requests going to your ingress controller using the /servicea path would be served by the Pods behind the servicea Service. And requests going to your ingress controller using the /serviceb path would be served by the Pods behind the serviceb Service.
For anyone reading this, my configuration was correct (even though unorthodox, as pointed out by fiunchinho), the error was in my Spring Boot applications, that were running in the containers. I needed to change the context paths to match the Ingress path - I could, of course, have changed the #GetMapping and #PostMapping methods in my Spring Controller, but I opted to change the context path.

Kubernetes Ingress not resolving backend service

I'm trying to create an ingress within minikube. I have already enabled the ingress add on and checked all the associated services and pods have been added and are running.
When I create the ingress I point it to a service.NodePort that is in the same namespace as the ingress. But when I describe the ingress the backend IP address is <none>
This is my deployment yaml
apiVersion: v1
kind: Namespace
metadata:
name: proxy
labels:
name: proxy
---
apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: deployment
namespace: proxy
labels:
app: proxy
spec:
replicas: 1
template:
metadata:
labels:
app: proxy
spec:
containers:
- name: proxy
image: wildapplications/proxy:latest
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8080
imagePullSecrets:
- name: regsecret
---
apiVersion: v1
kind: Service
metadata:
name: service
namespace: proxy
spec:
type: NodePort
ports:
- port: 8080
targetPort: 8080
selector:
app: proxy
externalName: proxy
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: ingress
namespace: proxy
annotations:
ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: echo.example.com
http:
paths:
- path: /test
backend:
serviceName: service
servicePort: 8080
when I describe the ingress I get
Name: ingress
Namespace: proxy
Address: 192.168.99.100
Default backend: default-http-backend:80 (172.17.0.14:8080)
Rules:
Host Path Backends
---- ---- --------
echo.example.com
/test service:8080 (<none>)
Annotations:
rewrite-target: /
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal CREATE 16m ingress-controller Ingress proxy/ingress
Normal CREATE 15m ingress-controller Ingress proxy/ingress
Normal UPDATE 15m ingress-controller Ingress proxy/ingress
Is there anything glaringly obvious as to why the ingress isnt resolving the backend specified to the service created directly above it?
I found the solution to my question so i'll post just in case someone else comes across something similar.
I was trying to access the ingress through my minikube ip address (minikube ip to get the ip), this was providing a 404 because I was not using the host to navigate to it.
To solve the 404 I executed
echo "$(minikube ip) echo.example.com" | sudo tee -a /etc/hosts
and then from there navigating to the host url in my browser.