Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ingress: Allow for multiple hosts #43633

Closed
klausenbusk opened this issue Mar 24, 2017 · 41 comments
Closed

Ingress: Allow for multiple hosts #43633

klausenbusk opened this issue Mar 24, 2017 · 41 comments
Labels
sig/network Categorizes an issue or PR as relevant to SIG Network. triage/unresolved Indicates an issue that can not or will not be resolved.

Comments

@klausenbusk
Copy link
Contributor

Is this a request for help?
No

What keywords did you search in Kubernetes issues before filing this one?
Ingress controller, "hosts", multiple host.

I found this issue: kubernetes/ingress-nginx#87 but it was closed as it was in the wrong repo.


Is this a BUG REPORT or FEATURE REQUEST? (choose one):
FEATURE REQUEST

With the current implementation, if you have a few sub-/domains which need to point to the same service, you get a "lot" of duplicated code.

Example:

spec:
  rules:
  - host: foobar.com
    http:
      paths:
      - backend:
          serviceName: foobar
          servicePort: 80
  - host: api.foobar.com
    http:
      paths:
      - backend:
          serviceName: foobar
          servicePort: 80
  - host: admin.foobar.com
    http:
      paths:
      - backend:
          serviceName: foobar
          servicePort: 80
  - host: status.foobar.com
    http:
      paths:
      - backend:
          serviceName: foobar
          servicePort: 80

So I propose that the Host field get changed from a single FQDN to a array of FQDN.
So I could do something like:

spec:
  rules:
  - host: ["foobar.com", "api.foobar.com", "admin.foobar.com", "status.foobar.com"]
    http:
      paths:
      - backend:
          serviceName: foobar
          servicePort: 80

It save me 18 lines and makes the config more clear.

Maybe dup of: #41881 , but this seems easier to implement.

cc @aledbf (you closed the last issues, not sure if you "work" in this part of k8s)

Kubernetes version (use kubectl version):

Client Version: version.Info{Major:"1", Minor:"5", GitVersion:"v1.5.4", GitCommit:"7243c69eb523aa4377bce883e7c0dd76b84709a1", GitTreeState:"clean", BuildDate:"2017-03-07T23:53:09Z", GoVersion:"go1.7.4", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"5", GitVersion:"v1.5.4+coreos.0", GitCommit:"97c11b097b1a2b194f1eddca8ce5468fcc83331c", GitTreeState:"clean", BuildDate:"2017-03-08T23:54:21Z", GoVersion:"go1.7.4", Compiler:"gc", Platform:"linux/amd64"}

Environment:
DigitalOcean, CoreOS.

@deitch
Copy link
Contributor

deitch commented Apr 7, 2017

+1 for this as well. As referenced by both @klausenbusk and me at #41881 , this would go a long way.

I prefer to have a wildcard or a subdomain-only option, so I can specify host: web.* or host: api.web.* and have anything that starts with that pattern pass through, leaving the service ignorant as to its final domain (is it running in .example.com? .prod.example.com? .beta.example.com? .it.internal?), but anything that moves it past the current monolithic "must list entire single domain in host: is a big step forward.

Personally, I also think the ingress controller (which usually is deployed by cluster admins) should have a restriction that says, "only service the following domains or subdomains of them...", but that is a separate issue.

@Markbnj
Copy link

Markbnj commented May 25, 2017

Another +1. I think almost anyone with a non-trivial ingress use-case will benefit from this.

@k8s-github-robot k8s-github-robot added the needs-sig Indicates an issue or PR lacks a `sig/foo` label and requires one. label May 31, 2017
@ethernetdan ethernetdan added sig/network Categorizes an issue or PR as relevant to SIG Network. and removed needs-sig Indicates an issue or PR lacks a `sig/foo` label and requires one. labels Jun 15, 2017
@jbelinchonm
Copy link

+1

nottrobin added a commit to nottrobin/deployment-configs that referenced this issue Nov 2, 2017
and redirect.

