Skip to main content
This guide explains how to deploy StreamNative Private Cloud on Kubernetes with Istio service mesh integration. Istio provides enhanced security, observability, and traffic management for your Pulsar cluster.

Why Use Istio with Pulsar

Deploying Pulsar with Istio provides:
  • Enhanced Security: Automatic mTLS encryption for service-to-service communication
  • Traffic Management: Advanced routing, load balancing, and traffic control
  • Observability: Built-in metrics, logging, and distributed tracing
  • External Access: Unified ingress gateway for all protocols (Pulsar, Kafka, MQTT, AMQP)
  • Policy Enforcement: Fine-grained authorization policies

Prerequisites

Istio Requirements

  1. Istio Installation: Istio installed in your Kubernetes cluster
    • Tested with Istio 1.24.2 and earlier versions
    • Use the default revision or adjust according to your Istio setup
    • Default trust domain is cluster.local, adjust if needed
  2. Istio Ingress Gateway: Must be installed and configured
    • Service type must be LoadBalancer
    • Required port mappings:
      • 443->8443: HTTP/HTTPS
      • 6651->6651: Pulsar with TLS
      • 9093->9093: Kafka with TLS
      • 5671->5671: AMQP with TLS
      • 8883->8883: MQTT with TLS

TLS Certificate

  • A TLS certificate secret exists in the Istio Ingress Gateway namespace
  • Covers your endpoint domain (e.g., pulsar.example.com)
  • Covers per-broker domains (e.g., pb0-pulsar.example.com, pb1-pulsar.example.com, etc.)
  • Alternative: A wildcard certificate is used (e.g., *.example.com)

DNS Configuration

  • DNS records point to the Ingress Gateway LoadBalancer IP
  • Main endpoint: pulsar.example.com
  • Per-broker endpoints: pb0-pulsar.example.com, pb1-pulsar.example.com, up to pb${replicas-1}-pulsar.example.com
  • Alternative: Wildcard DNS *.example.com is configured
If the StreamNative Operator is not Istio sidecar injected, configure the cloud.streamnative.io/ignore-leader-check: "true" annotation on the ZooKeeperCluster resource.

Deploy Pulsar Cluster

For a complete working example, see the Pulsar with Istio example in the StreamNative Private Cloud repository.

Istio-Specific Configuration

Add the following Istio configurations to your Pulsar components:

PulsarCoordinator

Configure the Istio revision and trust domain for the cluster:
spec:
  istio:
    revision: default
    trustDomain: cluster.local

ZooKeeperCluster

Enable Istio with mTLS:
spec:
  istio:
    enabled: true
    mtls:
      mode: strict
    revision: default
If the StreamNative Operator is not Istio sidecar injected, add this annotation:
metadata:
  annotations:
    cloud.streamnative.io/ignore-leader-check: "true"

BookKeeperCluster

Enable Istio with mTLS:
spec:
  istio:
    enabled: true
    mtls:
      mode: strict
    revision: default

PulsarBroker

Enable Istio with mTLS and Gateway configuration for external access:
spec:
  config:
    advertisedDomain: pulsar.example.com
    serviceURLGenerationPolicy: OrdinalPrefix
  istio:
    enabled: true
    mtls:
      mode: strict
    revision: default
    gateway:
      selector:
        istio: ingressgateway
      tls:
        certSecretName: "ingressgateway-tls"
        mode: "simple"
Key Istio Configuration Fields:
  • spec.istio.enabled: Enables Istio integration
  • spec.istio.mtls.mode: mTLS mode (strict, permissive, or none)
  • spec.istio.revision: Istio revision to use
  • spec.istio.gateway.selector: Label selector for the Istio Ingress Gateway
  • spec.istio.gateway.tls.certSecretName: Name of the TLS certificate secret
  • spec.istio.gateway.tls.mode: TLS mode (simple for standard TLS)
  • spec.config.advertisedDomain: Domain for external access
  • spec.config.serviceURLGenerationPolicy: Set to OrdinalPrefix for per-broker routing

Verify Deployment

Check Pod Status

Verify that all pods are running with Istio sidecars (2/2 containers):
kubectl get pods -n pulsar
Expected output:
NAME                          READY   STATUS    RESTARTS   AGE
private-cloud-bk-0            2/2     Running   0          5m
private-cloud-bk-1            2/2     Running   0          5m
private-cloud-bk-2            2/2     Running   0          5m
private-cloud-broker-0        2/2     Running   0          3m
private-cloud-broker-1        2/2     Running   0          3m
private-cloud-zk-0            2/2     Running   0          8m
private-cloud-zk-1            2/2     Running   0          8m
private-cloud-zk-2            2/2     Running   0          8m

Get Service Endpoints

Get the service endpoints from the PulsarBroker status:
kubectl get pulsarbroker private-cloud -n pulsar -o=jsonpath='{.status.serviceEndpoints.cluster}{"\n"}{.status.serviceEndpoints.external}'
Expected output:
{"pulsarServiceURL":"pulsar://private-cloud-broker.pulsar.svc.cluster.local:6650","webServiceURL":"http://private-cloud-broker.pulsar.svc.cluster.local:8080"}
{"pulsarServiceURL":"pulsar+ssl://pulsar.example.com:6651","webServiceURL":"https://pulsar.example.com"}
Internal Endpoints (within Kubernetes cluster):
  • Admin: http://private-cloud-broker.pulsar.svc.cluster.local:8080
  • Pulsar: pulsar://private-cloud-broker.pulsar.svc.cluster.local:6650
External Endpoints (outside Kubernetes cluster):
  • Admin: https://pulsar.example.com
  • Pulsar TLS: pulsar+ssl://pulsar.example.com:6651

Test Connectivity

Test Within Kubernetes Cluster

Test Pulsar using the toolset created by the StreamNative Operator or any Istio-injected pod:
kubectl exec -it -n pulsar private-cloud-toolset-0 -- bash

# List tenants
pulsar-admin --admin-url http://private-cloud-broker.pulsar.svc.cluster.local:8080 tenants list

# Consume messages
pulsar-client --url pulsar://private-cloud-broker.pulsar.svc.cluster.local:6650 \
  consume public/default/test -s sub1 -n 10

# Produce messages
pulsar-client --url pulsar://private-cloud-broker.pulsar.svc.cluster.local:6650 \
  produce public/default/test -m "hello" -n 10

Test Outside Kubernetes Cluster

Test Pulsar using TLS from outside the cluster:
# List tenants
pulsar-admin --admin-url https://pulsar.example.com tenants list

# Consume messages
pulsar-client --url pulsar+ssl://pulsar.example.com:6651 \
  consume public/default/test -s sub1 -n 10

# Produce messages
pulsar-client --url pulsar+ssl://pulsar.example.com:6651 \
  produce public/default/test -m "hello" -n 10

Enable Protocol Handlers

After deploying the base Pulsar cluster with Istio, you can enable additional protocol handlers: