When deploying a proxy outside of Kubernetes, users typically reach for solutions like nginx or Traefik; it's pretty rare to see Kubernetes-native load balancers, like Istio, used outside of the Kubernetes context. While it is not documented anywhere on istio.io, it is completely possible to set up an Istio Gateway outside of Kubernetes - not just running out of the cluster, but not connected to any Kubernetes api-server whatsoever.

In this post, we will set up Istiod, and Istio ingress gateway, and a test application using docker-compose. The full configuration can be found in howardjohn/local-istio-gateway. Setting up a full mesh outside of Kubernetes is possible, but outside of the scope of this post.

Setup Istiod

First, we will run the control plane. Because we don't have an api-server to act as a config store, we will use local files as configuration. First, we need to create a folder to store our configurations and secrets (Istio will fail if it cannot write some certificates to disk; this is not really needed for our setup since everything is over localhost, but its not easy to disable).

mkdir configs/ secrets/

We also need a mesh config, stored in this example as mesh, specified:

enableAutoMtls: false # We are not handling mTLS here.
accessLogFile: /dev/stdout # Setup access logs so we can verify traffic.
defaultConfig:
  discoveryAddress: istiod:15010 # Address proxies can reach us at.
  controlPlaneAuthPolicy: NONE # We are not using TLS for control plane communication in this example.
configSources:
# Tell Istiod to read configurations from files only (and not Kubernetes)
- address: fs:///var/lib/istio/config/data

Next, we can set up the container. Create a docker-compose.yml:

version: "3.3"
services:
  istiod:
    image: gcr.io/istio-testing/pilot:latest
    command: [discovery, --registries=] # --registries= tells Istiod to not look at Kubernetes for Endpoints, Services, etc
    hostname: istiod # Setup a stable hostname for the proxies to connect to
    volumes:
    - ./mesh:/etc/istio/config/mesh
    - ./configs:/var/lib/istio/config/data
    - ./secrets:/var/run/secrets

With that setup, you should be able to run docker-compose up and see Istiod running successfully.

Setup the gateway

Next, we can add a new service to our docker-compose.yml for the Gateway. We will also add a simple test app so we can verify our setup works:

  ingress:
    image: gcr.io/istio-testing/proxyv2:latest
    command: [proxy, router]
    volumes:
    - ./mesh:/etc/istio/config/mesh
    environment:
      FILE_MOUNTED_CERTS: "true" # We don't have the full certificate flow setup here, so just use local files.
      ISTIO_META_NAMESPACE: istio-system
      ISTIO_METAJSON_LABELS: '{"istio": "ingressgateway", "app": "istio-ingressgateway"}'
      GRPC_XDS_BOOTSTRAP: ""
    ports:
    - 80:80
  echo:
    hostname: echo.local
    image: gcr.io/istio-testing/app:latest
    command: [--port=80]

Running docker-compose up now should have all three applications running. However, if you try to curl localhost, you will not get any response. This is because we haven't yet configured the Gateway at all.

Setup the config

In the configs/ folder we created previously, add the following configuration:

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: echo
  namespace: default
spec:
  selector:
    istio: ingressgateway
  servers:
  - port:
      number: 80
      name: http
      protocol: HTTP
    hosts:
    - "*"
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: echo
  namespace: default
spec:
  hosts:
  - "*"
  gateways:
  - echo
  http:
  - route:
    - destination:
        host: echo.local
        port:
          number: 80
---
apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
  name: echo
spec:
  hosts:
  - "echo.local"
  ports:
  - number: 80
    name: http
    protocol: HTTP
  resolution: DNS

When the file is added, Istiod will automatically pick up the changes and send them to the gateway, without needing to restart.

Now a curl localhost should succeed.