I've divided this answer on parts:
- Two backends when creating an
Ingress resource with GKE.
- Ingress definition in the question.
- Integrating
Cloud Armor with Istio.
Two backends when creating an Ingress resource with GKE
This is working as expected as Ingress created with GKE will have 2 backends:
- The one specified in the
YAML manifest.
- The default backend:
default-http-backend.
As an example you can follow below steps:
$ kubectl create deployment nginx --image=nginx
$ kubectl expose deployment nginx --port=80 --type=NodePort
- Create an
Ingress resource for nginx but with a hello path (for example purposes)
After that you should be seeing a similar setup:

The first backend service is using an Instance group to send the requests to the default-backend that are not matching the Ingress resource.
The second backend service is using NEG (Network Endpoint Groups) to send the requests that are matching with the Ingress resource (in this example to an nginx Deployment).
I've marked the red squares to "connect it" with the Kubernetes resources (look on ports):
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx NodePort 10.20.6.229 <none> 80:32612/TCP 51m
$ kubectl get svc -n kube-system default-http-backend
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
default-http-backend NodePort 10.20.15.39 <none> 80:30603/TCP 121m
Ingress definition in the question
The part of the Ingress definition that was included in the question is/was created in a way that was referencing the same paths with 2 different backends:
http:
paths:
- backend:
serviceName: istio-ingressgateway
servicePort: 80
- backend:
serviceName: istio-ingressgateway
servicePort: 15021
Above example:
- Is having 2 different backends.
- Is configured that 2 different backends share the same path.
- The requests (as I've reproduced it) were coming to the "
15021" backend which is only for health checking.
To fix that, you will need to remove the 15021 backend and use backendConfig resource to configure health checking and security policy (more on that later).
A side note!
The YAML manifest is using and old and soon to be deprecated way to describe Ingress. Please refer to this documentation for more reference:
Integrating Cloud Armor with Istio
One of the ways that you can use Cloud Armor with Istio is the following:
- Create a security policy.
- Create a
backendConfig as a prerequisite for Istio Service.
- Install Istio with modification to its
Service.
- Create an
Ingress resource to point to istio-ingressgateway.
- Test with an example.
Create a security policy
For example purposes a security policy can be created that only blocks a single IP address. It can be done either by gcloud or Cloud Console (Web UI):
Let's assume that the security policy named: deny-single was created that blocks a single IP address.
Create a backendConfig as a prerequisite for Istio Service.
You will need to create a backendConfig that will configure health checks and will enforce the security policy:
apiVersion: cloud.google.com/v1
kind: BackendConfig
metadata:
name: ingress-backendconfig
namespace: istio-system
spec:
healthCheck:
requestPath: /healthz/ready
port: 15021
type: HTTP
securityPolicy:
name: deny-single # <-- IMPORTANT
Install Istio with modification to its Service
You will need to add following annotations to the Service of your istio-ingressgateway:
cloud.google.com/backend-config: '{"default": "ingress-backendconfig"}'
cloud.google.com/neg: '{"ingress":true}'
This annotations will inform GCP on the security policy to apply as well on the health checks that are required for the traffic to be passed to the istio-ingressgateway.
Create an Ingress resource to point to istio-ingressgateway
A basic Ingress definition that will send the request from HTTP(S) Load Balancer to istio-ingressgateway can be following:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: istio-ingress
namespace: istio-system
spec:
rules:
- http:
paths:
- path: /*
pathType: ImplementationSpecific
backend:
service:
name: istio-ingressgateway
port:
number: 80
Test with an example
To check if the setup is working correctly you can spawn the Bookinfo Application.
Testing with 2 different IP addresses:
217.AAA.BBB.CCC
$ curl 34.XXX.YYY.ZZZ/productpage
<!doctype html><meta charset="utf-8"><meta name=viewport content="width=device-width, initial-scale=1"><title>403</title>403 Forbidden%
94.EEE.FFF.GGG
$ curl 34.XXX.YYY.ZZZ/productpage
<html>
<head>
<title>Simple Bookstore App</title>
<-- REDACTED -->
A side note!
The "closed port" that you've received could be related to the fact that istio-ingressgateway was configured to listen on specific path like /productpage and not /. (if the request was specifically targeted to port 80 instead of 15021)
Additional resources: