Using kubernetes pulsar.streamnative.io with gateway.envoyproxy.io
TypeScriptTo integrate Apache Pulsar with an Envoy Proxy Gateway on Kubernetes, we need to define a Kubernetes service that represents a Pulsar broker and a corresponding Envoy Gateway configuration that routes traffic to this service. This setup involves creating multiple resources in your Kubernetes cluster, such as a Deployment, a Service, and an Ingress resource, possibly with custom annotations for Envoy, or using an Envoy-specific Custom Resource Definition (CRD) if needed.
First, you'd typically create a Deployment resource to deploy Apache Pulsar in the cluster. This will ensure that a given number of Pulsar replicas are maintained and scheduled across your nodes.
Next, a Service resource is created to allow network access to the Pulsar pods from within the Kubernetes cluster. The service will define a stable IP address and port that other services within the cluster can use to access Apache Pulsar.
Lastly, an Ingress resource, or an Envoy-specific CRD, is defined to forward external traffic into the services in the Kubernetes cluster. Ingress resources require an Ingress controller to be running in the cluster, and in this case, you'll be using Envoy Proxy as the controller.
Here's an example of a Pulumi program, written in TypeScript, that sets up these resources.
import * as k8s from "@pulumi/kubernetes"; const pulsarLabels = { app: "pulsar" }; // Deploy Apache Pulsar using a Deployment resource. const pulsarDeployment = new k8s.apps.v1.Deployment("pulsar-deployment", { spec: { selector: { matchLabels: pulsarLabels }, replicas: 2, template: { metadata: { labels: pulsarLabels }, spec: { containers: [ { name: "pulsar", image: "apachepulsar/pulsar:latest", ports: [{ name: "http", containerPort: 8080 }], }, ], }, }, }, }); // Create a Service to expose the Pulsar Deployment within the cluster. const pulsarService = new k8s.core.v1.Service("pulsar-service", { metadata: { labels: pulsarDeployment.metadata.labels }, spec: { type: "ClusterIP", ports: [{ port: 80, targetPort: "http" }], selector: pulsarLabels, }, }); // Define an Ingress to expose Pulsar Service to the internet via Envoy. const pulsarIngress = new k8s.networking.v1.Ingress("pulsar-ingress", { metadata: { // Here you can add annotations for Envoy if needed, such as custom configuration or filters. }, spec: { rules: [ { http: { paths: [ { path: "/", pathType: "Prefix", backend: { service: { name: pulsarService.metadata.name, port: { number: 80 }, }, }, }, ], }, }, ], }, }); // Export the service and ingress URLs so you can easily access them. export const pulsarServiceUrl = pulsarService.metadata.name.apply(name => `http://${name}.svc.cluster.local`); export const pulsarIngressUrl = pulsarIngress.status.loadBalancer.ingress[0].hostname.apply(hostname => `http://${hostname}`);
In this example, we're creating three major resources:
Deployment
: This manages the Pulsar pods, ensuring that we have the desired number of replicas running.Service
: By setting up a service, we create a stable endpoint within the Kubernetes cluster that will route traffic to the Pulsar pods managed by the Deployment.Ingress
: This defines rules for routing external HTTP(S) traffic to different backend services, such as the Pulsar service we have created.
You would need to ensure that Envoy Proxy is correctly configured to handle Ingress resources and that you have set up any necessary RBAC permissions for Envoy to interact with Kubernetes API.
Please replace
"apachepulsar/pulsar:latest"
with the appropriate Pulsar Docker image tag suited for your use case. Additionally, theports
,path
, and annotations within theIngress
resource may need to be adjusted according to your specific Envoy and Pulsar setup.Once your Pulumi program is ready, you would run it using the Pulumi CLI. Ensure you have the Kubernetes cluster context set correctly and then apply your Pulumi program as follows:
pulumi up
This command will prompt you with a preview of the resources that will be created or updated. Once you review the changes, confirm the prompt to proceed with the deployment.