We initially wanted to use [the redirect-from-to-www annotation](https://github.com/kubernetes/ingress-nginx/blob/master/docs/user-guide/annotations.md#redirect-from-to-www), as this is nice and neat, but unfortunately that [isn't able to serve a TLS certificate for the redirected domain](kubernetes/ingress-nginx#605).

Until that's fixed, we have to use this solution, [as others are doing](kubernetes/ingress-nginx#605 (comment)).

(It would also help to make this more DRY if we were able to [specify multiple hosts in a http rule](kubernetes/kubernetes#43633))
@fejta-bot
Copy link

Issues go stale after 90d of inactivity.
Mark the issue as fresh with /remove-lifecycle stale.
Stale issues rot after an additional 30d of inactivity and eventually close.

Prevent issues from auto-closing with an /lifecycle frozen comment.

If this issue is safe to close now please do so with /close.

Send feedback to sig-testing, kubernetes/test-infra and/or @fejta.
/lifecycle stale

@k8s-ci-robot k8s-ci-robot added the lifecycle/stale Denotes an issue or PR has remained open with no activity and has become stale. label Jan 1, 2018
@deitch
Copy link
Contributor

deitch commented Jan 1, 2018

/remove-lifecycle stale

@k8s-ci-robot k8s-ci-robot removed the lifecycle/stale Denotes an issue or PR has remained open with no activity and has become stale. label Jan 1, 2018
@deitch
Copy link
Contributor

deitch commented Jan 1, 2018

Apparently, I cannot remove it from stale...

@dims
Copy link
Member

dims commented Jan 1, 2018

looks like it worked @deitch !

@kramarz
Copy link

kramarz commented Jan 31, 2018

I also would like to see this feature, but as a workaround, I use YAML ids. Here is how it would look for given example.

spec:
  rules:
  - host: foobar.com
    http: &http_rules
      paths:
      - backend:
          serviceName: foobar
          servicePort: 80
  - host: api.foobar.com
    http: *http_rules
  - host: admin.foobar.com
    http: *http_rules
  - host: status.foobar.com
    http: *http_rules

@gtirloni
Copy link
Contributor

gtirloni commented Feb 7, 2018

I don't have much to add except to say this would be very welcome. Hopefully the rules for beta APIs still allow some flexibility to modify this.

@alex-sainer
Copy link

same here - have to add multiple domains i.e.

*.foobar.com
*.foobar.net
*.foobar.biz

what is not really comfortable in the current implementation...

so, vote up...

@fejta-bot
Copy link

Issues go stale after 90d of inactivity.
Mark the issue as fresh with /remove-lifecycle stale.
Stale issues rot after an additional 30d of inactivity and eventually close.

If this issue is safe to close now please do so with /close.

Send feedback to sig-testing, kubernetes/test-infra and/or fejta.
/lifecycle stale

@k8s-ci-robot k8s-ci-robot added the lifecycle/stale Denotes an issue or PR has remained open with no activity and has become stale. label May 24, 2018
@gtirloni
Copy link
Contributor

/remove-lifecycle stale

@k8s-ci-robot k8s-ci-robot removed the lifecycle/stale Denotes an issue or PR has remained open with no activity and has become stale. label May 24, 2018
@aclowkey
Copy link

This is much needed :((

@shubb30
Copy link

shubb30 commented Jul 28, 2018

+1 for this feature.

I also tried @kramarz suggested workaround, and I get the following error:
Error: YAML parse error on mysite-web/templates/ingress.yaml: error converting YAML to JSON: yaml: line 4: mapping values are not allowed in this context

@gexinworks
Copy link

+1 for this feature.

@fejta-bot
Copy link

Issues go stale after 90d of inactivity.
Mark the issue as fresh with /remove-lifecycle stale.
Stale issues rot after an additional 30d of inactivity and eventually close.

If this issue is safe to close now please do so with /close.

Send feedback to sig-testing, kubernetes/test-infra and/or fejta.
/lifecycle stale

@k8s-ci-robot k8s-ci-robot added the lifecycle/stale Denotes an issue or PR has remained open with no activity and has become stale. label Nov 27, 2018
@deitch
Copy link
Contributor

deitch commented Nov 27, 2018

/remove-lifecycle stale

@k8s-ci-robot k8s-ci-robot removed the lifecycle/stale Denotes an issue or PR has remained open with no activity and has become stale. label Nov 27, 2018
@aelmanaa
Copy link

feature needed indeed

@alexeldeib
Copy link
Member

Use case I haven't seen yet, we have some domains that look like api[0-9].domain.io -- existing wildcard domains don't cover this case. The set is small enough to manage manually using yaml IDs, but would be ideal to not need that fallback (e.g., regex domain names)

@ayyazzafar
Copy link

We really need this feature

@mkstephenson
Copy link

Another vote for this feature

@ar4hc
Copy link

ar4hc commented Feb 15, 2019

another work around using range loop:

rules:
          {{- range .Values.ingress.hosts }}
    - host: {{ . }}
      http:
        paths:
          - path: /
            backend:
              serviceName: {{ $fullName }}
              servicePort: 80
              {{- end }}

and in values yaml:

ingress:
  hosts:
    - "bla.blub"
    - "foo.bar"

and set a variable fullName...

Still i'd prefer an array or regex or ... for the hosts element

@thockin thockin added the triage/unresolved Indicates an issue that can not or will not be resolved. label Mar 8, 2019
@thockin
Copy link
Member

thockin commented May 9, 2019

This is almost certainly not happening in Ingress , but we should keep it in mind for the API to follow Ingress (proposals coming soon?)

@thockin thockin closed this as completed May 9, 2019
@deitch
Copy link
Contributor

deitch commented May 9, 2019

API to follow Ingress, @thockin? Is there a replacement in the works?

@HighwayofLife
Copy link

HighwayofLife commented Sep 5, 2019

This is almost certainly not happening in Ingress

No? Seems a frequently requested feature to avoid a lot of duplication. -- What's our alternatives?

@catalinpan
Copy link

Might be useful for someone, I use server-alias option on the nginx ingress to have multiple domains for a single ingress.

@angelogwapo
Copy link

angelogwapo commented Oct 22, 2019

Might be useful for someone, I use server-alias option on the nginx ingress to have multiple domains for a single ingress.

@catalinpan how does it work on your end? My server-alias doesn't work with this config.

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: foobar-ingress
  annotations:
    kubernetes.io/ingress.class: "nginx"
    nginx.ingress.kubernetes.io/rewrite-target: /
    nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
    nginx.ingress.kubernetes.io/server-alias: "two-app.foobar.dev"
spec:
  tls:
  - secretName: tls-secret
  rules:
  - host: "one-app.foobar.dev"
    http:
      paths:
      - backend:
          serviceName: foobar
          servicePort: 80

@catalinpan
Copy link

catalinpan commented Oct 22, 2019

@angelogwapo is worth checking if the nginx ingress version you have supports the alias implementation. If the version is newer check here how the rewrite-target syntax should look like.
There is a case where your alias will not work if there is another ingress which uses the same domain, here is the explanation.

As long as the above case doesn't apply to you and the DNS record for two-app.foobar.dev points to the same load balancer as one-app.foobar.dev your example should work.

I manage the server alias in Route 53 using terraform because of my specific use case, multiple deployments in different regions = multiple server alias CNAMEs pointing to multiple hosts with health checks and few more options.

example:
CNAME two-app.foobar.dev --> one-app-ew1.foobar.dev
CNAME two-app.foobar.dev --> one-app-ase1.foobar.dev

Below is an example of something I use.

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/server-alias: public_url
  name: app1
spec:
  tls:
  - hosts:
    - public_region_url
      secretName: my_wildcard
  rules:
    - host: public_region_url
      http:
        paths:
          - path: /
            backend:
              serviceName: app1
              servicePort: 80

@FabianSperrle
Copy link

This feature would be great to have for users of traefik who are also using the automated Let's Encrypt feature. Here, traefik expects a comma-separated list of domains as the Host (https://docs.traefik.io/v1.7/configuration/acme/#onhostrule), where the first domain will become the main domain of the certificate and all others will be SANs.

@jacqinthebox
Copy link

jacqinthebox commented Jan 30, 2020

@catalinpan I am also struggling with the server-alias annotation.
I have almost the same config as @angelogwapo. I have two domains:

  • one-app.one-domain.dev
  • two-app.two-domain.dev

Both are pointing to the same loadbalancer. Both have a valid TLS certificate.
Below my config. I get directed to the correct page, but the TLS certificate is only valid for the domain mentioned as the host. When I browse to the other domain, I am presented the Kubernetes Ingress Controller Fake Certificate. And vice versa. Any help is appreciated...

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  annotations:
    app.kubernetes.io/instance: ngress-rules
    cert-manager.io/issuer: letsencrypt-prod
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/rewrite-target: /
    nginx.ingress.kubernetes.io/server-alias: two-app.two-domain.dev
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
  name: ingress-rules
  namespace: default
spec:
  rules:
  - host: one-app.one-domain.dev
    http:
      paths:
      - backend:
          serviceName: service1
          servicePort: 80
        path: /
      - backend:
          serviceName: service2
          servicePort: 80
        path: /portal/
  tls:
  - hosts:
    - one-app.one-domain.dev
    secretName: one-app-tls
  - hosts:
    - two-app.two-domain.dev
    secretName: two-app-tls

Btw, I am using version 0.27 which should contain this change: https://github.com/kubernetes/ingress-nginx/pull/4472/files#diff-9bba411a7c28f1ef63c3a5339db109d5

@anton-johansson
Copy link

anton-johansson commented Jan 30, 2020

@jacqinthebox: Your Ingress configuration actually only configures one host (one-app.one-domain.dev). Sure, your tls configures both of them, but you still need one rule for each domain. Specifically see the array under spec.rules. Currently, there is nothing that tells NGINX which service that the 2nd domain should proxy to.

EDIT: My bad, I was too quick. I didn't realize you were talking about the server alias annotation.

@voron
Copy link

voron commented Jan 30, 2020

@jacqinthebox

Both are pointing to the same loadbalancer. Both have a valid TLS certificate.

you may use multiple independent domains in one TLS secret

  - hosts:
    - one-app.one-domain.dev
    - two-app.two-domain.dev
    secretName: all-app-tls

@ioMatrix
Copy link

ioMatrix commented Mar 5, 2020

You can always use a helm chart to create the dup config for each domain in an array. "If" you are using helm of course :)

@owenson
Copy link

owenson commented Mar 28, 2020

+1

@shenmou98
Copy link

@kramarz , Thanks, this workround work for me.

@AndreKoepke
Copy link

The workaround works also perfectly with https://github.com/jetstack/cert-manager .
Here is my example

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
   name: site
   annotations:
      cert-manager.io/issuer: letsencrypt-prod
      nginx.ingress.kubernetes.io/server-alias: host2.com
spec:
   rules:
   - host: host1.com
     http:
      paths:
      - path: /
        backend:
           serviceName: site
           servicePort: 8080
   tls:
   - secretName: nice-name
     hosts:
     - host1.com
     - host2.com

@benjick
Copy link

benjick commented Sep 25, 2020

@AndreKoepke thank you for this. It worked somewhat for me but after adding domain.com to spec.rules[0].host and www.domain.com,domain.se,www.domain.se to nginx.ingress.kubernetes.io/server-alias I get the following error: controller.go:1155] Conflicting hostname (domain.com) and alias (www.domain.se). Removing alias to avoid conflicts.

Any suggestions?

@ulfgebhardt
Copy link

ulfgebhardt commented Feb 17, 2021

kind: Ingress
apiVersion: networking.k8s.io/v1
metadata:
  name:  ingress-{{ .Release.Name }}-webapp
  labels:
    app.kubernetes.io/name:       "{{ .Chart.Name }}"
    app.kubernetes.io/instance:   "{{ .Release.Name }}"
    app.kubernetes.io/version:    "{{ .Chart.AppVersion }}"
    app.kubernetes.io/component:  "ingress-webapp"
    app.kubernetes.io/part-of:    "{{ .Chart.Name }}"
    app.kubernetes.io/managed-by: "{{ .Release.Service }}"
    helm.sh/chart:                "{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}"
  annotations:
    kubernetes.io/ingress.class: "nginx"
    cert-manager.io/cluster-issuer: {{ .Values.LETSENCRYPT.ISSUER }}
    nginx.ingress.kubernetes.io/proxy-body-size: {{ .Values.NGINX.PROXY_BODY_SIZE }}
spec:
  tls:
    - hosts:
    {{- range .Values.LETSENCRYPT.DOMAINS }}
      - {{ . }}
    {{- end }}
      secretName: tls
  rules:
    {{- range .Values.LETSENCRYPT.DOMAINS }}
    - host: {{ . }}
      http:
        paths:
          - path: /
            pathType: ImplementationSpecific
            backend:
              service:
                name: {{ $.Release.Name }}-webapp
                port:
                  number: 3000
    {{- end }}
LETSENCRYPT:
  ...
  DOMAINS:
    - "wir.social"
    - "www.wir.social"

@dstibbe
Copy link

dstibbe commented Jul 6, 2021

I also would like to see this feature, but as a workaround, I use YAML ids. Here is how it would look for given example.

spec:
  rules:
  - host: foobar.com
    http: &http_rules
      paths:
      - backend:
          serviceName: foobar
          servicePort: 80
  - host: api.foobar.com
    http: *http_rules
  - host: admin.foobar.com
    http: *http_rules
  - host: status.foobar.com
    http: *http_rules

this is the way :)

@Brianm0823
Copy link

The workaround works also perfectly with https://github.com/jetstack/cert-manager . Here is my example

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
   name: site
   annotations:
      cert-manager.io/issuer: letsencrypt-prod
      nginx.ingress.kubernetes.io/server-alias: host2.com
spec:
   rules:
   - host: host1.com
     http:
      paths:
      - path: /
        backend:
           serviceName: site
           servicePort: 8080
   tls:
   - secretName: nice-name
     hosts:
     - host1.com
     - host2.com

Does host2.com return a valid cert or do you get "Kubernetes Ingress Controller Fake Certificate"? How did you combine them so both domains use the same secret

@Brianm0823
Copy link

@catalinpan I am also struggling with the server-alias annotation. I have almost the same config as @angelogwapo. I have two domains:

* one-app.one-domain.dev

* two-app.two-domain.dev

Both are pointing to the same loadbalancer. Both have a valid TLS certificate. Below my config. I get directed to the correct page, but the TLS certificate is only valid for the domain mentioned as the host. When I browse to the other domain, I am presented the Kubernetes Ingress Controller Fake Certificate. And vice versa. Any help is appreciated...

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  annotations:
    app.kubernetes.io/instance: ngress-rules
    cert-manager.io/issuer: letsencrypt-prod
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/rewrite-target: /
    nginx.ingress.kubernetes.io/server-alias: two-app.two-domain.dev
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
  name: ingress-rules
  namespace: default
spec:
  rules:
  - host: one-app.one-domain.dev
    http:
      paths:
      - backend:
          serviceName: service1
          servicePort: 80
        path: /
      - backend:
          serviceName: service2
          servicePort: 80
        path: /portal/
  tls:
  - hosts:
    - one-app.one-domain.dev
    secretName: one-app-tls
  - hosts:
    - two-app.two-domain.dev
    secretName: two-app-tls

Btw, I am using version 0.27 which should contain this change: https://github.com/kubernetes/ingress-nginx/pull/4472/files#diff-9bba411a7c28f1ef63c3a5339db109d5

What was the fix for this? I cannot get it to return anything but "Kubernetes Ingress Controller Fake Certificate" for the aliased domain.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
sig/network Categorizes an issue or PR as relevant to SIG Network. triage/unresolved Indicates an issue that can not or will not be resolved.
Projects
None yet
Development

No branches or pull requests