Skip to content

Modify listener isolation rules for routes #3159

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

Merged
merged 2 commits into from
Mar 4, 2025
Merged

Conversation

salonichf5
Copy link
Contributor

@salonichf5 salonichf5 commented Feb 21, 2025

Proposed changes

Write a clear and concise description that helps reviewers understand the purpose and impact of your changes. Use the
following format:

Problem: Users are unable to configure server blocks with listener sharing the same hostname with another listener but on a different port.

Solution: Modify rules for listener isolation in the following way

  1. if 2 listeners have the same hostname and different ports, do not do listener isolation. Attach it to the listener specified in the section name
  2. if no sectionName is specified in the routes, attach all listeners to the route.

Note: Not adding unit tests for same hostname and port combination for L4Routes because we never do not attach L4Route to listeners with same port and combination by design.

Testing: Manual Testing

Also verified tests from previous PR

  1. L4Routes

Gateway

apiVersion: gateway.networking.k8s.io/v1beta1
kind: Gateway
metadata:
  name: gateway
  namespace: default
spec:
  gatewayClassName: nginx
  listeners:
  - name: tls
    port: 443
    protocol: TLS
    hostname: "*.example.com"
    allowedRoutes:
      namespaces:
        from: All
      kinds:
        - kind: TLSRoute
    tls:
      mode: Passthrough
  - name: tls-diff-port
    port: 300
    protocol: TLS
    hostname: "*.example.com"
    allowedRoutes:
      namespaces:
        from: All
      kinds:
        - kind: TLSRoute
    tls:
      mode: Passthrough

Route

apiVersion: gateway.networking.k8s.io/v1alpha2
kind: TLSRoute
metadata:
  name: tls-secure-app-route
  namespace: default
spec:
  parentRefs:
  - name: gateway
    namespace: default
    sectionName: tls
  hostnames:
  - "*.example.com"
  rules:
  - backendRefs:
    - name: secure-app
      port: 8443

curl to cafe.example.com should succeed

curl --resolve cafe.example.com:8443:$GW_IP https://cafe.example.com:8443 --insecure   
Handling connection for 8443
hello from pod \secure-app-7bfb966596-rbkhx
  1. L7 Routes

Gateway

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"
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

Should receive response from coffee

 curl --resolve cafe.example.com:$GW_PORT:$GW_IP http://cafe.example.com:$GW_PORT/coffee                     
Handling connection for 8080
Server address: 10.244.0.183:8080
Server name: coffee-676c9f8944-2l79x
Date: 21/Feb/2025:21:23:30 +0000
URI: /coffee
Request ID: 5eea03210c43b1d170a284f517f5a41a

Please focus on (optional): If you any specific areas where you would like reviewers to focus their attention or provide
specific feedback, add them here.

Closes #3137

Checklist

Before creating a PR, run through this checklist and mark each as complete.

  • I have read the CONTRIBUTING doc
  • I have added tests that prove my fix is effective or that my feature works
  • I have checked that all unit tests pass after adding my changes
  • I have updated necessary documentation
  • I have rebased my branch onto main
  • I will ensure my PR is targeting the main branch and pulling from my branch from my own fork

Release notes

If this PR introduces a change that affects users and needs to be mentioned in the release notes,
please add a brief note that summarizes the change.

NONE

@github-actions github-actions bot added the bug Something isn't working label Feb 21, 2025
Copy link

codecov bot commented Feb 21, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 86.15%. Comparing base (3914e8f) to head (b4ee102).
Report is 1 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3159      +/-   ##
==========================================
+ Coverage   86.14%   86.15%   +0.01%     
==========================================
  Files         113      113              
  Lines       11648    11658      +10     
  Branches       62       62              
==========================================
+ Hits        10034    10044      +10     
  Misses       1553     1553              
  Partials       61       61              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@salonichf5 salonichf5 force-pushed the bug/listener-isolation branch 3 times, most recently from abf1e57 to 45651cb Compare February 24, 2025 18:02
@salonichf5 salonichf5 marked this pull request as ready for review February 24, 2025 18:11
@salonichf5 salonichf5 requested a review from a team as a code owner February 24, 2025 18:11
Copy link
Collaborator

@sjberman sjberman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still need to review the unit tests.

Did you verify that the previously failing NFR test now passes?

@salonichf5
Copy link
Contributor Author

Still need to review the unit tests.

Did you verify that the previously failing NFR test now passes?

I did not run the NFR test. I can do that but verified using the gateway and route spec that led to the failure, examples are added above.

@salonichf5 salonichf5 force-pushed the bug/listener-isolation branch 2 times, most recently from 9d41a66 to f70b7e2 Compare March 3, 2025 23:01
@bjee19
Copy link
Contributor

bjee19 commented Mar 4, 2025

With this route:

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
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: tea
spec:
  parentRefs:
  - name: gateway
    sectionName: https
  hostnames:
  - "cafe.example.com"
  rules:
  - matches:
    - path:
        type: PathPrefix
        value: /tea
    backendRefs:
    - name: tea
      port: 80

and with this gateway:

apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: gateway
spec:
  gatewayClassName: nginx
  listeners:
  - name: http
    port: 80
    protocol: HTTP
    hostname: "cafe.example.com"
  - name: https
    port: 80
    protocol: HTTP
    hostname: "*.example.com"

