-
Notifications
You must be signed in to change notification settings - Fork 715
Wrong gateway is chosen as HTTPRoute parent #3872
Description
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
EOFCreate 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: /
EOFCreate 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: /
EOFconsumer1/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: egconsumer2/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
consumer2namespace toconsumer2/backendHTTPRoute parentRef the issue is resolved. - When looking at the code It seems like the root cause is in
IsRefToGatewayfunction:
gateway/internal/gatewayapi/helpers.go
Lines 121 to 123 in 85e57ae
if parentRef.Namespace != nil && string(*parentRef.Namespace) != gateway.Namespace { return false }
WhenparentRef.Namespaceis 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).