Gateways

Red Hat OpenShift Service Mesh 3.3

Gateways and OpenShift Service Mesh

Red Hat OpenShift Documentation Team

Abstract

This documentation provides information about using gateways with OpenShift Service Mesh.

Chapter 1. About gateways

Manage ingress and egress traffic at the mesh edge by using gateway injection or the Kubernetes Gateway API to deploy standalone Envoy proxies across sidecar and ambient architectures.

1.1. Understanding gateways

A gateway is a standalone Envoy proxy deployment and an associated Kubernetes service operating at the edge of a service mesh. You can configure a gateway to give fine-grained control over the traffic that enters or leaves the mesh.

In Red Hat OpenShift Service Mesh, you can install gateways by using gateway injection or by using the Gateway API. Red Hat OpenShift Service Mesh supports different gateway configurations based on the deployment mode. You can deploy gateways by using gateway injection and configure them with Istio Gateway and VirtualService resources in sidecar mode or with Kubernetes Gateway API resources in both sidecar and ambient modes.

1.2. About gateway injection

You can install a gateway by applying labels and annotations to Kubernetes Deployment and Service resources, triggering the Istio control plane to inject and configure the gateway proxy.

Gateway injection relies upon the same mechanism as sidecar injection to inject the Envoy proxy into gateway pods. To install a gateway by using gateway injection, you create a Kubernetes Deployment object and an associated Kubernetes Service object in a namespace that is visible to the Istio control plane. When creating the Deployment object, you apply labels and annotations so the Istio control plane injects and configures a proxy to act as a gateway. After installing the gateway, you configure it to control ingress and egress traffic by using the Istio Gateway and VirtualService resources.

1.2.1. Installing a gateway by using gateway injection

Install a gateway by using gateway injection to deploy and configure an Envoy proxy for managing traffic at the edge of the mesh.

Note

You can use this procedure to create ingress or egress gateways.

Prerequisites

  • You have installed the OpenShift Service Mesh Operator version 3.0 or later.
  • You have created an Istio control plane.
  • You have created an IstioCNI resource.

Procedure

  1. Create a namespace that you will use to install the gateway.

    $ oc create namespace <gateway_namespace>
    Note

    Install the gateway and the Istio control plane in different namespaces.

    You can install the gateway in a dedicated gateway namespace. This approach allows many applications in different namespaces to share the same gateway. Or, you can install the gateway in an application namespace. In this approach, the gateway acts as a dedicated gateway for the application in that namespace.

  2. Create a YAML file named secret-reader.yml that defines the service account, role, and role binding for the gateway deployment, similar to the following example:

    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: secret-reader
      namespace: <gateway_namespace>
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: Role
    metadata:
      name: secret-reader
      namespace: <gateway_namespace>
    rules:
      - apiGroups: [""]
        resources: ["secrets"]
        verbs: ["get", "watch", "list"]
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: RoleBinding
    metadata:
      name:  secret-reader
      namespace: <gateway_namespace>
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: Role
      name: secret-reader
    subjects:
      - kind: ServiceAccount
        name:  secret-reader

    These settings enable the gateway to read secrets so that it can obtain TLS credentials.

  3. Apply the YAML file by running the following command:

    $ oc apply -f secret-reader.yml
  4. Create a YAML file named gateway-deployment.yml that defines the Kubernetes Deployment object for the gateway, similar to the following example:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: <gateway_name>
      namespace: <gateway_namespace>
    spec:
      selector:
        matchLabels:
          istio: <gateway_name>
      template:
        metadata:
          annotations:
            inject.istio.io/templates: gateway
          labels:
            istio: <gateway_name>
            sidecar.istio.io/inject: "true"
        spec:
          containers:
            - name: istio-proxy
              image: auto
              securityContext:
                capabilities:
                  drop:
                  - ALL
                allowPrivilegeEscalation: false
                privileged: false
                readOnlyRootFilesystem: true
                runAsNonRoot: true
              ports:
              - containerPort: 15090
                protocol: TCP
                name: http-envoy-prom
              resources:
                limits:
                  cpu: 2000m
                  memory: 1024Mi
                requests:
                  cpu: 100m
                  memory: 128Mi
          securityContext:
            sysctls:
            - name: net.ipv4.ip_unprivileged_port_start
              value: "0"
          serviceAccountName: secret-reader
    • spec.template.annotations.inject.istio.io/templates indicates that the Istio control plane uses the gateway injection template instead of the default sidecar template.
    • spec.template.labels.istio ensures that you set a unique label for the gateway deployment. Istio Gateway resources require a unique label to select gateway workloads.
    • spec.template.labels.sidecar.istio.io/inject enables gateway injection by setting this label to true. If the name of the Istio resource is not default you must use the istio.io/rev: <istio_revision> label instead, where the revision represents the active revision of the Istio resource.
    • spec.template.spec.containers.image sets the image field to auto so that the image automatically updates each time the pod starts.
    • spec.template.spec.serviceAccountName sets the serviceAccountName to the name of the ServiceAccount created previously.
  5. Apply the YAML file by running the following command:

    $ oc apply -f gateway-deployment.yml
  6. Verify that the gateway Deployment rollout was successful by running the following command:

    $ oc rollout status deployment/<gateway_name> -n <gateway_namespace>

    You should see output similar to the following example:

    Waiting for deployment "<gateway_name>" rollout to finish: 0 of 1 updated replicas are available...
    deployment "<gateway_name>" successfully rolled out
  7. Create a YAML file named gateway-service.yml that has the Kubernetes Service object for the gateway.

    apiVersion: v1
    kind: Service
    metadata:
      name: <gateway_name>
      namespace: <gateway_namespace>
    spec:
      type: ClusterIP 1
      selector:
        istio: <gateway_name> 2
      ports:
        - name: status-port
          port: 15021
          protocol: TCP
          targetPort: 15021
        - name: http2
          port: 80
          protocol: TCP
          targetPort: 80
        - name: https
          port: 443
          protocol: TCP
          targetPort: 443
    • spec.type sets the type of the gateway Service object. Setting spec.type to ClusterIP restricts gateway Service access to the internal cluster network. If the gateway has to handle ingress traffic from outside the cluster, set spec.type to LoadBalancer. Or, you can use OpenShift Routes.
    • spec.selector sets the selector to the unique label or set of labels specified in the pod template of the gateway deployment that you created previously.
  8. Apply the YAML file by running the following command:

    $ oc apply -f gateway-service.yml
  9. Verify that the gateway service is targeting the endpoint of the gateway pods by running the following command:

    $ oc get endpoints <gateway_name> -n <gateway_namespace>

    You should see output similar to the following example:

    Example output:

    NAME              ENDPOINTS                             AGE
    <gateway_name>    10.131.0.181:8080,10.131.0.181:8443   1m
  10. Optional: Create a YAML file named gateway-hpa.yml that defines a horizontal pod autoscaler for the gateway. The following example sets the minimum replicas to 2 and the maximum replicas to 5 and scales the replicas up when average CPU usage exceeds 80% of the CPU resource limit. The gateway deployment’s pod template specifies this limit.

    apiVersion: autoscaling/v2
    kind: HorizontalPodAutoscaler
    metadata:
      name: <gateway_name>
      namespace: <gateway_namespace>
    spec:
      minReplicas: 2
      maxReplicas: 5
      metrics:
      - resource:
          name: cpu
          target:
            averageUtilization: 80
            type: Utilization
        type: Resource
      scaleTargetRef:
        apiVersion: apps/v1
        kind: Deployment
        name: <gateway_name>
    • spec.scaleTargetRef.name specifies the name of the gateway deployment created previously.
  11. Optional: Apply the YAML file by running the following command:

    $ oc apply -f gateway-hpa.yml
  12. Optional: Create a YAML file named gateway-pdb.yml that defines a pod disruption budget for the gateway. The following example allows gateway pods eviction only when at least 1 healthy gateway pod will remain on the cluster after the eviction:

    apiVersion: policy/v1
    kind: PodDisruptionBudget
    metadata:
      name: <gateway_name>
      namespace: <gateway_namespace>
    spec:
      minAvailable: 1
      selector:
        matchLabels:
          istio: <gateway_name>
    • spec.selector.matchLabels specifies the unique label or set of labels specified in the pod template of the gateway deployment created previously.
  13. Optional: Apply the YAML file by running the following command:

    $ oc apply -f gateway-pdb.yml

Chapter 2. Getting traffic into a mesh

Route external traffic to mesh services by configuring Istio gateway proxies and exposing them through LoadBalancer services or OpenShift routes.

2.1. About ingress traffic routing approaches

Red Hat OpenShift Service Mesh offers two approaches to configure ingress traffic routing to services in the mesh. The approach depends on the service mesh deployment mode and traffic management requirements.

Ingress routing with gateway injection and Istio APIs
When you install a gateway by using gateway injection, you can configure it to receive ingress traffic by using the Istio Gateway and VirtualService resources in combination.

The gateway injection approach is compatible with sidecar-based service mesh deployments where you enable sidecar injection in namespaces by using the istio-injection=enabled label or the istio.io/rev=<revision> label.

Ingress routing with Kubernetes Gateway API
The Kubernetes Gateway API provides a standardized approach for configuring ingress traffic routing using native Kubernetes resources. With this approach, you use Gateway and HTTPRoute (or GRPCRoute) resources to configure how traffic enters the mesh and routes to services.

While Istio Gateway and VirtualService resources support certain ingress use cases in ambient mode, the recommended approach is to use the Kubernetes Gateway API, which provides full support and integration with ambient. You can also use the Gateway API with sidecar-based deployments.

2.2. Exposing a service by using the Istio Gateway and VirtualService resources

Expose mesh services to external traffic by configuring injected gateways with Istio Gateway and VirtualService resources to route traffic from outside the cluster.

Note

You can set the gateway Service type to LoadBalancer to allow traffic from outside the cluster.

Prerequisites

  • You have installed Istio gateways using gateway injection.
  • You are using the Istio Gateway and VirtualService resources.
  • You have existing VirtualService configurations and do not plan on migrating to ambient mode.