When I checkout these changes, here's the generated nginx conf:

server {
    listen 80;
    listen [::]:80;

    server_name cafe.example.com;


    location /coffee/ {




        proxy_http_version 1.1;
        proxy_set_header Host "$gw_api_compliant_host";
        proxy_set_header X-Forwarded-For "$proxy_add_x_forwarded_for";
        proxy_set_header X-Real-IP "$remote_addr";
        proxy_set_header X-Forwarded-Proto "$scheme";
        proxy_set_header X-Forwarded-Host "$host";
        proxy_set_header X-Forwarded-Port "$server_port";
        proxy_set_header Upgrade "$http_upgrade";
        proxy_set_header Connection "$connection_upgrade";
        proxy_pass http://default_coffee_80$request_uri;



    }
    location = /coffee {




        proxy_http_version 1.1;
        proxy_set_header Host "$gw_api_compliant_host";
        proxy_set_header X-Forwarded-For "$proxy_add_x_forwarded_for";
        proxy_set_header X-Real-IP "$remote_addr";
        proxy_set_header X-Forwarded-Proto "$scheme";
        proxy_set_header X-Forwarded-Host "$host";
        proxy_set_header X-Forwarded-Port "$server_port";
        proxy_set_header Upgrade "$http_upgrade";
        proxy_set_header Connection "$connection_upgrade";
        proxy_pass http://default_coffee_80$request_uri;



    }
    location / {

        return 404 "";



        proxy_http_version 1.1;
    }
}

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.7:8080;




}

upstream default_tea_80 {
    random two least_conn;
    zone default_tea_80 512k;


    server 10.244.0.6:8080;


Is it expected behavior that the tea route is missing?

@salonichf5
Copy link
Contributor Author

With this route:

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
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: tea
spec:
  parentRefs:
  - name: gateway
    sectionName: https
  hostnames:
  - "cafe.example.com"
  rules:
  - matches:
    - path:
        type: PathPrefix
        value: /tea
    backendRefs:
    - name: tea
      port: 80

and with this gateway:

apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: gateway
spec:
  gatewayClassName: nginx
  listeners:
  - name: http
    port: 80
    protocol: HTTP
    hostname: "cafe.example.com"
  - name: https
    port: 80
    protocol: HTTP
    hostname: "*.example.com"

When I checkout these changes, here's the generated nginx conf:

server {
    listen 80;
    listen [::]:80;

    server_name cafe.example.com;


    location /coffee/ {




        proxy_http_version 1.1;
        proxy_set_header Host "$gw_api_compliant_host";
        proxy_set_header X-Forwarded-For "$proxy_add_x_forwarded_for";
        proxy_set_header X-Real-IP "$remote_addr";
        proxy_set_header X-Forwarded-Proto "$scheme";
        proxy_set_header X-Forwarded-Host "$host";
        proxy_set_header X-Forwarded-Port "$server_port";
        proxy_set_header Upgrade "$http_upgrade";
        proxy_set_header Connection "$connection_upgrade";
        proxy_pass http://default_coffee_80$request_uri;



    }
    location = /coffee {




        proxy_http_version 1.1;
        proxy_set_header Host "$gw_api_compliant_host";
        proxy_set_header X-Forwarded-For "$proxy_add_x_forwarded_for";
        proxy_set_header X-Real-IP "$remote_addr";
        proxy_set_header X-Forwarded-Proto "$scheme";
        proxy_set_header X-Forwarded-Host "$host";
        proxy_set_header X-Forwarded-Port "$server_port";
        proxy_set_header Upgrade "$http_upgrade";
        proxy_set_header Connection "$connection_upgrade";
        proxy_pass http://default_coffee_80$request_uri;



    }
    location / {

        return 404 "";



        proxy_http_version 1.1;
    }
}

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.7:8080;




}

upstream default_tea_80 {
    random two least_conn;
    zone default_tea_80 512k;


    server 10.244.0.6:8080;

Is it expected behavior that the tea route is missing?

Yes I believe so, same ports. The second route has hostname cafe.example.com , even though it attaches to the second listener (https) . It needs to isolated because cafe.example.com is part of another listener on the same port.

This has been my understanding of listener isolation. Try using tea.example.com as hostname in second route and see what you get ? That should not be isolated.

@salonichf5 salonichf5 force-pushed the bug/listener-isolation branch from f70b7e2 to 8443058 Compare March 4, 2025 16:49
@salonichf5 salonichf5 requested a review from sjberman March 4, 2025 16:50
@salonichf5 salonichf5 force-pushed the bug/listener-isolation branch from 8443058 to b4ee102 Compare March 4, 2025 17:50
Copy link
Contributor

@bjee19 bjee19 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for running through some of my examples, lgtm! 🚀

@salonichf5
Copy link
Contributor Author

Scale tests pass now so merging this PR.

@salonichf5 salonichf5 merged commit 4c51b05 into main Mar 4, 2025
40 checks passed
@salonichf5 salonichf5 deleted the bug/listener-isolation branch March 4, 2025 22:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Gateway listeners with same hostname not working
3 participants