You can use a gateway to manage inbound and outbound traffic for your mesh to specify which traffic you want to enter or leave the mesh. Gateway configurations are applied to standalone Envoy proxies that are running at the edge of the mesh, rather than sidecar Envoy proxies running alongside your service workloads.
Unlike other mechanisms for controlling traffic entering your systems, such as the Kubernetes Ingress APIs, Red Hat OpenShift Service Mesh gateways use the full power and flexibility of traffic routing.
The Red Hat OpenShift Service Mesh gateway resource can use layer 4-6 load balancing properties, such as ports, to expose and configure Red Hat OpenShift Service Mesh TLS settings. Instead of adding application-layer traffic routing (L7) to the same API resource, you can bind a regular Red Hat OpenShift Service Mesh virtual service to the gateway and manage gateway traffic like any other data plane traffic in a service mesh.
Gateways are primarily used to manage ingress traffic, but you can also configure egress gateways. An egress gateway lets you configure a dedicated exit node for the traffic leaving the mesh. This enables you to limit which services have access to external networks, which adds security control to your service mesh. You can also use a gateway to configure a purely internal proxy.
Gateway example
A gateway resource describes a load balancer operating at the edge of the mesh receiving incoming or outgoing HTTP/TCP connections. The specification describes a set of ports that should be exposed, the type of protocol to use, SNI configuration for the load balancer, and so on.
The following example shows a sample gateway configuration for external HTTPS ingress traffic:
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: ext-host-gwy
spec:
selector:
istio: ingressgateway # use istio default controller
servers:
- port:
number: 443
name: https
protocol: HTTPS
hosts:
- ext-host.example.com
tls:
mode: SIMPLE
serverCertificate: /tmp/tls.crt
privateKey: /tmp/tls.key
This gateway configuration lets HTTPS traffic from ext-host.example.com
into the mesh on port 443, but doesn’t specify any routing for the traffic.
To specify routing and for the gateway to work as intended, you must also bind the gateway to a virtual service. You do this using the virtual service’s gateways field, as shown in the following example:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: virtual-svc
spec:
hosts:
- ext-host.example.com
gateways:
- ext-host-gwy
You can then configure the virtual service with routing rules for the external traffic.
Enabling gateway injection
Gateway configurations apply to standalone Envoy proxies running at the edge of the mesh, rather than sidecar Envoy proxies running alongside your service workloads. Because gateways are Envoy proxies, you can configure Service Mesh to inject gateways automatically, similar to how you can inject sidecars.
Using automatic injection for gateways, you can deploy and manage gateways independent from the ServiceMeshControlPlane
resource and manage the gateways with your user applications. Using auto-injection for gateway deployments gives developers full control over the gateway deployment while simplifying operations. When a new upgrade is available, or a configuration has changed, you restart the gateway pods to update them. Doing so makes the experience of operating a gateway deployment the same as operating sidecars.
|
Injection is disabled by default for the ServiceMeshControlPlane namespace, for example the istio-system namespace. As a security best practice, deploy gateways in a different namespace from the control plane.
|
Deploying automatic gateway injection
When deploying a gateway, you must opt-in to injection by adding an injection label or annotation to the gateway deployment
object. The following example deploys a gateway.
Procedure
-
Set a unique label for the Istio ingress gateway. This setting is required to ensure that the gateway can select the workload. This example uses ingressgateway
as the name of the gateway.
apiVersion: v1
kind: Service
metadata:
name: istio-ingressgateway
namespace: istio-ingress
spec:
type: ClusterIP
selector:
istio: ingressgateway
ports:
- name: http
port: 80
targetPort: 8080
- name: https
port: 443
targetPort: 8443
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: istio-ingressgateway
namespace: istio-ingress
spec:
selector:
matchLabels:
istio: ingressgateway
template:
metadata:
annotations:
inject.istio.io/templates: gateway
labels:
istio: ingressgateway
sidecar.istio.io/inject: "true" (1)
spec:
containers:
- name: istio-proxy
image: auto (2)
1 |
Enable gateway injection by setting the sidecar.istio.io/inject field to "true" . |
2 |
Set the image field to auto so that the image automatically updates each time the pod starts. |
-
Set up roles to allow reading credentials for TLS.
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: istio-ingressgateway-sds
namespace: istio-ingress
rules:
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get", "watch", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: istio-ingressgateway-sds
namespace: istio-ingress
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: istio-ingressgateway-sds
subjects:
- kind: ServiceAccount
name: default
-
Grant access to the new gateway from outside the cluster, which is required whenever spec.security.manageNetworkPolicy
is set to true
.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: gatewayingress
namespace: istio-ingress
spec:
podSelector:
matchLabels:
istio: ingressgateway
ingress:
- {}
policyTypes:
- Ingress
-
Automatically scale the pod when ingress traffic increases. This example sets the minimum replicas to 2
and the maximum replicas to 5
. It also creates another replica when utilization reaches 80%.
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
labels:
istio: ingressgateway
release: istio
name: ingressgatewayhpa
namespace: istio-ingress
spec:
maxReplicas: 5
metrics:
- resource:
name: cpu
target:
averageUtilization: 80
type: Utilization
type: Resource
minReplicas: 2
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: istio-ingressgateway
-
Specify the minimum number of pods that must be running on the node. This example ensures one replica is running if a pod gets restarted on a new node.
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
labels:
istio: ingressgateway
release: istio
name: ingressgatewaypdb
namespace: istio-ingress
spec:
minAvailable: 1
selector:
matchLabels:
istio: ingressgateway
Managing ingress traffic
In Red Hat OpenShift Service Mesh, the Ingress Gateway enables features such as monitoring, security, and route rules to apply to traffic that enters the cluster. Use a Service Mesh gateway to expose a service outside of the service mesh.
Determining the ingress IP and ports
Ingress configuration differs depending on if your environment supports an external load balancer. An external load balancer is set in the ingress IP and ports for the cluster. To determine if your cluster’s IP and ports are configured for external load balancers, run the following command. In this example, istio-system
is the name of the Service Mesh control plane project.
$ oc get svc istio-ingressgateway -n istio-system
That command returns the NAME
, TYPE
, CLUSTER-IP
, EXTERNAL-IP
, PORT(S)
, and AGE
of each item in your namespace.
If the EXTERNAL-IP
value is set, your environment has an external load balancer that you can use for the ingress gateway.
If the EXTERNAL-IP
value is <none>
, or perpetually <pending>
, your environment does not provide an external load balancer for the ingress gateway. You can access the gateway using the service’s node port.
Determining ingress ports with a load balancer
Follow these instructions if your environment has an external load balancer.
Procedure
-
Run the following command to set the ingress IP and ports. This command sets a variable in your terminal.
$ export INGRESS_HOST=$(oc -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
-
Run the following command to set the ingress port.
$ export INGRESS_PORT=$(oc -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="http2")].port}')
-
Run the following command to set the secure ingress port.
$ export SECURE_INGRESS_PORT=$(oc -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="https")].port}')
-
Run the following command to set the TCP ingress port.
$ export TCP_INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="tcp")].port}')
|
In some environments, the load balancer may be exposed using a hostname instead of an IP address. For that case, the ingress gateway’s EXTERNAL-IP value is not an IP address. Instead, it’s a hostname, and the previous command fails to set the INGRESS_HOST environment variable.
In that case, use the following command to correct the INGRESS_HOST value:
|
$ export INGRESS_HOST=$(oc -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].hostname}')
Determining ingress ports without a load balancer
If your environment does not have an external load balancer, determine the ingress ports and use a node port instead.
Procedure
-
Set the ingress ports.
$ export INGRESS_PORT=$(oc -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="http2")].nodePort}')
-
Run the following command to set the secure ingress port.
$ export SECURE_INGRESS_PORT=$(oc -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="https")].nodePort}')
-
Run the following command to set the TCP ingress port.
$ export TCP_INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="tcp")].nodePort}')
Configuring an ingress gateway
An ingress gateway is a load balancer operating at the edge of the mesh that receives incoming HTTP/TCP connections. It configures exposed ports and protocols but does not include any traffic routing configuration. Traffic routing for ingress traffic is instead configured with routing rules, the same way as for internal service requests.
The following steps show how to create a gateway and configure a VirtualService
to expose a service in the Bookinfo sample application to outside traffic for paths /productpage
and /login
.
Procedure
-
Create a gateway to accept traffic.
-
Create a YAML file, and copy the following YAML into it.
Gateway example gateway.yaml
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: bookinfo-gateway
spec:
selector:
istio: ingressgateway
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "*"
-
Apply the YAML file.
$ oc apply -f gateway.yaml
-
Create a VirtualService
object to rewrite the host header.
-
Create a YAML file, and copy the following YAML into it.
Virtual service example
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: bookinfo
spec:
hosts:
- "*"
gateways:
- bookinfo-gateway
http:
- match:
- uri:
exact: /productpage
- uri:
prefix: /static
- uri:
exact: /login
- uri:
exact: /logout
- uri:
prefix: /api/v1/products
route:
- destination:
host: productpage
port:
number: 9080
-
Apply the YAML file.
-
Test that the gateway and VirtualService have been set correctly.
-
Set the Gateway URL.
export GATEWAY_URL=$(oc -n istio-system get route istio-ingressgateway -o jsonpath='{.spec.host}')
-
Set the port number. In this example, istio-system
is the name of the Service Mesh control plane project.
export TARGET_PORT=$(oc -n istio-system get route istio-ingressgateway -o jsonpath='{.spec.port.targetPort}')
-
Test a page that has been explicitly exposed.
curl -s -I "$GATEWAY_URL/productpage"
The expected result is 200
.