{"id":19704830,"url":"https://github.com/datastax/pulsar-helm-chart","last_synced_at":"2025-09-10T08:38:50.997Z","repository":{"id":37823371,"uuid":"323941346","full_name":"datastax/pulsar-helm-chart","owner":"datastax","description":"Apache Pulsar Helm chart","archived":false,"fork":false,"pushed_at":"2025-01-09T04:51:51.000Z","size":1709,"stargazers_count":46,"open_issues_count":46,"forks_count":37,"subscribers_count":12,"default_branch":"master","last_synced_at":"2025-01-10T12:03:37.511Z","etag":null,"topics":["helm-chart","pulsar","pulsar-cluster","pulsar-heartbeat"],"latest_commit_sha":null,"homepage":"","language":"Mustache","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/datastax.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-12-23T15:46:15.000Z","updated_at":"2024-11-20T21:02:07.000Z","dependencies_parsed_at":"2023-10-27T18:15:13.806Z","dependency_job_id":"1ef4ea6b-b23e-4e5e-aa0a-f3ac182ec711","html_url":"https://github.com/datastax/pulsar-helm-chart","commit_stats":null,"previous_names":[],"tags_count":46,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/datastax%2Fpulsar-helm-chart","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/datastax%2Fpulsar-helm-chart/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/datastax%2Fpulsar-helm-chart/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/datastax%2Fpulsar-helm-chart/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/datastax","download_url":"https://codeload.github.com/datastax/pulsar-helm-chart/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":241020207,"owners_count":19895390,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["helm-chart","pulsar","pulsar-cluster","pulsar-heartbeat"],"created_at":"2024-11-11T21:24:42.632Z","updated_at":"2025-09-10T08:38:50.983Z","avatar_url":"https://github.com/datastax.png","language":"Mustache","funding_links":[],"categories":["Get Pulsar"],"sub_categories":["Self-managed"],"readme":"[![GitHub](https://avatars1.githubusercontent.com/u/9919?s=30\u0026v=4)](https://github.com/datastax/pulsar-helm-chart) \n[![CircleCI](https://circleci.com/gh/datastax/pulsar-helm-chart.svg?style=svg)](https://circleci.com/gh/datastax/pulsar-helm-chart)\n[![LICENSE](https://img.shields.io/hexpm/l/pulsar.svg)](https://github.com/datastax/pulsar-helm-chart/blob/master/LICENSE)\n\n# [DEPRECATED] Helm Chart for an Apache Pulsar Cluster\n\n**⚠️ DEPRECATION NOTICE: This Helm chart is deprecated and will no longer receive updates.**\n\nPlease migrate to [KAAP (Kubernetes Autoscaling for Apache Pulsar)](https://github.com/datastax/kaap) for your Apache Pulsar deployments on Kubernetes. KAAP provides an operator-based approach for managing Pulsar clusters with enhanced features and better resource management.\n\n---\n\nThis Helm chart configures an Apache Pulsar cluster. It is designed for production use, but can also be used in local development environments with the proper settings.\n\nIt includes support for:\n* [TLS](#tls)\n* [Authentication](#authentication)\n* [OpenID Connect Authentication](#openid-connect-authentication)\n* [OpenID / OAuth2 with Starlight for Kafka](#openid-with-starlight-for-kafka)\n* WebSocket Proxy\n* Standalone Functions Workers\n* Pulsar IO Connectors\n* [Tiered Storage](#tiered-storage) including Tardigrade distributed cloud storage\n* [Pulsar SQL Workers](#pulsar-sql)\n* [Admin Console](#managing-pulsar-using-admin-console) for managing the cluster\n* [Pulsar heartbeat](https://github.com/datastax/pulsar-heartbeat)\n* [Burnell](https://github.com/datastax/burnell) for API-based token generation\n* Prometheus/Grafana/Alertmanager [stack](https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack) with default Grafana dashboards and Pulsar-specific alerting rules\n* cert-manager with support for self-signed certificates as well as public certificates using ACME (for example, Let's Encrypt)\n* Ingress configuration for all HTTP ports (Admin Console, Prometheus, Grafana, etc.)\n\n[Helm](https://helm.sh) must be installed and initialized to use the chart. Only Helm 3 is supported.\nPlease refer to Helm's [documentation](https://helm.sh/docs/) to get started.\n\n## Upgrade considerations\n\n## Minikube quick start\n\nMake sure you have minikube [installed](https://minikube.sigs.k8s.io/docs/start/) and running (e.g., `minikube start --cpus 6 --memory 16G`.)\n\nInstall the Helm chart:\n\n```\nhelm repo add datastax-pulsar https://datastax.github.io/pulsar-helm-chart\nhelm repo update\ncurl -LOs https://datastax.github.io/pulsar-helm-chart/examples/dev-values.yaml\nhelm install pulsar -f dev-values.yaml --wait datastax-pulsar/pulsar\n```\n\nThe Helm command waits until all pods are up, which takes about 5 minutes.\n\nIn another terminal, start the minikube tunnel:\n\n```\nminikube tunnel\n```\n\nOpen your browser to http://localhost to view the Admin Console:\n\n![Admin Console](assets/admin_console.png?raw=true \"Admin Console\")\n\n\nYou can view the embedded Grafana charts using the Cluster/Monitoring menu in the Admin Console:\n\n![Grafana in Admin Console](assets/grafana.png?raw=true \"Grafana in Admin Console\")\n\nGrafana is password protected. The username is `admin`. You can get the password with this command:\n\n```\nkubectl get secret pulsar-grafana -o=jsonpath=\"{.data.admin-password}\" | base64 --decode\n```\n\n\n## Quick start\n\nWith Helm installed to your local machine and with access to a Kubernetes cluster (e.g. minikube):\n\n```\nhelm repo add datastax-pulsar https://datastax.github.io/pulsar-helm-chart\nhelm repo update\ncurl -LOs https://datastax.github.io/pulsar-helm-chart/examples/dev-values.yaml\nhelm install pulsar -f dev-values.yaml datastax-pulsar/pulsar \n```\n\nOnce all the pods are running (takes 5 to 10 minutes), you can access the admin console by forwarding to localhost: \n\n```kubectl port-forward $(kubectl get pods -l component=adminconsole -o jsonpath='{.items[0].metadata.name}') 8888:80```\n\nThen open a browser to http://localhost:8888. In the admin console, you can test your Pulsar setup using the built-in clients (Test Clients in the left-hand menu).\n\nIf you also forward the Grafana port, like this:\n\n```kubectl port-forward $(kubectl get pods -l app.kubernetes.io/name=grafana -o jsonpath='{.items[0].metadata.name}') 3000:3000```\n\nYou can view metrics for the Pulsar cluster via the Cluster, Monitoring menu item. You will have to log into Grafana. The username is `admin` and the password is in the downloaded file `dev-values.yaml` under the `adminPassword` setting.\n\nTo use the Pulsar admin and client tools (ex pulsar-admin, pulsar-client, pulsar-perf), log into the bastion pod:\n\n```kubectl exec $(kubectl get pods -l component=bastion -o jsonpath=\"{.items[*].metadata.name}\") -it -- /bin/bash```\n\nYou will find the tools in the `/pulsar/bin` directory.\n\nNote: if you are using Cert-Manager to manage TLS certificates, see [Enabling TLS using Cert-Manager](#enabling-tls-using-cert-manager) for additional configuration information.\n\n## Add to local Helm repository \nTo add this chart to your local Helm repository:\n\n```helm repo add datastax-pulsar https://datastax.github.io/pulsar-helm-chart```\n\nTo update to the latest chart:\n\n```helm repo update```\n\nNote: This command updates all your Helm charts.\n\nTo list the version of the chart in the local Helm repository:\n\n```helm search repo datastax-pulsar```\n\n\n## Installing Pulsar in a Cloud Provider\n\nBefore you can install the chart, you need to configure the storage class settings for your cloud provider. The handling of storage varies from cloud provider to cloud provider.\n\nCreate a new file called ```storage_values.yaml``` for the storage class settings. To use an existing storage class (including the default one) set this value:\n\n```\ndefault_storage:\n  existingStorageClassName: default or \u003cname of storage class\u003e\n```\nFor each volume of each component (Zookeeper, Bookkeeper), you can override the `default_storage` setting by specifying a different `existingStorageClassName`. This allows you to match the optimum storage type to the volume. \n\nIf you have specific storage class requirement, for example fixed IOPS disks in AWS, you can have the chart configure the storage classes for you. Here are examples from the cloud providers:\n\n```\n# For AWS\n# default_storage:\n#  provisioner: kubernetes.io/aws-ebs\n#  type: gp2\n#  fsType: ext4\n#  extraParams:\n#     iopsPerGB: \"10\"\n\n\n# For GCP\n# default_storage:\n#   provisioner: kubernetes.io/gce-pd\n#   type: pd-ssd\n#   fsType: ext4\n#   extraParams:\n#      replication-type: none\n\n# For Azure\n# default_storage:\n#   provisioner: kubernetes.io/azure-disk\n#   fsType: ext4\n#   type: managed-premium\n#   extraParams:\n#     storageaccounttype: Premium_LRS\n#     kind: Managed\n#     cachingmode: ReadOnly\n```\nSee the [values file](https://github.com/datastax/pulsar-helm-chart/blob/master/helm-chart-sources/pulsar/values.yaml) for more details on these settings.\n\nOnce you have your storage settings in the values file, install the chart like this :\n\n```\nhelm install pulsar datastax-pulsar/pulsar --namespace pulsar --values storage_values.yaml --create-namespace\n```\n\n## Using namespace scoped or cluster level RBAC resources\n\nUp to Helm chart version 2.0.3, the Helm deployment uses `ClusterRole` and `ClusterRoleBinding` resources for defining access for service accounts by default. These resources get created outside the namespace defined for deployment.\nSince version 2.0.4, namespace scoped `Role` and `RoleBinding` resources are used by default.\n\nIt is possible to revert to use the legacy behavior by setting `rbac.clusterRoles` to `true`.\n\n## Installing Pulsar for development\n\nThis chart is designed for production use, but it can be used in development environments. To use this chart in a development environment (ex minikube), you need to:\n\n* Disable anti-affinity rules that ensure components run on different nodes\n* Reduce resource requirements\n* Disable persistence (configuration and messages are not stored so are lost on restart). If you want persistence, you will have to configure storage settings that are compatible with your development environment as described above.\n\nFor an example set of values, download this [values file](https://github.com/datastax/pulsar-helm-chart/blob/master/examples/dev-values.yaml). Use that values file or one like it to start the cluster:\n\n\n```\nhelm install pulsar -f dev-values.yaml datastax-pulsar/pulsar\n```\n\n## Accessing the Pulsar cluster in cloud\n\nThe default values will create a ClusterIP for all components. ClusterIPs are only accessible within the Kubernetes cluster. The easiest way to work with Pulsar is to log into the bastion host:\n\n```\nkubectl exec $(kubectl get pods -l component=bastion -o jsonpath=\"{.items[*].metadata.name}\") -it -- /bin/bash\n```\nOnce you are logged into the bastion, you can run Pulsar admin commands:\n\n```\nbin/pulsar-admin tenants list\n```\nFor external access, you can use a load balancer. Here is an example set of values to use for load balancer on the proxy:\n\n```\nproxy:\n service:\n    type: LoadBalancer\n```\n\nIf you are using a load balancer on the proxy, you can find the IP address using:\n\n```kubectl get service```\n\n## Accessing the Pulsar cluster on localhost\n\nTo port forward the proxy admin and Pulsar ports to your local machine:\n\n```kubectl port-forward -n pulsar $(kubectl get pods -l component=proxy -o jsonpath='{.items[0].metadata.name}') 8080:8080```\n\n```kubectl port-forward -n pulsar $(kubectl get pods -l component=proxy -o jsonpath='{.items[0].metadata.name}') 6650:6650```\n\nOr if you would rather go directly to the broker:\n\n```kubectl port-forward -n pulsar $(kubectl get pods -l component=broker -o jsonpath='{.items[0].metadata.name}') 8080:8080```\n\n```kubectl port-forward -n pulsar $(kubectl get pods -l component=broker -o jsonpath='{.items[0].metadata.name}') 6650:6650```\n\n## Managing Pulsar using Admin Console\n\n\nYou can install the Pulsar admin console in your cluster by enabling with this values setting:\n\n```\ncomponent:\n  pulsarAdminConsole: true\n```\n\nIt will be automatically configured to connect to the Pulsar cluster.\n\nBy default, the admin console has authentication disabled. You can enable authentication with these settings:\n\n```\npulsarAdminConsole:\n    authMode: k8s\n```\nWhen `k8s` authentication mode is enabled, the admin console gets the users from Kubernetes secrets that start with `dashboard-user-` in the same namespace where it is deployed. The text that follows the prefix is the username. For example, for a user `admin` you need to have a secret `dashboard-user-admin`. The secret data must have a key named `password` with the base-64 encoded password. The following command will create a secret for a user `admin` with a password of `password`:\n\n```\nkubectl create secret generic dashboard-user-admin --from-literal=password=password\n```\n\nYou can create multiple users for the admin console by creating multiple secrets. To change the password for a user, delete the secret then recreate it with a new password:\n\n```\nkubectl delete secret dashboard-user-admin\nkubectl create secret generic dashboard-user-admin --from-literal=password=newpassword\n```\n\nFor convenience, the Helm chart is able to create an initial user for the admin console with the following settings:\n\n```\npulsarAdminConsole:\n    createUserSecret:\n      enabled: true\n      user: 'admin'\n      password: 'password'\n```\n\n### Accessing Admin Console on your local machine\n\nTo access the Pulsar admin console on your local machine, forward port 80:\n\n```\nkubectl port-forward -n pulsar $(kubectl get pods -n pulsar -l component=adminconsole -o jsonpath='{.items[0].metadata.name}') 8888:80\n```\n\n### Accessing Admin Console from cloud provider\n\nTo access Pulsar admin console from a cloud provider, the chart supports [Kubernetes Ingress](https://kubernetes.io/docs/concepts/services-networking/ingress/). Your Kubernetes cluster must have a running Ingress controller (ex Nginx, Traefik, etc.).\n\nSet these values to configure the Ingress for the admin console:\n\n```\npulsarAdminConsole:\n  ingress:\n    enabled: true\n    host: pulsar-ui.example.com\n```\n\n## Enabling TLS using Cert-Manager\n\nWhen using Cert-Manager to create your TLS certificates, you must first install the Cert-Manager CRDs. These are\ninstalled using the following command:\n\n```shell\nkubectl apply -f https://github.com/jetstack/cert-manager/releases/download/v1.8.0/cert-manager.crds.yaml\n```\n\nNOTE: if you're deploying a version of the chart before 3.0.0, you'll need to use version `v1.5.5` of the CRDs.\n\nIf you don't, you will get error messages like this:\n\n\u003e Error: INSTALLATION FAILED: unable to build kubernetes objects from release manifest: [resource mapping not found for name: \"pulsar-ca-certificate\" namespace: \"pulsar\" from \"\": no matches for kind \"Certificate\" in version \"cert-manager.io/v1\"\n\n## Prometheus stack\n\n### Enabling the Prometheus stack\n\nYou can enable a full Prometheus stack (Prometheus, Alertmanager, Grafana) from [kube-prometheus](https://github.com/prometheus-operator/kube-prometheus). This includes default Prometheus rules and Grafana dashboards for Kubernetes. \n\nIn an addition, this chart can deploy Grafana dashboards for Pulsar as well as Pulsar-specific rules for Prometheus. \n\nTo deploy the Prometheus stack, use the following setting in your values file:\n\n```\nkube-prometheus-stack:\n  enabled: true\n```\n\nTo enable the Kubernetes default rules, use the following setting:\n```\nkube-prometheus-stack:\n  defaultRules:\n    create: true\n```\n\n## Deploying and Discovering a PodMonitor\n\nIn order to simplify metrics gathering, the helm chart has support for deploying a `PodMonitor`. This single monitor\nconfigures scraping all the available metrics endpoints for a given Pulsar Cluster deployed by the helm chart. This\n`PodMonitor` can be deployed by setting the following in your values file:\n\n```yaml\nenablePulsarPodMonitor: true\n```\n\nNote that this will deploy a `PodMonitor` in the release's namespace. If you are running a Prometheus Operator in\nanother Kubernetes namespace, you may need to modify the configuration to make sure that the operator can discover\n`PodMonitors` in the release's namespace.\n\n### Disabling the Prometheus stack\n\nAs some  `kube-prometheus-stack` components need CRDs to be installed and `kube-prometheus-stack.enabled: false` does not alone prevent components' CRDs installation, the `kube-prometheus-stack` components should be disabled one by one, if the service account used to deploy the cluster does not have enough permissions to install CRDs.\n\nIn order to prevent all `kube-prometheus-stack` CRDs from being installed, the following should be added to `values.yaml`:\n\n```\nkube-prometheus-stack:\n  enabled: false\n  prometheusOperator:\n    enabled: false\n  grafana:\n    enabled: false\n  alertmanager:\n    enabled: false\n  prometheus:\n    enabled: false\n```\n\n### Grafana Dashboards\n\nDataStax has several custom dashboards to help interpret Pulsar metrics. These custom dashboards are installed when the\nfollowing is set in the values file:\n\n```\ngrafanaDashboards:\n  enabled: true\n```\n\nStarting in Pulsar 2.8.0, the bundled Zookeeper process exports its own metrics instead of using the Pulsar metrics\nimplementation. This results in new metrics names. As a result, we install two Grafana dashboards for Zookeeper. The\nfirst is a custom DataStax dashboard that works for versions before 2.8.0. The second is the official Zookeeper\ncommunity Grafana dashboard: https://grafana.com/grafana/dashboards/10465.\n\n## Example configurations\n\nThere are several example configurations in the [examples](https://github.com/datastax/pulsar-helm-chart/blob/master/examples) directory:\n\n* [dev-values.yaml](https://github.com/datastax/pulsar-helm-chart/blob/master/examples/dev-values.yaml). A configuration for setting up a development environment to run in a local Kubernetes environment (ex [minikube](https://minikube.sigs.k8s.io/docs/start/), [kind](https://kind.sigs.k8s.io/)). Message/state persistence, redundancy, authentication, and TLS are disabled. \n\nNote: With message/state persistence disabled, the cluster will not survive a restart of the ZooKeeper or BookKeeper.\n\n* dev-values-persistence. Same as above, but persistence is enabled. This will allow for the cluster to survive the restarts of the pods, but requires persistent volume claims (PVC) to be supported by the Kubernetes environment. \n* dev-values-auth.yaml. A development environment with authentication enabled. New keys and tokens from those keys are automatically generated and stored in Kubernetes secrets. You can retrieve the superuser token from the admin console (Credentials menu) or from the secret `token-superuser`.\n* dev-values-keycloak-auth.yaml. A deployment environment with authentication enabled along with a running keycloak server that can create additional tokens. Like the `dev-values-auth.yaml`, it will create a superuser token for use by pulsar components.\n\n```helm install pulsar -f dev-values-auth.yaml datastax-pulsar/pulsar```\n\n* dev-values-tls.yaml. Development environment with self-signed certificate created by cert-manager. You need to install the cert-manager CRDs before installing the Helm chart. The chart will install the cert-manager application.\n\n```\nkubectl apply -f https://github.com/jetstack/cert-manager/releases/download/v1.8.0/cert-manager.crds.yaml\nhelm install pulsar -f dev-values-tls.yaml datastax-pulsar/pulsar\n```\n\nNOTE: if you're deploying a version of the chart before 3.0.0, you'll need to use version `v1.5.5` of the CRDs.\n\n## Tiered Storage\n\nTiered storage (offload to blob storage) can be configured in the `storageOffload` section of the `values.yaml` file. Instructions for AWS S3, Google Cloud Storage and Azure are provided in the file.\n\nIn addition, you can configure any S3 compatible storage. There is explicit support for [Tardigrade](https://tardigrade.io), which is a provider of secure, decentralized storage. You can enable the Tardigrade S3 gateway in the `extra` configuration. The instructions for configuring the gateway are provided in the `tardigrade` section of the `values.yaml` file.\n\n## Pulsar SQL\nIf you enable Pulsar SQL, the cluster provides [Presto](https://prestodb.io/) access to the data stored in BookKeeper (and tiered storage, if enabled). Presto is exposed on the service named `\u003crelease\u003e-sql`.\n\nThe easiest way to access the Presto command line is to log into the bastion host and then connect to the Presto service port, like this:\n\n```\nbin/pulsar sql --server pulsar-sql:8090\n```\nWhere the value for the `server` option should be the service name plus port. Once you are connected, you can enter Presto commands:\n\n```\npresto\u003e SELECT * FROM system.runtime.nodes;\n               node_id                |         http_uri         | node_version | coordinator | state  \n--------------------------------------+--------------------------+--------------+-------------+--------\n 64b7c5a1-9a72-4598-b494-b140169abc55 | http://10.244.5.164:8080 | 0.206        | true        | active \n 0a92962e-8b44-4bd2-8988-81cbde6bab5b | http://10.244.5.196:8080 | 0.206        | false       | active \n(2 rows)\n\nQuery 20200608_155725_00000_gpdae, FINISHED, 2 nodes\nSplits: 17 total, 17 done (100.00%)\n0:04 [2 rows, 144B] [0 rows/s, 37B/s]\n```\nTo access Pulsar SQL from outside the cluster, you can enable the `ingress` option which will expose the Presto port on hostname. We have tested with the Traefik ingress, but any Kubernetes ingress should work. You can then run SQL queries using the Presto CLI and monitoring Presto using the built-in UI (point browser to the ingress hostname). Authentication is not enabled on the UI, so you can log in with any username.\n\nIt is recommended that you match the Presto CLI version to the version running as part of Pulsar SQL.\n\nThe Presto CLI supports basic authentication, so if you enabled that on the ingress (using annotations), you can have secure Presto access.\n\n```\npresto --server https://presto.example.com --user admin --password\nPassword: \npresto\u003e show catalogs;\n Catalog \n---------\n pulsar  \n system  \n(2 rows)\n\nQuery 20200610_131641_00027_tzc7t, FINISHED, 1 node\nSplits: 19 total, 19 done (100.00%)\n0:01 [0 rows, 0B] [0 rows/s, 0B/s]\n```\n\n## Dependencies\n\nThe Helm chart has the following optional dependencies:\n\n* [kube-prometheus-stack](https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack)\n* [cert-manager](https://cert-manager.io/)\n\n\n## Authentication\nThe chart can enable two forms of token-based authentication for a Pulsar cluster. See below for information on each:\n\n* [OpenID Connect Authentication](#openid-connect-authentication)\n* [Pulsar's Token Based Authentication](#pulsars-token-based-authentication)\n\nThe chart includes tooling to automatically create the necessary secrets, or you can do this manually.\n\n### OpenID Connect Authentication\n\nDataStax created the [OpenID Connect Authentication Plugin](https://github.com/datastax/pulsar-openid-connect-plugin)\nto provide a more dynamic authentication option for Pulsar. This plugin integrates with your OIDC compliant Identity\nProvider or the chart can deploy a Keycloak instance in the kubernetes cluster. This plugin integrates with an Identity\nProvider to dynamically retrieve Public Keys from the Identity Provider for token validation. This dynamic\npublic key retrieval enables support for key rotation and multiple authentication/identity providers by configuring\nmultiple allowed token issuers. It also means that token secret keys will not be stored in Kubernetes secrets.\n\nIn order to simplify deployment for Pulsar cluster components, the plugin provides the option to use OIDC in\nconjunction with Pulsar's basic token based authentication. See the [plugin project](https://github.com/datastax/pulsar-openid-connect-plugin)\nfor information about configuration.\n\n#### Bring Your Own Identity Provider\n\nTo enable OpenID Connect with your already running Identity Provider, configure the `openid` section in the\nvalues and the `authenticationProviders` in the broker, proxy, and function worker.\n\nHere is an example of the values using Okta:\n\n```yaml\nopenid:\n  enabled: true\n  # Comma delimited list of issuers to trust\n  allowedIssuerUrls: \"https://dev-1111111.okta.com/oauth2/abcd878787\"\n  allowedAudience: api://pulsarClient\n\nbroker:\n  authenticationProviders: \"com.datastax.oss.pulsar.auth.AuthenticationProviderOpenID\"\nproxy:\n  authenticationProviders: \"com.datastax.oss.pulsar.auth.AuthenticationProviderOpenID\"\nfunction:\n  authenticationProviders: \"com.datastax.oss.pulsar.auth.AuthenticationProviderOpenID\"\n```\n\nThe `AuthenticationProviderOpenID` class is included with all Luna Streaming Docker images.\n\n#### Using Keycloak Deployed by Chart\n\nHere is an example helm [values file](./examples/dev-values-keycloak-auth.yaml) for deploying a working cluster that\nintegrates with keycloak. By default, the helm chart creates a `pulsar` realm within keycloak and sets up the client\nused by the Pulsar Admin Console as well as a sample client and some sample groups. The configuration for the broker\nside auth plugin should be placed in the `.Values.\u003ccomponent\u003e.configData` maps.\n\n#### Configuring Keycloak for Token Generation\nFirst deploy the cluster:\n\n```shell\n$ helm install test --values ../../examples/dev-values-keycloak-auth.yaml .\n```\n\nThe name of the deployment is very important for a working cluster. The values file assumes that the cluster's name is\n`test`, as shown above. Once the cluster is operational, you can start configuring keycloak. Port forward to keycloak:\n\n```shell\n$ kubectl port-forward test-keycloak-0 8080:8080\n```\n\nThen, using a browser, navigate to `localhost:8080`. At this point, you will need to retrieve the configured username\nand password for the admin user in keycloak. The [values file](./examples/dev-values-keycloak-auth.yaml) configures\nthem here:\n\n```yaml\nkeycloak:\n  auth:\n    adminUser: \"admin\"\n    adminPassword: \"F3LVqnxqMmkCQkvyPdJiwXodqQncK@\"\n```\n\nOnce in to the keycloak UI, you can view the `pulsar` realm. Note that the realm name must match the configured realm\nname (`.Values.keycloak.realm`) for the OpenID Connect plugin to work properly.\n\nThe OpenID Connect plugin uses the `sub` (subject) claim from the JWT as the role used for authorization within Pulsar.\nIn order to get Keycloak to generate the JWT for a client with the right `sub`, you can create a special \"mapper\" that\nis a \"Hardcoded claim\" mapping claim name `sub` to a claim value that is the disired role, like `superuser`. The default\nconfig installed by this helm chart provides examples of how to add custom mapper protocols to clients.\n\n#### Retrieving and Using a token from Keycloak with Pulsar Admin CLI\nAfter creating your realm and client, you can retrieve a token. In order to generate a token that will have an allowed\nissuer, you should exec into a pod in the k8s cluster. Exec'ing into a bastion host will give you immediate access\nto a `pulsar-admin` cli tool that you can use to verify that you have access. The following is run from a bastion pod.\n\n```shell\npulsar@pulsar-bastion-85c9b777f6-gt9ct:/pulsar$ curl -d \"client_id=test-client\" \\\n       -d \"client_secret=19d9f4a2-65fb-4695-873c-d0c1d6bdadad\" \\\n       -d \"grant_type=client_credentials\" \\\n       \"http://test-keycloak/realms/pulsar/protocol/openid-connect/token\"\n{\"access_token\":\"eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJDY3c3ZXcwQ0hKMThfbWpCQzYxb2xOSU1wT0d3TkEyd1ZFbHBZLUdzb2tvIn0.eyJleHAiOjE2MjY5NzUwNzIsImlhdCI6MTYyNjk3NDQ3MiwianRpIjoiYTExZmFkY2YtYTJkZi00NmNkLTk0OWEtNDdkNzdmNDYxMDMxIiwiaXNzIjoiaHR0cDovL3Rlc3Qta2V5Y2xvYWsvYXV0aC9yZWFsbXMvcHVsc2FyIiwiYXVkIjoiYWNjb3VudCIsInN1YiI6ImQwN2UxOGIxLTE4YzQtNDZhMC1hNGU0LWE3YTZjNmRiMjFkYyIsInR5cCI6IkJlYXJlciIsImF6cCI6InRlc3QtY2xpZW50IiwiYWNyIjoiMSIsInJlYWxtX2FjY2VzcyI6eyJyb2xlcyI6WyJvZmZsaW5lX2FjY2VzcyIsImRlZmF1bHQtcm9sZXMtcHVsc2FyIiwidW1hX2F1dGhvcml6YXRpb24iXX0sInJlc291cmNlX2FjY2VzcyI6eyJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50IiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJ2aWV3LXByb2ZpbGUiXX19LCJzY29wZSI6ImVtYWlsIHByb2ZpbGUiLCJzdWIiOiJzdXBlcnVzZXIiLCJjbGllbnRIb3N0IjoiMTcyLjE3LjAuMSIsImNsaWVudElkIjoidGVzdC1jbGllbnQiLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsInByZWZlcnJlZF91c2VybmFtZSI6InNlcnZpY2UtYWNjb3VudC10ZXN0LWNsaWVudCIsImNsaWVudEFkZHJlc3MiOiIxNzIuMTcuMC4xIn0.FckQLOD64ZTKmx2uutP75QBpZAqHaqWyEE6jRUXvbSzsiXTAQyz-30zKsUSEjOMJp97NlTy3NZECVo_GdZ7oPcneFdglmFY62btWj-5s6ELcazj-AGQhyt0muGD4VP71xjpjCUpVxhyBIQlltGZLu7Rgw4trfh3LS8YjaY74vGg_BjOzZ8VI4S352lyGOULou7_dRbaeKhv43OfU7e_Y_ro_m_9UaDARypcj3uqSllhZdifA4YbHyaBCCu5eH19GCLtFm3I00PvWkOy3iTyOkkTcayqJ-Vlraf95qCZFN-sooIIU6o8L-wS-Zr7EvkoDJ-II9q49WHJJLIIvnCE2ug\",\"expires_in\":600,\"refresh_expires_in\":0,\"token_type\":\"Bearer\",\"not-before-policy\":0,\"scope\":\"email profile\"}\n```\n\nThen, you can copy the `access_token` contents and use it here:\n\n```shell\npulsar@pulsar-bastion-85c9b777f6-gt9ct:/pulsar$ bin/pulsar-admin --auth-params \"token:eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJDY3c3ZXcwQ0hKMThfbWpCQzYxb2xOSU1wT0d3TkEyd1ZFbHBZLUdzb2tvIn0.eyJleHAiOjE2MjY5NzUwNzIsImlhdCI6MTYyNjk3NDQ3MiwianRpIjoiYTExZmFkY2YtYTJkZi00NmNkLTk0OWEtNDdkNzdmNDYxMDMxIiwiaXNzIjoiaHR0cDovL3Rlc3Qta2V5Y2xvYWsvYXV0aC9yZWFsbXMvcHVsc2FyIiwiYXVkIjoiYWNjb3VudCIsInN1YiI6ImQwN2UxOGIxLTE4YzQtNDZhMC1hNGU0LWE3YTZjNmRiMjFkYyIsInR5cCI6IkJlYXJlciIsImF6cCI6InRlc3QtY2xpZW50IiwiYWNyIjoiMSIsInJlYWxtX2FjY2VzcyI6eyJyb2xlcyI6WyJvZmZsaW5lX2FjY2VzcyIsImRlZmF1bHQtcm9sZXMtcHVsc2FyIiwidW1hX2F1dGhvcml6YXRpb24iXX0sInJlc291cmNlX2FjY2VzcyI6eyJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50IiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJ2aWV3LXByb2ZpbGUiXX19LCJzY29wZSI6ImVtYWlsIHByb2ZpbGUiLCJzdWIiOiJzdXBlcnVzZXIiLCJjbGllbnRIb3N0IjoiMTcyLjE3LjAuMSIsImNsaWVudElkIjoidGVzdC1jbGllbnQiLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsInByZWZlcnJlZF91c2VybmFtZSI6InNlcnZpY2UtYWNjb3VudC10ZXN0LWNsaWVudCIsImNsaWVudEFkZHJlc3MiOiIxNzIuMTcuMC4xIn0.FckQLOD64ZTKmx2uutP75QBpZAqHaqWyEE6jRUXvbSzsiXTAQyz-30zKsUSEjOMJp97NlTy3NZECVo_GdZ7oPcneFdglmFY62btWj-5s6ELcazj-AGQhyt0muGD4VP71xjpjCUpVxhyBIQlltGZLu7Rgw4trfh3LS8YjaY74vGg_BjOzZ8VI4S352lyGOULou7_dRbaeKhv43OfU7e_Y_ro_m_9UaDARypcj3uqSllhZdifA4YbHyaBCCu5eH19GCLtFm3I00PvWkOy3iTyOkkTcayqJ-Vlraf95qCZFN-sooIIU6o8L-wS-Zr7EvkoDJ-II9q49WHJJLIIvnCE2ug\" \\\n      tenants list\n\"public\"\n\"pulsar\"\n```\n\n### Pulsar's Token Based Authentication\n\nThis token based authentication relies on a plugin provided by Apache Pulsar using the `AuthenticationProviderToken`\nclass that ships with Pulsar.\n\nFor information on token-based authentication from Apache Pulsar, go\n[here](https://pulsar.apache.org/docs/en/security-token-admin/).\n\nFor authentication to work, the token-generation keys need to be stored in Kubernetes secrets along with some default tokens (for superuser access).\n\nThe chart includes tooling to automatically create the necessary secrets, or you can do this manually.\n\n#### Automatic generation of secrets for token authentication\n\nUse these settings to enable automatic generation of the secrets and enable token-based authentication:\n\n```\nenableTokenAuth: true\nautoRecovery:\n  enableProvisionContainer: true\n```\n\nWhen the provision container is enabled, it will check if the required secrets exist. If they don't exist, it will generate new token keys and use those keys to generate the default set of tokens\n\nThe name of the key secrets are:\n\n* token-private-key\n* token-public-key\n\nUsing these keys, it will generate tokens for each role listed in `superUserRoles`. Based on the default settings, the following secrets will be created to store the tokens:\n\n* token-superuser\n* token-admin\n* token-proxy\n* token-websocket\n\n#### Manual secret creation for token authentication\n\nA number of values need to be stored in secrets prior to enabling token-based authentication. First, you need to generate a key-pair for signing the tokens using the Pulsar tokens command:\n\n```bin/pulsar tokens create-key-pair --output-private-key my-private.key --output-public-key my-public.key```\n\n**Note:** The names of the files used in this section match the default values in the chart. If you used different names, then you will have to update the corresponding values.\n\nThen you need to store those keys as secrets.\n\n```\nkubectl create secret generic token-private-key \\\n --from-file=my-private.key \\\n --namespace pulsar\n ```\n\n\n```\nkubectl create secret generic token-public-key \\\n --from-file=my-public.key \\\n --namespace pulsar\n ```\n\n\nUsing those keys, generate tokens with subjects(roles): \n\n```bin/pulsar tokens create --private-key file:///pulsar/token-private-key/my-private.key --subject \u003csubject\u003e```\n\nYou need to generate tokens with the following subjects:\n\n- admin\n- superuser\n- proxy\n- websocket (only required if using the standalone WebSocket proxy)\n\nOnce you have created those tokens, add each as a secret:\n\n```\nkubectl create secret generic token-\u003csubject\u003e \\\n --from-file=\u003csubject\u003e.jwt \\\n --namespace pulsar\n ```\n\nOnce you have created the required secrets, you can enable token-based authentication with this setting in the values:\n\n```\nenableTokenAuth: true\n```\n\n### TLS\n\n#### TLS with Client Facing Components\n\nThere are many components to consider when enabling TLS for a Pulsar Cluster. To enable TLS for all client facing\nendpoints, set `enableTls: true` in the values file and configure certificates. This setting will enable TLS endpoints\nfor the Broker pods, Function Worker pods, and Proxy pods. However, this setting will not configure the proxy or the\nfunction worker to use TLS for connections with the broker. You can enable those by configuring\n`tls.proxy.enableTlsWithBroker: true` and `tls.function.enableTlsWithBroker: true`, respectively. Because the function\nworker only connects to the broker over TLS when authentication is configured, make sure to enable authentication if\nyou'd like the function worker to connect to the broker over TLS.\n\n#### TLS within all components (zero-trust)\n\nIn order to support a zero-trust deployment of Pulsar please view the zero trust example values file [here](./examples/dev-values-zero-trust.yaml).\nThe example shows the key components necessary for configuring TLS for all connections in Pulsar cluster. Note that\nyou can supply a certificate per component now. Also note that the default values file has documentation for many of the\nfields related to zero trust.\n\nIf you are using Cert Manager, the zero trust example is a complete example. If you are using your own certificates,\nyou'll need to add the correct hostnames to the certificates in order to make hostname verification work. Please see\nthe [self-signed-cert-per-component.yaml](helm-chart-sources/pulsar/templates/cert-manager/self-signed-cert-per-component.yaml)\ntemplate to see which hostnames are required for each component.\n\n#### Hostname Verification\n\nIn order for hostname verification to work, you must configure the helm chart to deploy the broker cluster as a\nStatefulSet. This kind of deployment gives each pod a stable network identifier, which is necessary for hostname\nverification and the Pulsar Protocol.\n\nTo enable hostname verification with upstream servers, set `tls.\u003ccomponent\u003e.enableHostnameVerification: true`. Note that\nthese settings temporarily default to false for backwards compatibility, but will be updated to default to true in the\nnext major version bump.\n\n### Automatically generating certificates using cert-manager\n\n#### Manually configuring certificate secrets for TLS\n\nTo use TLS, you must first create a certificate and store it in the secret defined by ```tlsSecretName```.\nYou can create the certificate like this:\n\n```kubectl create secret tls \u003ctlsSecretName\u003e --key \u003ckeyFile\u003e --cert \u003ccertFile\u003e```\n\nThe resulting secret will be of type kubernetes.io/tls. The key should not be in PKCS 8 format even though that is the format used by Pulsar.  The format will be converted by chart to PKCS 8. \n\nYou can also specify the certificate information directly in the values:\n\n```\n# secrets:\n  # key: |\n  # certificate: |\n  # caCertificate: |\n```\n\nThis is useful if you are using a self-signed certificate.\n\nFor automated handling of publicly signed certificates, you can use a tool\nsuch as [cert-manager](https://cert-mananager). The following [page](https://github.com/datastax/pulsar-helm-chart/blob/master/aws-customer-docs.md) describes how to set up cert-manager in AWS.\n\nOnce you have created the secrets that store the certificate info (or specified it in the values), you can enable TLS in the values:\n\n```\nenableTls: true\n\n```\n### OpenID with Starlight for Kafka\nTo configure OpenID / OAuth2, you can use the values file that includes OpenID support with Starlight for Kafka: dev-values-tls-all-components-and-oauth2.yaml\nBe sure to provide your appropriate values in the openid section of the values file:\n\n```\nopenid:\n  enabled: true\n  # From token generated in Okta UI or other method:\n  allowedIssuerUrls: $ISSUER_URI\n  withS4k: true\n  allowedAudience: $AUDIENCE\n```\nlike with these example values:\n```\nopenid:\n  enabled: true\n  # From token generated in Okta UI or other method:\n  allowedIssuerUrls: https://dev-1111111.okta.com/oauth2/abcd878787\n  allowedAudience: api://pulsarClient\n  withS4k: true\n```\n\nThe chart can be installed as follows:\n\n```\nBASEDIR=/path/to/repo/on/your/local/filesystem\nhelm install pulsar datastax-pulsar/pulsar --namespace pulsar --values $BASEDIR/pulsar-helm-chart/examples/kafka/dev-values-tls-all-components-and-kafka-and-oauth2.yaml --create-namespace --debug\n```\n\nTo test the functionality (with and without TLS) for both token authentication, and for Starlight for Kafka, you can perform the following steps:\n1. Set variables that will be used for subsequent commands (making sure they match the values used in the Helm values file above):\nNote that these credentials can be obtained from Okta (https://www.youtube.com/watch?v=UQBrecHOXxU\u0026ab_channel=DataStaxDevelopers) or from an equivalent auth provider.\n\n```\nISSUER_URI=\"https://dev-1111111.okta.com/oauth2/abcd878787\"\nAUDIENCE=\"api://pulsarClient\"\nSCOPE=\"pulsar_client_m2m\"\nAUTH_PARAMS=$(cat \u003c\u003cEOF\n{\"privateKey\":\"/pulsar/conf/creds.json\",\"issuerUrl\":\"$ISSUER_URI\",\"scope\":\"$SCOPE\",\"audience\":\"$AUDIENCE\"}\nEOF\n)\nCLIENT_ID=\"your-client-id\"\nCLIENT_SECRET=\"your-client-secret\"\nKAFKA_VERSION=\"kafka_2.12-3.3.2\"\nOAUTH_CLIENT=\"2.10.3.2\"\n\nPROXY_HOSTNAME=\"pulsar-proxy.pulsar.svc.cluster.local\"\n```\n2. (Optional for TLS)\n```\n# Copy truststore from broker to bastion to simplify tests by first copying to local system. (Make sure you're not still in the bastion.)\nkubectl cp pulsar/pulsar-broker-0:/pulsar/tls.truststore.jks ~/Downloads/tls.truststore.jks\n# Provide the expected bastion path:\nkubectl cp ~/Downloads/tls.truststore.jks pulsar/$(kubectl get pods -o=jsonpath='{.items[?(@.metadata.labels.component==\"bastion\")].metadata.name}'):/pulsar/tls.truststore.jks \n```\n3. SSH to bastion, passing variables for convenience:\n```\nkubectl exec -it pod/$(kubectl get pods -o=jsonpath='{.items[?(@.metadata.labels.component==\"bastion\")].metadata.name}') -- env ISSUER_URI=$ISSUER_URI AUDIENCE=$AUDIENCE SCOPE=$SCOPE AUTH_PARAMS=$AUTH_PARAMS CLIENT_ID=$CLIENT_ID CLIENT_SECRET=$CLIENT_SECRET KAFKA_VERSION=$KAFKA_VERSION OAUTH_CLIENT=$OAUTH_CLIENT PROXY_HOSTNAME=$PROXY_HOSTNAME bash\n```\n4. Test Pulsar client with pulsar-perf with token auth against non-TLS endpoint:\n```\nbin/pulsar-perf produce --num-messages 1000 -r 1000 --size 1024 --auth_plugin org.apache.pulsar.client.impl.auth.AuthenticationToken --auth-params file:///pulsar/token-superuser-stripped.jwt --service-url pulsar://$PROXY_HOSTNAME:6650/ persistent://public/default/test\n```\n5. Test Pulsar client with pulsar-perf with token auth against TLS endpoint (requires the \"Optional for TLS\" step, above):\n```\nbin/pulsar-perf produce --num-messages 1000 -r 1000 --size 1024 --auth_plugin org.apache.pulsar.client.impl.auth.AuthenticationToken --auth-params file:///pulsar/token-superuser-stripped.jwt --service-url pulsar+ssl://$PROXY_HOSTNAME:6651/ persistent://public/default/test\n```\n6. Configure OIDC credentials (using variables set above)\n```\ncat \u003c\u003c EOF \u003e /pulsar/conf/creds.json\n{\"client_id\":\"$CLIENT_ID\",\"client_secret\":\"$CLIENT_SECRET\",\"grant_type\": \"client_credentials\"}\nEOF\n```\nVerify the credentials file was created as expected:\n```\ncat /pulsar/conf/creds.json\n```\n7. Test Pulsar client with pulsar-perf with token auth against non-TLS endpoint:\n```\nbin/pulsar-perf produce --num-messages 1000 -r 1000 --size 1024 --auth-plugin \"org.apache.pulsar.client.impl.auth.oauth2.AuthenticationOAuth2\" --auth-params $AUTH_PARAMS --service-url pulsar://$PROXY_HOSTNAME:6650/ persistent://public/default/test\n```\n8. Test Pulsar client with pulsar-perf with token auth against TLS endpoint:\n```\nbin/pulsar-perf produce --num-messages 1000 -r 1000 --size 1024 --auth-plugin \"org.apache.pulsar.client.impl.auth.oauth2.AuthenticationOAuth2\" --auth-params $AUTH_PARAMS --service-url pulsar+ssl://$PROXY_HOSTNAME:6651/ persistent://public/default/test\n```\n9. Test admin endpoints with token auth for non-TLS:\n```\nbin/pulsar-admin --auth-plugin \"org.apache.pulsar.client.impl.auth.oauth2.AuthenticationOAuth2\" --auth-params $AUTH_PARAMS --admin-url http://$PROXY_HOSTNAME:8080/ namespaces policies public/default\n```\n10. Test admin endpoints with token auth for TLS:\n```\nbin/pulsar-admin --auth-plugin \"org.apache.pulsar.client.impl.auth.oauth2.AuthenticationOAuth2\" --auth-params $AUTH_PARAMS --admin-url https://$PROXY_HOSTNAME:8443/ namespaces policies public/default\n```\n11. Configure Kafka client:\n```\nmkdir /pulsar/kafka \u0026\u0026 cd /pulsar/kafka\ncurl -LOs https://downloads.apache.org/kafka/3.3.2/$KAFKA_VERSION.tgz\ntar -zxvf /pulsar/kafka/$KAFKA_VERSION.tgz\ncd /pulsar/kafka/$KAFKA_VERSION/libs\ncurl -LOs \"https://github.com/datastax/starlight-for-kafka/releases/download/v$OAUTH_CLIENT/oauth-client-$OAUTH_CLIENT.jar\"\ncd ..\n```\nVerify the files were downloaded as expected:\n```\nls /pulsar/kafka/$KAFKA_VERSION\nls /pulsar/kafka/$KAFKA_VERSION/libs | grep -i \"oauth\"\n```\n12. Test OpenID/OAuth2 on non-TLS endpoint for Starlight for Kafka (S4K):\nSetup Kafka producer properties and then run test command:\n```\ncat \u003c\u003c EOF \u003e /pulsar/kafka/$KAFKA_VERSION/config/producer.properties\nbootstrap.servers=pulsar-proxy:9092\ncompression.type=none\nsasl.login.callback.handler.class=com.datastax.oss.kafka.oauth.OauthLoginCallbackHandler\nsecurity.protocol=SASL_PLAINTEXT\nsasl.mechanism=OAUTHBEARER\nsasl.jaas.config=org.apache.kafka.common.security.oauthbearer.OAuthBearerLoginModule \\\n   required oauth.issuer.url=\"$ISSUER_URI\"\\\n   oauth.credentials.url=\"file:///pulsar/conf/creds.json\"\\\n   oauth.audience=\"$AUDIENCE\"\\\n   oauth.scope=\"$SCOPE\";\nEOF\n```\nVerify the file looks right:\n```\ncat /pulsar/kafka/$KAFKA_VERSION/config/producer.properties\n```\nThen, you can run the producer:\n```\ncd /pulsar/kafka/$KAFKA_VERSION; bin/kafka-console-producer.sh --bootstrap-server PLAINTEXT://pulsar-proxy:9092 --topic test --producer.config /pulsar/kafka/$KAFKA_VERSION/config/producer.properties\n```\nIf you want to see the data come through, you can open another CLI tab and use the Pulsar client to subscribe to the topic when you produce the messages via Kafka:\n```\nkubectl exec -it pod/$(kubectl get pods -o=jsonpath='{.items[?(@.metadata.labels.component==\"bastion\")].metadata.name}') -- bash\ncd /pulsar\nbin/pulsar-client consume persistent://public/default/test --subscription-name test-kafka --num-messages 0\n```\nAlso, if you want to observe the logs during this process, you can follow them for the proxy and broker, as follows:\n```\nkubectl logs pod/$(kubectl get pods -o=jsonpath='{.items[?(@.metadata.labels.component==\"proxy\")].metadata.name}') --follow\nkubectl logs pod/$(kubectl get pods -o=jsonpath='{.items[?(@.metadata.labels.component==\"broker\")].metadata.name}') --follow\n```\nThen, produce messages from the Kafka terminal and observe them come through to the Pulsar consumer.\n\n13. Test OpenID/OAuth2 on TLS endpoint for S4K:\nWe must setup the Kafka producer a little differently since it requires TLS-specific configurations:\n```\ncat \u003c\u003c EOF \u003e /pulsar/kafka/$KAFKA_VERSION/config/producer.properties\nbootstrap.servers=pulsar-proxy:9093\ncompression.type=none\nssl.truststore.location=/pulsar/tls.truststore.jks \nsecurity.protocol=SASL_SSL\nsasl.login.callback.handler.class=com.datastax.oss.kafka.oauth.OauthLoginCallbackHandler\nsasl.mechanism=OAUTHBEARER\n# The identification algorithm must be empty\nssl.endpoint.identification.algorithm=\nsasl.jaas.config=org.apache.kafka.common.security.oauthbearer.OAuthBearerLoginModule \\\n   required oauth.issuer.url=\"$ISSUER_URI\"\\\n   oauth.credentials.url=\"file:///pulsar/conf/creds.json\"\\\n   oauth.audience=\"$AUDIENCE\"\\\n   oauth.scope=\"$SCOPE\";\nEOF\n```\nThen, you can run the command to start the producer:\n```\ncd /pulsar/kafka/$KAFKA_VERSION; bin/kafka-console-producer.sh --bootstrap-server SSL://pulsar-proxy:9093 --topic test --producer.config /pulsar/kafka/$KAFKA_VERSION/config/producer.properties\n```\n14. Test S4K with token authentication on non-TLS endpoint:\n```\nSUPERUSER_TOKEN=$(\u003c/pulsar/token-superuser-stripped.jwt)\n\n# To test token auth on non-TLS endpoint:\ncat \u003c\u003c EOF \u003e /pulsar/kafka/$KAFKA_VERSION/config/producer.properties\nbootstrap.servers=pulsar-proxy:9092\ncompression.type=none\nsecurity.protocol=SASL_PLAINTEXT\nsasl.mechanism=PLAIN\nsasl.jaas.config=org.apache.kafka.common.security.plain.PlainLoginModule \\\n   required username=\"public/default\"\\\n   password=\"token:$SUPERUSER_TOKEN\";\nEOF\n\ncd /pulsar/kafka/$KAFKA_VERSION; bin/kafka-console-producer.sh --bootstrap-server PLAINTEXT://pulsar-proxy:9092 --topic test --producer.config /pulsar/kafka/$KAFKA_VERSION/config/producer.properties\n```\n15. Test S4K with token authentication on TLS endpoint:\n```\ncat \u003c\u003c EOF \u003e /pulsar/kafka/$KAFKA_VERSION/config/producer.properties\nbootstrap.servers=pulsar-proxy:9093\ncompression.type=none\nsecurity.protocol=SASL_SSL\nsasl.mechanism=PLAIN\nsasl.jaas.config=org.apache.kafka.common.security.plain.PlainLoginModule \\\nrequired username=\"public/default\" password=\"token:$SUPERUSER_TOKEN\";\nssl.truststore.location=/pulsar/tls.truststore.jks\n# The identification algorithm must be empty\nssl.endpoint.identification.algorithm=\nEOF\n\ncd /pulsar/kafka/$KAFKA_VERSION; bin/kafka-console-producer.sh --bootstrap-server SSL://pulsar-proxy:9093 --topic test --producer.config /pulsar/kafka/$KAFKA_VERSION/config/producer.properties\n```\n### Grafana dashboards for S4K\nAdditionally, if you want to monitor Grafana dashboards for S4K, you can download them via this command:\n```\ncd ~/Downloads; curl -LOs https://raw.githubusercontent.com/datastax/starlight-for-kafka/2.10_ds/grafana/dashboard.json\n```\nThen, after you port-forward or otherwise connect to Grafana, you can follow the UI to import the dashboard from this JSON file.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdatastax%2Fpulsar-helm-chart","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdatastax%2Fpulsar-helm-chart","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdatastax%2Fpulsar-helm-chart/lists"}