Installing Gateways

Istio supports the Kubernetes Gateway API and intends to make it the default API for traffic management in the future. If you use the Gateway API, you will not need to install and manage a gateway Deployment as described in this document. By default, a gateway Deployment and Service will be automatically provisioned based on the Gateway configuration. Refer to the Gateway API task for details.

Along with creating a service mesh, Istio allows you to manage gateways, which are Envoy proxies running at the edge of the mesh, providing fine-grained control over traffic entering and leaving the mesh.

Some of Istio’s built in configuration profiles deploy gateways during installation. For example, a call to istioctl install with default settings will deploy an ingress gateway along with the control plane. Although fine for evaluation and simple use cases, this couples the gateway to the control plane, making management and upgrade more complicated. For production Istio deployments, it is highly recommended to decouple these to allow independent operation.

Follow this guide to separately deploy and manage one or more gateways in a production installation of Istio.

Prerequisites

This guide requires the Istio control plane to be installed before proceeding.

You can use the minimal profile, for example istioctl install --set profile=minimal, to prevent any gateways from being deployed during installation.

Deploying a gateway

Using the same mechanisms as Istio sidecar injection, the Envoy proxy configuration for gateways can similarly be auto-injected.

Using auto-injection for gateway deployments is recommended as it gives developers full control over the gateway deployment, while also simplifying operations. When a new upgrade is available, or a configuration has changed, gateway pods can be updated by simply restarting them. This makes the experience of operating a gateway deployment the same as operating sidecars.

To support users with existing deployment tools, Istio provides a few different ways to deploy a gateway. Each method will produce the same result. Choose the method you are most familiar with.

As a security best practice, it is recommended to deploy the gateway in a different namespace from the control plane.

All methods listed below rely on Injection to populate additional pod settings at runtime. In order to support this, the namespace the gateway is deployed in must not have the istio-injection=disabled label. If it does, you will see pods failing to startup attempting to pull the auto image, which is a placeholder that is intended to be replaced when a pod is created.

First, setup an IstioOperator configuration file, called ingress.yaml here:

  1. apiVersion: install.istio.io/v1alpha1
  2. kind: IstioOperator
  3. metadata:
  4. name: ingress
  5. spec:
  6. profile: empty # Do not install CRDs or the control plane
  7. components:
  8. ingressGateways:
  9. - name: istio-ingressgateway
  10. namespace: istio-ingress
  11. enabled: true
  12. label:
  13. # Set a unique label for the gateway. This is required to ensure Gateways
  14. # can select this workload
  15. istio: ingressgateway
  16. values:
  17. gateways:
  18. istio-ingressgateway:
  19. # Enable gateway injection
  20. injectionTemplate: gateway

Then install using standard istioctl commands:

  1. $ kubectl create namespace istio-ingress
  2. $ istioctl install -f ingress.yaml

Install using standard helm commands:

  1. $ kubectl create namespace istio-ingress
  2. $ helm install istio-ingressgateway istio/gateway -n istio-ingress

To see possible supported configuration values, run helm show values istio/gateway. The Helm repository README contains additional information on usage.

When deploying the gateway in an OpenShift cluster, use the openshift profile to override the default values, for example:

  1. $ helm install istio-ingressgateway istio/gateway -n istio-ingress --set profile=openshift

First, setup the Kubernetes configuration, called ingress.yaml here:

  1. apiVersion: v1
  2. kind: Service
  3. metadata:
  4. name: istio-ingressgateway
  5. namespace: istio-ingress
  6. spec:
  7. type: LoadBalancer
  8. selector:
  9. istio: ingressgateway
  10. ports:
  11. - port: 80
  12. name: http
  13. - port: 443
  14. name: https
  15. ---
  16. apiVersion: apps/v1
  17. kind: Deployment
  18. metadata:
  19. name: istio-ingressgateway
  20. namespace: istio-ingress
  21. spec:
  22. selector:
  23. matchLabels:
  24. istio: ingressgateway
  25. template:
  26. metadata:
  27. annotations:
  28. # Select the gateway injection template (rather than the default sidecar template)
  29. inject.istio.io/templates: gateway
  30. labels:
  31. # Set a unique label for the gateway. This is required to ensure Gateways can select this workload
  32. istio: ingressgateway
  33. # Enable gateway injection. If connecting to a revisioned control plane, replace with "istio.io/rev: revision-name"
  34. sidecar.istio.io/inject: "true"
  35. spec:
  36. # Allow binding to all ports (such as 80 and 443)
  37. securityContext:
  38. sysctls:
  39. - name: net.ipv4.ip_unprivileged_port_start
  40. value: "0"
  41. containers:
  42. - name: istio-proxy
  43. image: auto # The image will automatically update each time the pod starts.
  44. # Drop all privileges, allowing to run as non-root
  45. securityContext:
  46. capabilities:
  47. drop:
  48. - ALL
  49. runAsUser: 1337
  50. runAsGroup: 1337
  51. ---
  52. # Set up roles to allow reading credentials for TLS
  53. apiVersion: rbac.authorization.k8s.io/v1
  54. kind: Role
  55. metadata:
  56. name: istio-ingressgateway-sds
  57. namespace: istio-ingress
  58. rules:
  59. - apiGroups: [""]
  60. resources: ["secrets"]
  61. verbs: ["get", "watch", "list"]
  62. ---
  63. apiVersion: rbac.authorization.k8s.io/v1
  64. kind: RoleBinding
  65. metadata:
  66. name: istio-ingressgateway-sds
  67. namespace: istio-ingress
  68. roleRef:
  69. apiGroup: rbac.authorization.k8s.io
  70. kind: Role
  71. name: istio-ingressgateway-sds
  72. subjects:
  73. - kind: ServiceAccount
  74. name: default

This example shows the bare minimum needed to get a gateway running. For production usage, additional configuration such as HorizontalPodAutoscaler, PodDisruptionBudget, and resource requests/limits are recommended. These are automatically included when using the other gateway installation methods.

The sidecar.istio.io/inject label on the pod is used in this example to enable injection. Just like application sidecar injection, this can instead be controlled at the namespace level. See Controlling the injection policy for more information.

Next, apply it to the cluster:

  1. $ kubectl create namespace istio-ingress
  2. $ kubectl apply -f ingress.yaml

Managing gateways

The following describes how to manage gateways after installation. For more information on their usage, follow the Ingress and Egress tasks.

Gateway selectors

The labels on a gateway deployment’s pods are used by Gateway configuration resources, so it’s important that your Gateway selector matches these labels.

For example, in the above deployments, the istio=ingressgateway label is set on the gateway pods. To apply a Gateway to these deployments, you need to select the same label:

  1. apiVersion: networking.istio.io/v1
  2. kind: Gateway
  3. metadata:
  4. name: gateway
  5. spec:
  6. selector:
  7. istio: ingressgateway
  8. ...

Gateway deployment topologies

Depending on your mesh configuration and use cases, you may wish to deploy gateways in different ways. A few different gateway deployment patterns are shown below. Note that more than one of these patterns can be used within the same cluster.

Shared gateway

In this model, a single centralized gateway is used by many applications, possibly across many namespaces. Gateway(s) in the ingress namespace delegate ownership of routes to application namespaces, but retain control over TLS configuration.

Shared gateway
Shared gateway

This model works well when you have many applications you want to expose externally, as they are able to use shared infrastructure. It also works well in use cases that have the same domain or TLS certificates shared by many applications.

Dedicated application gateway

In this model, an application namespace has its own dedicated gateway installation. This allows giving full control and ownership to a single namespace. This level of isolation can be helpful for critical applications that have strict performance or security requirements.

Dedicated application gateway
Dedicated application gateway

Unless there is another load balancer in front of Istio, this typically means that each application will have its own IP address, which may complicate DNS configurations.

Upgrading gateways

In place upgrade

Because gateways utilize pod injection, new gateway pods that are created will automatically be injected with the latest configuration, which includes the version.

To pick up changes to the gateway configuration, the pods can simply be restarted, using commands such as kubectl rollout restart deployment.

If you would like to change the control plane revision in use by the gateway, you can set the istio.io/rev label on the gateway Deployment, which will also trigger a rolling restart.

In place upgrade in progress
In place upgrade in progress

Canary upgrade (advanced)

This upgrade method depends on control plane revisions, and therefore can only be used in conjunction with control plane canary upgrade.

If you would like to more slowly control the rollout of a new control plane revision, you can run multiple versions of a gateway deployment. For example, if you want to roll out a new revision, canary, create a copy of your gateway deployment with the istio.io/rev=canary label set:

  1. apiVersion: apps/v1
  2. kind: Deployment
  3. metadata:
  4. name: istio-ingressgateway-canary
  5. namespace: istio-ingress
  6. spec:
  7. selector:
  8. matchLabels:
  9. istio: ingressgateway
  10. template:
  11. metadata:
  12. annotations:
  13. inject.istio.io/templates: gateway
  14. labels:
  15. istio: ingressgateway
  16. istio.io/rev: canary # Set to the control plane revision you want to deploy
  17. spec:
  18. containers:
  19. - name: istio-proxy
  20. image: auto

When this deployment is created, you will then have two versions of the gateway, both selected by the same Service:

  1. $ kubectl get endpoints -n istio-ingress -o "custom-columns=NAME:.metadata.name,PODS:.subsets[*].addresses[*].targetRef.name"
  2. NAME PODS
  3. istio-ingressgateway istio-ingressgateway-...,istio-ingressgateway-canary-...
Canary upgrade in progress
Canary upgrade in progress

Unlike application services deployed inside the mesh, you cannot use Istio traffic shifting to distribute the traffic between the gateway versions because their traffic is coming directly from external clients that Istio does not control. Instead, you can control the distribution of traffic by the number of replicas of each deployment. If you use another load balancer in front of Istio, you may also use that to control the traffic distribution.

Because other installation methods bundle the gateway Service, which controls its external IP address, with the gateway Deployment, only the Kubernetes YAML method is supported for this upgrade method.

Canary upgrade with external traffic shifting (advanced)

A variant of the canary upgrade approach is to shift the traffic between the versions using a high level construct outside Istio, such as an external load balancer or DNS.

Canary upgrade in progress with external traffic shifting
Canary upgrade in progress with external traffic shifting

This offers fine-grained control, but may be unsuitable or overly complicated to set up in some environments.

Cleanup

  • Cleanup Istio ingress gateway

    1. $ istioctl uninstall --istioNamespace istio-ingress -y --purge
    2. $ kubectl delete ns istio-ingress