---
schema_version: "1"
id: 3538e4aa78dbc0af1aea5cae079cee80bd9287e2070bb2e88296efafaea00533
title: Integrating Omni Gateway with Istio Service Mesh
collection: mulesoft
version: current
locale: en-us
portal_url: https://docs.salesforce.com/mulesoft/current/en-us/gateway/latest/gateway-istio.md
canonical_url: https://docs.mulesoft.com/gateway/latest/gateway-istio
source_site: docs.mulesoft.com
content_type: documentation
content_hash: bf16231a5fc57cec77be9164d9c46470f8490e2ed95eb5585f2dfd83171ec373
description: MuleSoft Documentation Site
release: "1.14"
latest: true
---
---
product: Omni Gateway
version: 1.14
is-latest-version: true
---

# Integrating Omni Gateway with Istio Service Mesh

> For the full documentation index, see: https://docs.mulesoft.com/llms.txt

To leverage Omni Gateway policies, logging, and metrics from the Anypoint Platform control plane,
integrate Omni Gateway into your Istio Service Mesh. Deploy Omni Gateway as an ingress gateway to
manage ingress north-south cluster traffic and internal east-west traffic inside the cluster.

To integrate Omni Gateway, use the following architecture diagram and tutorial. Omni Gateway is
integrated by using a modified version of the
[Istio Bookinfo sample application](https://istio.io/latest/docs/examples/bookinfo/). In the Omni
Gateway integration:

- An Istio virtual service forwards all ingress north-south traffic to Omni Gateway.

- Direct access to the `bookinfo` name space is restricted. All external traffic into the `bookinfo`
  namespace must come from the `flex` namespace. Istio automatically configures mTLS configuration
  between the `bookinfo` and `flex`.

- Omni Gateway protects and monitors the exposed product page service from ingress traffic with an
  API instance.

- The Istio sidecar intercepts east-west traffic between the product page service and the reviews
  service. Omni Gateway acts as an ingress gateway managing incoming traffic to the reviews service.

![A diagram demonstrating the architecture to integrate Omni Gateway with Istio](/mulesoft/current/en-us/gateway/latest/_images/istio-deployment.png)

> [!NOTE] In the diagram, Omni Gateway is running in Connected Mode. If Omni Gateway runs in Local
> Mode, the Anypoint Platform control plane is absent.

To configure the architecture:

1.  [Complete Before You Begin](#before-you-begin).

2.  [Set up your environment](#setup-environment).

3.  [Intercept ingress north-south traffic](#forward-ingress-traffic).

4.  [Intercept east-west traffic between services](#create-a-service).

## Before You Begin

Before you begin, install the following prerequisites:

- [Docker](https://docs.docker.com/get-docker/)

- [Download Omni Gateway for Use in a Kubernetes Cluster](https://docs.mulesoft.com/gateway/latest/install#kubernetes)

- [K3d](https://k3d.io/v5.0.0/#installation) to create a Kubernetes cluster inside of docker

- [kubectl](https://kubernetes.io/docs/tasks/tools/#kubectl) to control the Kubernetes cluster

- [Helm](https://helm.sh/docs/intro/install/) to install Omni Gateway and Istio

## Set up Environment

1.  Create a Kubernetes cluster for this demo or skip this step if you already have a cluster you
    want to use:

    ```ssh
    k3d cluster create demo-istio --k3s-arg "--disable=traefik@server:0" --port '80:80@server:0' --port '443:443@server:0'
    ```

2.  Add the Omni Gateway and Istio Helm repositories:

    ```ssh
    helm repo add istio https://istio-release.storage.googleapis.com/charts \
    && helm repo add flex-gateway https://flex-packages.anypoint.mulesoft.com/helm \
    && helm repo up
    ```

3.  Install Istio:

    1.  Install the Istio base chart that contains the cluster-wide Custom Resource Definitions
        (CRDs) that must be installed before deploying the Istio control plane:

        ```ssh
        helm upgrade -i --wait --create-namespace -n istio-system istio-base istio/base --version 1.21.2 --set defaultRevision=default
        ```

    2.  Install the Istio discovery chart that deploys the `istiod` service:

        ```ssh
        helm upgrade -i --wait --create-namespace -n istio-system istiod istio/istiod --version 1.21.2
        ```

    3.  Install an Istio ingress gateway:

        ```ssh
        helm upgrade -i --wait --create-namespace -n istio-system istio-ingress istio/gateway --version 1.21.2
        ```

4.  Install Omni Gateway:

    1.  Create the namespace and set up the label to enable the sidecar injection:

        ```ssh
        kubectl create ns flex && kubectl label ns flex istio-injection=enabled --overwrite
        ```

    2.  Install Omni Gateway:

        ```ssh
        helm upgrade -i --wait -n flex --version 1.7.0 flex flex-gateway/flex-gateway \
        --set gateway.scope=Namespace \
        --set gateway.mode=connected \
        --set service.type=ClusterIP \
        --set service.http.port=8081 \
        --set service.https.enabled=false \
        --set-file registration.content=registration.yaml
        ```

    3.  List all services and API instances previously created:

        ```ssh
        kubectl -n flex get svc
        ```

5.  Install the `bookinfo` application:

    1.  Enable Istio label injection in the default namespace and install the `bookinfo`
        application:

        ```ssh
        kubectl create ns bookinfo \
        && kubectl label ns bookinfo istio-injection=enabled --overwrite \
        && kubectl -n bookinfo apply -l version!=v2,version!=v3 -f https://raw.githubusercontent.com/istio/istio/release-1.20/samples/bookinfo/platform/kube/bookinfo.yaml
        ```

    2.  Check the pod status:

        ```ssh
        kubectl -n bookinfo get pods
        ```

6.  Install the `sleep` application to test traffic:

    1.  Create the `test` namespace and install the `sleep` application:

        ```ssh
        kubectl create ns test \
        && kubectl label ns test istio-injection=enabled --overwrite \
        && kubectl -n test apply -f https://raw.githubusercontent.com/istio/istio/release-1.20/samples/sleep/sleep.yaml
        ```

    2.  Check the status of the pods:

        ```ssh
        kubectl -n test get pods
        ```

## Intercept Ingress North-South Traffic

Intercept ingress north-south traffic to protect services from external traffic.

To intercept ingress north-south traffic:

1.  Create the Omni Gateway ingress API instance to forward all ingress north-south traffic in the
    `bookinfo` namespace to the `productpage` service:

    - Local Mode:

      ```ssh
      cat <<EOF | kubectl apply -f -
      ---
      apiVersion: gateway.mulesoft.com/v1alpha1
      kind: ApiInstance
      metadata:
        name: ingress
        namespace: flex
      spec:
        address: http://0.0.0.0:8081/ingress/
        services:
          productpage:
            address: http://productpage.bookinfo.svc:9080
      EOF
      ```

    - Connected Mode:

      To add an API instance in Connected Mode, see
      [Adding an Omni Gateway API Instance](https://docs.mulesoft.com/api-manager/latest/create-instance-task-flex).

      Configure the API instance with the following downstream parameters:

      - **Protocol**: **HTTP**

      - **Port**: `8081`

      - **Base Path**: `/ingress/`

        Configure the API instance with the following upstream parameters:

      - **Route label**: `productpage`

      - **Upstream URL**:
        `[http://productpage.bookinfo.svc:9080](http://productpage.bookinfo.svc:9080)`

2.  Create the `flex` Istio ingress gateway to forward the ingress traffic to Omni Gateway using a
    Istio virtual service:

    1.  Create the Omni Gateway:

        ```ssh
        cat <<EOF | kubectl apply -f -
        ---
        apiVersion: networking.istio.io/v1alpha3
        kind: Gateway
        metadata:
          name: flex
          namespace: flex
        spec:
          selector:
            app: istio-ingress
          servers:
          - port:
              number: 80
              name: http
              protocol: HTTP
            hosts:
            - "*"
        ---
        apiVersion: networking.istio.io/v1alpha3
        kind: VirtualService
        metadata:
          name: flex
          namespace: flex
        spec:
          hosts:
          - "*"
          gateways:
          - flex
          http:
          - route:
            - destination:
                host: flex
                port:
                  number: 8081
            rewrite:
              uri: /ingress/
        EOF
        ```

    2.  Wait a few seconds (approximately 10) and send a test request to the `/api/v1/products/1`
        page:

        ```ssh
        curl -v http://localhost/api/v1/products/1
        ```

    3.  Ensure you receive this output:

        ```ssh
        < HTTP/1.1 200 OK
        < server: istio-envoy
        < date: Tue, 27 Feb 2024 22:06:33 GMT
        < content-type: application/json
        < content-length: 195
        < x-envoy-upstream-service-time: 8
        <
        * Connection #0 to host localhost left intact
        {"id": 2, "author": "William Shakespeare", "year": 1595, "type": "paperback", "pages": 200, "publisher": "PublisherA", "language": "English", "ISBN-10": "1234567890", "ISBN-13": "123-1234567890"}
        ```

3.  Protect the Omni Gateway API instance by applying the Basic Authentication policy:

    1.  Add the policy:

        ```ssh
        cat <<EOF | kubectl apply -f -
        ---
        apiVersion: gateway.mulesoft.com/v1alpha1
        kind: ApiInstance
        metadata:
          name: ingress
          namespace: flex
        spec:
          address: http://0.0.0.0:8081/ingress/
          services:
            productpage:
              address: http://productpage.bookinfo.svc:9080
          policies:
          - policyRef:
              name: http-basic-authentication-flex
            config:
              username: user1
              password: password1
        EOF
        ```

    2.  Wait a few seconds (approximately 10) and send a test request:

        ```ssh
        curl -v http://localhost/
        ```

    3.  Make sure you receive a `401` response.

4.  Add the Message Logging policy to log traffic:

    ```ssh
    cat <<EOF | kubectl apply -f -
    ---
    apiVersion: gateway.mulesoft.com/v1alpha1
    kind: ApiInstance
    metadata:
      name: ingress
      namespace: flex
    spec:
      address: http://0.0.0.0:8081/ingress/
      services:
        productpage:
          address: http://productpage.bookinfo.svc:9080
      policies:
      - policyRef:
          name: http-basic-authentication-flex
        config:
          username: user1
          password: password1
      - policyRef:
          name: message-logging-flex
        config:
          loggingConfiguration:
          - itemName: "Request"
            itemData:
              message: "#['> ' ++ attributes.version ++ ' ' ++  attributes.method ++ ' ' ++ attributes.headers.host ++ attributes.requestUri]"
              level: "INFO"
              firstSection: true
          - itemName: "Response"
            itemData:
              message: "#['< Status=' ++ attributes.statusCode ++ ' Length=' ++ (attributes.headers['content-length'] default 'none') ++ ' Time=' ++ (attributes.headers['x-envoy-upstream-service-time'] default 'none')]"
              level: "INFO"
              secondSection: true
        order: 0
    EOF
    ```

## Intercept East-West Traffic Between Services

Use Omni Gateway to intercept east-west traffic between services and protect them with policies.

To intercept east-west traffic:

1.  Create the `bookinfo-reviews` API instance to forward the east-west traffic to the `reviews`
    service:

    - Local Mode:

      ```ssh
      cat <<EOF | kubectl apply -f -
      ---
      apiVersion: gateway.mulesoft.com/v1alpha1
      kind: ApiInstance
      metadata:
        name: bookinfo-reviews
        namespace: flex
      spec:
        address: http://0.0.0.0:8081/bookinfo/reviews/
        services:
          upstream:
            address: http://reviews.bookinfo.svc:9080
        policies:
        - policyRef:
            name: message-logging-flex
          config:
            loggingConfiguration:
            - itemName: "Request"
              itemData:
                message: "#['> ' ++ attributes.version ++ ' ' ++  attributes.method ++ ' ' ++ attributes.headers.host ++ attributes.requestUri]"
                level: "INFO"
                firstSection: true
            - itemName: "Response"
              itemData:
                message: "#['< Status=' ++ attributes.statusCode ++ ' Length=' ++ (attributes.headers['content-length'] default 'none') ++ ' Time=' ++ (attributes.headers['x-envoy-upstream-service-time'] default 'none')]"
                level: "INFO"
                secondSection: true
      EOF
      ```

    - Connected Mode:

      To add an API instance in Connected Mode, see
      [Adding an Omni Gateway API Instance](https://docs.mulesoft.com/api-manager/latest/create-instance-task-flex).

      Configure the API instance with these downstream parameters:

      - **Protocol**: **HTTP**

      - **Port**: `8081`

      - **Base Path**: `/bookinfo/reviews/`

        Configure the API instance with these upstream parameters:

      - **Route label**: `reviews`

      - **Upstream URL**: `[http://reviews.bookinfo.svc:9080](http://reviews.bookinfo.svc:9080)`

2.  Intercept the traffic between the `productpage` service and the `reviews` service and forward it
    to the `flex` service:

    1.  Create the Istio API instance:

        ```ssh
        cat <<EOF | kubectl apply -f -
        ---
        apiVersion: networking.istio.io/v1alpha3
        kind: VirtualService
        metadata:
          name: bookinfo-reviews
          namespace: istio-system
        spec:
          hosts:
          - reviews.bookinfo.svc.cluster.local
          http:
          - match:
            - sourceLabels:
                app: flex
            route:
            - destination:
                host: reviews.bookinfo.svc.cluster.local
                port:
                  number: 9080
          - route:
            - destination:
                host: flex.flex.svc.cluster.local
                port:
                  number: 8081
            rewrite:
              uri: /bookinfo/reviews/
        EOF
        ```

    2.  Send a test request with the `user1` username and `password1` password to the
        `/productpage`:

        ```ssh
        curl -v -u user1:password1 http://localhost/productpage
        ```

    3.  Check the Omni Gateway logs to ensure the request sent from the `productpage` service to the
        `reviews` service passed through Omni Gateway. The logs appear similar to:

        ```ssh
        [flex-gateway-envoy][info] wasm log productpage-message-logging-flex-2.flex.productpage.flex.svc main: [policy: productpage-message-logging-flex-2.flex][api: productpage.flex.svc][req: 6e1f7c32-918d-4b6a-af3f-36a4430f80ae] [accessLog] > HTTP/1.1 GET localhost/ingress/productpage
        [flex-gateway-envoy][info] wasm log bookinfo-reviews-message-logging-flex-1.flex.bookinfo-reviews.flex.svc main: [policy: bookinfo-reviews-message-logging-flex-1.flex][api: bookinfo-reviews.flex.svc][req: b23e9c64-a2aa-4464-8984-d1dd6c18f7ea] [accessLog] > HTTP/1.1 GET reviews:9080/bookinfo/reviews/reviews/0
        ```

        > [!NOTE] Use the standard output logs for a quick log check. To learn how to view standard
        > output logs, see [Viewing Standard Output Logs](https://docs.mulesoft.com/gateway/latest/local-view-logs).

    4.  Apply the Rate Limiting policy to the `bookinfo-reviews` API instance to protect the
        `reviews` service:

        ```ssh
        cat <<EOF | kubectl apply -f -
        ---
        apiVersion: gateway.mulesoft.com/v1alpha1
        kind: ApiInstance
        metadata:
          name: bookinfo-reviews
          namespace: flex
        spec:
          address: http://0.0.0.0:8081/bookinfo/reviews/
          services:
            upstream:
              address: http://reviews.bookinfo.svc:9080
          policies:
          - policyRef:
              name: message-logging-flex
            config:
              loggingConfiguration:
              - itemName: "Request"
                itemData:
                  message: "#['> ' ++ attributes.version ++ ' ' ++  attributes.method ++ ' ' ++ attributes.headers.host ++ attributes.requestUri]"
                  level: "INFO"
                  firstSection: true
              - itemName: "Response"
                itemData:
                  message: "#['< Status=' ++ attributes.statusCode ++ ' Length=' ++ (attributes.headers['content-length'] default 'none') ++ ' Time=' ++ (attributes.headers['x-envoy-upstream-service-time'] default 'none')]"
                  level: "INFO"
                  secondSection: true
            order: 0
          - policyRef:
              name: rate-limiting-flex
            config:
              rateLimits:
              - timePeriodInMilliseconds: 60000
                maximumRequests: 2
              exposeHeaders: true
        EOF
        ```

3.  Restrict direct access to the `bookinfo` service:

    1.  Restrict access:

        ```ssh
        cat <<EOF | kubectl apply -f -
        ---
        apiVersion: security.istio.io/v1
        kind: AuthorizationPolicy
        metadata:
          name: flex-allow
          namespace: bookinfo
        spec:
          action: ALLOW
          rules:
          - from:
            - source:
                namespaces:
                - flex
                - bookinfo
        EOF
        ```

    2.  Send a test request from the test namespace to the `details` service:

        ```ssh
        kubectl -n test exec -ti -c sleep $(kubectl -n test get pod --no-headers -o=name) -- curl -v details.bookinfo:9080/details/0
        ```

    3.  Make sure you receive this `403 forbidden` response:

        ```ssh
        < HTTP/1.1 403 Forbidden
        < content-length: 19
        < content-type: text/plain
        < date: Thu, 09 May 2024 15:51:11 GMT
        < server: envoy
        < x-envoy-upstream-service-time: 0
        <
        * Connection #0 to host details.bookinfo left intact
        RBAC: access denied
        ```

    4.  Send this request to the `details` service to find out how to access the `bookinfo` service
        from the `flex` namespace:

        ```ssh
        kubectl -n flex exec -ti -c app  $(kubectl -n flex get pod --no-headers -o=name) -- flexctl check http http://details.bookinfo:9080/details/0
        ```

    5.  Make sure you receive this response:

        ```ssh
        [flexctl][info] Access to http address 'http://details.bookinfo:9080/details/0': ok
        ```
