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

Wrong gateway is chosen as HTTPRoute parent #3872

Closed
shahar-h opened this issue Jul 16, 2024 · 0 comments · Fixed by #3876
Closed

Wrong gateway is chosen as HTTPRoute parent #3872

shahar-h opened this issue Jul 16, 2024 · 0 comments · Fixed by #3876
Assignees
Labels
kind/bug Something isn't working
Milestone

Comments

@shahar-h
Copy link
Contributor

shahar-h commented Jul 16, 2024

Description:
When creating 2 Gateways with the same name in 2 different namespaces, and then create for each one HTTPRoute, only one of the routes will be attached to a gateway. The reason is that Gateway is selected only by parentRef name in case namespace is omitted. The expected behavior in case namespace is omitted is to select the gateway in the local namespace.

Repro steps:
Create a GatewayClass:

cat <<EOF | kubectl apply -f -
apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
  name: eg
spec:
  controllerName: gateway.envoyproxy.io/gatewayclass-controller
EOF

Create Gateway and HTTPRoute with www.example.com hostname in consumer1 namespace:

cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Namespace
metadata:
  name: consumer1
---
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: eg
  namespace: consumer1
spec:
  gatewayClassName: eg
  listeners:
    - name: http
      protocol: HTTP
      port: 80
      hostname: www.example.com
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: backend
  namespace: consumer1
---
apiVersion: v1
kind: Service
metadata:
  name: backend
  namespace: consumer1
  labels:
    app: backend
    service: backend
spec:
  ports:
    - name: http
      port: 3000
      targetPort: 3000
  selector:
    app: backend
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: backend
  namespace: consumer1
spec:
  replicas: 1
  selector:
    matchLabels:
      app: backend
      version: v1
  template:
    metadata:
      labels:
        app: backend
        version: v1
    spec:
      serviceAccountName: backend
      containers:
        - image: gcr.io/k8s-staging-gateway-api/echo-basic:v20231214-v1.0.0-140-gf544a46e
          imagePullPolicy: IfNotPresent
          name: backend
          ports:
            - containerPort: 3000
          env:
            - name: POD_NAME
              valueFrom:
                fieldRef:
                  fieldPath: metadata.name
            - name: NAMESPACE
              valueFrom:
                fieldRef:
                  fieldPath: metadata.namespace
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: backend
  namespace: consumer1
spec:
  parentRefs:
    - name: eg
  hostnames:
    - "www.example.com"
  rules:
    - backendRefs:
        - group: ""
          kind: Service
          name: backend
          port: 3000
          weight: 1
      matches:
        - path:
            type: PathPrefix
            value: /
EOF

Create Gateway and HTTPRoute with www.example2.com hostname in consumer2 namespace:

cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Namespace
metadata:
  name: consumer2
---
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: eg
  namespace: consumer2
spec:
  gatewayClassName: eg
  listeners:
    - name: http
      protocol: HTTP
      port: 80
      hostname: www.example2.com
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: backend
  namespace: consumer2
---
apiVersion: v1
kind: Service
metadata:
  name: backend
  namespace: consumer2
  labels:
    app: backend
    service: backend
spec:
  ports:
    - name: http
      port: 3000
      targetPort: 3000
  selector:
    app: backend
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: backend
  namespace: consumer2
spec:
  replicas: 1
  selector:
    matchLabels:
      app: backend
      version: v1
  template:
    metadata:
      labels:
        app: backend
        version: v1
    spec:
      serviceAccountName: backend
      containers:
        - image: gcr.io/k8s-staging-gateway-api/echo-basic:v20231214-v1.0.0-140-gf544a46e
          imagePullPolicy: IfNotPresent
          name: backend
          ports:
            - containerPort: 3000
          env:
            - name: POD_NAME
              valueFrom:
                fieldRef:
                  fieldPath: metadata.name
            - name: NAMESPACE
              valueFrom:
                fieldRef:
                  fieldPath: metadata.namespace
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: backend
  namespace: consumer2
spec:
  parentRefs:
    - name: eg
  hostnames:
    - "www.example2.com"
  rules:
    - backendRefs:
        - group: ""
          kind: Service
          name: backend
          port: 3000
          weight: 1
      matches:
        - path:
            type: PathPrefix
            value: /
EOF

consumer1/backend HTTPRoute status:

 status:
    parents:
    - conditions:
      - lastTransitionTime: "2024-07-16T20:36:36Z"
        message: Route is accepted
        observedGeneration: 1
        reason: Accepted
        status: "True"
        type: Accepted
      - lastTransitionTime: "2024-07-16T20:36:36Z"
        message: Resolved all the Object references for the Route
        observedGeneration: 1
        reason: ResolvedRefs
        status: "True"
        type: ResolvedRefs
      controllerName: gateway.envoyproxy.io/gatewayclass-controller
      parentRef:
        group: gateway.networking.k8s.io
        kind: Gateway
        name: eg

consumer2/backend HTTPRoute status:

status:
    parents:
    - conditions:
      - lastTransitionTime: "2024-07-16T20:36:36Z"
        message: No listeners included by this parent ref allowed this attachment.
        observedGeneration: 1
        reason: NotAllowedByListeners
        status: "False"
        type: Accepted
      - lastTransitionTime: "2024-07-16T20:36:36Z"
        message: Resolved all the Object references for the Route
        observedGeneration: 1
        reason: ResolvedRefs
        status: "True"
        type: ResolvedRefs
      controllerName: gateway.envoyproxy.io/gatewayclass-controller
      parentRef:
        group: gateway.networking.k8s.io
        kind: Gateway
        name: eg
  • Notice that both gateways name are eg.
  • When adding an explicit consumer2 namespace to consumer2/backend HTTPRoute parentRef the issue is resolved.
  • When looking at the code It seems like the root cause is in IsRefToGateway function:
    if parentRef.Namespace != nil && string(*parentRef.Namespace) != gateway.Namespace {
    return false
    }

    When parentRef.Namespace is nil only name is being compared.

A possible solution would be to add the route namespace in GetParentReferences to each parentRef with a missing namespace.

Environment:
Latest chart(v0.0.0-latest).

@guydc guydc added kind/bug Something isn't working help wanted Extra attention is needed and removed triage labels Jul 16, 2024
@guydc guydc added this to the v1.1.0 milestone Jul 16, 2024
@zirain zirain removed the help wanted Extra attention is needed label Jul 17, 2024
@zirain zirain self-assigned this Jul 17, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind/bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants