Setup Eventing with OpenShift Service Mesh

Prerequisites
  • You have access to an OpenShift account with cluster administrator access.

  • You have created a project or have access to a project with the appropriate roles and permissions to create applications and other workloads in OpenShift.

  • Install the OpenShift Service Mesh Operator and create a ServiceMeshControlPlane resource in the istio-system namespace. If you want to use mTLS functionality, you must also set the spec.security.dataPlane.mtls field for the ServiceMeshControlPlane resource to true.

    Using OpenShift Serverless with Service Mesh is only supported with OpenShift Service Mesh version 2.0.5 or later.

  • Install the OpenShift Serverless Operator.

  • Install the OpenShift CLI (oc).

Procedure
  1. Add the namespaces that you would like to integrate with Service Mesh to the ServiceMeshMemberRoll object as members:

    apiVersion: maistra.io/v1
    kind: ServiceMeshMemberRoll
    metadata:
      name: default
      namespace: istio-system
    spec:
      members: (1)
        - knative-serving
        - knative-eventing
        - <namespace>
    1 A list of namespaces to be integrated with Service Mesh.

    This list of namespaces must include the knative-serving and knative-eventing namespaces.

  2. Apply the ServiceMeshMemberRoll resource:

    $ oc apply -f <filename>
  3. Create the necessary gateways so that Service Mesh can accept traffic:

    Example knative-local-gateway object using HTTP
    apiVersion: networking.istio.io/v1alpha3
    kind: Gateway
    metadata:
      name: knative-ingress-gateway
      namespace: knative-serving
    spec:
      selector:
        istio: ingressgateway
      servers:
        - port:
            number: 443
            name: https
            protocol: HTTPS
          hosts:
            - "*"
          tls:
            mode: SIMPLE
            credentialName: <wildcard_certs> (1)
    ---
    apiVersion: networking.istio.io/v1alpha3
    kind: Gateway
    metadata:
     name: knative-local-gateway
     namespace: knative-serving
    spec:
     selector:
       istio: ingressgateway
     servers:
       - port:
           number: 8081
           name: http
           protocol: HTTP (2)
         hosts:
           - "*"
    ---
    apiVersion: v1
    kind: Service
    metadata:
     name: knative-local-gateway
     namespace: istio-system
     labels:
       experimental.istio.io/disable-gateway-port-translation: "true"
    spec:
     type: ClusterIP
     selector:
       istio: ingressgateway
     ports:
       - name: http2
         port: 80
         targetPort: 8081
    1 Add the name of the secret that contains the wildcard certificate.
    2 The knative-local-gateway serves HTTP traffic. Using HTTP means that traffic coming from outside of Service Mesh, but using an internal hostname, such as example.default.svc.cluster.local, is not encrypted. You can set up encryption for this path by creating another wildcard certificate and an additional gateway that uses a different protocol spec.
    Example knative-local-gateway object using HTTPS
    apiVersion: networking.istio.io/v1alpha3
    kind: Gateway
    metadata:
      name: knative-local-gateway
      namespace: knative-serving
    spec:
      selector:
        istio: ingressgateway
      servers:
        - port:
            number: 443
            name: https
            protocol: HTTPS
          hosts:
            - "*"
          tls:
            mode: SIMPLE
            credentialName: <wildcard_certs>
  4. Apply the Gateway resources:

    $ oc apply -f <filename>
  5. Install Knative Serving by creating the following KnativeServing custom resource, which also enables the Istio integration:

    apiVersion: operator.knative.dev/v1beta1
    kind: KnativeServing
    metadata:
      name: knative-serving
      namespace: knative-serving
    spec:
      ingress:
        istio:
          enabled: true (1)
      deployments: (2)
      - name: activator
        annotations:
          "sidecar.istio.io/inject": "true"
          "sidecar.istio.io/rewriteAppHTTPProbers": "true"
      - name: autoscaler
        annotations:
          "sidecar.istio.io/inject": "true"
          "sidecar.istio.io/rewriteAppHTTPProbers": "true"
    1 Enables Istio integration.
    2 Enables sidecar injection for Knative Serving data plane pods.
  6. Apply the KnativeServing resource:

    $ oc apply -f <filename>
  7. Install Knative Eventing by creating the following KnativeEventing custom resource, which also enables the Istio integration:

    apiVersion: operator.knative.dev/v1beta1
    kind: KnativeEventing
    metadata:
      name: knative-eventing
      namespace: knative-eventing
    spec:
      config:
        features:
          istio: enabled (1)
      workloads: (2)
      - name: pingsource-mt-adapter
        annotations:
          "sidecar.istio.io/inject": "true"
          "sidecar.istio.io/rewriteAppHTTPProbers": "true"
      - name: imc-dispatcher
        annotations:
          "sidecar.istio.io/inject": "true"
          "sidecar.istio.io/rewriteAppHTTPProbers": "true"
      - name: mt-broker-ingress
        annotations:
          "sidecar.istio.io/inject": "true"
          "sidecar.istio.io/rewriteAppHTTPProbers": "true"
      - name: mt-broker-filter
        annotations:
          "sidecar.istio.io/inject": "true"
          "sidecar.istio.io/rewriteAppHTTPProbers": "true"
    1 Enables Eventing istio controller to create a DestinationRule for each InMemoryChannel or KafkaChannel service.
    2 Enables sidecar injection for Knative Eventing pods.
  8. Apply the KnativeEventing resource:

    $ oc apply -f <filename>
  9. Install Knative Kafka by creating the following KnativeKafka custom resource, which also enables the Istio integration:

    apiVersion: operator.serverless.openshift.io/v1alpha1
    kind: KnativeKafka
    metadata:
      name: knative-kafka
      namespace: knative-eventing
    spec:
      channel:
        enabled: true
        bootstrapServers: <bootstrap_servers> (1)
      source:
        enabled: true
      broker:
        enabled: true
        defaultConfig:
          bootstrapServers: <bootstrap_servers> (1)
          numPartitions: <num_partitions>
          replicationFactor: <replication_factor>
        sink:
          enabled: true
      workloads: (2)
      - name: kafka-controller
        annotations:
          "sidecar.istio.io/inject": "true"
          "sidecar.istio.io/rewriteAppHTTPProbers": "true"
      - name: kafka-broker-receiver
        annotations:
          "sidecar.istio.io/inject": "true"
          "sidecar.istio.io/rewriteAppHTTPProbers": "true"
      - name: kafka-broker-dispatcher
        annotations:
          "sidecar.istio.io/inject": "true"
          "sidecar.istio.io/rewriteAppHTTPProbers": "true"
      - name: kafka-channel-receiver
        annotations:
          "sidecar.istio.io/inject": "true"
          "sidecar.istio.io/rewriteAppHTTPProbers": "true"
      - name: kafka-channel-dispatcher
        annotations:
          "sidecar.istio.io/inject": "true"
          "sidecar.istio.io/rewriteAppHTTPProbers": "true"
      - name: kafka-source-dispatcher
        annotations:
          "sidecar.istio.io/inject": "true"
          "sidecar.istio.io/rewriteAppHTTPProbers": "true"
      - name: kafka-sink-receiver
        annotations:
          "sidecar.istio.io/inject": "true"
          "sidecar.istio.io/rewriteAppHTTPProbers": "true"
    1 The Apache Kafka cluster URL, for example: my-cluster-kafka-bootstrap.kafka:9092.
    2 Enables sidecar injection for Knative Kafka pods.
  10. Apply the KnativeKafka resource:

    $ oc apply -f <filename>
  11. Install ServiceEntry to make OpenShift Service Mesh aware of the communication between KnativeKafka components and an Apache Kafka cluster:

    apiVersion: networking.istio.io/v1alpha3
    kind: ServiceEntry
    metadata:
      name: kafka-cluster
      namespace: knative-eventing
    spec:
      hosts: (1)
        - <bootstrap_servers_without_port>
      exportTo:
        - "."
      ports: (2)
        - number: 9092
          name: tcp-plain
          protocol: TCP
        - number: 9093
          name: tcp-tls
          protocol: TCP
        - number: 9094
          name: tcp-sasl-tls
          protocol: TCP
        - number: 9095
          name: tcp-sasl-tls
          protocol: TCP
        - number: 9096
          name: tcp-tls
          protocol: TCP
      location: MESH_EXTERNAL
      resolution: NONE
    1 The list of Apache Kafka cluster hosts, for example: my-cluster-kafka-bootstrap.kafka.
    2 Apache Kafka cluster listeners ports.

    The listed ports in spec.ports are example TPC ports and depend on how the Apache Kafka cluster is configured.

  12. Apply the ServiceEntry resource:

    $ oc apply -f <filename>
Verification
  1. Create a Knative Service that has sidecar injection enabled and uses a pass-through route:

    apiVersion: serving.knative.dev/v1
    kind: Service
    metadata:
      name: <service_name>
      namespace: <namespace> (1)
      annotations:
        serving.knative.openshift.io/enablePassthrough: "true" (2)
    spec:
      template:
        metadata:
          annotations:
            sidecar.istio.io/inject: "true" (3)
            sidecar.istio.io/rewriteAppHTTPProbers: "true"
        spec:
          containers:
          - image: <image_url>
    1 A namespace that is part of the Service Mesh member roll.
    2 Instructs Knative Serving to generate an OpenShift pass-through enabled route, so that the certificates you have generated are served through the ingress gateway directly.
    3 Injects Service Mesh sidecars into the Knative service pods.
  2. Apply the Service resource:

    $ oc apply -f <filename>
  3. Access your serverless application by using a secure connection that is now trusted by the CA:

    $ curl --cacert root.crt <service_url>
    Example command
    $ curl --cacert root.crt https://hello-default.apps.openshift.example.com
    Example output
    Hello Openshift!