<p>The problem at hand concerns preserving the client's original IP address while utilizing the Kong Ingress Controller in a GKE cluster. Following the Kong documentation, I added the &quot;externalTrafficPolicy: Local&quot; annotation to the Kubernetes service object responsible for the Kong Ingress Controller. However, the real IP headers are not present in requests forwarded by Kong. Additionally, I added the &quot;cloud.google.com/load-balancer-type: Internal&quot; annotation to the service object, yet the issue remains. I have used netcat to test the connectivity to the Kong pod and discovered that the response headers do not contain the original client IP address. I am looking for assistance in identifying the problem and finding a solution to maintain the original client IP address.</p>
<p><em><strong>deployment.yaml</strong></em></p>
<pre><code>apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: ingress-kong
  name: ingress-kong
  namespace: kong
spec:
  replicas: 1
  selector:
    matchLabels:
      app: ingress-kong
  template:
    metadata:
      annotations:
        kuma.io/gateway: enabled
        kuma.io/service-account-token-volume: kong-serviceaccount-token
        traffic.sidecar.istio.io/includeInboundPorts: &quot;&quot;
      labels:
        app: ingress-kong
    spec:
      automountServiceAccountToken: false
      containers:
      - env:
        - name: KONG_PROXY_LISTEN
          value: 0.0.0.0:8000 reuseport backlog=16384, 0.0.0.0:8443 http2 ssl reuseport
            backlog=16384
        - name: KONG_PORT_MAPS
          value: 80:8000, 443:8443
        - name: KONG_ADMIN_LISTEN
          value: 127.0.0.1:8444 http2 ssl reuseport backlog=16384
        - name: KONG_STATUS_LISTEN
          value: 0.0.0.0:8100
        - name: KONG_DATABASE
          value: &quot;off&quot;
        - name: KONG_NGINX_WORKER_PROCESSES
          value: &quot;2&quot;
        - name: KONG_KIC
          value: &quot;on&quot;
        - name: KONG_ADMIN_ACCESS_LOG
          value: /dev/stdout
        - name: KONG_ADMIN_ERROR_LOG
          value: /dev/stderr
        - name: KONG_PROXY_ERROR_LOG
          value: /dev/stderr
        - name: KONG_ROUTER_FLAVOR
          value: traditional
        image: kong:3.1
        lifecycle:
          preStop:
            exec:
              command:
              - /bin/bash
              - -c
              - kong quit
        livenessProbe:
          failureThreshold: 3
          httpGet:
            path: /status
            port: 8100
            scheme: HTTP
          initialDelaySeconds: 5
          periodSeconds: 10
          successThreshold: 1
          timeoutSeconds: 1
        name: proxy
        ports:
        - containerPort: 8000
          name: proxy
          protocol: TCP
        - containerPort: 8443
          name: proxy-ssl
          protocol: TCP
        - containerPort: 8100
          name: metrics
          protocol: TCP
        readinessProbe:
          failureThreshold: 3
          httpGet:
            path: /status
            port: 8100
            scheme: HTTP
          initialDelaySeconds: 5
          periodSeconds: 10
          successThreshold: 1
          timeoutSeconds: 1
      - env:
        - name: CONTROLLER_KONG_ADMIN_URL
          value: https://127.0.0.1:8444
        - name: CONTROLLER_KONG_ADMIN_TLS_SKIP_VERIFY
          value: &quot;true&quot;
        - name: CONTROLLER_PUBLISH_SERVICE
          value: kong/kong-proxy
        - name: POD_NAME
          valueFrom:
            fieldRef:
              apiVersion: v1
              fieldPath: metadata.name
        - name: POD_NAMESPACE
          valueFrom:
            fieldRef:
              apiVersion: v1
              fieldPath: metadata.namespace
        image: kong/kubernetes-ingress-controller:2.8.1
        imagePullPolicy: IfNotPresent
        livenessProbe:
          failureThreshold: 3
          httpGet:
            path: /healthz
            port: 10254
            scheme: HTTP
          initialDelaySeconds: 5
          periodSeconds: 10
          successThreshold: 1
          timeoutSeconds: 1
        name: ingress-controller
        ports:
        - containerPort: 8080
          name: webhook
          protocol: TCP
        - containerPort: 10255
          name: cmetrics
          protocol: TCP
        readinessProbe:
          failureThreshold: 3
          httpGet:
            path: /readyz
            port: 10254
            scheme: HTTP
          initialDelaySeconds: 5
          periodSeconds: 10
          successThreshold: 1
          timeoutSeconds: 1
        volumeMounts:
        - mountPath: /var/run/secrets/kubernetes.io/serviceaccount
          name: kong-serviceaccount-token
          readOnly: true
      serviceAccountName: kong-serviceaccount
      volumes:
      - name: kong-serviceaccount-token
        secret:
          items:
          - key: token
            path: token
          - key: ca.crt
            path: ca.crt
          - key: namespace
            path: namespace
          secretName: kong-serviceaccount-token
</code></pre>
<p><em><strong>service.yaml</strong></em></p>
<pre><code>apiVersion: v1
kind: Service
metadata:
  name: kong-proxy
  namespace: kong
spec:
  ports:
  - name: proxy
    port: 80
    protocol: TCP
    targetPort: 8000
  - name: proxy-ssl
    port: 443
    protocol: TCP
    targetPort: 8443
  selector:
    app: ingress-kong
  type: LoadBalancer
  externalTrafficPolicy: Local
</code></pre>
<p><em><strong>ingress.yaml</strong></em></p>
<pre><code>apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: kong-ingress
  namespace: kong
  annotations:
    kubernetes.io/ingress.class: gce
    kubernetes.io/ingress.allow-http: &quot;false&quot;
    kubernetes.io/ingress.global-static-ip-name: kong-static-ip
    ingress.gcp.kubernetes.io/pre-shared-cert: kong-ssl-certificate
spec:
  defaultBackend:
    service:
      name: kong-proxy
      port:
        number: 80
</code></pre>

Pedro Guilherme
<p>I think your goal here is not use to GCE Ingress and to use Kong Ingress instead.</p>
<p>Right now, your config is GCE Ingress -&gt; kong-proxy Service, which I do not think is what you want.</p>
<p>I believe what you want to do is:</p>
<pre><code>apiVersion: v1
kind: Service
metadata:
  name: kong-proxy
  namespace: kong
spec:
  ports:
  - name: proxy
    port: 80
    protocol: TCP
    targetPort: 8000
  - name: proxy-ssl
    port: 443
    protocol: TCP
    targetPort: 8443
  selector:
    app: ingress-kong
  type: LoadBalancer
  externalTrafficPolicy: Local
  loadBalancerIP: REPLACE_WITH_STATIC_IP_ADDRESS
</code></pre>
<p>You will need to get the actual IP address of <code>kong-static-ip</code> and use that above.</p>
<p>Once you've done that, in order to use= the Kong Ingress controller instead of the GCE controller, you need to set <code>ingressClassName: kong</code>:</p>
<pre><code>apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: kong-ingress
  namespace: kong
  annotations:
    kubernetes.io/ingress.class: kong
    kubernetes.io/ingress.allow-http: &quot;false&quot;
spec:
  defaultBackend:
    service:
      name: kong-proxy
      port:
        number: 80
</code></pre>
<p>Note that in this case you will need to terminate TLS in the Kong proxy itself and not the load balancer.</p>
