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

Gateway listeners with same hostname not working #3137

Open
bjee19 opened this issue Feb 14, 2025 · 0 comments · May be fixed by #3159
Open

Gateway listeners with same hostname not working #3137

bjee19 opened this issue Feb 14, 2025 · 0 comments · May be fixed by #3159
Assignees
Milestone

Comments

@bjee19
Copy link
Contributor

bjee19 commented Feb 14, 2025

Describe the bug
When gateway listeners have the same hostname but different port/name, they are not generating server blocks correctly and traffic cannot flow to either listener.

To Reproduce
Given a gateway like such:

kind: Gateway
metadata:
  name: gateway
spec:
  gatewayClassName: nginx
  listeners:
  - name: diffport
    port: 7777
    protocol: HTTP
    hostname: "cafe.example.com"
  - name: http
    port: 80
    protocol: HTTP
    hostname: "cafe.example.com"

and an httproute like such:

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: coffee
spec:
  parentRefs:
  - name: gateway
    sectionName: http
  hostnames:
  - "cafe.example.com"
  rules:
  - matches:
    - path:
        type: PathPrefix
        value: /coffee
    backendRefs:
    - name: coffee
      port: 80

and coffee application like such:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: coffee
spec:
  replicas: 1
  selector:
    matchLabels:
      app: coffee
  template:
    metadata:
      labels:
        app: coffee
    spec:
      containers:
      - name: coffee
        image: nginxdemos/nginx-hello:plain-text
        ports:
        - containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
  name: coffee
spec:
  ports:
  - port: 80
    targetPort: 8080
    protocol: TCP
    name: http
  selector:
    app: coffee

There is no server block in the nginx configuration and traffic cannot flow to either listener.

Expected behavior
I expect that the HTTPRoute should be able to match to the http listener because it is set in the sectionName and for traffic to be able to flow.

Your environment

  • Version of the NGINX Gateway Fabric - edge
  • Version of Kubernetes : v1.32.0
  • Kubernetes platform - kind
  • Details on how you expose the NGINX Gateway Fabric Pod (e.g. Service of type LoadBalancer or port-forward) - local kind cluster
  • Logs of NGINX container:
Defaulted container "nginx-gateway" out of: nginx-gateway, nginx, init (init)
{"level":"info","ts":"2025-02-14T19:36:08Z","msg":"Starting NGINX Gateway Fabric in static mode","version":"edge","commit":"3bd5020121796173bdad8afcce036c1c5310f908","date":"2025-02-13T17:49:12Z","dirty":"true"}
{"level":"info","ts":"2025-02-14T19:36:08Z","msg":"Starting manager"}
{"level":"info","ts":"2025-02-14T19:36:08Z","msg":"starting server","name":"health probe","addr":"[::]:8081"}
{"level":"info","ts":"2025-02-14T19:36:08Z","logger":"controller-runtime.metrics","msg":"Starting metrics server"}
{"level":"info","ts":"2025-02-14T19:36:08Z","logger":"controller-runtime.metrics","msg":"Serving metrics server","bindAddress":":9113","secure":false}
{"level":"info","ts":"2025-02-14T19:36:08Z","msg":"attempting to acquire leader lease nginx-gateway/my-release-nginx-gateway-fabric-leader-election..."}
{"level":"info","ts":"2025-02-14T19:36:08Z","msg":"successfully acquired lease nginx-gateway/my-release-nginx-gateway-fabric-leader-election"}
{"level":"info","ts":"2025-02-14T19:36:09Z","logger":"eventLoop.eventHandler","msg":"NGINX configuration was successfully updated","batchID":1}
{"level":"info","ts":"2025-02-14T19:36:09Z","logger":"telemetryJob","msg":"Starting cronjob"}
{"level":"info","ts":"2025-02-14T19:36:09Z","logger":"eventLoop.eventHandler","msg":"Reconfigured control plane.","batchID":2}
{"level":"info","ts":"2025-02-14T19:36:09Z","logger":"eventLoop.eventHandler","msg":"NGINX configuration was successfully updated","batchID":2}
{"level":"info","ts":"2025-02-14T19:36:09Z","logger":"eventLoop.eventHandler","msg":"Reconfigured control plane.","batchID":3}
{"level":"info","ts":"2025-02-14T19:36:09Z","logger":"eventLoop.eventHandler","msg":"Handling events didn't result into NGINX configuration changes","batchID":3}
{"level":"info","ts":"2025-02-14T19:36:11Z","logger":"eventLoop.eventHandler","msg":"Handling events didn't result into NGINX configuration changes","batchID":4}
{"level":"info","ts":"2025-02-14T19:36:13Z","logger":"eventLoop.eventHandler","msg":"Handling events didn't result into NGINX configuration changes","batchID":5}
{"level":"info","ts":"2025-02-14T19:36:19Z","logger":"eventLoop.eventHandler","msg":"NGINX configuration was successfully updated","batchID":6}
{"level":"info","ts":"2025-02-14T19:36:22Z","logger":"eventLoop.eventHandler","msg":"Handling events didn't result into NGINX configuration changes","batchID":7}
{"level":"info","ts":"2025-02-14T19:36:22Z","logger":"eventLoop.eventHandler","msg":"Handling events didn't result into NGINX configuration changes","batchID":8}
{"level":"info","ts":"2025-02-14T19:36:22Z","logger":"eventLoop.eventHandler","msg":"Handling events didn't result into NGINX configuration changes","batchID":9}
{"level":"info","ts":"2025-02-14T19:36:22Z","logger":"eventLoop.eventHandler","msg":"Handling events didn't result into NGINX configuration changes","batchID":10}
{"level":"info","ts":"2025-02-14T19:36:22Z","logger":"eventLoop.eventHandler","msg":"Handling events didn't result into NGINX configuration changes","batchID":11}
{"level":"info","ts":"2025-02-14T19:36:22Z","logger":"eventLoop.eventHandler","msg":"Handling events didn't result into NGINX configuration changes","batchID":12}
{"level":"info","ts":"2025-02-14T19:36:25Z","logger":"eventLoop.eventHandler","msg":"NGINX configuration was successfully updated","batchID":13}
{"level":"info","ts":"2025-02-14T19:36:28Z","logger":"eventLoop.eventHandler","msg":"NGINX configuration was successfully updated","batchID":14}
{"level":"info","ts":"2025-02-14T19:36:29Z","logger":"eventLoop.eventHandler","msg":"Handling events didn't result into NGINX configuration changes","batchID":15}
{"level":"info","ts":"2025-02-14T19:36:29Z","logger":"eventLoop.eventHandler","msg":"NGINX configuration was successfully updated","batchID":16}
{"level":"info","ts":"2025-02-14T19:36:30Z","logger":"eventLoop.eventHandler","msg":"Handling events didn't result into NGINX configuration changes","batchID":17}
{"level":"info","ts":"2025-02-14T19:36:31Z","logger":"eventLoop.eventHandler","msg":"Handling events didn't result into NGINX configuration changes","batchID":18}
{"level":"info","ts":"2025-02-14T19:36:31Z","logger":"eventLoop.eventHandler","msg":"NGINX configuration was successfully updated","batchID":19}
{"level":"info","ts":"2025-02-14T19:36:32Z","logger":"eventLoop.eventHandler","msg":"NGINX configuration was successfully updated","batchID":20}
{"level":"info","ts":"2025-02-14T19:36:33Z","logger":"eventLoop.eventHandler","msg":"NGINX configuration was successfully updated","batchID":21}
{"level":"info","ts":"2025-02-14T19:36:33Z","logger":"eventLoop.eventHandler","msg":"Handling events didn't result into NGINX configuration changes","batchID":22}
{"level":"info","ts":"2025-02-14T19:36:34Z","logger":"eventLoop.eventHandler","msg":"Handling events didn't result into NGINX configuration changes","batchID":23}

  • NGINX Configuration:
2025/02/14 19:38:45 [notice] 301#301: js vm init njs: 0000FFFF980FAA00
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
# configuration file /etc/nginx/nginx.conf:
load_module /usr/lib/nginx/modules/ngx_http_js_module.so;
include /etc/nginx/main-includes/*.conf;

worker_processes auto;

pid /var/run/nginx/nginx.pid;

events {
  worker_connections 1024;
}

http {
  include /etc/nginx/conf.d/*.conf;
  include /etc/nginx/mime.types;
  js_import /usr/lib/nginx/modules/njs/httpmatches.js;

  default_type application/octet-stream;

  proxy_headers_hash_bucket_size 512;
  proxy_headers_hash_max_size 1024;
  server_names_hash_bucket_size 256;
  server_names_hash_max_size 1024;
  variables_hash_bucket_size 512;
  variables_hash_max_size 1024;

  sendfile on;
  tcp_nopush on;

  server_tokens off;

  server {
    listen unix:/var/run/nginx/nginx-status.sock;
    access_log off;

    location /stub_status {
        stub_status;
    }
  }
}

stream {
  variables_hash_bucket_size 512;
  variables_hash_max_size 1024;

  map_hash_max_size 2048;
  map_hash_bucket_size 256;

  log_format stream-main '$remote_addr [$time_local] '
                         '$protocol $status $bytes_sent $bytes_received '
                         '$session_time "$ssl_preread_server_name"';
  access_log /dev/stdout stream-main;
  include /etc/nginx/stream-conf.d/*.conf;
}

# configuration file /etc/nginx/main-includes/main.conf:

error_log stderr info;


# configuration file /etc/nginx/conf.d/config-version.conf:

server {
    listen unix:/var/run/nginx/nginx-config-version.sock;
    access_log off;

    location /version {
        return 200 18;
    }
}

# configuration file /etc/nginx/conf.d/http.conf:
http2 on;

# Set $gw_api_compliant_host variable to the value of $http_host unless $http_host is empty, then set it to the value
# of $host. We prefer $http_host because it contains the original value of the host header, which is required by the
# Gateway API. However, in an HTTP/1.0 request, it's possible that $http_host can be empty. In this case, we will use
# the value of $host. See http://nginx.org/en/docs/http/ngx_http_core_module.html#var_host.
map $http_host $gw_api_compliant_host {
    '' $host;
    default $http_host;
}

# Set $connection_header variable to upgrade when the $http_upgrade header is set, otherwise, set it to close. This
# allows support for websocket connections. See https://nginx.org/en/docs/http/websocket.html.
map $http_upgrade $connection_upgrade {
    default upgrade;
    '' close;
}

## Returns just the path from the original request URI.
map $request_uri $request_uri_path {
  "~^(?P<path>[^?]*)(\?.*)?$"  $path;
}


js_preload_object matches from /etc/nginx/conf.d/matches.json;
server {
    listen 7777 default_server;
    listen [::]:7777 default_server;
    default_type text/html;
    return 404;
}

server {
    listen 80 default_server;
    listen [::]:80 default_server;
    default_type text/html;
    return 404;
}

server {
    listen unix:/var/run/nginx/nginx-503-server.sock;
    access_log off;

    return 503;
}

server {
    listen unix:/var/run/nginx/nginx-500-server.sock;
    access_log off;

    return 500;
}


upstream default_coffee_80 {
    random two least_conn;
    zone default_coffee_80 512k;
    
        
    server 10.244.0.26:8080;
    
    
    
    
}

upstream invalid-backend-ref {
    random two least_conn;
    
        
    server unix:/var/run/nginx/nginx-500-server.sock;
    
    
    
    
}





# configuration file /etc/nginx/conf.d/plus-api.conf:

# configuration file /etc/nginx/mime.types:

types {
    text/html                                        html htm shtml;
    text/css                                         css;
    text/xml                                         xml;
    image/gif                                        gif;
    image/jpeg                                       jpeg jpg;
    application/javascript                           js;
    application/atom+xml                             atom;
    application/rss+xml                              rss;

    text/mathml                                      mml;
    text/plain                                       txt;
    text/vnd.sun.j2me.app-descriptor                 jad;
    text/vnd.wap.wml                                 wml;
    text/x-component                                 htc;

    image/avif                                       avif;
    image/png                                        png;
    image/svg+xml                                    svg svgz;
    image/tiff                                       tif tiff;
    image/vnd.wap.wbmp                               wbmp;
    image/webp                                       webp;
    image/x-icon                                     ico;
    image/x-jng                                      jng;
    image/x-ms-bmp                                   bmp;

    font/woff                                        woff;
    font/woff2                                       woff2;

    application/java-archive                         jar war ear;
    application/json                                 json;
    application/mac-binhex40                         hqx;
    application/msword                               doc;
    application/pdf                                  pdf;
    application/postscript                           ps eps ai;
    application/rtf                                  rtf;
    application/vnd.apple.mpegurl                    m3u8;
    application/vnd.google-earth.kml+xml             kml;
    application/vnd.google-earth.kmz                 kmz;
    application/vnd.ms-excel                         xls;
    application/vnd.ms-fontobject                    eot;
    application/vnd.ms-powerpoint                    ppt;
    application/vnd.oasis.opendocument.graphics      odg;
    application/vnd.oasis.opendocument.presentation  odp;
    application/vnd.oasis.opendocument.spreadsheet   ods;
    application/vnd.oasis.opendocument.text          odt;
    application/vnd.openxmlformats-officedocument.presentationml.presentation
                                                     pptx;
    application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
                                                     xlsx;
    application/vnd.openxmlformats-officedocument.wordprocessingml.document
                                                     docx;
    application/vnd.wap.wmlc                         wmlc;
    application/wasm                                 wasm;
    application/x-7z-compressed                      7z;
    application/x-cocoa                              cco;
    application/x-java-archive-diff                  jardiff;
    application/x-java-jnlp-file                     jnlp;
    application/x-makeself                           run;
    application/x-perl                               pl pm;
    application/x-pilot                              prc pdb;
    application/x-rar-compressed                     rar;
    application/x-redhat-package-manager             rpm;
    application/x-sea                                sea;
    application/x-shockwave-flash                    swf;
    application/x-stuffit                            sit;
    application/x-tcl                                tcl tk;
    application/x-x509-ca-cert                       der pem crt;
    application/x-xpinstall                          xpi;
    application/xhtml+xml                            xhtml;
    application/xspf+xml                             xspf;
    application/zip                                  zip;

    application/octet-stream                         bin exe dll;
    application/octet-stream                         deb;
    application/octet-stream                         dmg;
    application/octet-stream                         iso img;
    application/octet-stream                         msi msp msm;

    audio/midi                                       mid midi kar;
    audio/mpeg                                       mp3;
    audio/ogg                                        ogg;
    audio/x-m4a                                      m4a;
    audio/x-realaudio                                ra;

    video/3gpp                                       3gpp 3gp;
    video/mp2t                                       ts;
    video/mp4                                        mp4;
    video/mpeg                                       mpeg mpg;
    video/quicktime                                  mov;
    video/webm                                       webm;
    video/x-flv                                      flv;
    video/x-m4v                                      m4v;
    video/x-mng                                      mng;
    video/x-ms-asf                                   asx asf;
    video/x-ms-wmv                                   wmv;
    video/x-msvideo                                  avi;
}

# configuration file /etc/nginx/stream-conf.d/stream.conf:


server {
    listen unix:/var/run/nginx/connection-closed-server.sock;
    return "";
}


Additional context

This probably has to do with an error with how we are supposed to implement listener isolation. Currently we do something along the lines of

isolateHostnamesForParentRefs iterates through the parentRefs of a route to identify the list of accepted hostnames
for each listener. If any accepted hostname belongs to another listener,
it removes those hostnames to ensure listener isolation.

However after some discussion in the gateway api slack channel with clarification of listener isolation, HTTPRoutes should be able to match and attach to multiple Gateway listeners, however the request which goes through the HTTPRoute should only get sent to a single listener. I think we've implemented listener isolation at the route level instead of at the request level, which may be causing this issue.

@mpstefan mpstefan added this to the v2.0.0 milestone Feb 19, 2025
@salonichf5 salonichf5 moved this from 🆕 New to 🏗 In Progress in NGINX Gateway Fabric Feb 19, 2025
@salonichf5 salonichf5 linked a pull request Feb 21, 2025 that will close this issue
6 tasks
@salonichf5 salonichf5 moved this from 🏗 In Progress to 👀 In Review in NGINX Gateway Fabric Feb 24, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: 👀 In Review
Development

Successfully merging a pull request may close this issue.

3 participants