kubernetes-ingress icon indicating copy to clipboard operation
kubernetes-ingress copied to clipboard

Support for not setting explicit host

Open kbirger opened this issue 6 years ago • 29 comments

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

kbirger avatar Nov 01 '17 15:11 kbirger

@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?

pleshakov avatar Nov 01 '17 17:11 pleshakov

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 avatar Nov 01 '17 17:11 kbirger

@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

pleshakov avatar Nov 01 '17 18:11 pleshakov

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 avatar Nov 02 '17 12:11 kbirger

@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.

pleshakov avatar Nov 02 '17 19:11 pleshakov

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 avatar Jan 30 '18 18:01 alvgarvilla

@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.

pleshakov avatar Jan 31 '18 11:01 pleshakov

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 avatar Mar 12 '18 18:03 benmathews

@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?

pleshakov avatar Mar 13 '18 14:03 pleshakov

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.

benmathews avatar Mar 13 '18 15:03 benmathews

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 avatar Mar 13 '18 20:03 pleshakov

@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 avatar Aug 15 '18 16:08 luispollo

@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 avatar Aug 15 '18 17:08 pleshakov

@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.

luispollo avatar Aug 15 '18 21:08 luispollo

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.

delfer avatar Mar 22 '19 11:03 delfer

Fully agree, I don't want to care on my igress IP.

jjindrich avatar Jun 03 '19 17:06 jjindrich

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 *

nfds89 avatar Jun 20 '19 10:06 nfds89

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?

clarktlaugh avatar Jul 29 '19 20:07 clarktlaugh

Have in mind these are also valid wildcards: host: "*.elb.amazonaws.com" host: "*.com"

htonkovac avatar Aug 11 '19 20:08 htonkovac

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

cseeger-epages avatar Jan 06 '20 15:01 cseeger-epages

I agree not accepting all hosts is very limiting.

Benjamin-Beeman avatar Jan 31 '20 16:01 Benjamin-Beeman

Any update on this issue ? Seems like a very common requirement.

lokeshmadan avatar Feb 03 '20 18:02 lokeshmadan

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.

pleshakov avatar Feb 04 '20 00:02 pleshakov

Any change of plans on this?

skashyap7 avatar Feb 06 '20 23:02 skashyap7

can you support * similar to istio?

lubinson avatar Feb 28 '20 08:02 lubinson

The workaround posted on Feb 3, 2020 does not work for me.

johnzeng2010 avatar Mar 03 '21 19:03 johnzeng2010

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.

github-actions[bot] avatar May 11 '21 01:05 github-actions[bot]

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.

congenica-peter-fox avatar Jun 23 '21 12:06 congenica-peter-fox

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.

github-actions[bot] avatar Sep 01 '21 01:09 github-actions[bot]