Skip to content

Random flows DROPPED targetting service using GAMMA HTTPRoutes #41970

Description

@corrieriluca

Is there an existing issue for this?

  • I have searched the existing issues

Version

equal or higher than v1.18.2 and lower than v1.19.0

What happened?

Hi,

We are using the Gateway API feature with Cilium, and for one of our internal services we created a GAMMA HTTPRoute for internal routing (mostly path rewrite / redirect).

From time to time, we observe a lot of DROPPED flows in the DataPath and we don't understand why. It can last at most 30 minutes.

2 kinds of dropped flows for GAMMA services only:

DROPPED flows because POLICY_DENIED

These drops are very strange because they happen not systematically. We don't really know which policy drops these flows because we allow egress to 0.0.0.0/0 (see below our network policies).

hubble --kube-namespace cilium observe  -P -f -4 --print-policy-names --verdict DROPPED

Oct  1 13:11:37.763: brc-preprod/main-bff-765b7b9976-djwnq:49754 (ID:5309) -> brc-preprod/third-party-api:80 (world) http-request DROPPED (HTTP/1.1 GET http://third-party-api/XXXXXX)
Oct  1 13:15:46.681: brc-preprod/backoffice-bff-86cbfdbbd-pl8ns:46050 (ID:19059) -> brc-preprod/third-party-api:80 (world) http-request DROPPED (HTTP/1.1 GET http://third-party-api/XXXXXXX)

If we inspect the flow in JSON, Cilium mentions as destination the Service ClusterIP and labels it as world (is it normal? our service range is 10.100.0.0/16):

  "IP": {
    "ipVersion": "IPv4",
    "destination": "10.100.134.234",
    "source": "172.24.84.148"
  },
  "destination": {
    "identity": 2,
    "labels": [
      "reserved:world"
    ]
  },

On the client-side (here main-bff and backoffice-bff) a 403 Access Denied response is received (probably from cilium-envoy because third-party-api does not receive anything).

DROPPED flows because DROP_EP_NOT_READY

These drops happen systematically when I rollout restart third-party-api (the API with a GAMMA route on its service).

The source is systematically a reserved:world and reference an IP address not used in our cluster (neither a Pod IP, nor a Node IP, just an unused IP attached to an ENI). Is it a problem of garbage-collection?

{
  "IP": {
    "ipVersion": "IPv4",
    "destination": "172.24.82.122",
    "source": "172.24.83.63"
  },
  "destination": {
    "cluster_name": "default",
    "identity": 47882,
    "namespace": "brc-preprod",
    "labels": [
      "...",
    ],
    "pod_name": "third-party-api-ff9944cfc-bcqzg"
  },
  "l4": {
    "TCP": {
      "destination_port": 8080,
      "source_port": 54792,
      "flags": {
        "PSH": true,
        "ACK": true,
        "FIN": true
      }
    }
  },

  "source": {
    "identity": 16777217,
    "labels": [
      "cidr:172.24.82.0/23",
      "reserved:world"
    ]
  },

  "drop_reason_desc": "DROP_EP_NOT_READY",
  "traffic_direction": "INGRESS"
}

Definition of our GAMMA HTTPRoute

The third-party-api service has pods behind it.

We designed the HTTPRoute to have a catch-all route at the end for requests that need to be sent to third-party-api.

HTTPRoute manifest
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: third-party-api-internal
  namespace: preprod
spec:
  parentRefs:
    # gamma route
    - group: ""
      kind: Service
      name: third-party-api
      port: 80
  rules:
    - backendRefs:
        - group: ""
          kind: Service
          name: permission-api
          port: 80
          weight: 1
      filters:
        - requestHeaderModifier:
            set:
              - name: x-forwarded-prefix
                value: /some-route
          type: RequestHeaderModifier
        - type: URLRewrite
          urlRewrite:
            path:
              replacePrefixMatch: /some-route
              type: ReplacePrefixMatch
      matches:
        - path:
            type: PathPrefix
            value: /some-route
    # catch all rules
    - backendRefs:
        - group: ""
          kind: Service
          name: third-party-api
          port: 80
          weight: 1
      filters:
        - requestHeaderModifier:
            set:
              - name: x-forwarded-prefix
                value: /third-party
          type: RequestHeaderModifier
      matches:
        - path:
            type: PathPrefix
            value: /

Network policy configuration

The API has a NetworkPolicy authorizing the pods that can contact it:

Details
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-ingress-third-party-api
  namespace: brc-preprod
spec:
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app.kubernetes.io/instance: backoffice-bff
          app.kubernetes.io/name: backoffice-bff
    ports:
    - port: 8080
      protocol: TCP
	# a few other from rules...
  podSelector:
    matchLabels:
      app.kubernetes.io/instance: third-party-api
      app.kubernetes.io/name: third-party-api
  policyTypes:
  - Ingress

As well as a CiliumNetworkPolicy to authorize ingress from reserved:ingress

Details
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
  name: allow-cilium-ingress-entity-to-third-party-api
  namespace: brc-preprod
spec:
  endpointSelector:
    matchLabels:
      app.kubernetes.io/instance: third-party-api
  ingress:
  - fromEntities:
    - ingress

We have a default egress policy that applies to all pods to the namespace:

Details
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: deny-metadata-access
  namespace: brc-preprod
spec:
  egress:
  - to:
    - ipBlock:
        cidr: 0.0.0.0/0
        except:
        - 169.254.169.254/32
  - to:
    - namespaceSelector: {}
  podSelector: {}
  policyTypes:
  - Egress

And finally, we have a CCNP for the ingress identity (not sure it is useful)

Details
apiVersion: cilium.io/v2
kind: CiliumClusterwideNetworkPolicy
metadata:
  name: allow-all-to-ingress-entity
spec:
  description: "Allow all the ingress+egress traffic from reserved ingress identity to any endpoints in the cluster"
  endpointSelector:
    matchExpressions:
    - key: reserved:ingress
      operator: Exists
  egress:
  - toEntities:
    - cluster
  ingress:
  - fromEntities:
    - all

Some ideas we are considering

  • We use the default iptables-based IPv4 masquerading, is it "hiding" the source in some flows?
  • We have a lot of rollouts on our cluster, is Cilium IP/identity cache may show incorrect information? Is Garbage collection tunable?
  • Is cilium-envoy caching some identities on its side that may break traffic in case of rollouts?
  • Should we add a CiliumNetworkPolicy like the one below?
CiliumNetworkPolicy for contacting ingress and service CIDR
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
  name: allow-all-traffic
  namespace: brc-preprod
spec:
  description: "allow all egress to ingress and services"
  egress:
  - toEntities:
    - ingress
  - toCIDR:
    - 10.100.0.0/16
  endpointSelector: {}

Thank you very much in advance, I have trouble to reproduce the issue in a deterministic manner as it seems to happen very randomly 😕

How can we reproduce the issue?

Install cilium with Helm with the following values:

Values
cilium:
  # Enable "native" routing mode to let the Node take care of the routing part
  routingMode: native

  eni:
    enabled: true
    awsReleaseExcessIPs: true
    # restrict Cilium to use only subnets dedicated to the cluster
    subnetTagsFilter:
      - karpenter.sh/discovery=PPRD_aws_eks_cluster

  ipam:
    mode: eni

  cni:
    exclusive: true

  # Enable Wireguard transparent encryption
  encryption:
    enabled: true
    type: wireguard

  # Enable egress masquerade only for Node interfaces (not Pods)
  egressMasqueradeInterfaces: eth+
  enableIPv4Masquerade: true

  # Rollout Cilium Pods on config updates
  rollOutCiliumPods: true

  # Enable matching of node IPs in NetworkPolicies
  # ⚠️ This is required by SNAT netpols for istio to work
  policyCIDRMatchMode: nodes

  prometheus:
    enabled: true

  operator:
    rollOutPods: true
    tolerations:
      - operator: Exists
    unmanagedPodWatcher:
      restart: false

  # Enable Hubble
  hubble:
    # Redact L7 information (headers, querys, etc.) for security
    redact:
      enabled: true
    relay:
      enabled: true
      rollOutPods: true

    ui:
      enabled: true
      rollOutPods: true

    export:
      # Configure Hubble events export
      static:
        enabled: true
        fileCompress: true
        filePath: /var/run/cilium/hubble/events.log
        allowList:
          # Filter Hubble events to only keep DENIED or AUDITED network flows
          - '{"verdict":["DROPPED","AUDIT"],"protocol":["udp","tcp"],"ip_version":["IPv4"]}'
        denyList:
          # Remove flows to the metadata server that are blocked on purpose
          - '{"destination_ip":["169.254.169.254"]}'

  ## Gateway API Features ------------------------------------------------------

  # Control L7 traffic via CRDs (e.g. CiliumNetworkPolicies)
  # Deploys a DaemonSet of cilium-envoy
  l7Proxy: true

  # We need NodePort Service for making Gateway API working
  # Can be disabled once Cilium replaces kube-proxy
  nodePort:
    enabled: true

  # Enable Gateway API Controller
  gatewayAPI:
    enabled: true

  envoy:
    rollOutPods: true

Important notes: for now we do not use kube-proxy-replacement nor bpf-masquerading

Do you see some configuration that may impact the behavior of the GAMMA Routes / Gateway API features? and/or may explain the DROPPED flows?

Cilium Version

v1.18.2

but also ran into this issue with v1.17.8

Kernel Version

Linux ip-XXX.eu-west-3.compute.internal 6.12.40 #1 SMP PREEMPT_DYNAMIC Mon Sep 15 21:58:12 UTC 2025 x86_64 x86_64 x86_64 GNU/Linux

Kubernetes Version

v1.33.4-eks-e386d34

Regression

No response

Sysdump

No response

Relevant log output

Anything else?

I already checked these issues but did not find anything related to my problems:

Cilium Users Document

  • Are you a user of Cilium? Please add yourself to the Users doc

Code of Conduct

  • I agree to follow this project's Code of Conduct

Metadata

Metadata

Assignees

Labels

area/agentCilium agent related.area/servicemeshGH issues or PRs regarding servicemeshfeature/k8s-gateway-apikind/bugThis is a bug in the Cilium logic.kind/community-reportThis was reported by a user in the Cilium community, eg via Slack.staleThe stale bot thinks this issue is old. Add "pinned" label to prevent this from becoming stale.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions