Calico Ingress Gateway IPv6 and Dual-Stack Setup

By default, the EnvoyProxy fleet operates in IPv4-only mode. On IPv6-only or dual-stack clusters, the Calico Ingress Gateway requires additional configuration after enablement so that the Envoy listener binds to the correct IP family.

The ipFamily value differs by cluster type:

Cluster type

ipFamily value

IPv6-only cluster

IPv6

Dual-stack cluster

DualStack

IPv6-only Cluster

  1. Create a custom EnvoyProxy with the IPv6 ipFamily.

    $ kubectl apply -f - <<'EOF'
    apiVersion: gateway.envoyproxy.io/v1alpha1
    kind: EnvoyProxy
    metadata:
      name: tigera-gateway-ipv6
      namespace: tigera-gateway
    spec:
      ipFamily: IPv6
      logging:
        level:
          default: warn
      provider:
        kubernetes:
          envoyDeployment:
            container:
              image: registry.local:9001/quay.io/calico/envoy-proxy:v3.31.5
            pod:
              imagePullSecrets:
              - name: registry-local-secret
        type: Kubernetes
    EOF
    

    Setting ipFamily: IPv6 makes the Envoy listener bind to :: (IPv6), allowing kubelet probes to succeed on IPv6-only nodes.

  2. Update the GatewayAPI custom resource with envoyProxyRef.

    $ kubectl apply -f - <<'EOF'
    apiVersion: operator.tigera.io/v1
    kind: GatewayAPI
    metadata:
      name: default
    spec:
      crdManagement: PreferExisting
      gatewayClasses:
      - name: tigera-gateway-class
        envoyProxyRef:
          name: tigera-gateway-ipv6
          namespace: tigera-gateway
    EOF
    

    Verify:

    $ kubectl get envoyproxy -n tigera-gateway tigera-gateway-ipv6 \
        -o jsonpath='{.spec.ipFamily}'
    IPv6
    

Dual-stack (IPv4/IPv6) Cluster

  1. Create a custom EnvoyProxy with the DualStack ipFamily.

    $ kubectl apply -f - <<'EOF'
    apiVersion: gateway.envoyproxy.io/v1alpha1
    kind: EnvoyProxy
    metadata:
      name: tigera-gateway-dualstack
      namespace: tigera-gateway
    spec:
      ipFamily: DualStack
      logging:
        level:
          default: warn
      provider:
        kubernetes:
          envoyDeployment:
            container:
              image: registry.local:9001/quay.io/calico/envoy-proxy:v3.31.5
            pod:
              imagePullSecrets:
              - name: registry-local-secret
        type: Kubernetes
    EOF
    

    Setting ipFamily: DualStack makes the Envoy listener bind to :: and, with the system default net.ipv6.bindv6only=0, serve both IPv4 and IPv6 traffic. Using ipFamily: IPv6 on a dual-stack cluster would drop IPv4 ingress.

  2. Update the GatewayAPI custom resource with envoyProxyRef.

    $ kubectl apply -f - <<'EOF'
    apiVersion: operator.tigera.io/v1
    kind: GatewayAPI
    metadata:
      name: default
    spec:
      crdManagement: PreferExisting
      gatewayClasses:
      - name: tigera-gateway-class
        envoyProxyRef:
          name: tigera-gateway-dualstack
          namespace: tigera-gateway
    EOF
    

    Verify:

    $ kubectl get envoyproxy -n tigera-gateway tigera-gateway-dualstack \
        -o jsonpath='{.spec.ipFamily}'
    DualStack
    

Create the Gateway and Verify (both types)

  1. Create the Gateway resource.

    $ kubectl apply -f - <<'EOF'
    apiVersion: gateway.networking.k8s.io/v1
    kind: Gateway
    metadata:
      name: calico-ingress-gateway
    spec:
      gatewayClassName: tigera-gateway-class
      listeners:
      - name: http
        protocol: HTTP
        port: 80
    EOF
    
  2. Verify the gateway pods are running.

    $ kubectl get pods -n tigera-gateway
    NAME                                          READY   STATUS    RESTARTS   AGE
    envoy-default-calico-ingress-gateway-xxxxx    2/2     Running   0          ...
    envoy-gateway-xxxxx                           1/1     Running   0          ...
    

    Both containers (envoy and shutdown-manager) should be 2/2 Ready with 0 restarts.

Once the gateway is operational, proceed with creating routes as described in Create a Gateway and Routes.