Kubernetes Ingress not resolving backend service - kubernetes

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.

Related

Ingress-Nginx-Controller failed to find the 2nd service deployed on Google Cloud Platform

I deployed following 2 services (built in Java) on GCP:
mply6 (service 1, listening on port 8080 external of GCP), corresponding to the URL: http://example.com/path1
gami6 (service 2, listening on port 8081 external of GCP), corresponding to the URL: http://example.com/path2
The yaml to deploy and expose the service 1:
kind: Service
apiVersion: v1
metadata:
name: mply6
spec:
selector:
app: mply6
ports:
- protocol: "TCP"
port: 80
targetPort: 8080
type: LoadBalancer
loadBalancerIP: "35.223.241.9"
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: mply6
spec:
replicas: 1
selector:
matchLabels:
app: mply6
template:
metadata:
labels:
app: mply6
spec:
containers:
- name: mply6
image: gcr.io/mply6-271000/mply6:latest
ports:
- containerPort: 8080
The yaml to deploy and expose the service 2:
kind: Service
apiVersion: v1
metadata:
name: gami6
spec:
selector:
app: gmai6
ports:
- protocol: "TCP"
port: 81
targetPort: 8081
type: LoadBalancer
loadBalancerIP: "35.223.241.9"
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: gami6
spec:
replicas: 1
selector:
matchLabels:
app: gami6
template:
metadata:
labels:
app: gami6
spec:
containers:
- name: gami6
image: gcr.io/mply6-271000/gami6:latest
ports:
- containerPort: 8081
And, the yaml to create the Ingress resource:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: basic-ingress
annotations:
kubernetes.io/ingress.global-static-ip-name: "35.223.241.9"
spec:
rules:
- http:
paths:
- path: /path1
backend:
serviceName: mply6
servicePort: 80
- path: /path2
backend:
serviceName: gami6
servicePort: 81
Furthermore, the result of 'kubectl describe ingress basic-ingress':
Name: basic-ingress
Namespace: default
Address: 35.244.199.199
Default backend: default-http-backend:80 (10.60.1.4:8080)
Rules:
Host Path Backends
---- ---- --------
*
/multiplications/random mply6:80 (10.60.0.32:8080)
/results mply6:80 (10.60.0.32:8080)
/leaders gami6:81 (10.60.0.32:8081)
/stats gami6:81 (10.60.0.32:8081)
Annotations:
kubernetes.io/ingress.global-static-ip-name: 35.223.241.9
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal CREATE 35m nginx-ingress-controller Ingress default/basic-ingress
Warning Translate 21m loadbalancer-controller error while evaluating the ingress spec: could not find service "default/gami6"; could not find service"
default/gami6"
Warning Translate 6m17s (x34 over 77m) loadbalancer-controller error while evaluating the ingress spec: could not find port "8081" in service "default/gami6"; could no
t find port "8081" in service "default/gami6"
Normal CREATE 44s (x1153 over 22h) loadbalancer-controller ip: 35.244.199.199
Normal UPDATE 7s (x13 over 35m) nginx-ingress-controller Ingress default/basic-ingress
Basically I'm expecting that when I give the URL 'http://example.com/path2', the Ingress-Nginx-Controller would find the 2nd service 'gami6', but why is the above error message: could not find service "default/gami6"? (http://example.com/path1 can be found without a problem in the case)
First, I’ve noticed a typo the second service yaml:
spec:
selector:
app: gmai6 <-- should this be gami6?
To use Google’s Ingress with more than one backend you may need to use “NodePort” instead of “LoadBalancer” to expose the services. You can find about this on this documentation:
https://cloud.google.com/kubernetes-engine/docs/concepts/ingress#multiple_backend_services
In case that you want to use nginx ingress controller you should follow this: guide: https://cloud.google.com/community/tutorials/nginx-ingress-gke
I cannot add any remarks on the deployment you have above. However this deployment is very similar to the http-balancer documentation
I tried the deployment mentioned in the documentation and I was able to achieve what you are trying to do. Having a load-balancer routing requests based on the path.

How do I add a service and traefik ingress to an EKS cluster?

Notes
I am trying to deploy a service and ingress for a demo service (from 'Kubernetes in Action') to an AWS EKS cluster in which the traefik ingress controller has been Helm installed.
I am able to access the traefik dashboard from the traefik.example.com hostname after manually adding the IP address of the AWS ELB provisioned by traefik to that hostname in my local /etc/hosts file.
If I describe the service and ingress of the traefik-dashboard:
$ kubectl describe svc -n kube-system traefik-dashboard
Name: traefik-dashboard
Namespace: kube-system
Labels: app=traefik
chart=traefik-1.52.6
heritage=Tiller
release=traefik
Annotations: <none>
Selector: app=traefik,release=traefik
Type: ClusterIP
IP: 10.100.164.81
Port: <unset> 80/TCP
TargetPort: 8080/TCP
Endpoints: 172.31.27.70:8080
Session Affinity: None
Events: <none>
$ kubectl describe ing -n kube-system traefik-dashboard
Name: traefik-dashboard
Namespace: kube-system
Address:
Default backend: default-http-backend:80 (<none>)
Rules:
Host Path Backends
---- ---- --------
traefik.example.com
traefik-dashboard:80 (172.31.27.70:8080)
Annotations:
Events: <none>
The service and ingress controller seem to be using the running traefik-575cc584fb-v4mfn pod in the kube-system namespace.
Given this info and looking at the traefik docs, I try to expose a demo service through its ingress with the following YAML:
apiVersion: apps/v1beta2
kind: ReplicaSet
metadata:
name: kubia
spec:
replicas: 3
selector:
matchLabels:
app: kubia
template:
metadata:
labels:
app: kubia
spec:
containers:
- name: kubia
image: luksa/kubia
---
apiVersion: v1
kind: Service
metadata:
name: kubia
namespace: default
spec:
selector:
app: traefik
release: traefik
ports:
- name: web
port: 80
targetPort: 8080
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: kubia
namespace: default
spec:
rules:
- host: kubia.int
http:
paths:
- path: /
backend:
serviceName: kubia
servicePort: web
After applying this, I am unable to access the kubia service from the kubia.int hostname after manually adding the IP address of the AWS ELB provisioned by traefik to that hostname in my local /etc/hosts file. Instead, I get a Service Unavailable in the response. Describing the created resources shows some differing info.
$ kubectl describe svc kubia
Name: kubia
Namespace: default
Labels: <none>
Annotations: kubectl.kubernetes.io/last-applied-configuration:
{"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"name":"kubia","namespace":"default"},"spec":{"ports":[{"name":"web","por...
Selector: app=traefik,release=traefik
Type: ClusterIP
IP: 10.100.142.243
Port: web 80/TCP
TargetPort: 8080/TCP
Endpoints: <none>
Session Affinity: None
Events: <none>
$ kubectl describe ing kubia
Name: kubia
Namespace: default
Address:
Default backend: default-http-backend:80 (<none>)
Rules:
Host Path Backends
---- ---- --------
kubia.int
/ kubia:web (<none>)
Annotations:
kubectl.kubernetes.io/last-applied-configuration: {"apiVersion":"extensions/v1beta1","kind":"Ingress","metadata":{"annotations":{},"name":"kubia","namespace":"default"},"spec":{"rules":[{"host":"kubia.int","http":{"paths":[{"backend":{"serviceName":"kubia","servicePort":"web"},"path":"/"}]}}]}}
Events: <none>
I also notice that the demo kubia service has no endpoints, and the corresponding ingress shows no available backends.
Another thing I notice is that the demo kubia service and ingress is in the default namespace, while the traefik-dashboard service and ingress are in the kube-system namespace.
Does anything jump out to anyone? Any suggestions on the best way to diagnose it?
Many thanks in advance!
It would seem that you are missing the kubernetes.io/ingress.class: traefik that tells your Traefik ingress controller to serve for that Ingress definition.
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: kubia
namespace: default
annotations:
kubernetes.io/ingress.class: traefik
spec:
rules:
- host: kubia.int
http:
paths:
- path: /
backend:
serviceName: kubia
servicePort: web
If you look at the examples in the docs you can see that the only Ingress that doesn't have annotation is traefik-web-ui that points to the Traefik Web UI.

GKE Ingress - Simple nginx example yet getting error "Could not find nodeport for backend"

I'm trying to create a simple nginx service on GKE, but I'm running into strange problems.
Nginx runs on port 80 inside the Pod. The service is accessible on port 8080. (This works, I can do curl myservice:8080 inside of the pod and see the nginx home screen)
But when I try to make it publicly accessible using an ingress, I'm running into trouble. Here are my deployment, service and ingress files.
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80
kind: Service
apiVersion: v1
metadata:
name: my-service
spec:
selector:
app: nginx
ports:
- protocol: TCP
port: 8080
nodePort: 32111
targetPort: 80
type: NodePort
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: test-ingress
spec:
rules:
- http:
paths:
# The * is needed so that all traffic gets redirected to nginx
- path: /*
backend:
serviceName: my-service
servicePort: 80
After a while, this is what my ingress status looks like:
$ k describe ingress test-ingress
Name: test-ingress
Namespace: default
Address: 35.186.255.184
Default backend: default-http-backend:80 (10.44.1.3:8080)
Rules:
Host Path Backends
---- ---- --------
*
/* my-service:32111 (<none>)
Annotations:
backends: {"k8s-be-30030--ecc76c47732c7f90":"HEALTHY"}
forwarding-rule: k8s-fw-default-test-ingress--ecc76c47732c7f90
target-proxy: k8s-tp-default-test-ingress--ecc76c47732c7f90
url-map: k8s-um-default-test-ingress--ecc76c47732c7f90
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ADD 18m loadbalancer-controller default/test-ingress
Normal CREATE 17m loadbalancer-controller ip: 35.186.255.184
Warning Service 1m (x5 over 17m) loadbalancer-controller Could not find nodeport for backend {ServiceName:my-service ServicePort:{Type:0 IntVal:32111 StrVal:}}: could not find matching nodeport from service
Normal Service 1m (x5 over 17m) loadbalancer-controller no user specified default backend, using system default
I don't understand why it's saying that it can't find nodeport - the service has nodePort defined and it is of type NodePort as well. Going to the actual IP results in default backend - 404.
Any ideas why?
The configuration is missing a health check endpoint, for the GKE loadbalancer to know whether the backend is healthy. The containers section for the nginx should also specify:
livenessProbe:
httpGet:
path: /
port: 80
The GET / on port 80 is the default configuration, and can be changed.

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 not accessible (localhost)

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.