Procedure

  1. Create namespace called httpbin by running the following command:

    $ oc create namespace httpbin
  2. Enable sidecar injection in the namespace. If you are using the InPlace upgrade strategy, run the following command:

    $ oc label namespace httpbin istio-injection=enabled
    Note

    If you are using the RevisionBased upgrade strategy, run the following commands:

    1. To find your <revision-name>, run the following command:

      $ oc get istiorevisions.sailoperator.io

      You should see output similar to the following example:

      NAME      TYPE    READY   STATUS    IN USE   VERSION   AGE
      default   Local   True    Healthy   True    v1.24.3   3m33s
    2. Label the namespace with the revision name to enable sidecar injection:

      $ oc label namespace httpbin istio.io/rev=default
  3. Deploy a sample service named httpbin by running the following command:

    $ oc apply -n httpbin -f https://raw.githubusercontent.com/openshift-service-mesh/istio/refs/heads/master/samples/httpbin/httpbin.yaml
  4. Create a YAML file named httpbin-gw.yaml that defines an Istio Gateway resource. This resource configures gateway proxies to expose port 80 (HTTP) for the host, httpbin.example.com.

    You can see the following example configuration for reference:

    apiVersion: networking.istio.io/v1
    kind: Gateway
    metadata:
      name: httpbin-gateway
      namespace: httpbin
    spec:
      selector:
        istio: <gateway_name>
      servers:
      - port:
          number: 80
          name: http
          protocol: HTTP
        hosts:
        - httpbin.example.com
    • spec.selector specifies the unique label or set of labels in the pod template of the gateway proxy Deployment. By default, the Istio Gateway resource configuration will apply to matching gateway pods in all namespaces.
    • spec.servers.hosts specifies a list of addresses that the clients use when attempting to access a mesh service at the associated port.
  5. Apply the YAML file by running the following command:

    $ oc apply -f httpbin-gw.yaml
  6. Create a YAML file named httpbin-vs.yaml for a VirtualService. The VirtualService defines the rules that route traffic from the gateway proxy to the httpbin service.

    You can see the following example configuration for reference:

    apiVersion: networking.istio.io/v1
    kind: VirtualService
    metadata:
      name: httpbin
      namespace: httpbin
    spec:
      hosts:
      - httpbin.example.com
      gateways:
      - httpbin-gateway
      http:
      - match:
        - uri:
            prefix: /status
        - uri:
            prefix: /headers
        route:
        - destination:
            port:
              number: 8000
            host: httpbin
    • spec.hosts the destination hosts for the VirtualService routing rules. The Istio Gateway resource must expose the hosts that you bind to the VirtualService.
    • spec.gateways binds the VirtualService to the Istio Gateway resource created in the previous step by adding the Gateway name to the list of gateways.
    • spec.http.route route matching traffic to the httpbin service deployed earlier by defining a destination that includes the host and port of the httpbin Service.
  7. Apply the YAML file by running the following command:

    $ oc apply -f httpbin-vs.yaml
  8. For verification purposes, create a namespace for a curl client by running the following command:

    $ oc create namespace curl
  9. Deploy the curl client by running the following command:

    $ oc apply -n curl -f https://raw.githubusercontent.com/openshift-service-mesh/istio/refs/heads/master/samples/curl/curl.yaml
  10. Set a CURL_POD variable with the name of the curl pod by running the following command:

    $ CURL_POD=$(oc get pods -n curl -l app=curl -o jsonpath='{.items[*].metadata.name}')
  11. Using the curl client, send a request to the /headers endpoint of the httpbin application through the ingress gateway Service resource. Set the Host header of the request to httpbin.example.com to match the host that the Istio Gateway and VirtualService resources specify. Run the following curl command to send the request:

    $ oc exec $CURL_POD -n curl -- \
      curl -s -I \
        -H Host:httpbin.example.com \
        <gateway_name>.<gateway_namespace>.svc.cluster.local/headers
  12. The response should have a 200 OK HTTP status indicating that the request was successful.

    HTTP/1.1 200 OK
    server: istio-envoy
    ...
  13. Send a curl request to an endpoint that does not have a corresponding URI prefix match defined in the httpbin VirtualService by running the following command:

    $ oc exec $CURL_POD -n curl -- \
      curl -s -I \
        -H Host:httpbin.example.com \
        <gateway_name>.<gateway_namespace>.svc.cluster.local/get

    The response should return a 404 Not Found status as the httpbin VirtualService resource lacks a matching URI prefix for the /get endpoint.

    HTTP/1.1 404 Not Found
    server: istio-envoy
    ...
  14. Expose the gateway proxy to traffic outside the cluster by setting the Service type to LoadBalancer:

    $ oc patch service <gateway_name> -n <gateway_namespace> -p '{"spec": {"type": "LoadBalancer"}}'
    Note

    OpenShift Routes can also expose a gateway to traffic outside the cluster. For more information, see "Exposing a gateway to traffic outside the cluster using OpenShift Routes".

  15. Verify that you can access the httpbin service from outside the cluster when using the external hostname or IP address of the gateway Service resource. Ensure that you set the INGRESS_HOST variable appropriately for the environment that your cluster is running in.

    1. If the cluster runs on AWS, set the INGRESS_HOST variable by running the following command:

      $ INGRESS_HOST=$(oc get service <gateway_name> -n <gateway_namespace> -o jsonpath='{.status.loadBalancer.ingress[0].hostname}')
    2. If the cluster runs on GCP or Azure, set the INGRESS_HOST variable by running the following command:

      $ INGRESS_HOST=$(oc get service <gateway_name> -n <gateway_namespace> -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
    3. Send a curl request to the httpbin service using the host of the gateway by running the following command:

      $ curl -s -I -H Host:httpbin.example.com http://$INGRESS_HOST/headers
  16. Verify that the response has the HTTP/1.1 200 OK status, which indicates that the request was successful.

2.3. About exposing services to traffic outside a cluster

To enable traffic from outside an OpenShift cluster to access services in a mesh, you must expose a gateway proxy by either setting its Service type to LoadBalancer or by using the OpenShift Router.

Using Kubernetes load balancing to handle incoming traffic directly through the inbound gateway can reduce latency associated with data encryption. By managing encryption at the inbound gateway, you avoid the intermediate decryption and re-encryption steps within the mesh that often add latency. This approach encrypts and decrypts mesh traffic only once, which is generally more efficient.

The OpenShift Router provides a standard approach for managing ingress traffic, and you can use the router to manage certificates for all cluster ingress traffic by using the same methods. However, the OpenShift Router introduces an additional hop between the inbound traffic and the mesh applications. Typically, you route the traffic by decrypting it at the router and then re-encrypting it at the service mesh ingress gateway, which introduces latency.

2.3.1. Exposing a gateway to traffic outside the cluster by using OpenShift Routes

You can expose a gateway to traffic outside the cluster by using OpenShift Routes. This approach provides an alternative to using Kubernetes LoadBalancer service when you have to expose gateways to traffic outside the cluster.

Prerequisites

  • You have completed the procedure, "Exposing a Service by using the Istio Gateway and VirtualService resources".

Procedure

  1. Ensure that you set the Service type to ClusterIP by running the following command:

    $ oc patch service <gateway_name> -n <gateway_namespace> -p '{"spec": {"type": "ClusterIP"}}'
  2. Create a YAML file named httpbin-route.yaml that defines a Route for the httpbin service similar to the following example:

    apiVersion: route.openshift.io/v1
    kind: Route
    metadata:
      name: httpbin
      namespace: <gateway_namespace>
    spec:
      host: httpbin.example.com
      port:
        targetPort: http2
      to:
        kind: Service
        name: <gateway_name>
        weight: 100
      wildcardPolicy: None
  3. Apply the YAML file by running the following command:

    $ oc apply -f httpbin-route.yaml
  4. Verify that you can access the httpbin service from outside the cluster through the ingress router. Ensure that you set the INGRESS_HOST variable appropriately for the environment that your cluster is running in.

    1. If the cluster runs on AWS, set the INGRESS_HOST variable by running the following command:

      $ INGRESS_HOST=$(oc get service router-default -n openshift-ingress -o jsonpath='{.status.loadBalancer.ingress[0].hostname}')
    2. If the cluster runs on GCP or Azure, set the INGRESS_HOST variable by running the following command:

      $ INGRESS_HOST=$(oc get service router-default -n openshift-ingress -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
    3. Send a curl request to the httpbin service using the host of the ingress router by running the following command:

      $ curl -s -I -H Host:httpbin.example.com http://$INGRESS_HOST/headers
  5. Verify that the response has the HTTP/1.1 200 OK status, which indicates that the request was successful.

2.4. Exposing a service by using the Kubernetes Gateway API in sidecar mode

You can use the Kubernetes Gateway API to create Gateway and HTTPRoute resources and deploy a gateway. The resources configure the gateway to expose a service in the mesh to traffic outside the mesh.

Prerequisites

  • You have logged in to the OpenShift Container Platform web console as a user with the cluster-admin role.
  • You installed the Red Hat OpenShift Service Mesh Operator.
  • You have deployed the Istio resource.

Procedure

  1. Create a namespace called httpbin by running the following command:

    $ oc create namespace httpbin
  2. When using sidecar injection instead of ambient mode, you must enable the sidecar injection in the namespace:

    1. For the InPlace upgrade strategy, run the following command:

      $ oc label namespace httpbin istio-injection=enabled
    2. For the RevisionBased upgrade strategy, run the following command:

      $ oc label namespace httpbin istio.io/rev=<revision-name>
  3. Deploy a sample service named httpbin by running the following command:

    $ oc apply -n httpbin -f https://raw.githubusercontent.com/openshift-service-mesh/istio/refs/heads/master/samples/httpbin/httpbin.yaml
  4. Create a YAML file named httpbin-gw.yaml that defines a Kubernetes Gateway resource, similar to the following example:

    apiVersion: gateway.networking.k8s.io/v1
    kind: Gateway
    metadata:
      name: httpbin-gateway
      namespace: httpbin
    spec:
      gatewayClassName: istio
      listeners:
      - name: default
        hostname: "httpbin.example.com"
        port: 80
        protocol: HTTP
        allowedRoutes:
          namespaces:
            from: All
    "httpbin.example.com"
    Specifies the virtual hostname that clients use when attempting to access a mesh service on the associated port.

    The HTTPRoute resource specifies the rules that route traffic from the gateway proxy to the httpbin service.

  5. Apply the YAML file by running the following command:

    $ oc apply -f httpbin-gw.yaml
  6. Create a YAML file named httpbin-ingress-hr.yaml that defines an HTTPRoute resource for the ingress gateway, similar to the following example:

    apiVersion: gateway.networking.k8s.io/v1
    kind: HTTPRoute
    metadata:
      name: httpbin-ingress
      namespace: httpbin
    spec:
      parentRefs:
      - name: httpbin-gateway
        namespace: httpbin
      hostnames:
      - "httpbin.example.com"
      rules:
      - matches:
        - path:
            type: PathPrefix
            value: /status
        - path:
            type: PathPrefix
            value: /headers
      - backendRefs:
        - name: httpbin
          port: 8000
    • spec.parentRefs binds the HTTPROUTE resource to the Kubernetes Gateway resource you created in the previous step.
    • spec.rules.backendRefs routes the matching traffic to the httpbin service by defining a backendRefs that includes the name and port of the httpbin service.

    The HTTPRoute resource specifies the rules that route traffic from the gateway proxy to the httpbin service.

  7. Apply the YAML file by running the following command:

    $ oc apply -f httpbin-ingress-hr.yaml
  8. Ensure that the Gateway API service is ready and has an allocated address by running the following command:

    $ oc wait --for=condition=programmed gtw httpbin-gateway -n httpbin

Verification

  1. Create a namespace for a curl client by running the following command:

    $ oc create namespace curl
  2. Deploy a curl client by running the following command:

    $ oc apply -n curl -f https://raw.githubusercontent.com/openshift-service-mesh/istio/refs/heads/master/samples/curl/curl.yaml
  3. Set a CURL_POD variable with the name of the curl pod by running the following command:

    $ CURL_POD=$(oc get pods -n curl -l app=curl -o jsonpath='{.items[*].metadata.name}')
  4. Using the curl client, send a request to the /headers endpoint of the httpbin application through the ingress gateway Service resource. Set the Host header of the request to httpbin.example.com to match the host that the Kubernetes Gateway and HTTPROUTE resources specify. Send the curl request by running the following command:

    $ oc exec $CURL_POD -n curl -- \
      curl -s -I \
        -H Host:httpbin.example.com \
        <gateway_name>-istio.<gateway_namespace>.svc.cluster.local/headers

    The response should return a 200 OK HTTP status, which indicates that the request was successful, similar to the following example:

    HTTP/1.1 200 OK
    server: istio-envoy
    ...
  5. Send a curl request to an endpoint that does not have a corresponding Uniform Resource Identifier (URI) prefix match defined in the httpbin HTTPROUTE by running the following command:

    $ oc exec $CURL_POD -n curl -- \
      curl -s -I \
        -H Host:httpbin.example.com \
        <gateway_name>-istio.<gateway_namespace>.svc.cluster.local/get

    The response returns a 404 Not Found status, as expected, because the /get endpoint does not have a matching URI prefix in the httpbin HTTPROUTE resource, similar to the following example:

    HTTP/1.1 404 Not Found
    server: istio-envoy
    ...
  6. Expose the gateway proxy to traffic outside the cluster by setting the Service type to LoadBalancer. Run the following command:

    $ oc patch service <gateway_name>-istio -n <gateway_namespace> -p '{"spec": {"type": "LoadBalancer"}}'
    Note

    OpenShift Routes can also expose a gateway to traffic outside the cluster. For more information, see "Exposing a gateway to traffic outside the cluster using OpenShift Routes".

  7. Verify that you can access the httpbin service from outside the cluster when using the external hostname or IP address of the gateway Service resource. Ensure that you set the INGRESS_HOST variable appropriately for the environment in which your cluster is running.

    1. Set the INGRESS_HOST variable by running the following command:

      $ export INGRESS_HOST=$(oc get gtw <gateway_name> -n <gateway_namespace> -o jsonpath='{.status.addresses[0].value}')
    2. Set the INGRESS_PORT variable by running the following command:

      $ INGRESS_PORT=$(oc get gtw <gateway_name> -n <gateway_namespace> -o jsonpath='{.spec.listeners[?(@.name=="http")].port}')
    3. Using the gateway host, send a curl request to the httpbin service by running the following command:

      $ curl -s -I -H Host:httpbin.example.com http://$INGRESS_HOST:$INGRESS_PORT/headers
  8. Verify that the response has the HTTP/1.1 200 OK status, which indicates that the request was successful.

2.5. About ingress traffic routing approaches in ambient mode

When using the Istio ambient mode, you can use the Kubernetes Gateway API to configure ingress traffic routing.

Waypoint proxies for Layer 7 routing
You can deploy a waypoint proxy in the namespace that has your service to apply Layer 7 (L7) routing policies, such as path-based routing or header matching. In ambient mode, waypoint proxies process L7 traffic and enforce HTTPRoute and GRPCRoute rules.
Important

Service Mesh classifies VirtualService resources as Technology Preview (TP) in ambient mode. Therefore, you should not mix them with Gateway API configuration. The recommended approach in ambient mode is to use Kubernetes Gateway API resources.

2.6. Exposing a service by using the Kubernetes Gateway API in ambient mode

You can use the Kubernetes Gateway API to create Gateway and HTTPRoute resources and deploy a gateway in ambient mode. The resources configure the gateway to expose a service in the mesh to traffic outside the mesh.

Prerequisites

  • You have logged in to the OpenShift Container Platform web console as a user with the cluster-admin role.
  • You have installed the Red Hat OpenShift Service Mesh Operator.
  • You have deployed the Istio resource.
  • You use the Kubernetes-native Gateway API resources.
  • You are either using the Istio ambient mode or planning on migrating to the ambient mode.
Note

Service Mesh recommends the Kubernetes Gateway API for ingress configuration in ambient mode (istio.io/dataplane-mode=ambient), because Istio Gateway and VirtualService resources lack full compatibility.

Procedure

  1. Create a namespace called httpbin by running the following command:

    $ oc create namespace httpbin
  2. Apply the label for ambient mode by running the following command:

    $ oc label namespace httpbin istio.io/dataplane-mode=ambient
  3. Deploy a sample service named httpbin by running the following command:

    $ oc apply -n httpbin -f https://raw.githubusercontent.com/openshift-service-mesh/istio/refs/heads/master/samples/httpbin/httpbin.yaml
  4. Deploy a waypoint proxy by creating a YAML file named httpbin-waypoint.yaml, similar to the following example:

    apiVersion: gateway.networking.k8s.io/v1
    kind: Gateway
    metadata:
      name: httpbin-waypoint
      namespace: httpbin
      labels:
        istio.io/waypoint-for: service
    spec:
      gatewayClassName: istio-waypoint
      listeners:
      - name: mesh
        port: 15008
        protocol: HBONE
  5. Apply the YAML file by running the following command:

    $ oc apply -f httpbin-waypoint.yaml
  6. Enable ingress waypoint routing on the httpbin service by running the following command:

    $ oc label service httpbin -n httpbin istio.io/ingress-use-waypoint=true

    The label ensures that the ingress gateway routes traffic through the waypoint proxy, which applies its Layer 7 (L7) policies to the traffic before it reaches the httpbin service.

  7. Apply the waypoint label to the namespace so that all the services inside the namespace routes through the waypoint, by running the following command:

    $ oc label ns httpbin istio.io/use-waypoint=httpbin-waypoint
  8. Create a YAML file named httpbin-gw.yaml that defines a Kubernetes Gateway resource. This resource configures gateway proxies to expose port 80 (HTTP) for the host, httpbin.example.com.

    apiVersion: gateway.networking.k8s.io/v1
    kind: Gateway
    metadata:
      name: httpbin-gateway
      namespace: httpbin
    spec:
      gatewayClassName: istio
      listeners:
      - name: default
        hostname: "httpbin.example.com"
        port: 80
        protocol: HTTP
        allowedRoutes:
          namespaces:
            from: All
    "httpbin.example.com"
    Specifies the virtual hostname that clients use when attempting to access a mesh service on the associated port.
  9. Apply the YAML file by running the following command:

    $ oc apply -f httpbin-gw.yaml
  10. Create a YAML file named httpbin-ingress-hr.yaml that defines an HTTPRoute resource for the ingress gateway, similar to the following example:

    apiVersion: gateway.networking.k8s.io/v1
    kind: HTTPRoute
    metadata:
      name: httpbin-ingress
      namespace: httpbin
    spec:
      parentRefs:
      - name: httpbin-gateway
        namespace: httpbin
      hostnames:
      - "httpbin.example.com"
      rules:
      - backendRefs:
        - name: httpbin
          port: 8000
    • spec.parentRefs binds the HTTPROUTE resource to the Kubernetes Gateway resource that you created in the previous step.
    • spec.rules.backendRefs routes the matching traffic to the httpbin service by defining a backendRefs that includes the name and port of the httpbin service.

    The HTTPRoute resource specifies the rules that route traffic from the gateway proxy to the httpbin service.

  11. Apply the YAML file by running the following command:

    $ oc apply -f httpbin-ingress-hr.yaml
  12. Create a YAML file named httpbin-waypoint-hr.yaml that defines an HTTPRoute resource for the waypoint proxy.

    apiVersion: gateway.networking.k8s.io/v1
    kind: HTTPRoute
    metadata:
      name: httpbin-waypoint-route
      namespace: httpbin
    spec:
      parentRefs:
      - group: ""
        kind: service
        name: httpbin
        namespace: httpbin
      rules:
      - matches:
        - path:
            type: PathPrefix
            value: /status
        - path:
            type: PathPrefix
            value: /headers
        backendRefs:
        - name: httpbin
          port: 8000
    • spec.parentRefs binds the HTTPRoute resource to the httpbin service. When combined with the istio.io/ingress-use-waypoint=true label on the service, the HTTPRoute configures the L7 routing rules that the waypoint proxy will enforce for traffic destined to that service.
    • spec.rules.backendRefs routes the matching traffic to the httpbin service by defining a backendRefs that includes the name and port of the httpbin service.
  13. Apply the YAML file by running the following command:

    $ oc apply -f httpbin-waypoint-hr.yaml
    Note

    In this example use case, traffic from the ingress gateway flows through the waypoint proxy because of the istio.io/ingress-use-waypoint=true label. The HTTPRoute resource then applies path-based routing policies before the traffic reaches the httpbin service.

  14. Ensure that the waypoint proxy is ready by running the following command:

    $ oc wait --for=condition=programmed gtw httpbin-waypoint -n httpbin

Verification

  1. Create a namespace for a curl client by running the following command:

    $ oc create namespace curl
  2. Deploy a curl client by running the following command:

    $ oc apply -n curl -f https://raw.githubusercontent.com/openshift-service-mesh/istio/refs/heads/master/samples/curl/curl.yaml
  3. Apply the label for ambient mode to the curl namespace by running the following command:

    $ oc label namespace curl istio.io/dataplane-mode=ambient
  4. Set a CURL_POD variable with the name of the curl pod by running the following command:

    $ CURL_POD=$(oc get pods -n curl -l app=curl -o jsonpath='{.items[*].metadata.name}')
  5. Using the curl client, send a request to the /headers endpoint of the httpbin application through the ingress gateway Service resource. Set the Host header of the request to httpbin.example.com to match the host that the Kubernetes Gateway and HTTPROUTE resources specify. Send the curl request by running the following command:

    $ oc exec $CURL_POD -n curl -- \
      curl -s -I \
        -H Host:httpbin.example.com \
        httpbin-gateway-istio.httpbin.svc.cluster.local/headers

    The response should return a 200 OK HTTP status, which indicates that the request was successful, similar to the following example:

    HTTP/1.1 200 OK
    server: istio-envoy
    ...
  6. Send a curl request to an endpoint that does not have a corresponding Uniform Resource Identifier (URI) prefix match defined in the httpbin HTTPROUTE by running the following command:

    $ oc exec $CURL_POD -n curl -- \
      curl -s -I \
        -H Host:httpbin.example.com \
        httpbin-gateway-istio.httpbin.svc.cluster.local/get

    The response returns a 404 Not Found status, as expected, because the /get endpoint does not have a matching URI prefix in the httpbin HTTPROUTE resource, similar to the following example:

    HTTP/1.1 404 Not Found
    server: istio-envoy
    ...
  7. Expose the gateway proxy to traffic outside the cluster by setting the Service type to LoadBalancer. Run the following command:

    $ oc patch service httpbin-gateway-istio -n httpbin -p '{"spec": {"type": "LoadBalancer"}}'
    Note

    OpenShift Routes can also expose a gateway to traffic outside the cluster. For more information, see "Exposing a gateway to traffic outside the cluster using OpenShift Routes".

  8. Verify that the you can access the httpbin service from outside the cluster when using the external hostname or IP address of the gateway Service resource. Ensure that you set the INGRESS_HOST variable appropriately for the environment in which your cluster is running.

    1. Set the INGRESS_HOST variable by running the following command:

      $ export INGRESS_HOST=$(oc get gtw httpbin-gateway -n httpbin -o jsonpath='{.status.addresses[0].value}')
    2. Set the INGRESS_PORT variable by running the following command:

      $ INGRESS_PORT=$(oc get gtw httpbin-gateway -n httpbin -o jsonpath='{.spec.listeners[?(@.name=="http")].port}')
    3. Using the gateway host, send a curl request to the httpbin service by running the following command:

      $ curl -s -I -H Host:httpbin.example.com http://$INGRESS_HOST:$INGRESS_PORT/headers
  9. Verify that the response has the HTTP/1.1 200 OK status, which indicates that the request was successful.

2.7. Additional resources

Chapter 3. Directing outbound traffic through a gateway

Using Istio APIs, you configure gateway proxies, installed through gateway injection, to direct traffic bound for an external service.

3.1. About directing egress traffic through a gateway

You can configure a gateway installed through gateway injection as an exit point for traffic leaving the service mesh. It acts as a forward proxy for requests sent to services external to the mesh.

Egress gateway

An egress gateway acts as a forward proxy and serves as the exit point for traffic exiting the service mesh toward external services. You can configure an egress gateway to fulfill security requirements:

  • Traffic Restrictions: In environments with strict traffic restrictions, an egress gateway ensures all outbound traffic flows through a dedicated set of nodes.
  • Network Policy Enforcement: When network policies prevent application nodes from directly accessing external services, the egress gateway handles the external access.

In these scenarios, you deploy gateway proxies on dedicated egress nodes that can access external services. You can then enforce strict network policies or add monitoring to these nodes to enhance security.

Configure egress traffic

You can configure a gateway installed through gateway injection to direct the egress traffic by combining the following Istio resources:

  • The ServiceEntry adds the external service to the Istio service registry. You can then apply Istio features, such as monitoring and routing rules, to traffic heading toward that external service.
  • Use the Gateway, VirtualService, and DestinationRule resources to set up rules that route traffic from the mesh to the external service using the gateway proxy.
Egress routing in ambient mode

If your deployment uses ambient mode, you must configure egress routing using the Kubernetes Gateway API instead of Istio Gateway and VirtualService resources. The Kubernetes Gateway API provides a standardized, Kubernetes-native method for defining how traffic exits the mesh and reaches external services.

You can use Gateway and HTTPRoute (or GRPCRoute) resources to route mesh traffic to destinations outside the cluster. Service Mesh fully supports the Gateway API in ambient mode, and you can also use it with sidecar-based deployments, providing a consistent configuration model for both ingress and egress routing.

3.2. Directing egress traffic through a gateway using Istio APIs

Use Istio APIs to direct outbound HTTP traffic through a gateway that you installed using gateway injection.

Prerequisites

  • You have installed a gateway using gateway injection.

Procedure

  1. Create a namespace called curl by running the following command:

    $ oc create namespace curl
  2. Depending on the update strategy you are using, enable sidecar injection in the namespace by running the appropriate commands:

    1. If you are using the InPlace update strategy, run the following command:

      $ oc label namespace curl istio-injection=enabled
    2. If you are using the RevisionBased update strategy, run the following commands:

      1. Display the revision name by running the following command:

        $ oc get istiorevisions.sailoperator.io

        You should see output similar to the following example:

        NAME     TYPE    READY   STATUS    IN USE   VERSION   AGE
        default  Local   True    Healthy   True     v1.24.3   3m33s
      2. Label the namespace with the revision name to enable sidecar injection by running the following command:

        $ oc label namespace curl istio.io/rev=default
  3. Deploy a curl application by running the following command:

    $ oc apply -n curl -f https://raw.githubusercontent.com/openshift-service-mesh/istio/refs/heads/master/samples/curl/curl.yaml
  4. Export a CURL_POD environment variable and initialize it with the name of the curl pod by running the following command:

    $ export CURL_POD=$(oc get pod -n curl -l app=curl -o jsonpath='{.items[0].metadata.name}')
  5. Create a YAML file named http-se.yaml that directs traffic from the mesh to an external service. The following example defines a ServiceEntry for a URL:

    apiVersion: networking.istio.io/v1
    kind: ServiceEntry
    metadata:
      name: egress-se
      namespace: curl
    spec:
      hosts:
        - docs.redhat.com
      ports:
        - number: 80
          name: http-port
          protocol: HTTP
      location: MESH_EXTERNAL
      resolution: DNS
  6. Apply the YAML file by running the following command:

    $ oc apply -f http-se.yaml
  7. Ensure that you applied the ServiceEntry configuration correctly. Send an HTTP request to the host that you specified in the previous step by running the following command:

    $ oc exec "$CURL_POD" -n curl -c curl -- curl -sSL -o /dev/null -D - http://docs.redhat.com

    This command should return HTTP status codes, such as 301 (redirect) or 200 (success), indicating that the connection works.

  8. Create a YAML file named http-gtw.yaml that creates an egress Gateway and routes traffic from the mesh to the host specified for the external service, similar to the following example:

    apiVersion: networking.istio.io/v1alpha3
    kind: Gateway
    metadata:
      name: egress-gw
      namespace: <gateway_namespace> # Namespace where the egress gateway is deployed
    spec:
      selector:
        istio: <gateway_name> # Selects the egress-gateway instance to handle this traffic
      servers:
        - port:
            number: 80
            name: http
            protocol: HTTP
          hosts:
            - docs.redhat.com # External service host, not a full URL.
    ---
    apiVersion: networking.istio.io/v1alpha3
    kind: DestinationRule
    metadata:
      name: egress-dr
      namespace: <gateway_namespace> # Namespace where the egress gateway is deployed
    spec:
      host: <gateway_name>.<gateway_namespace>.svc.cluster.local
      subsets:
        - name: rh-docs
  9. Apply the YAML file by running the following command:

    $ oc apply -f http-gtw.yaml
  10. Create a YAML file named http-vs.yaml that sets up a VirtualService to manage the flow of traffic from the application sidecars through the egress gateway to the external host, similar to the following example:

    apiVersion: networking.istio.io/v1alpha3
    kind: VirtualService
    metadata:
      name: egress-vs
      namespace: curl # Namespace where the curl pod is running
    spec:
      hosts:
        - docs.redhat.com # External service host, not a full URL.
      gateways:
        - mesh
        - <gateway_namespace>/egress-gw # Egress gateway name defined in the file that you used in the previous step.
      http:
        - match:
            - gateways:
                - mesh
              port: 80
          route:
            - destination:
                host: <gateway_name>.<gateway_namespace>.svc.cluster.local
                subset: rh-docs
                port:
                  number: 80
              weight: 100
        - match:
            - gateways:
                - <gateway_namespace>/egress-gw # Egress gateway name defined in the file that you used in the previous step.
              port: 80
          route:
            - destination:
                host: docs.redhat.com
                port:
                  number: 80
              weight: 100
  11. Apply the YAML file by running the following command:

    $ oc apply -f http-vs.yaml
  12. Resend the HTTP request to the URL:

    $ oc exec "$CURL_POD" -n curl -c curl -- curl -sSL -o /dev/null -D - http://docs.redhat.com

    The terminal should display information similar to the following output:

    ...
    HTTP/1.1 301 Moved Permanently
    ...
    location: <example_url>
    ...
    
    HTTP/2 200
    Content-Type: text/html; charset=utf-8
  13. Ensure that the gateway routed the request by running the following command:

    $ oc logs deployment/<gateway_name> -n <gateway_namespace> | tail -1
    Note

    You must enable access logging for this verification step to work. You can enable access logging to the standard output by setting the spec.values.meshConfig.accessLogFile field to /dev/stdout in the Istio resource.

    The terminal should display information similar to the following output:

    [2024-11-07T14:35:52.428Z] "GET / HTTP/2" 301 - via_upstream - "-" 0 0 24 24 "10.128.2.30" "curl/8.11.0" "79551af2-341b-456d-b414-9220b487a03b" "docs.redhat.com" "23.55.176.201:80" outbound|80||docs.redhat.com 10.128.2.29:49766 10.128.2.29:80 10.128.2.30:38296 -

3.3. Directing egress traffic through a gateway by using the Kubernetes Gateway API

Use the Kubernetes Gateway API to direct outbound HTTP traffic through an egress gateway.

Prerequisites

  • You installed an Istio control plane.
  • You configured the Istio and IstioCNI resources.

Procedure

  1. Optional: Enable the Kubernetes Gateway API custom resource definitions (CRDs).

    Note

    As of Kubernetes 1.28 and OpenShift Container Platform 4.18 or earlier version of Red Hat OpenShift Service Mesh, the Kubernetes Gateway API CRDs are not available by default and you must install the CRDs before you can use them. OpenShift Container Platform 4.19 and later versions install the CRDs by default.

    1. Create a YAML file named gateway-cr.yaml that enables the Kubernetes Gateway API CRDs, similar to the following example:

      apiVersion: gateway.networking.k8s.io/v1
      kind: Gateway
      metadata:
        name: bookinfo-gateway
      spec:
        gatewayClassName: istio
        listeners:
        - name: http
          port: 80
          protocol: HTTP
          allowedRoutes:
            namespaces:
              from: Same
      ---
      apiVersion: gateway.networking.k8s.io/v1
      kind: HTTPRoute
      metadata:
        name: bookinfo
      spec:
        parentRefs:
        - name: bookinfo-gateway
        rules:
        - matches:
          - path:
              type: Exact
              value: /productpage
          - path:
              type: PathPrefix
              value: /static
          - path:
              type: Exact
              value: /login
          - path:
              type: Exact
              value: /logout
          - path:
              type: PathPrefix
              value: /api/v1/products
          backendRefs:
          - name: productpage
            port: 9080
    2. Apply the YAML file by running the following command:

      $ oc apply -f gateway-cr.yaml
  2. Create a namespace called egress-gateway by running the following command:

    $ oc create namespace egress-gateway
  3. Apply the istio-injection label to the namespace by running the following command:

    $ oc label namespace egress-gateway istio-injection=enabled
  4. Create a YAML file named egress-gateway-cr.yaml that defines the egress gateway, similar to the following example:

    # ServiceEntry to allow traffic to httpbin.org
    apiVersion: networking.istio.io/v1
    kind: ServiceEntry
    metadata:
      name: httpbin-ext
    spec:
      hosts:
      - httpbin.org
      ports:
      - number: 80
        name: http
        protocol: HTTP
      location: MESH_EXTERNAL
      resolution: DNS
    ---
    # Gateway API Gateway for egress
    apiVersion: gateway.networking.k8s.io/v1
    kind: Gateway
    metadata:
      name: httpbin-egress-gateway
      annotations:
        networking.istio.io/service-type: ClusterIP
    spec:
      gatewayClassName: istio
      listeners:
      - name: http
        hostname: httpbin.org
        port: 80
        protocol: HTTP
        allowedRoutes:
          namespaces:
            from: Same
    ---
    # HTTPRoute to direct traffic from sidecars to the egress gateway
    apiVersion: gateway.networking.k8s.io/v1
    kind: HTTPRoute
    metadata:
      name: direct-httpbin-to-egress-gateway
    spec:
      parentRefs:
      - kind: ServiceEntry
        group: networking.istio.io
        name: httpbin-ext
      rules:
      - backendRefs:
        - name: httpbin-egress-gateway-istio
          port: 80
    ---
    # HTTPRoute to forward traffic from the egress gateway to httpbin.org
    apiVersion: gateway.networking.k8s.io/v1
    kind: HTTPRoute
    metadata:
      name: forward-httpbin-from-egress-gateway
    spec:
      parentRefs:
      - name: httpbin-egress-gateway
      hostnames:
      - httpbin.org
      rules:
      - backendRefs:
        - kind: Hostname
          group: networking.istio.io
          name: httpbin.org
          port: 80
    1. Apply the YAML file by running the following command:

      $ oc apply -f egress-gateway-cr.yaml

Verification

  1. Verify the status of the gateway configuration by running the following command:

    $ oc describe gateway -n egress-gateway

    The Status column displays Programmed to indicate the required output.

  2. Create a curl pod in the egress-gateway namespace by running the following command:

    $ oc run test-pod --image=curlimages/curl:latest -n egress-gateway --rm -it --restart=Never -- sh
  3. By using the curl client, verify that you can access httpbin.org through the egress gateway by entering following command:

    $ curl -v http://httpbin.org/get

    The required output shows a response from httpbin.org that indicates egress traffic routes through the configured gateway.

3.4. Directing egress traffic through a gateway using the Kubernetes Gateway API in ambient mode

Use the Kubernetes Gateway API and waypoint proxy to direct outbound HTTP traffic through an egress gateway.

Prerequisites

  • You have installed the OpenShift Service Mesh Operator version 3.2 or later.
  • You configured the Istio and IstioCNI resources with ambient profile.
  • You have created a Ztunnel resource.

Procedure

  1. Optional: Enable the {k8} Gateway API custom resource definitions (CRDs).

    Note

    As of Kubernetes 1.28 and OpenShift Container Platform 4.18 or earlier version of Red Hat OpenShift Service Mesh, the Kubernetes Gateway API CRDs are not available by default and you must install the CRDs before you can use them. OpenShift Container Platform 4.19 and later versions install the CRDs by default.

  2. Create a namespace called egress-gateway by running the following command:

    $ oc create namespace egress-gateway
  3. Apply the ambient mode label to the namespace by running the following command:

    $ oc label namespace egress-gateway istio.io/dataplane-mode=ambient
  4. Create a YAML file named egress-se.yaml that defines the ServiceEntry, similar to the following example:

    apiVersion: networking.istio.io/v1
    kind: ServiceEntry
    metadata:
      name: httpbin-ext
      namespace: egress-gateway
      labels:
        istio.io/use-waypoint: waypoint
    spec:
      hosts:
      - httpbin.org
      ports:
      - number: 80
        name: http
        protocol: HTTP
      resolution: DNS
    1. Apply the YAML file by running the following command:

      $ oc apply -f egress-se.yaml
    2. Create a YAML file named waypoint.yaml that creates a waypoint proxy in egress-gateway namespace similar to the following example:

      apiVersion: gateway.networking.k8s.io/v1
      kind: Gateway
      metadata:
        name: waypoint
        namespace: egress-gateway
        labels:
          istio.io/gateway-for: service
      spec:
        gatewayClassName: istio-waypoint
        listeners:
        - name: mesh
          port: 15008
          protocol: HBONE
    3. Apply the YAML file by running the following command:

      $ oc apply -f waypoint.yaml
      Note

      As an alternate to creating the waypoint.yaml YAML file, you can also set up waypoint proxy by running the following command:

      $ istioctl waypoint apply --enroll-namespace --name waypoint --namespace egress-gateway

      When you use the --enroll-namespace option, all services in the egress-gateway namespace (including ServiceEntries), will route their traffic through the waypoint.

Verification

  1. Verify the status of the gateway configuration by running the following command:

    $ oc get gateways.gateway.networking.k8s.io waypoint -n egress-gateway

    The PROGRAMMED column shows True when the configuration succeeds, similar to the following example:

    NAME       CLASS            ADDRESS          PROGRAMMED   AGE
    waypoint   istio-waypoint   172.30.227.148   True         9s
  2. Create a curl pod in the egress-gateway namespace by running the following command:

    $ oc run test-pod --image=curlimages/curl:latest -n egress-gateway --rm -it --restart=Never -- sh
  3. By using the curl client, verify that you can access httpbin.org through the egress gateway by running the following command:

    $ curl -v http://httpbin.org/get

    The output shows a response from httpbin.org service that indicates egress traffic routes through the configured gateway. The ztunnel logs should show traffic routed through the waypoint. The terminal should display information similar to the following output:

    2025-10-24T08:08:35.242159Z info access connection complete src.addr=[fd01:0:0:5::b0]:56288 src.workload="test-pod" src.namespace="egress-gateway" src.identity="spiffe://cluster.local/ns/egress-gateway/sa/default" dst.addr=[fd01:0:0:5::af]:15008 dst.hbone_addr=[2001:2::2]:80 dst.service="httpbin.org" dst.workload="waypoint-5b668759d5-vrnx8" dst.namespace="egress-gateway" dst.identity="spiffe://cluster.local/ns/egress-gateway/sa/waypoint" direction="outbound" bytes_sent=78 bytes_recv=540 duration="957ms"

3.5. Additional resources

Chapter 4. Configuring quantum secure gateways

Use the Kubernetes Gateway API with a post-quantum cryptographic algorithm to establish a secure ingress gateway.

4.1. Generating TLS certificates

Generate Transport Layer Security (TLS) certificates and create a secret to secure ingress traffic for a service mesh gateway.

Procedure

  1. Create a directory for your certificates by running the following command:

    $ mkdir certs
  2. Generate the certificates for your gateway similar to the following examples:

    • Create the first certificate by running the following command:

      $ openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 \
        -subj '/O=example Inc./CN=example.com' \
        -keyout certs/example.com.key \
        -out certs/example.com.crt
    • Create the second certificate by running the following command:

      $ openssl req -out certs/httpbin.example.com.csr -newkey rsa:2048 -nodes \
        -keyout certs/httpbin.example.com.key \
        -subj "/CN=httpbin.example.com/O=httpbin organization"
    • Create the third certificate by running the following command:

      $ openssl x509 -req -sha256 -days 365 \
        -CA certs/example.com.crt -CAkey certs/example.com.key \
        -set_serial 0 -in certs/httpbin.example.com.csr \
        -out certs/httpbin.example.com.crt
  3. Create a secret containing the TLS certificate for your gateway by running the following command:

    $ oc create -n istio-system secret tls httpbin-credential \
        --key=certs/httpbin.example.com.key \
        --cert=certs/httpbin.example.com.crt

4.2. Deploying quantum secure gateways

Configure and deploy a service mesh gateway by using the Kubernetes Gateway API to enable post-quantum cryptographic protection for ingress traffic.

Prerequisites

  • You have logged in to the OpenShift Container Platform web console 4.19+ as a user with the cluster-admin role.
  • You have installed the Red Hat OpenShift Service Mesh Operator 3.2.1+
  • You have created an Istio resource with PQC enabled, and the Operator has deployed Istio. For more information, see "Installing service mesh with post-quantum cryptography (PQC)".
  • You have installed the following CLI tools locally:

    • oc
    • podman
    • curl

Procedure

  1. Deploy a gateway using the Kubernetes Gateway API by running the following command:

    $ oc apply -f - <<EOF
    apiVersion: gateway.networking.k8s.io/v1beta1
    kind: Gateway
    metadata:
     name: pqc-gateway
     namespace: istio-system
    spec:
     gatewayClassName: istio
     listeners:
     - name: https
       port: 443
       protocol: HTTPS
       tls:
         mode: Terminate
         certificateRefs:
         - name: httpbin-credential
           namespace: istio-system
       allowedRoutes:
         namespaces:
           from: All
    ---
    apiVersion: gateway.networking.k8s.io/v1beta1
    kind: HTTPRoute
    metadata:
     name: httpbin-route
     namespace: default
    spec:
     parentRefs:
     - name: pqc-gateway
       namespace: istio-system
     hostnames:
     - "httpbin.example.com"
     rules:
     - matches:
       - path:
           type: PathPrefix
           value: /
       backendRefs:
       - name: httpbin
         port: 8000
    EOF
  2. Add the istio-injection=enabled label to the default namespace by running the following command:

    $ oc label ns default istio-injection=enabled
  3. Deploy the backend server by running the following command:

    $ oc apply -n default -f \
    https://raw.githubusercontent.com/openshift-service-mesh/istio/master/samples/httpbin/httpbin.yaml

4.3. Verifying quantum secure gateways

Verify the post-quantum gateway configuration by testing connections with both post-quantum cryptography (PQC)-enabled and standard clients to confirm that the gateway accepts only quantum-safe handshakes.

Procedure

  1. Retrieve the external address based on the type of load balancer:

    1. Retrieve the external address for your hostname-based load balancer by running the following command:

      $ INGRESS_ADDR=$(oc get svc pqc-gateway-istio \
      -n istio-system \
      -o jsonpath='{.status.loadBalancer.ingress[0].hostname}')
    2. Retrieve the external address for your IP-based load balancer by running the following command:

      $ INGRESS_ADDR=$(oc get svc pqc-gateway-istio \
      -n istio-system \
      -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
  2. Test the connection with the PQC-enabled client by running the following command:

    $ podman run --rm -it \
      -v ./certs/example.com.crt:/etc/certs/example.com.crt \
      docker.io/openquantumsafe/curl \
      curl -vk "https://$INGRESS_ADDR:443/headers" \
      -H "Host: httpbin.example.com" \
      --curves X25519MLKEM768 \
      --cacert /etc/certs/example.com.crt

    The request should succeed, and you should receive the HTTP status as 200.

  3. Verify that the connection fails with a standard curl client by running the following command:

    $ curl -vk "https://$INGRESS_ADDR:443/headers" \
      -H "Host: httpbin.example.com" \
      --cacert ./certs/example.com.crt

    You will get errors similar to the following example:

    * TLSv1.3 (OUT), TLS handshake, Client hello (1):
    * TLSv1.3 (IN), TLS alert, handshake failure (552):
    * TLS connect error: error:0A000410:SSL routines::ssl/tls alert handshake failure
    * closing connection #0
    curl: (35) TLS connect error: error:0A000410:SSL routines::ssl/tls alert handshake failure

4.4. Additional resources

Legal Notice

Copyright © Red Hat.
Except as otherwise noted below, the text of and illustrations in this documentation are licensed by Red Hat under the Creative Commons Attribution–Share Alike 3.0 Unported license . If you distribute this document or an adaptation of it, you must provide the URL for the original version.
Red Hat, as the licensor of this document, waives the right to enforce, and agrees not to assert, Section 4d of CC-BY-SA to the fullest extent permitted by applicable law.
Red Hat, the Red Hat logo, JBoss, Hibernate, and RHCE are trademarks or registered trademarks of Red Hat, LLC. or its subsidiaries in the United States and other countries.
Linux® is the registered trademark of Linus Torvalds in the United States and other countries.
XFS is a trademark or registered trademark of Hewlett Packard Enterprise Development LP or its subsidiaries in the United States and other countries.
The OpenStack® Word Mark and OpenStack logo are trademarks or registered trademarks of the Linux Foundation, used under license.
All other trademarks are the property of their respective owners.