Open kbirger opened 7 years ago
@kbirger this restriction is intentional. While the Ingress spec allows rules with no hosts or an Ingress with no rules but with the default backend, this Ingress controller doesn't support those.
The reason such rules are not supported is that it is possible to create multiple Ingress rules with no hosts, however, NGINX can only handle one such rule.
What is your use-case? Do you only need a single server with no host?
Thanks @pleshakov. Sometimes I'm working with an internal environment where the worker nodes have no machine name. We are still working to see if we can connect our load balancer (F5 Big-IP) to talk to K8S. It would be useful to set up a single server with no host so that regardless of which node the ingress controller is running on and regardless of which node you address, you could access applications on a standard port (80/443).
Right now I'm getting around it by using xip and creating a rule for each worker node, but this of course means I need to reference the node IPs from my ingress configuration.
So instead of having to do:
spec:
rules:
- host: 10.74.151.67.xip.io
http:
paths:
- path: /
backend:
serviceName: my-service
servicePort: 80
- host: 10.74.151.70.xip.io
http:
paths:
- path: /
backend:
serviceName: my-service
servicePort: 80
I'd rather be able to write:
spec:
rules:
- http:
paths:
- path: /
backend:
serviceName: my-service
servicePort: 80
@kbirger if you need to expose only one application, regardless of its DNS name, I recommend deploying NGINX without the Ingress controller, and configure NGINX using its native configuration. You can put that configuration into a ConfigMap resources(https://kubernetes.io/docs/tasks/configure-pod-container/configmap/) and mount that configuration on the filesystem of NGINX container. A simplified config for your case is below:
upstream backend {
server my-service;
}
server {
listen 80 default_server;
location / {
proxy_pass http://backend;
proxy_set_header Host $host;
}
}
Also, for the Ingress resource you attached above, you can use a wildcard host. For example, - host: *.xip.io
I do want multiple applications, though I didn't include it in this example. My understanding is that you may have multiple applications on the same host, and thus on the same server.
The following is what I would like to represent:
upstream service-one {
server service-one;
}
upstream service-two {
server service-two;
}
server {
listen 80 default_server; # underscore causes nginx to match any host
location /one {
proxy_pass http://service-one;
proxy_set_header Host $host;
}
location /two {
proxy_pass http://service-two;
proxy_set_header Host $host;
}
}
Also, host: *.xip.io violates the schema for that field. At least in K8S 1.6, which is what I am currently on (soon upgrading to 1.7, if that makes any difference)
@kbirger Yes, that is a valid case. However, what I meant by an application is that an application has a unique DNS name. This Ingress controller is designed for load balancing several applications, each with a unique DNS name. The case when you only need to load balance one application (with possible path-based routing across multiple k8s services, as in your second example), regardless of the application DNS name, is far less common. Even for a single application, it is common to have a DNS name. That is why it is not supported in this Ingress controller.
Could you try like this : host: "*.xip.io"
? My mistake, I gave you an invalid example.
Is there any new about this Issue? What if I want to call my ingress service from javascript for example? I cannot set Host header from it. As @kbirger says, documentation says it is possible to set a rule without host, but then it is mandatory to add Host to the header...
@alvgarvilla we are not planning to support rules without hosts, as (1) this use case is not common and (2) NGINX can only handle one rule without host, because one NGINX is used for all Ingress rules.
I've a case with a client that I don't control that is calling me via an IP. There is no hostname. This bug makes it impossible to serve the content through a nginx ingress controller.
@benmathews Thanks for sharing. Unfortunately, we don't have any plans to support that use case. For cases when clients don't use the DNS name, we recommend using NGINX without the Ingress controller. Please see https://github.com/nginxinc/kubernetes-ingress/issues/209#issuecomment-341196060 Can that approach solve your problem?
We have lots of applications, this is just one of them. Ingress is certainly wanted and needed. There are always workarounds, but I'd wish to avoid them if possible. In our case, I'll probably put some code on our load balancer to add a host name header.
as a workaround in the Ingress controller, you can create an Ingress resource for which NGINX will create a virtual server that will listen on a custom port. For example:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: cafe-ingress
annotations:
kubernetes.io/ingress.class: "nginx"
nginx.org/listen-ports: "8080"
In the Ingress resource, you can use an arbitrary name as the value of the host.
In this case the generated virtual server will listen on port 8080. If you make a request to NGINX using its IP and port 8080, it will respond even if you don't specify the host header in the request.
Note that you can only have one Ingress resource with exactly one Ingress rule per port.
@pleshakov I just came across this issue while researching a problem we were facing, where we previously had several ingresses using path-based rules and no hosts on the same ingress controller, and the controller would happily route traffic regardless of the hostname, and then suddenly it stopped doing that.
We found that, when there was at least one ingress object picked up by the same controller which did have a host specified, then routing with that particular hostname for other ingress objects which did not have a matching host would not work. However, when we removed the host rule from all the ingresses, leaving only the paths, the controller would route just fine.
I thought I should bring that up because it contradicts your and other statements above that this configuration is not supported... Or was there something I missed?
Hope this helps. (And I would ask the team to please not remove that capability. 😃)
@luispollo we don't support Ingress resources without hosts. It might be the case that you're using a different Ingress Controller https://github.com/kubernetes/ingress-nginx Could you possible double check?
@pleshakov Oh, yes, I'm using the Ingress Controller hosted in the Kubernetes org. I assumed it was just a fork but can see the README clearly states it's a different implementation. My apologies.
In my case to avoid CORS I'm using path-based routing instead of host-based.
And better have something like host: *
to do not binds to stage or prod domains.
Fully agree, I don't want to care on my igress IP.
Is there any solution for this issue? I tried using the rule "hosts: ''" on the config file but got an error: range can't iterate over
we are not planning to support rules without hosts, as (1) this use case is not common and (2) NGINX can only handle one rule without host, because one NGINX is used for all Ingress rules.
Seems like it would be common when using path-based routing -- I don't care what the host name is. Or is there another simple way to do it?
Have in mind these are also valid wildcards:
host: "*.elb.amazonaws.com"
host: "*.com"
I have the same problem i'm using a setup which is later deployed on a system where i dont know (and dont want to care about) the hostname yet so i dont want to specify it. I just need a default vhost routing different paths to different services in different namespaces
I agree not accepting all hosts is very limiting.
Any update on this issue ? Seems like a very common requirement.
There is a workaround that uses server snippet annotation:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: cafe-ingress
annotations:
kubernetes.io/ingress.class: "nginx"
nginx.org/server-snippets: "server_name ~^.*$;"
spec:
tls:
- hosts:
- cafe.example.com
secretName: cafe-secret
rules:
- host: cafe.example.com
http:
paths:
- path: /tea
backend:
serviceName: tea-svc
servicePort: 80
- path: /coffee
backend:
serviceName: coffee-svc
servicePort: 80
As a result, requests that use IP addresses or random host names will be routed to that Ingress resource. For example, curl https://127.0.0.1/coffee -sk
or curl https://bogus.example.com/coffee -sk
Note that you can only deploy one Ingress resource with such a server_name ~^.*$;
. If you deploy multiple Ingresses like that , only one will catch requests with IP addresses or random host names.
Any change of plans on this?
can you support *
similar to istio?
The workaround posted on Feb 3, 2020 does not work for me.
This issue is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 7 days.
I'm another me too. Trying to deploy the same application multiple times to the same Kubernetes cluster. I want to use the same host name. So
http://host.com/production routes to production deployment and http://host.com/preproduction routes to preproduction.
I want to use the same host so I can have one registration in external OpenId Connect provider
Using a similar set up in development with each team/branch having its down deployment with different path to route off. Actually I really want to use a wild card host so I have a DNS record *.myapp.mydomain.com points at the cluster. The wild carded host acts a way of picking a tenant and I route to deployment off path.
So
http://tenant1.myapp.mydomain.com/live routes as tenant1 (and tenant1 OIDC provider) to deployment live
and
http://tenant2.myapp.mydomain.com/test routes as tenant2 to deployment test
This means I can add new tenants by adding the OIDC configuration to the relevant application and I can deploy new environments (or applications) by deploying the app and deploying some ingress rules.
This issue is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 7 days.
Hi folks 👋 It's very clear from all of the comments that there are many use-cases for this. We are looking into re-evaluating the value, priority and effort of this request.
We encourage everyone to keep an eye on the existing Epic Roadmap and Prioritized Backlog for the project.
I am currently in the process of grooming our existing issues, starting with the oldest ones. As you look at the backlog now, know that it is very likely to change in the near future. Some issues may be added, and some removed 🙂
According to the K8S Ingress spec, I should be able to either set a rule with no host, or an ingress with no rules, and be able to have a default backend.
In the first case, the controller rejects the ingress because it has a rule with no host, and in the second case, it fails to create a server entry that has a proxy_pass to the default backend of the rule.
Is this a bug, or is this intentional? (if so, why?)
I'd like to see support for both of these cases as they are in the documentation: https://kubernetes.io/docs/concepts/services-networking/ingress/
If there is some reason why they cannot be supported organically, I'd like to see a way to override the server_name directive that gets generated so that I can have a server that listens to all hosts.
Aha! Link: https://nginx.aha.io/features/IC-111