# Geo Replication on StreamNative Cloud
Source: https://docs.streamnative.io/cloud/clusters/cloud-geo-replication
Geo Replication on StreamNative Cloud provides an asynchronous mechanism for replicating data between geographically distributed Pulsar clusters. It is typically used for disaster recovery, enabling the replication of persistently stored message data across multiple data centers. For instance, your application is publishing data in one region and you would like to process it for consumption in other regions. With Pulsar's geo-replication mechanism, messages can be produced and consumed in different geo-locations.
## Components of Geo Replication
* Pulsar Instance: a Pulsar instance is a group of Pulsar clusters that function together as a unified entity. Multiple Pulsar clusters under the same Pulsar Instance are automatically configured for the Geo Replication.
* Pulsar Cluster: A Pulsar cluster is a messaging environment which can be distributed across geographical locations and can replicate among themselves using geo-replication.
* Replication policies: Geo-replication is managed at the namespace level or topic level which means you only need to create and configure a namespace or topic to replicate messages between two or more provisioned clusters that a tenant can access.
* Replicated subscriptions: Pulsar supports replicated subscriptions, so you can keep the subscription state in sync, within a sub-second timeframe, in the context of a topic that is being asynchronously replicated across multiple geographical regions.
## Cross-Cluster mTLS Authentication
StreamNative Cloud secures geo-replication traffic between clusters with mutual TLS (mTLS). Each Pulsar cluster is provisioned with its own dedicated `geo-replication-tls` certificate, scoped to that cluster only. This per-cluster certificate model isolates replication credentials, so a certificate event in one cluster does not affect other clusters in the same Pulsar Instance.
Per-cluster certificates also simplify rotation: certificates are issued, renewed, and revoked independently for each cluster, providing defense-in-depth across replicated clusters. No customer action is required—StreamNative Cloud manages the certificate lifecycle automatically.
* The first Pulsar cluster under the Instance can’t be deleted before the following created Pulsar clusters.
* API Key is not supported for the cross-cluster authentication if the existing TS channel Pulsar cluster exists under the Instance. Users should use the oauth2 as the cross-cluster authentication.
## Getting Started
**Create Pulsar Instance and first Pulsar cluster**
1. On the Cloud Console main page, click the **Create** icon to create a new Pulsar Instance and its first Pulsar cluster
2. Input the Pulsar Instance name and select the Cloud provider.
3. Input the Pulsar cluster name and select the location.
**Create the second Pulsar cluster under the Pulsar Instance**
1. Get into the Pulsar Instance page and click to create a new Pulsar cluster under the Instance
2. Input the second Pulsar cluster name
3. After Pulsar Clusters complete the deployment,clusters under the same Pulsar Instance are automatically configured for the Geo Replication.
**Grant permissions on Tenant**
1. Get into one Pulsar cluster and click the "Tenants" on the sidebar.
2. Click the "New Tenant" button and select the allowed clusters from the dropdown. Please note that only the selected allowed clusters could be configured the replication clusters could be used for message replication on the namespace level or topic level.
**Enable geo-replication at namespace level**
1. Get into the Tenant, and Click the "Namespaces" on the sidebar
2. Click the "New Namespace" button, select the replication clusters from the dropdown.
To create multiple Pulsar clusters under the Pulsar instance through the StreamNative Terraform Provider, just declare the `streamnative_pulsar_cluster` resource in the terraform file and set the `instance_name` and `depends_on` fields:
* `instance_name`: use the `streamnative_pulsar_instance` resource name.
* `depends_on`: use the first `streamnative_pulsar_cluster` resource name.
The full Terraform example:
```
resource "streamnative_pulsar_instance" "geo-instance" {
organization = "sndev"
name = "geo-instance"
availability_mode = "regional"
pool_name = "shared-aws"
pool_namespace = "streamnative"
}
resource "streamnative_pulsar_cluster" "us-east-cluster" {
organization = "sndev"
name = "us-east-cluster"
instance_name = streamnative_pulsar_instance.geo-instance.name
location = "us-east-2"
release_channel = "rapid"
bookie_replicas = 3
broker_replicas = 2
compute_unit = 0.3
storage_unit = 0.3
}
resource "streamnative_pulsar_cluster" "us-west-cluster" {
depends_on = [ streamnative_pulsar_cluster.us-east-cluster ]
organization = "sndev"
name = "us-west-cluster"
instance_name = streamnative_pulsar_instance.geo-instance.name
location = "us-east-2"
release_channel = "rapid"
bookie_replicas = 3
broker_replicas = 2
compute_unit = 0.3
storage_unit = 0.3
}
```
# Maintenance Notification
Source: https://docs.streamnative.io/cloud/clusters/cloud-maintenance-notification
## Overview
StreamNative Cloud performs regular maintenance on your Pulsar clusters and cloud environments to ensure their stability, security, and performance. The Maintenance Notification feature gives you a first-class view of planned and ongoing maintenance directly in the StreamNative Cloud Console. You can review what is changing, when it is scheduled, and — depending on your support plan — take action before the maintenance begins.
## Maintenance notifications
Please note that completed maintenance notices remain visible for the 90-day retention period
All maintenance notifications for your organization are listed on the **Maintenance Notices** page under **Organization Settings** > **Observability**. Notices are sorted with **Action Required** items at the top, so you can quickly see what needs your attention.
Click any notice to open the detail page. The detail page shows:
* **Change summary** — a description of what StreamNative is changing, such as the Pulsar version being upgraded or the configuration being applied.
* **Target resource** — the cluster or cloud environment affected by the maintenance.
* **Scheduled window** — the planned start and end time for the maintenance.
* **StreamNative owner** — the StreamNative team member responsible for the change.
* **Decision deadline** — the time by which you need to respond if the notice requires your action.
## Email notifications
StreamNative sends email notifications at key points in the maintenance lifecycle:
| Email | When it is sent |
| --------------------- | --------------------------------------------------------------------- |
| Initial notice | When a maintenance event requiring your attention is ready for review |
| Maintenance started | When the scheduled maintenance begins |
| Maintenance completed | When the maintenance finishes |
By default, emails are sent to the `technical contact` configured in your [Organization Profile](https://docs.streamnative.io/cloud/security/access/resource-hierarchy/organizations#organization-profile).
Please note that all future maintenance notifications will be sent by default to the technical contact. Make sure you have configured the correct technical contact email. If you want multiple people to receive the notifications, please create an email group and configure it here.
## Maintenance Notification and Maintenance Window
StreamNative's routine operational work — such as Pulsar version upgrades — follows the [Maintenance Window](/cloud/clusters/cloud-maintenance-window) you have configured for your cluster.
For maintenance events that require your explicit approval, you will receive an email and the notice will show an **Action Required** status in the console. You can respond directly from the detail page:
* **Approve** — confirm that StreamNative can proceed with the maintenance at the proposed time.
* **Reject** — decline the proposed maintenance. StreamNative will follow up to arrange a new time.
* **Reschedule** — submit your preferred time with an optional comment. StreamNative will review your request and confirm a new window.
If you do not respond before the decision deadline, the maintenance notification will be automatically rejected, and the maintenance will not proceed.
Please note that only users enrolled in the **Enterprise** or **Production** support plan tier could configure the maintenance window and use the **Approve**, **Reject**, and **Reschedule** actions to schedule the maintenance for your cluster. You can [contact StreamNative sales](https://www.streamnative.io/contact) to upgrade your support plan tier.
# Maintenance Window
Source: https://docs.streamnative.io/cloud/clusters/cloud-maintenance-window
## Overview
StreamNative Cloud performs regular maintenance to ensure the stability, performance, and security of the Pulsar cluster. During these periods, we perform updates, patches, and infrastructure improvements. This document outlines the process and best practices for managing maintenance windows.
Please note that only users enrolled in the **Enterprise** or **Production** support plan tier could configure the maintenance window to schedule the maintenance for your cluster. You can [contact StreamNative sales](https://www.streamnative.io/contact) to upgrade your support plan tier.
## What changes do and don't respect maintenance policies
With maintenance window, you can control the timing of the following types of events:
* Regular Pulsar cluster maintenance, including the Pulsar version upgrade or add some new features. The impact of change should be minimal and clients can handle gracefully.
Other types of maintenance aren't dependent on maintenance policies:
* Infrastructure Pools maintenance, including the including control plane upgrades, data plane upgrades which may cause temporary disruption to your cluster.
* Underlying Cloud services, primarily compute, network, storage.
With maintenance window, you can control the timing of the following types of events:
* Regular Pulsar cluster maintenance, including the Pulsar version upgrade or configuration changes. The impact of change should be minimal and clients can handle gracefully.
Other types of maintenance aren't dependent on maintenance policies:
* Infrastructure Pools maintenance, including the including control plane upgrades, data plane upgrades which may cause temporary disruption to your cluster.
* Underlying Cloud services, primarily compute, network, storage.
With maintenance window, you can control the timing of the following types of events:
* Regular Pulsar cluster maintenance, including the Pulsar version upgrade or configuration changes. The impact of change should be minimal and clients can handle gracefully.
* Infrastructure Pools maintenance, including the including control plane upgrades, data plane upgrades which may cause temporary disruption to your cluster.
Other types of maintenance aren't dependent on maintenance policies:
* Underlying Cloud services, primarily compute, network, storage.
## How to configure Maintenance windows
To configure the maintenance window when you create a Pulsar cluster, set the desired Maintenance window on the Cluster Operations.
When configuring maintenance windows:
* When configuring the maintenance window, the page will use your local time zone but transform into UTC before storing in the end.
* Select the maintenance window start time
* Select the maintenance window duration
* Check the permitted days for maintenance window
# Release Channel
Source: https://docs.streamnative.io/cloud/clusters/cloud-release-channel
## Introduction
Release channels in our platform provide users with the flexibility to choose between two main update streams: LTS (Long-Term Support) and Rapid. The LTS channel focuses on stability and long-term support, making it ideal for production environments that require minimal disruption. On the other hand, the Rapid channel offers access to the latest features and improvements at a faster pace, suitable for users who prioritize innovation and can adapt to frequent updates. This document aims to clarify the differences between these channels, helping users make informed decisions based on their specific requirements and use cases.
## Release Channel Overview
| Release Channel | Current version in channel |
| --------------- | -------------------------- |
| Rapid channel | `4.2.1.8` |
| LTS channel | `4.0.10.7` |
### LTS (Long-Term Support) Channel
* LTS releases prioritize stability and long-term API consistency.
* New features are introduced on a slower cadence.
* Non-GA (Generally Available) features are not accessible in LTS releases.
* LTS releases are recommended for production workloads and environments requiring stability and minimal disruption.
### Rapid Channel
* Rapid releases offer access to the latest features and improvements at a faster pace.
* New features are introduced approximately every three months.
* Users can access features in Private Preview or Public Preview through controlled flags.
* Rapid releases are suitable for users who prioritize innovation, are willing to adapt to frequent updates, and can accommodate potential changes in features and APIs.
### Channel limitation
* LTS channel clusters can't access the Private Preview or Public Preview features.
* There is a temporary restriction that the release channel cannot be changed after the cluster deployment. If you want to upgrade a cluster to a different release channel, please [reach out to the StreamNative support team](https://support.streamnative.io/hc/en-us/requests/new).
### Choose the release channel
In the [cluster provision process](/cloud/clusters/manage-clusters/cluster#create-a-cluster), there is a new step for selecting the release channel:
After cluster provision, you can view the current enrolled channel through the Configuration tab on the Pulsar Clusters page:
To specify the release channel when creating a Pulsar cluster using `snctl`, you can use the `--release-channel` flag. Here's how to do it:
1. Create a new Pulsar cluster with a specific release channel:
```
snctl create cluster --release-channel
```
Replace `` with your desired cluster name and `` with either `lts` or `rapid`.
For example, to create a cluster named "my-cluster" using the LTS channel:
```
snctl create pulsarcluster my-cluster --release-channel lts
```
2. View the release channel of an existing cluster:
```
snctl get pulsarcluster -o yaml
```
Look for the `releaseChannel` field in the output:
```yaml theme={null}
apiVersion: cloud.streamnative.io/v1alpha1
kind: PulsarCluster
metadata:
name: my-cluster
namespace:
spec:
releaseChannel: lts
```
3. If you need to update the release channel of an existing cluster, you can use the `patch` command:
```
snctl patch pulsarcluster --type merge -p '{"spec":{"releaseChannel":"rapid"}}'
```
Note: As mentioned in the channel limitation section, changing the release channel after deployment is currently restricted. Please contact StreamNative support if you need to change the release channel of an existing cluster.
Remember that the `releaseChannel` field in the PulsarCluster spec determines which channel the cluster will use for updates. The available options are `lts` for the Long-Term Support channel and `rapid` for the Rapid channel.
Alternatively, you can also include the release channel in the PulsarCluster custom resource YAML file when creating a new cluster:
```yaml theme={null}
apiVersion: cloud.streamnative.io/v1alpha1
kind: PulsarCluster
metadata:
name: my-cluster
namespace:
spec:
<...>
releaseChannel: lts
<...>
```
To specify the release channel when creating a cluster using [StreamNative Terraform Provider](https://registry.terraform.io/providers/streamnative/streamnative/latest), you can use the `release_channel` field in the `streamnative_pulsar_cluster` resource. Here's an example of how to structure the resource:
```hcl theme={null}
resource "streamnative_pulsar_cluster" "example" {
name = ""
namespace = ""
release_channel = "rapid"
}
```
For more details about how to create a cluster using StreamNative Terraform Provider, see [create a pulsar cluster](https://registry.terraform.io/providers/streamnative/streamnative/latest/docs/resources/pulsar_cluster). You can also find more examples in the [StreamNative Terraform Provider GitHub repository](https://github.com/streamnative/terraform-provider-streamnative/tree/main/examples).
## Key Considerations
### Stability
* Both LTS and Rapid channels provide stable releases.
* Stability is not compromised in either channel; the primary difference lies in the frequency of feature updates.
### Feature Availability
* **LTS**: Prioritizes stability over feature availability, with new features introduced on a yearly basis.
* **Rapid**: Offers the latest features and improvements every three months, allowing users to access cutting-edge functionalities.
### Support
* Both LTS and Rapid channels receive support.
* Users can expect assistance and maintenance regardless of the chosen release channel.
### Compatibility
* Rapid releases eventually transition into LTS releases, ensuring compatibility and forward version upgradeability.
* Users need to consider compatibility when selecting the appropriate release channel, especially for long-term projects and deployments.
## Recommendations
* **Active Development Projects**: The Rapid release channel is recommended for projects that are actively evolving and require access to the latest features and improvements.
* **Stable Environments**: The LTS release channel is suitable for stable environments and production workloads where long-term stability and minimal disruption are paramount.
## Best Practices
* **Clear Channel Mapping**: Ensure a clear mapping of clusters to different release channels, especially in environments with multiple Pulsar clusters.
* **Communication and Training**: Educate users about the implications of choosing between LTS and Rapid channels, including potential impacts on development workflows, feature availability, and long-term support.
* **Continuous Integration and Deployment (CI/CD)**: Incorporate release channel selection into CI/CD pipelines to ensure alignment with project requirements and compatibility considerations.
## Conclusion
Understanding the differences between LTS and Rapid release channels is essential for making informed decisions regarding software updates and maintenance. By aligning channel selection with project requirements and considering factors such as stability, feature availability, and compatibility, users can optimize their experience with our platform and maximize the value derived from new features and improvements.
# Cluster Profiles Overview
Source: https://docs.streamnative.io/cloud/clusters/cluster-profiles-overview
A cluster profile is a preconfigured performance and cost setting that determines how a data streaming cluster behaves based on its underlying storage, latency expectations, and workload characteristics. Each profile packages the right combination of infrastructure choices—such as disk-based storage for low-latency access or object storage for cost-efficient retention—to deliver a predictable experience without requiring users to tune individual parameters. By selecting a cluster profile, you can align your cluster with the needs of your applications, whether you prioritize real-time responsiveness, throughput, or cost optimization.
All cluster profiles run on the [URSA engine](/cloud/overview/data-streaming-engine), StreamNative Cloud's unified data streaming engine. The profile you pick determines the write-ahead log (WAL), metadata store, and supported protocols; the cluster type (Pulsar or Kafka) determines the API surface.
## Cluster profile types
StreamNative Cloud offers two cluster profiles. Pick the one that matches your workload's latency and cost priorities.
### Latency-Optimized profile
The Latency-Optimized cluster profile is designed for real-time, interactive, and mission-critical workloads that require consistently fast data access and low end-to-end latency. Backed by high-performance disk storage, this profile delivers predictable, single-digit to tens-of-milliseconds latency for producers and consumers, making it ideal for use cases such as event processing, fraud detection, user activity tracking, and any application where responsiveness directly impacts user experience or business outcomes. By prioritizing speed over cost, the Latency-Optimized profile ensures smooth, high-throughput performance even under demanding conditions.
Clusters using the Latency-Optimized profile are expected to deliver end-to-end latencies in the 5–200 millisecond range.
The infrastructure underpinning the Latency-Optimized profile varies by cluster type:
* **Pulsar Clusters** use Apache BookKeeper as the low-latency WAL. The metadata store is ZooKeeper by default; Oxia is available on request. Pulsar Clusters support the native Pulsar protocol, and the Kafka protocol is available through the [KSN](/kafka/kafka-cluster-vs-ksn) protocol handler with full Kafka feature parity. Lakehouse integration (Iceberg, Delta) is built in via the URSA storage layer.
* **Kafka Clusters** use KRaft and local disks as the low-latency WAL, delivering native Apache Kafka with the full Kafka feature set. Lakehouse integration is built in.
### Cost-Optimized profile
The Cost-Optimized cluster profile is engineered for throughput-intensive and cost-sensitive workloads that benefit from large-scale, durable, and economical object storage. While this profile accepts higher access latencies—typically in the hundreds of milliseconds—it provides significant cost savings and unlimited scalability, making it a strong fit for data pipelines, analytics sinks, long-term retention, and applications that do not require ultra-fast consumption. By leveraging object storage, the Cost-Optimized profile offers an efficient balance of price, durability, and flexibility for workloads where latency tolerance is higher and storage economics matter most.
Clusters using the Cost-Optimized profile are expected to deliver end-to-end latencies above 200 milliseconds.
The infrastructure underpinning the Cost-Optimized profile uses object storage—such as Amazon S3, Google Cloud Storage, or Azure Blob Storage—as the WAL, and Oxia as the metadata store. The capabilities exposed vary by cluster type:
* **Pulsar Clusters** currently expose the **Kafka-compatible protocol only** on the Cost-Optimized profile. Native Pulsar protocol support for this profile is coming after the Apache Pulsar 5.0 release. Lakehouse integration is built in.
* **Kafka Clusters** expose the native Kafka protocol with lakehouse integration built in. Kafka transactions and topic compaction on the Cost-Optimized profile are coming soon.
## Pulsar Clusters
Pulsar Clusters support all three deployment options. Serverless automatically manages performance and cost characteristics without user-defined profiles.
On Pulsar Clusters, the Cost-Optimized profile currently supports the Kafka-compatible protocol only. Native Pulsar protocol support for this profile is coming after the Apache Pulsar 5.0 release.
### Supported deployment options
| Deployment option | Latency-Optimized | Cost-Optimized |
| ------------------------------- | ----------------- | --------------------------- |
| **Serverless** | N/A | N/A |
| **Dedicated** | Supported | Not supported (Coming soon) |
| **Bring Your Own Cloud (BYOC)** | Supported | Supported\* |
\* Cost-Optimized BYOC Pulsar Clusters currently support the Kafka-compatible protocol only. Native Pulsar protocol support is coming after the Apache Pulsar 5.0 release.
### Supported features by deployment type
Cluster profiles do not apply to Serverless deployments. Serverless automatically manages performance and cost characteristics without user-defined profiles.
| Category | Features |
| --------------------- | ------------------------------------------------------------------- |
| **Protocol** | Pulsar (native), Kafka (via KSN, with full Kafka feature parity) |
| **Table formats** | Delta, Iceberg |
| **Catalog** | Unity Catalog, Snowflake Horizon Catalog, S3 Tables, Google BigLake |
| **Storage** | Disk (internal only) |
| **Availability Zone** | Single AZ (internal only) |
The Cost-Optimized profile is coming soon on Dedicated Pulsar Clusters. The table below lists the features available today on the Latency-Optimized profile.
| Category | Latency-Optimized profile |
| --------------------- | ------------------------------------------------------------------- |
| **Protocol** | Pulsar (native), Kafka (via KSN, with full Kafka feature parity) |
| **Table formats** | Delta, Iceberg |
| **Catalog** | Unity Catalog, Snowflake Horizon Catalog, S3 Tables, Google BigLake |
| **WAL** | Apache BookKeeper |
| **Metadata store** | ZooKeeper (default); Oxia on request |
| **Availability Zone** | Single AZ (Not available), Multi AZ |
| Category | Latency-Optimized profile | Cost-Optimized profile |
| --------------------- | ------------------------------------------------------------------- | ------------------------------------------------------------------- |
| **Protocol** | Pulsar (native), Kafka (via KSN, with full Kafka feature parity) | Kafka-compatible (Pulsar protocol coming after Pulsar 5.0) |
| **Table formats** | Delta, Iceberg | Delta, Iceberg |
| **Catalog** | Unity Catalog, Snowflake Horizon Catalog, S3 Tables, Google BigLake | Unity Catalog, Snowflake Horizon Catalog, S3 Tables, Google BigLake |
| **WAL** | Apache BookKeeper | Object Storage (Amazon S3, Google Cloud Storage, Azure Blob) |
| **Metadata store** | ZooKeeper (default); Oxia on request | Oxia |
| **Availability Zone** | Single AZ (Not available), Multi AZ | Single AZ (Not available), Multi AZ |
## Kafka Clusters
Kafka Clusters are currently in Public Preview. For a comparison with Kafka compatibility on Pulsar Clusters (KSN), see [Kafka Cluster vs. KSN](/kafka/kafka-cluster-vs-ksn).
Kafka transactions and topic compaction on the Cost-Optimized profile are coming soon. Use the Latency-Optimized profile today if your workloads require these features.
Kafka Clusters run native Apache Kafka on the URSA engine and support both cluster profiles. Serverless support is planned.
### Supported deployment options
| Deployment option | Latency-Optimized | Cost-Optimized |
| ------------------------------- | ----------------- | -------------- |
| **Serverless** | Coming soon | Coming soon |
| **Dedicated** | Supported | Supported |
| **Bring Your Own Cloud (BYOC)** | Supported | Supported |
### Supported features by deployment type
Serverless support for Kafka Clusters is coming soon.
| Category | Latency-Optimized profile | Cost-Optimized profile |
| --------------------- | ------------------------------------------------------------------- | ------------------------------------------------------------------- |
| **Protocol** | Kafka (native) | Kafka (native) |
| **Table formats** | Delta, Iceberg | Delta, Iceberg |
| **Catalog** | Unity Catalog, Snowflake Horizon Catalog, S3 Tables, Google BigLake | Unity Catalog, Snowflake Horizon Catalog, S3 Tables, Google BigLake |
| **WAL** | Local disk (KRaft + ISR) | Object Storage (Amazon S3, Google Cloud Storage, Azure Blob) |
| **Metadata store** | KRaft | Oxia |
| **Caveats** | — | Kafka transactions and topic compaction coming soon |
| **Availability Zone** | Single AZ (Not available), Multi AZ | Single AZ (Not available), Multi AZ |
| Category | Latency-Optimized profile | Cost-Optimized profile |
| --------------------- | ------------------------------------------------------------------- | ------------------------------------------------------------------- |
| **Protocol** | Kafka (native) | Kafka (native) |
| **Table formats** | Delta, Iceberg | Delta, Iceberg |
| **Catalog** | Unity Catalog, Snowflake Horizon Catalog, S3 Tables, Google BigLake | Unity Catalog, Snowflake Horizon Catalog, S3 Tables, Google BigLake |
| **WAL** | Local disk (KRaft + ISR) | Object Storage (Amazon S3, Google Cloud Storage, Azure Blob) |
| **Metadata store** | KRaft | Oxia |
| **Caveats** | — | Kafka transactions and topic compaction coming soon |
| **Availability Zone** | Single AZ (Not available), Multi AZ | Single AZ (Not available), Multi AZ |
## Next
* [Cluster Types and Regions](/cloud/clusters/cluster-types)
* [Kafka Cluster Guide](/kafka/kafka-cluster-guide)
* [Kafka Cluster vs. KSN](/kafka/kafka-cluster-vs-ksn)
* [Choose Kafka or Pulsar](/cloud/overview/choose-kafka-or-pulsar)
# Cluster Types & Regions in StreamNative Cloud
Source: https://docs.streamnative.io/cloud/clusters/cluster-types
StreamNative offers various cluster types in the StreamNative Cloud. The type of cluster you choose impacts its features, capabilities, and cost. Use this guide to identify the cluster that best meets your requirements.
StreamNative Cloud supports both **Kafka Clusters** and **Pulsar Clusters**. Kafka Clusters run native Apache Kafka protocol, while Pulsar Clusters support Pulsar protocol natively with optional Kafka compatibility through KSN. For help choosing between them, see [Choose Kafka or Pulsar](/cloud/overview/choose-kafka-or-pulsar).
For deployment models, use Serverless clusters for experimentation and early development. For a production cluster, choose from Dedicated (formerly Hosted) clusters, BYOC, or BYOC Pro clusters.
Native Kafka Clusters are currently available on Dedicated and BYOC deployment models. Serverless support for Kafka Clusters is coming soon.
The table below offers a high-level comparison of features across StreamNative Cloud cluster types.
| Category | Feature | Serverless | Dedicated | BYOC | BYOC Pro |
| -------------------------------------------------------- | ----------------------------------------------- | --------------------------------------------------- | --------------------------------------------------- | --------------------------------------------------- | --------------------------------------------------- |
| **Cluster Service** | Single AZ Clusters | N/A | Yes | Yes | Yes |
| | Multi-AZ Clusters | N/A | Yes | Yes | Yes |
| | Uptime SLA | 99.9% | 99.5% Single AZ / 99.99% Multi AZ² | 99.5% Single AZ / 99.99% Multi AZ | 99.5% Single AZ / 99.99% Multi AZ² |
| | Unlimited Pulsar Clusters | Yes | Yes | Yes | Yes |
| | Autoscaling | On by default | Configurable | Configurable | Configurable |
| | Latency Optimized Profile | N/A | Yes | Yes | Yes |
| | Cost Optimized Profile | N/A | Coming Soon | Yes | Yes |
| | Geo-Replication | Yes | Yes | Yes | Yes |
| **Infrastructure & Provisioning & Network Connectivity** | Supported Cloud Providers | AWS, GCP, Azure | AWS, GCP, Azure | AWS, GCP, Azure | AWS, GCP, Azure |
| | Choose any cloud region | No | No¹ | Yes | Yes |
| | Dedicated VPC | No | Yes | Yes | Yes |
| | Private Link | No | Pro only | Yes | Yes |
| | VPC/VNet Peering | No | Pro only | No | Yes |
| | Transit Gateway | No | Pro only | No | Yes |
| | Bring Your Own Network (BYON) | No | No | No | Yes |
| | Bring Your Own Domain (Custom DNS) | No | No | No | Yes |
| **Observability** | Metrics API | Yes | Yes | Yes | Yes |
| | Remote writes to external observability systems | No | Pro only | No | Yes |
| **Maintenance & Operations** | Custom Maintenance Window | `Production` or `Enterprise` Support Plan tier only | `Production` or `Enterprise` Support Plan tier only | `Production` or `Enterprise` Support Plan tier only | `Production` or `Enterprise` Support Plan tier only |
| **Multi-Protocol Support** | Pulsar | Yes | Yes | Yes | Yes |
| | Kafka | Yes | Yes | Yes | Yes |
| | MQTT | Yes | Yes | Yes | Yes |
| | WebSocket | Yes | Yes | Yes | Yes |
| | REST | Yes | Yes | Yes | Yes |
| **Connectivity and Processing** | Pulsar IO (Built-in & Custom) | Yes | Yes | Yes | Yes |
| | Kafka Connect (Built-in & Custom) | Yes | Yes | Yes | Yes |
| | Pulsar Functions | Yes | Yes | Yes | Yes |
| | Managed Flink | No | No | Yes (Private Preview) | Yes (Private Preview) |
| | Trusted Mode for Pulsar Functions and Pulsar IO | No | No | No | Yes |
| **Data Storage** | Tiered Storage | Transparent | Transparent | Your Bucket | Your Bucket |
| | Data Backup and Recovery | No | No | No | yes |
| **Security** | Multi-tenancy | Yes | Yes | Yes | Yes |
| | Authentication | Yes | Yes | Yes | Yes |
| | Authorization | Yes | Yes | Yes | Yes |
| | Audit Logs | Yes | Yes | Yes | Yes |
| | Data-at-rest Encryption | Yes | Yes | Yes | Yes |
| | TLS Encryption | Yes | Yes | Yes | Yes |
| | End-to-end Encryption | Yes | Yes | Yes | Yes |
| | Bring Your Own Key | No | Pro only | No | Yes |
| \*\* | | | | | |
The capabilities provided in this topic are for planning purposes, and are not a guarantee of performance, which varies depending on each unique configuration.
¹ Contact [StreamNative support](https://support.streamnative.io/hc/en-us/requests/new) for custom region requirements in Dedicated clusters.
² Dedicated Pro and BYOC Pro geo-replicated clusters achieve a 99.999% uptime SLA.
## Serverless Clusters
Serverless clusters are the newest addition to StreamNative Cloud, offering a fully managed, auto-scaling solution with minimal operational overhead. Key features include:
1. Instant provisioning with a minimum base cost of 1 ETU
2. Automatic scaling based on your workload, with billing only for resources used.
3. Simplified management with StreamNative handling all infrastructure concerns.
4. Ideal for development, testing, and production workloads with variable traffic patterns.
StreamNative uses [Elastic Throughput Units (ETUs)](/cloud/billing/billing-overview#elastic-throughput-unit-etu) to provision and bill for the Serverless clusters.
### ETU limits per Serverless cluster
Serverless clusters are elastic, shrinking and expanding automatically based on load. You don't need to size your cluster. When you need more capacity, your Serverless cluster expands up to the fixed maximum. When no capacity is in use, a minimum charge of 1 ETU applies.
**Serverless cluster capacity**
| Dimension | Minimum | Maximum |
| --------- | ------- | ------- |
| ETUs | 1 | 20 |
If no capacity is consumed, the system defaults to a minimum billing level of 1 ETU. For more information, see [Elastic Throughput Unit (ETU)](/cloud/billing/billing-overview#elastic-throughput-unit-etu).
### ETU capacity guidance
The dimensions in the following table describe the capacity of a single ETU. For more information about ETU, see [Elastic Throughput Unit (ETU)](/cloud/billing/billing-overview#elastic-throughput-unit-etu) and [ETU vs CU/SU](/cloud/billing/billing-overview#etu-vs-cu-su).
| Dimension | ETU Capacity |
| ----------------- | ------------------------------ |
| Ingress (Data In) | 5 megabytes per second (MBps) |
| Egress (Data Out) | 15 megabytes per second (MBps) |
| Data Entries | 500 entries per second |
### Serverless limits per cluster
| Dimension | Capability | Additional details |
| ----------------- | --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Ingress (Data In) | Max 100 MBps | Number of bytes that can be produced to the cluster in one second. To reduce usage on this dimension, you can compress your messages. `lz4` is recommended for compression. |
| Egress (Data Out) | Max 300 MBps | Number of bytes that can be consumed from the cluster in one second. To reduce usage on this dimension, you can compress your messages and ensure each consumer is only consuming from the topics it requires. `lz4` is recommended for compression. |
| Data Entries | Max 10,000 per second | Number of data entries produced to and consumed from the cluster in one second. Each data entry represents a batch of messages. Both Pulsar and Kafka clients do batching at the client side. To reduce usage on this dimension, you can adjust producer batching configurations and shut down otherwise inactive clients. |
### Serverless limits per partition
The partition capabilities that follow are based on benchmarking and intended as practical guidelines for planning purposes. Performance per partition will vary based on your specific configuration, and these benchmarks do not guarantee performance.
| Dimension | Capability |
| --------------------- | ---------- |
| Ingress per partition | 5 MBps |
| Egress per partition | 15 MBps |
| Storage per partition | Unlimited |
### Serverless Cloud Providers & Regions
Serverless clusters are currently available in limited regions. Please check the [StreamNative Cloud console](/cloud/get-started/cloud-console) for the most up-to-date information on available regions.
### Serverless Features and Usage Limits
Here are some guidelines for the serverless cluster limits:
The following max capacity is a guidance. Whether your serverless cluster can reach such capacity depending on the workload, number of topics, number of connections, and etc. If you want more predictable capacity, please contact StreamNative Sales
| Dimension | Capability | Additional details |
| ------------ | --------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Ingress | Max 100 MBps | Number of bytes that can be produced to the cluster in one second. To reduce usage on this dimension, you can compress your messages. `lz4` is recommended for compression. |
| Egress | Max 300 MBps | Number of bytes that can be consumed from the cluster in one second. To reduce usage on this dimension, you can compress your messages and ensure each consumer is only consuming from the topics it requires. `lz4` is recommended for compression. |
| Storage | Unlimited | Number of bytes retained on the cluster, pre-replication. You can configure retention policy settings at namespace or topic level so you can control exactly how much and how long to retain data in a way that makes sense for your applications and helps control your costs. To reduce usage on this dimension, you can compress your messages and reduce your retention settings. `lz4` is recommended for compression. |
| Data Entries | Max 10,000 per second | Number of data entries produced to and consumed from the cluster in one second. Each data entry represents a batch of messages. To reduce usage on this dimension, you can adjust producer batching configurations and shut down otherwise inactive clients. |
| Message size | Max 5 MB | None |
In addition to the usage limits, there are some additional limitations in features:
1. Tiered Storage is transparent, meaning you don't need to configure it. However, Serverless clusters don't support bringing your own bucket. If you need to use your own object storage bucket, you should consider using [BYOC](#byoc-clusters) or [BYOC Pro](#byoc-pro-clusters) clusters.
2. Serverless clusters use [Rapid Release Channel](/cloud/clusters/cloud-release-channel) by default. You can't choose a different release channel.
3. [Auto-scaling](/cloud/clusters/scale-clusters/cloud-autoscaling) is enabled by default. You don't need to configure it.
4. Remote writes to external observability systems are not supported.
5. Custom maintenance windows are not available.
6. Private networking options are not available.
## Dedicated Clusters
Dedicated (formerly Hosted) clusters are fully managed on StreamNative's cloud infrastructure. They support the following capabilities:
1. Deployment in supported regions on AWS, GCP, and Azure with [a 99.95% uptime SLA for Single-Zone and 99.99% for Multi-Zone](https://streamnative.io/pricing).
2. Optional multi-zone high availability, spreading a cluster across three availability zones for enhanced resilience.
3. Simplified scaling in terms of [Compute Units (CUs) and Storage Units (SUs)](/cloud/billing/billing-overview#cu-and-su).
4. Programmable or [automatic scaling](/cloud/clusters/scale-clusters/cloud-autoscaling) options.
### Dedicated Pro Offering
StreamNative offers a **Pro** offering within Dedicated clusters that provides enhanced networking and security capabilities for enterprise workloads. Dedicated Pro includes:
* **Private Link**: Secure private connectivity to your cluster
* **VPC/VNet Peering**: Connect your cluster to your existing network infrastructure
* **Transit Gateway**: Advanced network routing and connectivity options
* **Remote writes**: Send metrics to external observability systems
* **Managed Flink**: Stream processing capabilities (Private Preview, currently GCP only)
* **Bring Your Own Key**: Use your own encryption keys for data-at-rest encryption
Dedicated Pro maintains the same uptime SLAs and scaling capabilities as standard Dedicated clusters while providing additional enterprise-grade features.
### Dedicated Cloud Providers & Regions
The following is a list of cloud providers along with the regions and zones supported for Dedicated (formerly Hosted) Clusters:
#### AWS
| Identifier | Location |
| -------------- | --------------------- |
| ap-southeast-2 | Asia Pacific (Sydney) |
| eu-central-1 | Europe (Frankfurt) |
| eu-west-1 | Europe (Ireland) |
| us-east-2 | US East (Ohio) |
#### GCP
| Identifier | Location |
| ------------ | ----------------------------------- |
| europe-west1 | St. Ghislain, Belgium, Europe |
| us-central1 | Council Bluffs, Iowa, North America |
#### Azure
| Identifier | Location |
| ---------- | -------- |
| eastus | US East |
If you need to deploy a Dedicated cluster in a region not listed above, [contact StreamNative support](https://support.streamnative.io/hc/en-us/requests/new) to discuss your requirements. We may be able to accommodate specific region requests for Dedicated clusters.
### Dedicated Features and Usage Limits
The following table outlines the features and usage limits for the Dedicated (formerly Hosted) Clusters:
| Type |
Features |
Capability |
| Service |
Uptime SLA |
99.95% |
| Multi AZ |
99.99% |
| Scale |
Throughput limit per topic |
Max 100 MBps |
| Storage limit per topic |
Max 1000 TB |
| Tenant limit |
Max 128 |
| Namespace limit |
Max 1024 |
| Topic limit |
Max 10240 |
| Cloud providers |
GCP |
Yes |
| AWS |
Yes |
| Azure |
Yes |
In addition to the above, there are additional limitations in Dedicated (formerly Hosted) clusters:
1. Tiered Storage is transparent, meaning you don't need to configure it. However, Dedicated clusters don't support bringing your own bucket. If you need to use your own bucket, you should consider using [BYOC](#byoc-clusters) or [BYOC Pro](#byoc-pro-clusters) clusters.
2. Remote writes to external observability systems are only available in Dedicated Pro.
3. Custom maintenance windows are not available.
4. Private networking options (Private Link, VPC/VNet Peering, Transit Gateway) are only available in Dedicated Pro.
## BYOC Clusters
BYOC clusters are designed for production-ready deployments in your Cloud account, tailored to meet your data security, compliance, and sovereignty requirements. They offer the following capabilities:
1. Dedicated deployments in your chosen region within your cloud account (AWS, GCP, Azure) with [a 99.5% uptime SLA for Single-Zone and 99.99% for Multi-Zone](https://streamnative.io/pricing).
2. Private networking options including AWS PrivateLink, Azure PrivateLink, and GCP Private Service Connect.
3. Optional multi-zone high availability, spreading a cluster across three availability zones for increased resilience.
4. Simplified scaling in terms of CUs and SUs.
5. Programmable or [automatic scaling](/cloud/clusters/scale-clusters/cloud-autoscaling) options.
6. You can choose between **Latency Optimized Profile** and **Cost Optimized Profile**.
StreamNative uses [CU/SU](/cloud/billing/billing-overview#cu-and-su) to bill for the clusters with **Latency Optimized Profile** and uses [Elastic Throughput Units (ETUs)](/cloud/billing/billing-overview#elastic-throughput-unit-etu) to bill for the clusters with **Cost Optimized Profile**.
### BYOC Cloud Providers & Regions
A BYOC cluster can be deployed in any selected region in your cloud account across AWS, GCP, and Azure.
### BYOC Features and Usage Limits
1. The performance limit is majorly bound by the underlying resources of your cloud account.
2. You can use your own S3-compatible storage bucket for the clusters with **Cost Optimized Profile** or **Lakehouse tiered storage** for the clusters with **Latency Optimized Profile**.
3. You can use your own keys for data-at-rest encryption.
4. Only PrivateLink is supported for private networking. Other private networking options are not supported. You can manually configure them if you choose to use a different private networking option, but it will be out of scope for StreamNative support.
5. Geo-replication via private networking is not supported. Only public networking geo-replication is supported. If you need geo-replication via private networking, you should consider using [BYOC Pro](#byoc-pro-clusters).
6. Remote writes to external observability systems are not supported.
7. Custom maintenance windows are not available.
8. Bring Your Own Network (BYON) is not supported. Only StreamNative-managed VPCs are available.
9. Custom DNS (Bring Your Own Domain) is not supported.
### ETU capacity guidance
The dimensions in the following table describe the capacity of a single ETU in a BYOC cluster. For more information about ETUs, see [Elastic Throughput Unit (ETU)](/cloud/billing/billing-overview#elastic-throughput-unit-etu) and [ETU vs CU/SU](/cloud/billing/billing-overview#etu-vs-cu-su).
| Dimension | ETU Capacity |
| ----------------- | ------------------------------ |
| Ingress (Data In) | 25 megabytes per second (MBps) |
| Egress (Data Out) | 75 megabytes per second (MBps) |
| Data Entries | 2500 entries per second |
## BYOC Pro Clusters
BYOC Pro Clusters are designed for critical production workloads and offer enhanced security and networking features, including:
1. Advanced private networking options like VPC/VNet Peering and Transit Gateway.
2. Remote writes to external observability systems.
3. Self-managed keys (Bring-Your-Own-Key) for AWS, Azure, or GCP.
4. Bring Your Own Network (BYON) — use your own VPC/VNet instead of a StreamNative-managed VPC.
5. Custom DNS (Bring Your Own Domain) — use your own DNS zone for cluster endpoints.
**Lakehouse tiered storage** is available in both BYOC standard and BYOC Pro clusters, allowing you to use your own S3-compatible storage bucket for the **Cost Optimized Profile** or **Lakehouse tiered storage** for the **Latency Optimized Profile**.
Similar to BYOC clusters, BYOC Pro uses [CU/SU](/cloud/billing/billing-overview#cu-and-su) to bill for clusters with **Latency Optimized Profile** and uses [Elastic Throughput Units (ETUs)](/cloud/billing/billing-overview#elastic-throughput-unit-etu) for clusters with **Cost Optimized Profile**.
### BYOC Pro Cloud Providers & Regions
BYOC Pro Clusters can be deployed in any selected region in your cloud account across AWS, GCP, and Azure.
### BYOC Pro Features and Usage Limits
BYOC Pro is the most secure and flexible option, which provides you with full control over your data and network configurations.
1. The performance limit is majorly bound by the underlying resources of your cloud account.
2. You can use your own S3-compatible storage bucket for the clusters with **Cost Optimized Profile** or **Lakehouse tiered storage** for the clusters with **Latency Optimized Profile**.
3. You can use your own keys for data-at-rest encryption.
4. Private Link, VPC/VNet Peering, and Transit Gateway are supported for private networking.
5. Geo-replication via private networking is supported.
### ETU capacity guidance
The dimensions in the following table describe the capacity of a single ETU in a BYOC Pro cluster with **Cost Optimized Profile** . For more information about ETUs, see [Elastic Throughput Unit (ETU)](/cloud/billing/billing-overview#elastic-throughput-unit-etu) and [ETU vs CU/SU](/cloud/billing/billing-overview#etu-vs-cu-su).
| Dimension | ETU Capacity |
| ----------------- | ------------------------------ |
| Ingress (Data In) | 25 megabytes per second (MBps) |
| Egress (Data Out) | 75 megabytes per second (MBps) |
| Data Entries | 2500 entries per second |
# Cluster Configuration Overview
Source: https://docs.streamnative.io/cloud/clusters/configure-clusters/cluster-configuration-overview
The `config` section in a PulsarCluster specification allows users to configure the features and settings to be used for their Pulsar cluster. This topic aims to provide a comprehensive overview of the available configuration options, helping users tailor their Pulsar clusters to specific requirements and use cases.
## Available Configuration Options
The available settings in `config` section in a PulsarCluster specification can be grouped into the following three categories:
1. **Cluster Features**: These settings control the various features and functionalities of your Pulsar cluster.
2. **Protocols**: This setting allows you to configure the supported protocols for your Pulsar cluster, including Kafka, AMQP, MQTT, and Websocket.
3. **Cluster Settings**: This setting allows you to configure custom cluster settings for your Pulsar cluster.
The detailed descriptions of the available settings are as follows:
The `config` section in a PulsarCluster specification includes the following key components:
| Category | Configuration Option | Description |
| --------- | -------------------- | -------------------------------------------------- |
| Features | FunctionEnabled | Controls whether Pulsar Functions are enabled |
| Features | TransactionEnabled | Controls whether Pulsar Transactions are enabled |
| Features | AuditLog | Configures audit log settings |
| Protocols | Protocols | Configures supported protocols (Kafka, AMQP, MQTT) |
| Protocols | WebsocketEnabled | Controls whether WebSocket protocol is enabled |
| Settings | Custom | Allows for custom cluster settings |
## Update Cluster Configuration
To update the cluster configuration, you can use one of the following methods:
In the [cluster provision process](/cloud/clusters/manage-clusters/cluster#create-a-cluster), when you select a release channel, you can choose to enable or disable the cluster features and protocols based on your requirements. You can also click the "Add optional custom configuration" to set custom cluster settings for your Pulsar cluster.
After cluster is provisioned, you can view the current cluster configuration through the "Configuration" page of your Pulsar cluster. You can also update the cluster configuration by clicking the "Edit Cluster" button at the top right corner of the page. You will be redirected to the same configuration page you see in the provision process, where you can make the desired changes to the configuration options.
To update the cluster configuration using `snctl`:
1. Ensure you have the latest version of [`snctl`](/tools/cli/snctl/snctl-overview) installed and configured.
2. Update the PulsarCluster CRD file (e.g., `.yaml`) with the desired configuration options.
```yaml theme={null}
apiVersion: pulsar.streamnative.cloud/v1beta1
kind: PulsarCluster
metadata:
name:
spec:
config:
# Add your desired configuration options here
functionEnabled: true
transactionEnabled: true
<...>
```
3. Apply the updated PulsarCluster CRD file to the cluster:
```bash theme={null}
snctl apply -f .yaml
```
To view the cluster configuration, you can use the following command:
```bash theme={null}
snctl get pulsarcluster -o yaml
```
To update the cluster configuration using the StreamNative Terraform Provider:
1. Ensure you have the [StreamNative Terraform Provider](https://registry.terraform.io/providers/streamnative/streamnative/latest) configured in your environment.
2. Use the `streamnative_pulsar_cluster` resource to define or update your cluster configuration.
3. Specify the desired configuration options within the `config` block.
Here's an example of how to update the cluster configuration using Terraform:
```hcl theme={null}
resource "streamnative_pulsar_cluster" "example" {
name = "example"
config {
websocket_enabled = true
transaction_enabled = true
<...>
}
}
```
To apply the changes, run the following command:
```bash theme={null}
terraform apply
```
To view the cluster configuration, you can use the following command:
```bash theme={null}
terraform show
```
For more details, please refer to the [StreamNative Terraform Provider documentation](https://registry.terraform.io/providers/streamnative/streamnative/latest). See [a complete example](https://github.com/streamnative/terraform-provider-streamnative/blob/main/examples/pulsarclusters/hosted.tf) in the StreamNative Terraform Provider GitHub repository.
Please note that not all configuration options are modifiable. Some settings are determined by the release channel you selected during the cluster provision process and cannot be changed. Updating the cluster configuration will cause the cluster to roll restart all the brokers. Please make sure to update the cluster configuration during off-peak hours to avoid any disruptions to your service.
## Next Steps
* [Configure Cluster Features](/cloud/clusters/configure-clusters/configure-cluster-features)
* [Configure Protocols](/cloud/clusters/configure-clusters/configure-protocols)
* [Configure Cluster Settings](/cloud/clusters/configure-clusters/configure-cluster-settings)
# Configure Cluster Features
Source: https://docs.streamnative.io/cloud/clusters/configure-clusters/configure-cluster-features
This topic describes how to enable, disable, and configure cluster features for your cluster. For general guidance on configuring your cluster, see [Cluster Configuration Overview](/cloud/clusters/configure-clusters/cluster-configuration-overview).
To protect running workloads, the Cloud Console blocks both disabling and deleting a cluster feature while active resources are still attached to it. Remove or migrate the dependent resources first, then retry the disable or delete action.
The following features are available for configuration:
1. [Pulsar Functions](#pulsar-functions)
2. [Pulsar Transactions](#pulsar-transactions)
3. [Audit Log](#audit-log)
4. [Auto Scaling](#auto-scaling)
## Pulsar Functions
[Pulsar Functions](/cloud/process/pulsar-functions/functions-overview) allow you to process messages as they move between topics and external systems. This feature can be enabled or disabled for your cluster.
To enable Pulsar Functions for your cluster, you can set the `config.functionEnabled` field in your PulsarCluster specification to `true` if you are using `snctl` or `config.function_enabled` field in your PulsarCluster specification to `true` if you are using Terraform.
Please note that if you disable Pulsar Functions, you will not able to create new functions in the cluster. Existing functions will continue to run and process messages until they are deleted, but they are not be managed or monitored anymore.
## Pulsar Transactions
[Pulsar Transactions](/cloud/build/pulsar-clients/transactions-overview) provide atomic operations across multiple topics and partitions. This feature can be enabled or disabled for your cluster.
To enable Pulsar Transactions for your cluster, you can set the `config.transactionEnabled` field in your PulsarCluster specification to `true` if you are using `snctl` or `config.transaction_enabled` field in your PulsarCluster specification to `true` if you are using Terraform.
Please note that if you disable Pulsar Transactions on your cluster where you have enabled it before, you are not recommended to disable it because you will disrupt the existing applications that are using transactions and corrupt the data.
## Audit Log
[Audit logging](/cloud/security/monitor-activity/cloud-audit-log) helps track and record important events and actions within your Pulsar cluster. You can configure audit log settings for enhanced monitoring and compliance.
To configure audit logging for your cluster, you can use the `config.auditLog` field in your PulsarCluster specification. The audit log configuration allows you to specify which categories of events you want to log.
Here's how you can configure audit logging:
1. Using `snctl`:
```yaml theme={null}
apiVersion: cloud.streamnative.io/v1alpha1
kind: PulsarCluster
metadata:
name: my-cluster
spec:
config:
auditLog:
categories:
- 'Management'
- 'Describe'
- 'Produce'
- 'Consume'
```
2. Using Terraform:
```hcl theme={null}
resource "streamnative_cluster" "my_cluster" {
# ... other configuration ...
config {
audit_log {
categories = [
"Management",
"Describe",
"Produce",
"Consume"
]
}
}
}
```
The `categories` field is a list of strings that specify which types of events you want to include in the audit log. See the [Audit Log Overview](/cloud/security/monitor-activity/cloud-audit-log) for more details on the available categories.
You can add or remove categories based on your specific auditing needs. The exact list of available categories may depend on your StreamNative Cloud version, so consult the [documentation](/cloud/security/monitor-activity/cloud-audit-log) for a complete list of supported categories.
Note that enabling extensive audit logging may have performance implications and increase storage requirements. It's recommended to carefully consider which categories are necessary for your use case and compliance requirements.
To disable audit logging, you can remove the `config.auditLog` field in your PulsarCluster specification.
## Auto Scaling
Auto-scaling is a cluster-level feature that allows you to dynamically adjust the number of Broker nodes. You can refer [Configure Auto-Scaling](/cloud/clusters/scale-clusters/cloud-autoscaling) for more details.
# Configure Cluster Settings
Source: https://docs.streamnative.io/cloud/clusters/configure-clusters/configure-cluster-settings
This topic describes how to configure different cluster settings for your StreamNative Cloud clusters.
## Update cluster settings
To configure the cluster configuration, you can add the key-value setting pair to the `config.custom` field in the `PulsarCluster` specification.
For example, to configure the `ttlDurationDefaultInSeconds` setting via `snctl`, you can add the following to the `PulsarCluster` specification:
```yaml theme={null}
apiVersion: cloud.streamnative.io/v1alpha1
kind: PulsarCluster
metadata:
name: my-cluster
spec:
config:
custom:
ttlDurationDefaultInSeconds: 10
```
Alternatively, you can configure the `ttlDurationDefaultInSeconds` setting via Terraform by adding the following to the `PulsarCluster` resource:
```hcl theme={null}
resource "streamnative_pulsar_cluster" "my-cluster" {
name = "my-cluster"
config = {
custom = {
ttlDurationDefaultInSeconds = 10
}
}
}
```
## Available cluster settings
The following table of available cluster settings is subject to change based on StreamNative's ongoing development and improvements. Always refer to the latest documentation or consult with StreamNative support for the most up-to-date list of available settings.
### Backlog Settings
| Setting | Description |
| ------------------------------------ | ---------------------------------------------------------------------- |
| `backlogQuotaCheckEnabled` | Enables or disables the backlog quota check. |
| `backlogQuotaCheckIntervalInSeconds` | The interval at which the backlog quota check is performed in seconds. |
| `backlogQuotaDefaultLimitBytes` | The default limit for the backlog quota in bytes. |
| `backlogQuotaDefaultLimitSecond` | The default limit for the backlog quota in seconds. |
| `backlogQuotaDefaultRetentionPolicy` | The default retention policy for the backlog quota. |
### Retention Settings
| Setting | Description |
| --------------------------------- | ------------------------------------------------------------------ |
| `retentionCheckIntervalInSeconds` | The interval at which the retention check is performed in seconds. |
### TTL Settings
| Setting | Description |
| ------------------------------------- | ---------------------------------------------------------------- |
| `ttlDurationDefaultInSeconds` | The default Time-To-Live (TTL) duration for messages in seconds. |
| `messageExpiryCheckIntervalInMinutes` | The interval at which message expiry is checked, in minutes. |
### Resource Management Settings
| Setting | Description |
| ------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------- |
| `allowAutoTopicCreation` | Enables or disables automatic topic creation. |
| `allowAutoTopicCreationType` | Specifies the type of topics that can be automatically created. |
| `allowAutoSubscriptionCreation` | Enables or disables automatic subscription creation. |
| `defaultNumPartitions` | Sets the default number of partitions for automatically created partitioned topics. |
| `brokerDeleteInactiveTopicsEnabled` | Enables or disables the deletion of inactive topics by the broker. |
| `brokerDeleteInactiveTopicsFrequencySeconds` | Sets the frequency (in seconds) at which the broker checks for and deletes inactive topics. |
| `brokerDeleteInactiveTopicsMode` | Specifies the mode for deleting inactive topics (e.g., delete\_when\_no\_subscriptions, delete\_when\_subscriptions\_caught\_up). |
| `brokerDeleteInactivePartitionedTopicMetadataEnabled` | Enables or disables the deletion of metadata for inactive partitioned topics. |
| `brokerDeleteInactiveTopicsMaxInactiveDurationSeconds` | Sets the maximum duration (in seconds) a topic can be inactive before it's eligible for deletion. |
| `forceDeleteTenantAllowed` | Allows or disallows forced deletion of tenants. |
| `forceDeleteNamespaceAllowed` | Allows or disallows forced deletion of namespaces. |
| `subscriptionExpirationTimeMinutes` | Sets the expiration time (in minutes) for inactive subscriptions. |
| `subscriptionExpiryCheckIntervalInMinutes` | Sets the interval (in minutes) at which the system checks for expired subscriptions. |
### Throttling Settings
| Setting | Description |
| -------------------------------------------------- | ------------------------------------------------------------------------------------------ |
| `maxPendingPublishRequestsPerConnection` | Maximum number of pending publish requests per connection. |
| `brokerMaxConnections` | Maximum number of connections allowed to the broker. |
| `brokerMaxConnectionsPerIp` | Maximum number of connections allowed per IP address. |
| `maxUnackedMessagesPerConsumer` | Maximum number of unacknowledged messages allowed per consumer. |
| `maxUnackedMessagesPerSubscription` | Maximum number of unacknowledged messages allowed per subscription. |
| `maxUnackedMessagesPerBroker` | Maximum number of unacknowledged messages allowed per broker. |
| `maxUnackedMessagesPerSubscriptionOnBrokerBlocked` | Maximum number of unacknowledged messages allowed per subscription when broker is blocked. |
| `topicPublisherThrottlingTickTimeMillis` | Tick time for topic publisher throttling in milliseconds. |
| `preciseTopicPublishRateLimiterEnable` | Enables or disables precise topic publish rate limiter. |
| `brokerPublisherThrottlingTickTimeMillis` | Tick time for broker publisher throttling in milliseconds. |
| `brokerPublisherThrottlingMaxMessageRate` | Maximum message rate for broker publisher throttling. |
| `brokerPublisherThrottlingMaxByteRate` | Maximum byte rate for broker publisher throttling. |
| `maxPublishRatePerTopicInMessages` | Maximum publish rate per topic in messages. |
| `maxPublishRatePerTopicInBytes` | Maximum publish rate per topic in bytes. |
| `subscribeThrottlingRatePerConsumer` | Subscribe throttling rate per consumer. |
| `subscribeRatePeriodPerConsumerInSecond` | Subscribe rate period per consumer in seconds. |
| `dispatchThrottlingRatePerTopicInMsg` | Dispatch throttling rate per topic in messages. |
| `dispatchThrottlingRatePerTopicInByte` | Dispatch throttling rate per topic in bytes. |
| `dispatchThrottlingRatePerSubscriptionInMsg` | Dispatch throttling rate per subscription in messages. |
| `dispatchThrottlingRatePerSubscriptionInByte` | Dispatch throttling rate per subscription in bytes. |
| `dispatchThrottlingRatePerReplicatorInMsg` | Dispatch throttling rate per replicator in messages. |
| `dispatchThrottlingRatePerReplicatorInByte` | Dispatch throttling rate per replicator in bytes. |
| `dispatchThrottlingRateRelativeToPublishRate` | Dispatch throttling rate relative to publish rate. |
| `dispatchThrottlingOnNonBacklogConsumerEnabled` | Enables or disables dispatch throttling on non-backlog consumers. |
| `maxMessagePublishBufferSizeInMB` | Maximum message publish buffer size in MB. |
| `dispatcherMaxReadBatchSize` | Maximum read batch size for the dispatcher. |
### Quota Settings
| Setting | Description |
| ------------------------------------- | -------------------------------------------------------------------- |
| `maxNamespacesPerTenant` | Maximum number of namespaces allowed per tenant. |
| `maxTopicsPerNamespace` | Maximum number of topics allowed per namespace. |
| `maxProducersPerTopic` | Maximum number of producers allowed per topic. |
| `maxSameAddressProducersPerTopic` | Maximum number of producers with the same address allowed per topic. |
| `maxConsumersPerTopic` | Maximum number of consumers allowed per topic. |
| `maxSameAddressConsumersPerTopic` | Maximum number of consumers with the same address allowed per topic. |
| `maxSubscriptionsPerTopic` | Maximum number of subscriptions allowed per topic. |
| `maxConsumersPerSubscription` | Maximum number of consumers allowed per subscription. |
| `maxNumPartitionsPerPartitionedTopic` | Maximum number of partitions allowed per partitioned topic. |
| `replicationProducerQueueSize` | Size of the queue for replication producers. |
### Topic & Subscription Settings
| Setting | Description |
| ----------------------------------------------------- | ------------------------------------------------------------------------------------- |
| `enablePersistentTopics` | Enables or disables persistent topics. |
| `enableNonPersistentTopics` | Enables or disables non-persistent topics. |
| `subscriptionTypesEnabled` | Specifies the enabled subscription types. |
| `subscriptionKeySharedEnable` | Enables or disables key-shared subscriptions. |
| `subscriptionKeySharedUseConsistentHashing` | Enables or disables consistent hashing for key-shared subscriptions. |
| `subscriptionKeySharedConsistentHashingReplicaPoints` | Sets the number of replica points for consistent hashing in key-shared subscriptions. |
### Deduplication Settings
| Setting | Description |
| ----------------------------------------------------- | --------------------------------------------------------------------------------------------------------------- |
| `brokerDeduplicationEnabled` | Enables or disables message deduplication on the broker. |
| `brokerDeduplicationMaxNumberOfProducers` | Maximum number of producers for which information will be kept for deduplication purposes. |
| `brokerDeduplicationSnapshotFrequencyInSeconds` | How often to take a snapshot of the deduplication information. |
| `brokerDeduplicationSnapshotIntervalSeconds` | Interval between deduplication information snapshots for indexing. |
| `brokerDeduplicationEntriesInterval` | Number of entries after which a deduplication informational snapshot is taken. |
| `brokerDeduplicationProducerInactivityTimeoutMinutes` | Time of inactivity after which the broker will discard deduplication information about a disconnected producer. |
### Namespace Bundles Settings
| Setting | Description |
| --------------------------------- | ------------------------------------ |
| `defaultNumberOfNamespaceBundles` | Default number of namespace bundles. |
### Message Size Settings
| Setting | Description |
| ---------------- | ----------------------------- |
| `maxMessageSize` | Maximum allowed message size. |
### Compaction Settings
| Setting | Description |
| -------------------------------------------------- | ------------------------------------------------- |
| `brokerServiceCompactionMonitorIntervalInSeconds` | Interval for monitoring compaction in seconds. |
| `brokerServiceCompactionThresholdInBytes` | Threshold for compaction in bytes. |
| `brokerServiceCompactionPhaseOneLoopTimeInSeconds` | Time for phase one of compaction loop in seconds. |
### Delayed Delivery Settings
| Setting | Description |
| ---------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `delayedDeliveryEnabled` | Enables or disables delayed message delivery. |
| `delayedDeliveryTickTimeMillis` | Tick time for delayed delivery in milliseconds. |
| `isDelayedDeliveryDeliverAtTimeStrict` | When `true`, delayed messages are delivered strictly at (not before) their scheduled time. Defaults to `false`. |
| `delayedDeliveryTrackerFactoryClassName` | Delayed delivery tracker implementation. Allowed values: `org.apache.pulsar.broker.delayed.InMemoryDelayedDeliveryTrackerFactory` (default) or `org.apache.pulsar.broker.delayed.bucket.BucketDelayedDeliveryTrackerFactory` (bucket-based, for large delayed backlogs). |
### Batch-index Acknowledgement Settings
| Setting | Description |
| ---------------------------------------- | -------------------------------------------------------- |
| `acknowledgmentAtBatchIndexLevelEnabled` | Enables or disables acknowledgment at batch index level. |
### Replicated Subscription Settings
| Setting | Description |
| --------------------------------------------------------- | ----------------------------------------------------------------------- |
| `enableReplicatedSubscriptions` | Enables or disables replicated subscriptions. |
| `replicatedSubscriptionsSnapshotFrequencyMillis` | Frequency of replicated subscriptions snapshot in milliseconds. |
| `replicatedSubscriptionsSnapshotTimeoutSeconds` | Timeout for replicated subscriptions snapshot in seconds. |
| `replicatedSubscriptionsSnapshotMaxCachedPerSubscription` | Maximum cached snapshots per subscription for replicated subscriptions. |
### Topic-level Policy Settings
| Setting | Description |
| ------------------------------------- | --------------------------------------------------------------- |
| `systemTopicEnabled` | Enables or disables system topic. |
| `topicLevelPoliciesEnabled` | Enables or disables topic-level policies. |
| `exposeTopicLevelMetricsInPrometheus` | Enables or disables exposing topic-level metrics in Prometheus. |
### Load Balancer Settings
| Setting | Description |
| ------------------------------------------------ | ------------------------------------------------------------------- |
| `loadBalancerBundleUnloadMinThroughputThreshold` | Minimum throughput threshold for bundle unloading in load balancer. |
| `loadBalancerNamespaceBundleMaxSessions` | Maximum sessions for namespace bundle in load balancer. |
| `loadBalancerReportUpdateMaxIntervalMinutes` | Maximum interval for load balancer report update in minutes. |
| `loadBalancerSheddingEnabled` | Enables or disables load shedding in load balancer. |
| `loadBalancerSheddingGracePeriodMinutes` | Grace period for load shedding in minutes. |
| `loadBalancerCPUResourceWeight` | CPU resource weight for load balancer. |
### Other Settings
| Setting | Description |
| -------------------------- | ------------------------------- |
| `keepAliveIntervalSeconds` | Keep-alive interval in seconds. |
| `numIOThreads` | Number of I/O threads. |
# Configure Protocols
Source: https://docs.streamnative.io/cloud/clusters/configure-clusters/configure-protocols
This topic describes how to enable, disable, and configure different messaging and data streaming protocols for your cluster. For general guidance on configuring your cluster, see [Cluster Configuration Overview](/cloud/clusters/configure-clusters/cluster-configuration-overview).
The following protocols are available for configuration:
1. [Kafka Protocol](#kafka-protocol)
2. [AMQP (Advanced Message Queuing Protocol)](#amqp-advanced-message-queuing-protocol)
3. [MQTT (Message Queuing Telemetry Transport)](#mqtt-message-queuing-telemetry-transport)
4. [WebSocket](#websocket)
Making changes to the protocols configuration results in restarting the Pulsar brokers in your cluster. Please plan these changes accordingly to avoid disruption to your business applications.
### Kafka Protocol
Kafka protocol support allows Kafka clients to interact with your Pulsar cluster. This enables seamless integration for applications already using Kafka.
To enable and configure the Kafka protocol for your Pulsar cluster, you can use the `config` section in your PulsarCluster specification. Here's how to do it:
1. In your PulsarCluster specification, locate or add the `config` section.
2. Within the `config` section, add a `protocols` field.
3. In the `protocols` field, add a `kafka` object to configure Kafka-specific settings.
Here's how you can configure Kafka protocol support:
1. Using `snctl`:
```yaml theme={null}
apiVersion: cloud.streamnative.io/v1alpha1
kind: PulsarCluster
metadata:
name: my-cluster
spec:
config:
protocols:
kafka: {}
```
2. Using Terraform:
```hcl theme={null}
resource "streamnative_cluster" "my_cluster" {
# ... other configuration ...
config {
protocols {
kafka = {
enabled = "true"
}
}
}
}
```
**Important:** If you try to disable the Kafka protocol in your cluster after you have enabled it, you will disrupt the existing Kafka clients connected to your cluster and cause data corruption.
### AMQP (Advanced Message Queuing Protocol)
AMQP protocol support is currently in Private Preview and is only available to select users. If you're interested in trying out this feature, please contact StreamNative support for more information.
AMQP support allows AMQP-compliant clients to connect to your Pulsar cluster. This is useful for applications that require AMQP compatibility.
To enable and configure the AMQP protocol for your Pulsar cluster, you can use the `config` section in your PulsarCluster specification. Here's how to do it:
1. In your PulsarCluster specification, locate or add the `config` section.
2. Within the `config` section, add a `protocols` field.
3. In the `protocols` field, add a `amqp` object to configure AMQP-specific settings.
Here's how you can configure AMQP protocol support:
1. Using `snctl`:
```yaml theme={null}
apiVersion: cloud.streamnative.io/v1alpha1
kind: PulsarCluster
metadata:
name: my-cluster
spec:
config:
protocols:
amqp: {}
```
2. Using Terraform:
```hcl theme={null}
resource "streamnative_cluster" "my_cluster" {
# ... other configuration ...
config {
protocols {
amqp = {
enabled = "true"
}
}
}
}
```
**Important:** If you try to disable the AMQP protocol in your cluster after you have enabled it, you will disrupt the existing AMQP clients connected to your cluster and cause data corruption.
### MQTT (Message Queuing Telemetry Transport)
MQTT support enables IoT devices and applications using the MQTT protocol to communicate with your Pulsar cluster. This is particularly useful for IoT and mobile scenarios.
To enable and configure the MQTT protocol for your Pulsar cluster, you can use the `config` section in your PulsarCluster specification. Here's how to do it:
1. In your PulsarCluster specification, locate or add the `config` section.
2. Within the `config` section, add a `protocols` field.
3. In the `protocols` field, add a `mqtt` object to configure MQTT-specific settings.
Here's how you can configure MQTT protocol support:
1. Using `snctl`:
```yaml theme={null}
apiVersion: cloud.streamnative.io/v1alpha1
kind: PulsarCluster
metadata:
name: my-cluster
spec:
config:
protocols:
mqtt: {}
```
2. Using Terraform:
```hcl theme={null}
resource "streamnative_cluster" "my_cluster" {
# ... other configuration ...
config {
protocols {
mqtt = {
enabled = "true"
}
}
}
}
```
**Important:** If you try to disable the MQTT protocol in your cluster after you have enabled it, you will disrupt the existing MQTT clients connected to your cluster and cause data corruption.
### WebSocket
[Pulsar WebSocket](https://pulsar.apache.org/docs/3.3.x/client-libraries-websocket/) support enables real-time, bidirectional communication between clients and your Pulsar cluster via WebSocket. This feature can be enabled or disabled based on your requirements.
To enable WebSocket for your cluster, you can set the `config.websocketEnabled` field in your PulsarCluster specification to `true` if you are using `snctl` or `config.websocket_enabled` field in your PulsarCluster specification to `true` if you are using Terraform.
Please note that if you disable WebSocket, you will not be able to create new WebSocket clients in the cluster. Existing WebSocket clients will be disconnected.
# Manage StreamNative Clusters
Source: https://docs.streamnative.io/cloud/clusters/manage-clusters/cluster
## Cluster Overview
A [StreamNative instance](/cloud/clusters/manage-instances/instance) comprises one or more **StreamNative clusters** that operate in unison. Clusters can be distributed across geographical locations and can replicate among themselves using geo-replication.
In StreamNative Console, you can create one and only one cluster for an instance.
### Cluster Features and Usage limits
You can find the features and usage limits of different Clusters in [Cluster Types and Regions](/cloud/clusters/cluster-types#hosted-features-and-limits).
For details about how to work with clusters, such as creating, editing, checking, and deleting clusters, see [work with clusters](/cloud/clusters/manage-clusters/cluster).
### Cluster Location
Each StreamNative cluster is associated with a geographical location. The locations are available at [Cluster Types & Regions in StreamNative Cloud](/cloud/clusters/cluster-types).
### Cluster Protocols and Settings
Each StreamNative Cluster has a set of protocols and settings that you can enable, disable, and configure.
For details, see:
* [Configuration Overview](/cloud/clusters/configure-clusters/cluster-configuration-overview)
* [Cluster Features](/cloud/clusters/configure-clusters/configure-cluster-features)
* [Available Protocols](/cloud/clusters/configure-clusters/configure-protocols)
* [Cluster Settings](/cloud/clusters/configure-clusters/configure-cluster-settings)
### Cluster Service URLs
Once provisioned, a StreamNative cluster is accessible through service URLs. A service URL is an HTTPS or TLS endpoint that is exposed to the Internet or private network and protected by authentication methods ([OAuth2](/cloud/security/authentication/service-accounts/use-oauth/oauth-overview) and [API Keys](/cloud/security/authentication/service-accounts/use-api-keys/api-keys-overview)). The Fully Qualified Domain Name (FQDN) of a service endpoint is based on the name of the StreamNative cluster.
StreamNative Cloud provides the following service URLs for a StreamNative cluster:
* **Pulsar HTTP Service URL**: the HTTP URL of a StreamNative cluster. After being granted the Admin access right, you can use the `pulsar-admin` or [`pulsarctl`](/tools/cli/pulsarctl/pulsarctl-overview) CLI tool to connect to and manage the StreamNative cluster.
* **Pulsar Broker Service URL**: the broker URL of a StreamNative cluster. After being granted the `produce` and `consume` permissions, you can use the `pulsar-client` CLI tool or [Pulsar clients](/cloud/build/pulsar-clients/qs-connect) to connect to and communicate with the StreamNative cluster.
* **Pulsar WebSocket Service URL**: the URL for a WebSocket-enabled StreamNative cluster. After being granted the Admin access right, you can use the [WebSocket API](/cloud/build/pulsar-clients/cloud-connect-websocket) to connect to and communicate with the StreamNative cluster.
* **Kafka Service URL**: the URL for a StreamNative cluster with the Kafka protocol enabled. After being granted the Admin access right, you can use the [Kafka CLI tool](/cloud/build/kafka-clients/quick-starts/cloud-connect-kafka-cli) or [Kafka clients](/cloud/build/kafka-clients/kafka-on-cloud#kafka-clients) to connect to and communicate with the StreamNative cluster.
* **Kafka Schema Registry Service URL**: the URL for [Kafka Schema Registry](/cloud/governance/kafka-schemas/kafka-schema-registry) service enabled on a StreamNative cluster.
* **MQTT Service URL**: the URL for [MQTT service](/cloud/build/mqtt-clients/mqtt-on-cloud-overview) enabled on a StreamNative cluster.
## Next steps
* [Manage Serverless Clusters](/cloud/clusters/manage-clusters/manage-serverless-clusters)
* [Manage Dedicated Clusters](/cloud/clusters/manage-clusters/manage-dedicated-clusters)
* [Manage BYOC Clusters](/cloud/clusters/manage-clusters/manage-byoc-clusters)
After creating a cluster, you can:
* [Manage Data Streams](/cloud/manage-data-streams/data-streams-overview)
* [Build Kafka Applications](/cloud/build/kafka-clients/kafka-on-cloud)
* [Build Pulsar Applications](/cloud/build/pulsar-clients/qs-connect)
* [Create a second cluster and configure geo-replication](/cloud/clusters/cloud-geo-replication)
# Manage BYOC Clusters on StreamNative Cloud
Source: https://docs.streamnative.io/cloud/clusters/manage-clusters/manage-byoc-clusters
## Prerequisites
Before creating a BYOC instance and clusters, you need to prepare for the BYOC infrastructure. See [BYOC Overview](/cloud/clusters/byoc/byoc-overview) for more information.
After you have prepared the BYOC infrastructure, you can create a BYOC instance and clusters.
## Create a cluster
You can follow the steps in [Create a BYOC Instance](/cloud/clusters/manage-instances/manage-byoc-instances#create-an-instance) to create a BYOC instance and its first cluster in it.
## View cluster details
Navigate to the **Clusters Dashboard** page.
* On the **Dashboard** tab, you can view some metrics about the cluster, including the number of topics, subscriptions, consumers, producers, throughput, storage size, and backlog size.
* On the **Details** tab, you can view the details about the cluster, including the cluster name, location, availability mode, cloud provider, cluster type, service URLs, the features enabled on the cluster, and your Pulsar, BookKeeper, and ZooKeeper versions.
To list all the clusters available for an organization, run the following command:
```bash theme={null}
snctl get pulsarclusters -O
```
If you want to get more details about a cluster, you can run the following command:
```bash theme={null}
snctl get pulsarcluster -O
```
If you want to get more details about a cluster, you can define a data source in the Terraform configuration file.
```hcl theme={null}
data "streamnative_pulsar_cluster" "test-cluster" {
organization = ""
name = ""
}
```
You can checkout [PulsarCluster](https://registry.terraform.io/providers/streamnative/streamnative/latest/docs/data-sources/pulsar_cluster) for more information.
## Update a cluster
1. Navigate to the **Cluster Dashboard** page.
2. Click **Configuration** at the left navigation pane.
3. On the **Cluster Configuration** page, you can click **Edit Cluster** button to update the cluster.
4. On the **Cluster Operations** page, you can update the cluster:
* **Release Channel**: Currently, it doesn't support switching the release channel after the cluster is created.
* **Features**: You can enable or disable features on the cluster.
* **Custom Configuration**: You can update the custom configuration of the cluster.
5. After update the cluster settings, click **Cluster Size** to change the cluster size.
You can use **Basic** or **Advanced** tabs to update the cluster size based on your needs.
6. Click **Finish** when you are done updating your cluster.
## Delete a cluster
You cannot delete a cluster if there are resources associated with the cluster.
1. Navigate to the **Clusters** page.
2. Click the ellipsis at the top right corner of the cluster card that you want to delete, and then click **Delete**.
3. In the **Are you sure you want to delete this?** dialog, enter the cluster name and then click **Confirm**.
There are two ways to delete a cluster.
* Delete the cluster by the cluster name.
```bash theme={null}
snctl delete pulsarcluster
```
* Delete the cluster by the cluster manifest file `cluster.yaml`.
```bash theme={null}
snctl delete -f cluster.yaml
```
Remove the cluster resource from the Terraform configuration file and run `terraform apply` to delete the cluster.
# Manage Dedicated Clusters on StreamNative Cloud
Source: https://docs.streamnative.io/cloud/clusters/manage-clusters/manage-dedicated-clusters
## Create a cluster
You can follow the steps in [Create a Dedicated Instance](/cloud/clusters/manage-instances/manage-dedicated-instances#create-an-instance) to create a Dedicated instance and its first cluster in it.
## View cluster details
Navigate to the **Clusters Dashboard** page.
* On the **Dashboard** tab, you can view some metrics about the cluster, including the number of topics, subscriptions, consumers, producers, throughput, storage size, and backlog size.
* On the **Details** tab, you can view the details about the cluster, including the cluster name, location, availability mode, cloud provider, cluster type, service URLs, the features enabled on the cluster, and your Pulsar, BookKeeper, and ZooKeeper versions.
To list all the clusters available for an organization, run the following command:
```bash theme={null}
snctl get pulsarclusters -O
```
If you want to get more details about a cluster, you can run the following command:
```bash theme={null}
snctl get pulsarcluster -O
```
If you want to get more details about a cluster, you can define a data source in the Terraform configuration file.
```hcl theme={null}
data "streamnative_pulsar_cluster" "test-cluster" {
organization = ""
name = ""
}
```
You can checkout [PulsarCluster](https://registry.terraform.io/providers/streamnative/streamnative/latest/docs/data-sources/pulsar_cluster) for more information.
## Update a cluster
1. Navigate to the **Cluster Dashboard** page.
2. Click **Configuration** at the left navigation pane.
3. On the **Cluster Configuration** page, you can click **Edit Cluster** button to update the cluster.
4. On the **Cluster Operations** page, you can update the cluster:
* **Release Channel**: Currently, it doesn't support switching the release channel after the cluster is created.
* **Features**: You can enable or disable features on the cluster.
* **Custom Configuration**: You can update the custom configuration of the cluster.
5. After update the cluster settings, click **Cluster Size** to change the cluster size.
You can use **Basic** or **Advanced** tabs to update the cluster size based on your needs.
6. Click **Finish** when you are done updating your cluster.
## Delete a cluster
You cannot delete a cluster if there are resources associated with the cluster.
1. Navigate to the **Clusters** page.
2. Click the ellipsis at the top right corner of the cluster card that you want to delete, and then click **Delete**.
3. In the **Are you sure you want to delete this?** dialog, enter the cluster name and then click **Confirm**.
There are two ways to delete a cluster.
* Delete the cluster by the cluster name.
```bash theme={null}
snctl delete pulsarcluster
```
* Delete the cluster by the cluster manifest file `cluster.yaml`.
```bash theme={null}
snctl delete -f cluster.yaml
```
Remove the cluster resource from the Terraform configuration file and run `terraform apply` to delete the cluster.
# Manage Serverless Clusters on StreamNative Cloud
Source: https://docs.streamnative.io/cloud/clusters/manage-clusters/manage-serverless-clusters
## Create a cluster
You can follow the steps in [Create a Serverless Instance](/cloud/clusters/manage-instances/manage-serverless-instances#create-an-instance) to create a Serverless instance and its first cluster in it.
Creating a serverless cluster is straightforward. You just need to select a region and define the cluster in the Terraform configuration file.
```hcl theme={null}
resource "streamnative_pulsar_instance" "test-serverless" {
...
}
resource "streamnative_pulsar_cluster" "test-serverless" {
depends_on = [streamnative_pulsar_instance.test-serverless]
organization = streamnative_pulsar_instance.test-serverless.organization
display_name = ""
instance_name = streamnative_pulsar_instance.test-serverless.name
location = "us-central1"
}
```
* `organization`: The organization ID.
* `display_name`: The display name of the cluster. Replace `` with the actual name.
* `instance_name`: The name of the instance where the cluster is created.
* `location`: The location of the cluster. In this example, it is `us-central1`.
See [PulsarCluster](https://registry.terraform.io/providers/streamnative/streamnative/latest/docs/resources/pulsar_cluster) for more information.
## View cluster details
Navigate to the **Clusters Dashboard** page.
* On the **Dashboard** tab, you can view some metrics about the cluster, including the number of topics, subscriptions, consumers, producers, throughput, storage size, and backlog size.
* On the **Details** tab, you can view the details about the cluster, including the cluster name, location, availability mode, cloud provider, cluster type, service URLs, the features enabled on the cluster, and your Pulsar, BookKeeper, and ZooKeeper versions.
To list all the clusters available for an organization, run the following command:
```bash theme={null}
snctl get pulsarclusters -O
```
If you want to get more details about a cluster, you can run the following command:
```bash theme={null}
snctl get pulsarcluster -O
```
If you want to get more details about a cluster, you can define a data source in the Terraform configuration file.
```hcl theme={null}
data "streamnative_pulsar_cluster" "test-cluster" {
organization = ""
name = ""
}
```
You can checkout [PulsarCluster](https://registry.terraform.io/providers/streamnative/streamnative/latest/docs/data-sources/pulsar_cluster) for more information.
## Update a cluster
**Serverless clusters** are fully autonomous and automatically scaled. You don't need to manually update them.
## Delete a cluster
You cannot delete a cluster if there are resources associated with the cluster.
1. Navigate to the **Clusters** page.
2. Click the ellipsis at the top right corner of the cluster card that you want to delete, and then click **Delete**.
3. In the **Are you sure you want to delete this?** dialog, enter the cluster name and then click **Confirm**.
There are two ways to delete a cluster.
* Delete the cluster by the cluster name.
```bash theme={null}
snctl delete pulsarcluster
```
* Delete the cluster by the cluster manifest file `cluster.yaml`.
```bash theme={null}
snctl delete -f cluster.yaml
```
Remove the cluster resource from the Terraform configuration file and run `terraform apply` to delete the cluster.
# Configure Auto-Scaling
Source: https://docs.streamnative.io/cloud/clusters/scale-clusters/cloud-autoscaling
[Serverless clusters](/cloud/clusters/cluster-types#serverless-clusters) are elastic and automatically scale based on workloads. There is no need to configure autoscaling.
Auto-Scaling automatically adjusts the available resources of your deployments, and eliminates the need for scripts or consulting services to make scaling decisions. It currently supports scaling for Pulsar Broker nodes only and works on a rolling basis, meaning the process doesn't incur any downtime.
Auto-scaling for BookKeeper clusters is not supported at this time.
You can specify a range of minimum and maximum Pulsar Broker nodes that your Pulsar cluster can automatically scale to, our Cloud auto-scaler will monitor the CPU workload of Broker nodes and adjust their nodes based on the scaling rule.
## Overview of autoscaling
One of the significant challenges faced by organizations dealing with real-time data is ensuring that the underlying infrastructure can handle varying workloads. Traditional scaling methods often involve manual intervention, leading to inefficiency and increased operational costs. Pulsar Broker Autoscaling addresses these challenges by providing an intelligent, automated solution.
The Power of Pulsar Broker Autoscaling:
* Dynamic Resource Allocation: Pulsar Broker Autoscaling dynamically adjusts resources based on the incoming workload. Whether it's handling a sudden spike in traffic or scaling down during periods of low activity, Pulsar ensures optimal resource utilization, leading to cost savings and improved performance.
* Efficient Load Balancing: Autoscaling in Pulsar ensures that the message processing load is evenly distributed across brokers. This prevents any single broker from becoming a bottleneck, allowing the system to maintain high throughput and low latency even under heavy loads.
* Cost-Effective Scaling: Traditional scaling methods often result in over-provisioning to handle peak loads, leading to unnecessary costs. Pulsar Broker Autoscaling optimizes resource allocation, ensuring that organizations pay only for the resources they need, making it a cost-effective solution for real-time data processing.
## When does autoscaling occur?
StreamNative Cloud has an observability stack to collect the Pulsar cluster workload status in real-time. After enabling the Broker nodes Auto-Scaling feature, the scaling controller will track the average CPU usage of the Broker nodes and adjust the Brokers to keep them at the target CPU usage level. If the average CPU usage for the Brokers is over the target, the scaling controller will scale out to bring in more Brokers. If the average CPU usage for the Brokers is less than the target, the scaling controller will downscale brokers to save resources.
## Enable or disable autoscaling
Auto-scaling is a cluster-level feature that allows you to dynamically adjust the number of Broker nodes. Here's how you can enable or disable Broker auto-scaling for your cluster:
1. Log in to the [StreamNative Cloud Console](https://console.streamnative.cloud/).
2. Navigate to your target [Cluster Workspace](/cloud/get-started/cloud-console#cluster-workspace).
3. Click **Configuration** in the left navigation pane to access **Cluster Configuration**.
4. On the **Cluster Configuration** page, click the **Edit Cluster** button in the top-right corner. You will be redirected to the **Cluster Provisioning** page where you can update the cluster configuration.
5. Find the `Cluster Autoscaling` feature, enable the switch, and choose the minimum and maximum number of nodes.
6. Click the **Cluster Size** button to move to the next step. Skip the **Cluster Size** page by clicking the **Finish** button to complete the operation.
7. After enabling Broker autoscaling, you can go back to the **Cluster Dashboard** page to check the number of Broker nodes.
To enable or disable Broker auto-scaling using `snctl`, you need to modify the PulsarCluster Custom Resource Definition (CRD). Follow these steps:
1. Retrieve the current cluster configuration:
```
snctl get -O pulsarcluster -o yaml > cluster-config.yaml
```
2. Open the `cluster-config.yaml` file in your preferred text editor.
3. Locate the `spec.broker` section in the YAML file. Add or modify the `autoScalingPolicy` field under `spec.broker`:
```yaml theme={null}
spec:
broker:
replicas: 3 # This will be the initial number of replicas
autoScalingPolicy:
minReplicas: 2 # Minimum number of broker replicas
maxReplicas: 5 # Maximum number of broker replicas
```
* Set `minReplicas` to the minimum number of Broker nodes you want to maintain.
* Set `maxReplicas` to the maximum number of Broker nodes you want to allow.
4. Save the changes to the `cluster-config.yaml` file.
5. Apply the updated configuration:
```
snctl apply -f cluster-config.yaml
```
6. To disable auto-scaling, you can either remove the `autoScalingPolicy` field entirely or set `minReplicas` and `maxReplicas` to the same value as `replicas`.
7. After applying the changes, you can verify the auto-scaling configuration:
```
snctl get -O pulsarcluster -o yaml
```
Look for the `autoScalingPolicy` field under `spec.broker` to confirm your changes.
Remember that the auto-scaling feature will automatically adjust the number of Broker nodes based on the CPU usage, within the range you've specified.
For other cluster features, You can follow [Configure Cluster Features](/cloud/clusters/configure-clusters/configure-cluster-features) to enable or disable Broker autoscaling.
# Resize a Cluster
Source: https://docs.streamnative.io/cloud/clusters/scale-clusters/resize-a-cluster
[Serverless clusters](/cloud/clusters/cluster-types#serverless-clusters) are elastic and automatically scale based on workloads. There is no need to manually size or resize a Serverless cluster.
This topic describes how to resize an existing StreamNative cluster, including Dedicated, BYOC, and BYOC Pro clusters. These clusters are provisioned and billed in terms of [CUs and SUs](/cloud/billing/billing-overview#cu-su). Evaluating the number of CUs and SUs your cluster requires helps you reduce costs or scale to meet your data streaming needs.
When you resize a StreamNative cluster, StreamNative automatically redistributes the traffic to help ensure a balanced load across the remaining brokers in the cluster. If you're reducing the size of the cluster, StreamNative removes unused brokers at the end of load balancing and removes unused bookies after re-replication.
Once you request a resize for your cluster, you cannot request another update until the initially requested resize has completed.
## Resize a Cluster
This section shows you how to resize an existing StreamNative Cloud cluster, including scaling up and down the cluster and adjusting the required resources.
Prerequisites:
* An existing [StreamNative Cluster](/cloud/clusters/cluster-types)
You can expand the number of CUs and SUs in the StreamNative Cloud Console.
1. Log in to the [StreamNative Cloud Console](https://console.streamnative.cloud/).
2. Navigate to the [**Cluster Workspace**](/cloud/get-started/cloud-console#cluster-workspace).
3. Click **Configuration** in the left navigation pane to access **Cluster Configuration**.
4. On the **Cluster Configuration** page, click the **Edit Cluster** button in the top-right corner. You will be redirected to the **Cluster Provisioning** page where you can update the cluster configuration and adjust the sizing of the cluster.
5. Skip the **Cluster Configuration** page by clicking the **Cluster Size** button. You will be redirected to the **Cluster Size** page.
6. On the **Cluster Size** page, you can choose between **Basic** or **Advanced** mode to expand the cluster.
* **Basic Mode**: Use the slider to adjust the required throughput. StreamNative Cloud will automatically calculate the number of brokers and bookies, as well as their respective CUs and SUs per node.
* **Advanced Mode**: Manually adjust the number of brokers, bookies, CUs, and SUs per node.
7. Click the **Finish** button to complete the cluster expansion.
The cluster will start scaling up, and you will be redirected to a **Deploying** page that shows the progress of the deployment process. The deployment might take a few minutes to complete, depending on how many resources you are scaling up. You can always click **Go To The Dashboard** to return to the **Cluster Dashboard** page. You can see the number of brokers and bookies in real-time on the **Cluster Dashboard** page.
CUs and SUs are reflected as the number of CPU and Memory used by the brokers and bookies. When expanding a cluster via `snctl`, you can modify the number of bookies and brokers, as well as their corresponding CPU, Memory, and Disk resources. This is done by updating the **PulsarCluster** Custom Resource Definition (CRD).
To expand your cluster using [`snctl`](/tools/cli/snctl/snctl-overview), follow these steps:
1. Retrieve the current cluster configuration:
```
snctl get -O pulsarcluster -o yaml > cluster-config.yaml
```
2. Edit the `cluster-config.yaml` file to increase the resources. For example:
* Increase the number of brokers or bookies:
```yaml theme={null}
spec:
broker:
replicas: 5 # Increase from default 3 to 5
bookkeeper:
replicas: 4 # Increase from default 3 to 4
```
* Adjust the CPU, memory, or storage for brokers or bookies:
```yaml theme={null}
spec:
broker:
resources:
cpu: '4'
memory: '8Gi'
heapPercentage: 50
directPercentage: 50
bookkeeper:
resources:
cpu: '4'
memory: '8Gi'
heapPercentage: 50
directPercentage: 50
ledgerDisk: '100Gi'
journalDisk: '50Gi'
```
These examples demonstrate how to modify the PulsarCluster CRD to scale your cluster's resources.
3. Apply the updated configuration:
```
snctl apply -f cluster-config.yaml
```
After `snctl apply` is completed, the cluster will initiate the expansion process. The operation may take several minutes to complete, depending on the scale of the expansion.
You can check the status of your PulsarCluster to monitor the progress. The PulsarCluster resource includes a status block that provides valuable information about the current state of your cluster components.
To check the status, you can use the following command:
```bash theme={null}
snctl clusters -O get -o yaml
```
Here's an example of what the status block might look like:
```yaml theme={null}
status:
bookkeeper:
readyReplicas: 3
replicas: 3
updatedReplicas: 3
broker:
readyReplicas: 3
replicas: 3
updatedReplicas: 3
```
When all the `readyReplicas`, `replicas`, and `updatedReplicas` are the same, the cluster expansion is complete.
CUs (Compute Units) and SUs (Storage Units) are reflected in the CPU and memory resources used by brokers and bookies, respectively. When expanding a cluster via the **Terraform Provider**, you can modify the number of bookies and brokers, as well as the CUs per broker and SUs per bookie. This is accomplished by updating the [**streamnative\_pulsar\_cluster**](https://registry.terraform.io/providers/streamnative/streamnative/latest/docs/resources/pulsar_cluster) resource.
To resize a cluster using the StreamNative Terraform Provider, follow these steps:
1. Update your Terraform configuration file (e.g., `main.tf`) to modify the cluster resources. Here's an example of how to update the cluster configuration:
```hcl theme={null}
resource "streamnative_pulsar_cluster" "my_cluster" {
# ... other configuration ...
broker_replicas = 5 # Increase the number of broker replicas
bookie_replicas = 5 # Increase the number of bookkeeper replicas
compute_unit = 0.4 # Increase compute units per broker
storage_unit = 0.4 # Increase storage units per bookie
config {
# ... other configuration ...
}
}
```
```
This example demonstrates how to modify the `streamnative_pulsar_cluster` resource to scale your cluster's resources.
```
2. After updating the configuration, run the following Terraform commands:
```bash theme={null}
terraform plan
```
This command will show you the planned changes to your StreamNative cluster.
3. If the plan looks correct, apply the changes:
```bash theme={null}
terraform apply
```
Terraform will then initiate the cluster expansion process. The operation may take several minutes to complete, depending on the scale of the expansion.
4. You can monitor the progress of the cluster scaling operation by checking the Terraform output or by using the **Cluster Dashboard** on the StreamNative Cloud console.
5. To verify the status of your cluster after the operation, you can use the `terraform show` command or check the **Cluster Dashboard** on StreamNative Cloud console for the most up-to-date information on your cluster's resources and status.
Remember to always review the changes carefully before applying them to your production environment. It's recommended to test any scaling operations in a non-production environment first.
# StreamNative Cloud Clusters Overview
Source: https://docs.streamnative.io/cloud/clusters/streamnative-cluster-overview
Use this topic to understand the cluster concepts in StreamNative Cloud.
## Management Concepts
StreamNative clusters in StreamNative Cloud differ from general Pulsar or Kafka clusters in that StreamNative offers a fully managed service. Use the following concepts to learn more.
### Basics
You can choose from different types of clusters for use in development, production, and high-traffic workloads. StreamNative Cloud is available from all major cloud providers in regions around the world, either fully hosted by StreamNative or as BYOC (Bring-Your-Own-Cloud). This provides access to StreamNative cluster and configuration settings for resources such as tenants, namespaces, and topics. For more information, see [Cluster Types and Regions](/cloud/clusters/cluster-types).
### Fault Tolerance
StreamNative Cloud provides a centralized global control plane that manages a distributed collection of servers running in multiple regions, either fully hosted by StreamNative or as BYOC (Bring-Your-Own-Cloud). Clusters can span cloud provider availability zones (AZs) and provide highly scalable and fault-tolerant systems that support mission-critical applications.
### Hosted vs BYOC
StreamNative Cloud offers two primary deployment models: Hosted and Bring-Your-Own-Cloud (BYOC). Hosted clusters, which include **Serverless** and **Dedicated** options, are deployed and managed entirely on StreamNative's cloud infrastructure. These are ideal for teams seeking a turnkey solution with minimal operational overhead. On the other hand, BYOC clusters allow customers to leverage StreamNative's management expertise while maintaining the clusters within their own cloud environment. This option is particularly suited for organizations with existing cloud infrastructure, specific compliance requirements, or those desiring greater control over their cloud resources. Both models benefit from StreamNative's full management and expertise, ensuring optimal performance and reliability. The choice between Hosted and BYOC depends on factors such as operational preferences, compliance needs, and existing cloud investments. For a detailed comparison of cluster types and available regions, refer to [Cluster Types and Regions](/cloud/clusters/cluster-types).
## Cluster Types
StreamNative Cloud supports two types of clusters:
* **Kafka Clusters**: Native Apache Kafka clusters powered by the Ursa Engine. Kafka Clusters run native Kafka protocol and support standard Kafka clients, tools, and ecosystems. For more information, see the [Kafka Cluster Guide](/kafka/kafka-cluster-guide).
* **Pulsar Clusters**: Apache Pulsar clusters that support Pulsar protocol natively and can also serve Kafka clients through KSN. Pulsar Clusters support additional capabilities such as Functions, Connectors, and multi-protocol access.
Currently, Kafka Clusters and Pulsar Clusters cannot co-exist in the same instance. Each instance supports one cluster type.
## Instances & Clusters
StreamNative Cloud organizes its clusters into **Instances**. Within any StreamNative Cloud [organization](/cloud/security/access/resource-hierarchy/organizations), you can create one or more instances. Each instance serves as a dedicated environment within a cloud provider, capable of hosting multiple clusters. This setup allows different departments or teams to operate in separate instances to prevent overlap and interference.
An **Instance** can be either fully **Hosted** on StreamNative's cloud account or on your own public cloud account through the **Bring-Your-Own-Cloud (BYOC)** deployment option.
Within each instance, multiple clusters can be deployed across various regions. Each cluster within an instance is deployed to a specific cloud region as configured in its cloud provider settings. Each cluster provides various service endpoints to enable client libraries to connect, produce, and consume messages.
Clusters within an instance can also replicate data among themselves using geo-replication.
StreamNative Cloud utilizes Public Cloud infrastructure to host instances and clusters. Below is a diagram illustrating the relationship between instances, clusters, and the cloud infrastructure:
## Infrastructure Pools
As illustrated above, StreamNative Cloud infrastructure is organized into infrastructure **pools**. Each *pool* encompasses a collection of infrastructure environments, known as **pool members**, distributed across multiple regions within a cloud provider. These members can be equated to Kubernetes clusters dedicated to deploying Pulsar clusters.
A **Pulsar Instance** can be created within and deployed to a specific infrastructure *pool*. Each infrastructure *pool* can support multiple **Pulsar Instances**. When setting up a **Pulsar Instance**, you select the appropriate pool using its namespace and name. Within each Pulsar Instance, you can deploy clusters to various regions by specifying the desired region. StreamNative Cloud then deploys the Pulsar Cluster to the corresponding **pool member** in that region.
The type of *Pulsar Instance*, whether **Hosted** or **BYOC**, is determined by the location and configuration of its *Infrastructure Pool*. Infrastructure **Pools** can either be fully **Hosted** by StreamNative or set up in your own public cloud account through the **BYOC** deployment option.
### Hosted Infrastructure Pools
Hosted Infrastructure *Pools* are fully managed and maintained on StreamNative's cloud account. These pools are pre-provisioned, allowing you to utilize them when setting up your Pulsar Instances and Clusters.
If you provision a Pulsar instance or cluster via the StreamNative Cloud console, you can simply select the cloud provider and the respective location. The console will automatically select the appropriate Hosted Pool for you.
If you prefer to provision a Pulsar instance or cluster using the `snctl` command-line tool, you can specify the pool using the `--pool` flag. For example:
```bash theme={null}
snctl create pulsarinstance --name --pool --organization
```
#### Finding Available Hosted Pools
You can use the `snctl get pooloptions` command to list all available Hosted Infrastructure Pools.
```bash theme={null}
$ snctl get pooloptions
NAME CREATED AT
streamnative-shared-aws 2022-03-04T00:44:51Z
streamnative-shared-azure 2024-03-25T20:32:15Z
streamnative-shared-gcp 2022-04-26T16:48:31Z
```
Each PoolOption contains the following key information of a **Hosted** pool:
1. **CloudType**: Indicates the cloud provider (e.g., AWS, GCP, Azure) for the pool.
2. **DeploymentType**: The type of deployment (e.g., Hosted, BYOC).
3. **PoolRef**: A reference to the specific infrastructure pool.
4. **Locations**: A list of available locations (regions) for the pool.
5. **Features**: A map of enabled features for the pool.
To view the details of a specific PoolOption, you can use the `snctl get pooloption ` command. It will display detailed information about the pool, including its configuration, features, and other relevant settings.
An example of the output of the `snctl get pooloption ` command is as follows:
```bash theme={null}
$ snctl get pooloption streamnative-shared-aws -o yaml
apiVersion: cloud.streamnative.io/v1alpha1
kind: PoolOption
metadata:
creationTimestamp: "2022-03-04T00:44:51Z"
generation: 28
name: streamnative-shared-aws
namespace: sndev
resourceVersion: "34349179"
uid: bf56b5c8-e99e-4376-96ab-aecf728343f7
spec:
cloudType: aws
deploymentType: ""
features:
AOP: true
ApiKey: true
AutoScaling: true
Function: true
Istio: true
KOP: true
MOP: true
SnRBAC: true
Transaction: true
WebSocket: true
locations:
- location: ap-southeast-2
- location: eu-central-1
- location: eu-west-1
- location: us-east-2
poolRef:
name: shared-aws
namespace: streamnative
status: {}
```
When selecting a pool for your Pulsar Instance or Cluster, consider the following:
* Choose a pool with a CloudType that matches your preferred cloud provider.
* Ensure the pool has Locations (regions) that meet your geographical requirements.
* Check that the Features align with your needs.
* Verify that the DeploymentType is "Hosted" for fully managed StreamNative infrastructure.
By carefully reviewing the PoolOptions, you can select the most suitable Hosted Infrastructure Pool for your StreamNative Cloud deployment.
### BYOC Infrastructure Pools
Unlike Hosted Infrastructure Pools, BYOC Infrastructure *Pools* must be **provisioned** prior to deploying any BYOC Pulsar Instances or Clusters. The setup process for a BYOC Pool includes establishing a **Cloud Connection**—this allows the StreamNative Cloud control plane to interact with your cloud account. It also involves defining and provisioning **Pool Members** within the Pool to deploy Pulsar Clusters across different regions of your cloud account. Provisioning **Pool Members** within a *Pool* is done by creating **Cloud Environments** in different regions. Each **Cloud Environment** defines the essential infrastructure resources such as compute, storage, and networking that are necessary for a *Pool Member* to deploy Pulsar clusters.
For more information about how to provision and manage BYOC infrastructure pools, see [Manage BYOC Infrastructure](/cloud/clusters/byoc/byoc-overview).
## Related Content
* Learn more information about cluster types and available regions, see [Cluster Types and Regions](/cloud/clusters/cluster-types).
* Learn more about how to provision & manage BYOC infrastructure pools, see [Manage BYOC Infrastructure](/cloud/clusters/byoc/byoc-overview).
* Learn more about how to manage StreamNative instances, see [Manage Instances](/cloud/clusters/manage-instances/instance).
* Learn more about how to manage StreamNative clusters, see [Manage Clusters](/cloud/clusters/manage-clusters/cluster).
# Pulsar IO Connectors
Source: https://docs.streamnative.io/cloud/connect/connector-index
Messaging systems are most powerful when you can easily use them with external systems like databases, cloud services, and other messaging systems.
In Apache Pulsar, connectors are components that facilitate data ingestion and processing within the Pulsar ecosystem. They provide a way to connect Pulsar with various data sources and sinks, allowing seamless integration and exchange of data.
Find out more:
* [Connector overview](/cloud/connect/pulsar-io/connector-overview)
- [Deploy connectors](/cloud/connect/pulsar-io/deploy-connectors/deploy-connector-index)
- [Manage connectors](/cloud/connect/pulsar-io/connector-manage)
- [Monitor and troubleshoot connectors](/cloud/connect/pulsar-io/connector-monitoring)
- [Configuration reference](/cloud/connect/pulsar-io/connector-config)
# Deploy kafka connectors
Source: https://docs.streamnative.io/cloud/connect/kafka-connect/deploy-kafka-connectors/deploy-kafka-connect-index
StreamNative cloud provides a pluggable architecture for kafka connectors, allowing you to deploy pre-built connectors and
develop custom connectors for external systems, such as databases, messaging systems, block storage, cloud services, or
any other system capable of producing or consuming data.
Currently, the Kafka Connect doesn't support multi-tenancy. All Kafka Connects are deployed to the `public/default` namespace.
And all of configured topics are also under the `public/default` namespace by default, unless you specified topics with the prefix: `${tenant}.${namespace}.`.
For more details about the multi-tenancy support for Kafka topics in StreamNative cloud, please refer to the [Kafka Multi-Tenancy](/cloud/build/kafka-clients/advanced-features/kafka-multi-tenancy).
To deploy kafka connectors on StreamNative Cloud, follow the following instructions.
* [Set up your environment](/cloud/connect/kafka-connect/deploy-kafka-connectors/kafka-connect-setup)
* [Check kafka connect availability](/cloud/connect/kafka-connect/deploy-kafka-connectors/kafka-connect-check)
* [Create kafka connectors](/cloud/connect/kafka-connect/deploy-kafka-connectors/kafka-connect-create)
# Check Kafka Connect Availability
Source: https://docs.streamnative.io/cloud/connect/kafka-connect/deploy-kafka-connectors/kafka-connect-check
You can check the latest availability of built-in kafka connectors on StreamNative Cloud using `snctl` or `kcctl`.
## Get Built-in Connectors
```
snctl kafka admin connect get plugins
TYPE CLASS VERSION
sink com.milvus.io.kafka.MilvusSinkConnector 1.0.1
sink com.mongodb.kafka.connect.MongoSinkConnector 1.13.0
sink com.snowflake.kafka.connector.SnowflakeSinkConnector 2.4.1
sink com.wepay.kafka.connect.bigquery.BigQuerySinkConnector 2.5.7
sink io.aiven.connect.elasticsearch.ElasticsearchSinkConnector 7.0.0
sink io.aiven.connect.jdbc.JdbcSinkConnector 6.10.0
sink io.debezium.connector.jdbc.JdbcSinkConnector 3.2.0.Final
sink io.tabular.iceberg.connect.IcebergSinkConnector 0.6.19
source com.mongodb.kafka.connect.MongoSourceConnector 1.13.0
source io.aiven.connect.jdbc.JdbcSourceConnector 6.10.0
source io.confluent.kafka.connect.datagen.DatagenConnector 0.6.5
source io.debezium.connector.mongodb.MongoDbConnector 3.2.0.Final
source io.debezium.connector.mysql.MySqlConnector 3.2.0.Final
source io.debezium.connector.postgresql.PostgresConnector 3.2.0.Final
source io.debezium.connector.sqlserver.SqlServerConnector 3.2.0.Final
source io.debezium.connector.yugabytedb.YugabyteDBConnector 1.9.5.y.220.3
source io.jrnd.kafka.connect.connector.JRSourceConnector 0.4.0
```
```
kcctl get plugins
TYPE CLASS VERSION
sink com.milvus.io.kafka.MilvusSinkConnector 1.0.1
sink com.mongodb.kafka.connect.MongoSinkConnector 1.13.0
sink com.snowflake.kafka.connector.SnowflakeSinkConnector 2.4.1
sink com.wepay.kafka.connect.bigquery.BigQuerySinkConnector 2.5.7
sink io.aiven.connect.elasticsearch.ElasticsearchSinkConnector 7.0.0
sink io.aiven.connect.jdbc.JdbcSinkConnector 6.10.0
sink io.debezium.connector.jdbc.JdbcSinkConnector 3.2.0.Final
sink io.tabular.iceberg.connect.IcebergSinkConnector 0.6.19
source com.mongodb.kafka.connect.MongoSourceConnector 1.13.0
source io.aiven.connect.jdbc.JdbcSourceConnector 6.10.0
source io.confluent.kafka.connect.datagen.DatagenConnector 0.6.5
source io.debezium.connector.mongodb.MongoDbConnector 3.2.0.Final
source io.debezium.connector.mysql.MySqlConnector 3.2.0.Final
source io.debezium.connector.postgresql.PostgresConnector 3.2.0.Final
source io.debezium.connector.sqlserver.SqlServerConnector 3.2.0.Final
source io.debezium.connector.yugabytedb.YugabyteDBConnector 1.9.5.y.220.3
source io.jrnd.kafka.connect.connector.JRSourceConnector 0.4.0
```
```
curl "https://public%2Fdefault:${APIKEY}@${KAFKA-SERVICE-URL}/admin/kafkaconnect/connector-plugins" | jq '.'
[
{
"class": "io.debezium.connector.mongodb.MongoDbConnector",
"type": "source",
"version": "3.2.0.Final"
},
{
"class": "io.aiven.connect.jdbc.JdbcSinkConnector",
"type": "sink",
"version": "6.10.0"
},
{
"class": "io.debezium.connector.yugabytedb.YugabyteDBConnector",
"type": "source",
"version": "1.9.5.y.220.3"
},
{
"class": "io.confluent.kafka.connect.datagen.DatagenConnector",
"type": "source",
"version": "0.6.5"
},
{
"class": "io.debezium.connector.postgresql.PostgresConnector",
"type": "source",
"version": "3.2.0.Final"
},
{
"class": "io.debezium.connector.mysql.MySqlConnector",
"type": "source",
"version": "3.2.0.Final"
},
{
"class": "io.debezium.connector.sqlserver.SqlServerConnector",
"type": "source",
"version": "3.2.0.Final"
},
{
"class": "io.jrnd.kafka.connect.connector.JRSourceConnector",
"type": "source",
"version": "0.4.0"
},
{
"class": "com.milvus.io.kafka.MilvusSinkConnector",
"type": "sink",
"version": "1.0.1"
},
{
"class": "io.tabular.iceberg.connect.IcebergSinkConnector",
"type": "sink",
"version": "0.6.19"
},
{
"class": "com.mongodb.kafka.connect.MongoSinkConnector",
"type": "sink",
"version": "1.13.0"
},
{
"class": "com.wepay.kafka.connect.bigquery.BigQuerySinkConnector",
"type": "sink",
"version": "2.5.7"
},
{
"class": "io.aiven.connect.jdbc.JdbcSourceConnector",
"type": "source",
"version": "6.10.0"
},
{
"class": "io.debezium.connector.jdbc.JdbcSinkConnector",
"type": "sink",
"version": "3.2.0.Final"
},
{
"class": "com.snowflake.kafka.connector.SnowflakeSinkConnector",
"type": "sink",
"version": "2.4.1"
},
{
"class": "io.aiven.connect.elasticsearch.ElasticsearchSinkConnector",
"type": "sink",
"version": "7.0.0"
},
{
"class": "com.mongodb.kafka.connect.MongoSourceConnector",
"type": "source",
"version": "1.13.0"
}
]
```
In addition to the built-in connectors, you can also deploy any custom connectors. For more information, see [Deploy Custom Connectors](/cloud/connect/kafka-connect/deploy-kafka-connectors/kafka-connect-create#create-a-custom-kafka-connect).
## What’s next?
* [Create kafka connectors](/cloud/connect/kafka-connect/deploy-kafka-connectors/kafka-connect-create)
# Create Kafka Connectors
Source: https://docs.streamnative.io/cloud/connect/kafka-connect/deploy-kafka-connectors/kafka-connect-create
## Prerequisites
Before deploying a kafka connect to StreamNative Cloud, make sure the following prerequisites have been met:
* A running external data system service.
* A running [Pulsar Cluster](/cloud/clusters/manage-clusters/cluster#create-a-cluster) with Kop feature enabled on StreamNative Cloud and the [required environment](/cloud/connect/kafka-connect/deploy-kafka-connectors/kafka-connect-setup) has been set up.
## Create a built-in kafka connect
Before creating a kafka connect, it’s highly recommended to do the following:
1. [Check kafka connect availability](/cloud/connect/kafka-connect/deploy-kafka-connectors/kafka-connect-check) to ensure the version number of the kafka connect you want to create is supported on StreamNative Cloud.
2. Go to [StreamNative Hub](/connect/overview) and find the connect-specific docs of your version for configuration reference.
You may see below error logs for the first time you create a connector:
```
org.apache.kafka.common.config.ConfigException: Topic '__kafka_connect_offset_storage' supplied via the 'offset.storage.topic' property is required to have 'cleanup.policy=compact' to guarantee consistency and durability of source connector offsets, but found the topic currently has 'cleanup.policy=delete'. Continuing would likely result in eventually losing source connector offsets and problems restarting this Connect cluster in the future. Change the 'offset.storage.topic' property in the Connect worker configurations to use a topic with 'cleanup.policy=compact'.
```
You should set the `cleanup.policy` of the `__kafka_connect_offset_storage` topic to `compact` to avoid the above error with below command:
```bash theme={null}
./bin/kafka-configs.sh --bootstrap-server xxxx:9093 --command-config ~/kafka/kafka-token.properties --alter --topic __kafka_connect_offset_storage --add-config cleanup.policy=compact
```
The following example shows how to create a data generator source connect named `test` on Streamnative Cloud using different tools.
To create a data generator source connect named `test`, run the following command.
```bash theme={null}
> cat datagen.json
{
"name": "test",
"config": {
"connector.class": "io.confluent.kafka.connect.datagen.DatagenConnector",
"kafka.topic": "testusers",
"quickstart": "users",
"key.converter": "org.apache.kafka.connect.storage.StringConverter",
"value.converter": "org.apache.kafka.connect.json.JsonConverter",
"value.converter.schemas.enable": "false",
"max.interval": 1000,
"iterations": 10000000,
"tasks.max": "1"
}
}
> snctl kafka admin connect apply -f datagen.json --use-service-account
```
You should see the following output:
```bash theme={null}
Created connector test
```
If you want to verify whether the data generator source connect has been created successfully, run the following command:
```bash theme={null}
snctl kafka admin connect get connectors
```
You should see the following output:
```bash theme={null}
NAME TYPE STATE TASKS
test source RUNNING 0: RUNNING
```
To create a data generator source connect named `test`, run the following command.
```bash theme={null}
> cat datagen.json
{
"name": "test",
"config": {
"connector.class": "io.confluent.kafka.connect.datagen.DatagenConnector",
"kafka.topic": "testusers",
"quickstart": "users",
"key.converter": "org.apache.kafka.connect.storage.StringConverter",
"value.converter": "org.apache.kafka.connect.json.JsonConverter",
"value.converter.schemas.enable": "false",
"max.interval": 1000,
"iterations": 10000000,
"tasks.max": "1"
}
}
> kcctl apply -f datagen.json
```
You should see the following output:
```bash theme={null}
Created connector test
```
If you want to verify whether the data generator source connect has been created successfully, run the following command:
```bash theme={null}
kcctl get connectors
```
You should see the following output:
```bash theme={null}
NAME TYPE STATE TASKS
test source RUNNING 0: RUNNING
```
To create a data generator source connect named `test`, run the following command.
```bash theme={null}
> cat datagen.json
{
"name": "test",
"config": {
"connector.class": "io.confluent.kafka.connect.datagen.DatagenConnector",
"kafka.topic": "testusers",
"quickstart": "users",
"key.converter": "org.apache.kafka.connect.storage.StringConverter",
"value.converter": "org.apache.kafka.connect.json.JsonConverter",
"value.converter.schemas.enable": "false",
"max.interval": 1000,
"iterations": 10000000,
"tasks.max": "1"
}
}
> curl -X POST --header "Content-Type: application/json" "https://public%2Fdefault:${APIKEY}@${KAFKA-SERVICE-URL}/admin/kafkaconnect/connectors/" --data @datagen.json
{"name":"test","config":{"connector.class":"io.confluent.kafka.connect.datagen.DatagenConnector","kafka.topic":"testusers","quickstart":"users","key.converter":"org.apache.kafka.connect.storage.StringConverter","value.converter":"org.apache.kafka.connect.json.JsonConverter","value.converter.schemas.enable":"false","max.interval":"1000","iterations":"10000000","tasks.max":"1","name":"test"},"tasks":[],"type":"source"}
```
If you want to list the submitted connect for a double check, run the following command:
```bash theme={null}
> curl "https://public%2Fdefault:${APIKEY}@${KAFKA-SERVICE-URL}/admin/kafkaconnect/connectors/"
["test"]
```
To create a data generator source connect named `test`, follow these steps:
1. Login to the [StreamNative Cloud Console](https://cloud.streamnative.io/).
2. In the left navigation pane, click **Connectors**, then click the **Kafka Sources** tab.
3. Click the **Create Kafka Source** button:
4. Fill in the required fields and optional fields as you wish, and then Click the **Submit** button.
If you want to verify whether the data generator source connect has been created successfully, go back to the **Connectors** page, and you should see the created connector in the **Kafka Sources** tab, like below:
## Create kafka connect with SMT
StreamNative Cloud supports Single Message Transformations (SMTs) for Kafka Connect. You can use SMTs to transform messages before they are written to the target system.
The following example shows how to create a Datagen source connector named `test` on StreamNative Cloud using different tools.
Please refer to the [Kafka Connect SMTs](/cloud/connect/kafka-connect/kafka-connect-smt) to check the supported SMTs in StreamNative cloud.
To create a data generator source connect named `test` with SMT, run the following command.
```bash theme={null}
> cat datagen.json
{
"name": "test",
"config": {
"connector.class": "io.confluent.kafka.connect.datagen.DatagenConnector",
"kafka.topic": "testusers",
"quickstart": "users",
"key.converter": "org.apache.kafka.connect.storage.StringConverter",
"value.converter": "org.apache.kafka.connect.json.JsonConverter",
"value.converter.schemas.enable": "false",
"max.interval": 1000,
"iterations": 10000000,
"tasks.max": "1",
"transforms": "InsertSource",
"transforms.InsertSource.type": "org.apache.kafka.connect.transforms.InsertField$Value",
"transforms.InsertSource.static.field": "data_source",
"transforms.InsertSource.static.value": "test-file-source"
}
}
> snctl kafka admin connect apply -f datagen.json --use-service-account
```
You should see the following output:
```bash theme={null}
Created connector test
```
If you want to verify whether the data generator source connect has been created successfully, run the following command:
```bash theme={null}
snctl kafka admin connect get connectors
```
You should see the following output:
```bash theme={null}
NAME TYPE STATE TASKS
test source RUNNING 0: RUNNING
```
To create a data generator source connect named `test` with SMT, run the following command.
```bash theme={null}
> cat datagen.json
{
"name": "test",
"config": {
"connector.class": "io.confluent.kafka.connect.datagen.DatagenConnector",
"kafka.topic": "testusers",
"quickstart": "users",
"key.converter": "org.apache.kafka.connect.storage.StringConverter",
"value.converter": "org.apache.kafka.connect.json.JsonConverter",
"value.converter.schemas.enable": "false",
"max.interval": 1000,
"iterations": 10000000,
"tasks.max": "1",
"transforms": "InsertSource",
"transforms.InsertSource.type": "org.apache.kafka.connect.transforms.InsertField$Value",
"transforms.InsertSource.static.field": "data_source",
"transforms.InsertSource.static.value": "test-file-source"
}
}
> kcctl apply -f datagen.json
```
You should see the following output:
```bash theme={null}
Created connector test
```
If you want to verify whether the data generator source connect has been created successfully, run the following command:
```bash theme={null}
kcctl get connectors
```
You should see the following output:
```bash theme={null}
NAME TYPE STATE TASKS
test source RUNNING 0: RUNNING
```
To create a data generator source connect named `test` with SMT, run the following command.
```bash theme={null}
> cat datagen.json
{
"name": "test",
"config": {
"connector.class": "io.confluent.kafka.connect.datagen.DatagenConnector",
"kafka.topic": "testusers",
"quickstart": "users",
"key.converter": "org.apache.kafka.connect.storage.StringConverter",
"value.converter": "org.apache.kafka.connect.json.JsonConverter",
"value.converter.schemas.enable": "false",
"max.interval": 1000,
"iterations": 10000000,
"tasks.max": "1",
"transforms": "InsertSource",
"transforms.InsertSource.type": "org.apache.kafka.connect.transforms.InsertField$Value",
"transforms.InsertSource.static.field": "data_source",
"transforms.InsertSource.static.value": "test-file-source"
}
}
> curl -X POST --header "Content-Type: application/json" "https://public%2Fdefault:${APIKEY}@${KAFKA-SERVICE-URL}/admin/kafkaconnect/connectors/" --data @datagen.json
{"name":"test","config":{"connector.class":"io.confluent.kafka.connect.datagen.DatagenConnector","kafka.topic":"testusers","quickstart":"users","key.converter":"org.apache.kafka.connect.storage.StringConverter","value.converter":"org.apache.kafka.connect.json.JsonConverter","value.converter.schemas.enable":"false","max.interval":"1000","iterations":"10000000","tasks.max":"1","transforms":"InsertSource","transforms.InsertSource.type":"org.apache.kafka.connect.transforms.InsertField$Value","transforms.InsertSource.static.value":"test-file-source","name":"test"},"tasks":[],"type":"source"}
```
If you want to list the submitted connect for a double check, run the following command:
```bash theme={null}
> curl "https://public%2Fdefault:${APIKEY}@${KAFKA-SERVICE-URL}/admin/kafkaconnect/connectors/"
["test"]
```
To create a data generator source connect named `test` with SMT, follow these steps:
1. Login to the [StreamNative Cloud Console](https://cloud.streamnative.io/).
2. In the left navigation pane, click **Connectors**, then click the **Kafka Sources** tab.
3. Click the **Create Kafka Source** button:
4. Fill in the required fields and optional fields as you wish
5. Click the **Advance Settings** tab, and then fill in the SMT fields:
6. Click the **Submit** button.
If you want to verify whether the data generator source connect has been created successfully, go back to the **Connectors** page, and you should see the created connector in the **Kafka Sources** tab, like below:
## Create kafka connect with secret
Some connects require sensitive information, such as passwords, token, to be passed to the connector. And you may not want to expose these sensitive information in the connector configuration.
To solve this problem, you can use the following methods to pass sensitive information to the connector:
* **Create a secret**
For example, the Milvus sink connector requires a token to be passed to the connector.
You can create a secret in the console UI and pass the secret name to the connector configuration.
The `location` should be the same as the region of your Pulsar cluster.
The `awsAccessKey` and `awsSecretKey` is the field name, and the `lambda-sink-secret` can be any unique name you want to give to the secret.
For a Milvus sink, we should create a secret with a `token` field.
* **Pass secrets to the connector configuration**
The following example shows how to create a Milvus sink connector named `test` on StreamNative Cloud using different tools.
To create a Milvus sink connector named `test`, run the following command.
```bash theme={null}
> cat milvus.json
{
"name": "test",
"config": {
"connector.class": "com.milvus.io.kafka.MilvusSinkConnector",
"public.endpoint": "http://dockerhost.default.svc.cluster.local:19530",
"collection.name": "demo",
"token": "${snsecret:miluvs-sec:token}",
"topics": "kafka-milvus-input",
"key.converter": "org.apache.kafka.connect.json.JsonConverter",
"key.converter.schemas.enable": "false",
"value.converter": "org.apache.kafka.connect.json.JsonConverter",
"value.converter.schemas.enable": "false",
"tasks.max": "1"
}
}
> snctl kafka admin connect apply -f milvus.json --use-service-account
```
The `miluvs-sec` is the name of the secret you created
You should see the following output:
```bash theme={null}
Created connector test
```
If you want to verify whether the data generator source connect has been created successfully, run the following command:
```bash theme={null}
snctl kafka admin connect get connectors
```
You should see the following output:
```bash theme={null}
NAME TYPE STATE TASKS
test sink RUNNING 0: RUNNING
```
To create a Milvus sink connector named `test`, run the following command.
```bash theme={null}
> cat milvus.json
{
"name": "test",
"config": {
"connector.class": "com.milvus.io.kafka.MilvusSinkConnector",
"public.endpoint": "http://dockerhost.default.svc.cluster.local:19530",
"collection.name": "demo"
"token": "${snsecret:miluvs-sec:token}",
"topics": "kafka-milvus-input",
"key.converter": "org.apache.kafka.connect.json.JsonConverter",
"key.converter.schemas.enable": "false",
"value.converter": "org.apache.kafka.connect.json.JsonConverter",
"value.converter.schemas.enable": "false",
"tasks.max": "1"
}
}
> kcctl apply -f milvus.json
```
The `miluvs-sec` is the name of the secret you created
You should see the following output:
```bash theme={null}
Created connector test
```
If you want to verify whether the data generator source connect has been created successfully, run the following command:
```bash theme={null}
kcctl get connectors
```
You should see the following output:
```bash theme={null}
NAME TYPE STATE TASKS
test sink RUNNING 0: RUNNING
```
To create a Milvus sink connector named `test`, run the following command.
```bash theme={null}
> cat milvus.json
{
"name": "test",
"config": {
"connector.class": "com.milvus.io.kafka.MilvusSinkConnector",
"public.endpoint": "http://dockerhost.default.svc.cluster.local:19530",
"collection.name": "demo"
"token": "${snsecret:miluvs-sec:token}",
"topics": "kafka-milvus-input",
"key.converter": "org.apache.kafka.connect.json.JsonConverter",
"key.converter.schemas.enable": "false",
"value.converter": "org.apache.kafka.connect.json.JsonConverter",
"value.converter.schemas.enable": "false",
"tasks.max": "1"
}
}
> curl -X POST --header "Content-Type: application/json" "https://public%2Fdefault:${APIKEY}@${KAFKA-SERVICE-URL}/admin/kafkaconnect/connectors/" --data @miluvs.json
{"name":"test","config":{"connector.class":"com.milvus.io.kafka.MilvusSinkConnector","topics":"kafka-milvus-input","public.endpoint":"http://dockerhost.default.svc.cluster.local:19530","collection.name":"demo","token":"${snsecret:miluvs-sec:token}","key.converter":"org.apache.kafka.connect.json.JsonConverte","key.converter.schemas.enable":"false","value.converter":"org.apache.kafka.connect.json.JsonConverter","value.converter.schemas.enable":"false","tasks.max":"1","name":"test"},"tasks":[],"type":"sink"}
```
If you want to list the submitted connect for a double check, run the following command:
```bash theme={null}
> curl "https://public%2Fdefault:${APIKEY}@${KAFKA-SERVICE-URL}/admin/kafkaconnect/connectors/"
["test"]
```
To create a Milvus sink connect named `test`, follow these steps:
1. Login to the [StreamNative Cloud Console](https://cloud.streamnative.io/).
2. In the left navigation pane, click **Connectors**, then click the **Kafka Sinks** tab.
3. Click the **Create Kafka Sink** button, and then choose the Milvus connect:
4. In the `Authentication Secrets` selection box, you can choose an existing secret or create a new secret.
5. Fill in the required fields and optional fields as you wish, and then Click the **Submit** button.
If you want to verify whether the data generator source connect has been created successfully, go back to the **Connectors** page, and you should see the created connector in the **Kafka Sources** tab, like below:
## Create a custom kafka connect
Before creating a kafka connect, it’s highly recommended to do the following:
1. [Check kafka connect availability](/cloud/connect/kafka-connect/deploy-kafka-connectors/kafka-connect-check) to ensure the version number of the kafka connect you want to create is supported on StreamNative Cloud.
2. Go to [StreamNative Hub](/connect/overview) and find the connect-specific docs of your version for configuration reference.
To create a custom kafka connect, you need to upload the connector jar/zip file to the StreamNative Cloud Package service first. Below are the steps:
### Upload your connector file to Pulsar
Upload packages
```bash theme={null}
snctl pulsar admin packages upload function://public/default/mongo-connect-zip@v1 \
--path /tmp/mongodb-kafka-connect-mongodb-1.12.0.zip \
--description "mongodb kafka connect in zip format" \
--properties fileName=mongo-kafka-connect.zip \
--properties libDir=mongodb-kafka-connect-mongodb-1.12.0/lib
```
You should see the following output:
```bash theme={null}
The package 'function://public/default/mongo-connect-zip@v1' uploaded from path '/tmp/mongodb-kafka-connect-mongodb-1.12.0.zip' successfully
```
the property `libDir` specifies the directory where the third-party libraries are located in the zip file.
You need to set the context for Pulsarctl first:
```bash theme={null}
# create a context
pulsarctl context set ${context-name} \
--admin-service-url ${admin-service-url} \
--issuer-endpoint ${issuerUrl} \
--audience urn:sn:pulsar:${orgName}:${instanceName} \
--key-file ${privateKey}
# activate oauth2
pulsarctl oauth2 activate
```
Replace the placeholder variables with the actual values that you can get when [setting up client tools](/cloud/process/pulsar-functions/function-setup#set-up-client-tools).
* `context-name`: any name you want
* `admin-service-url`: the HTTP service URL of your Pulsar cluster.
* `privateKey`: the path to the downloaded OAuth2 key file.
* `issuerUrl`: the URL of the OAuth2 issuer.
* `audience`: the [Uniform Resource Name (URN)](/cloud/references/glossary#uniform-resource-name-urn), which is a combination of the `urn:sn:pulsar`, your organization name, and your Pulsar instance name.
* `${orgName}`: the name of your [organization](/cloud/references/glossary#organization).
* `${instanceName}`: the name of your [instance](/cloud/references/glossary#instance).
Upload packages
```bash theme={null}
pulsarctl packages upload function://public/default/mongo-connect-zip@v1 \
--path /tmp/mongodb-kafka-connect-mongodb-1.12.0.zip \
--description "mongodb kafka connect in zip format" \
--properties fileName=mongo-kafka-connect.zip \
--properties libDir=mongodb-kafka-connect-mongodb-1.12.0/lib
```
You should see the following output:
```bash theme={null}
The package 'function://public/default/mongo-connect-zip@v1' uploaded from path '/tmp/mongodb-kafka-connect-mongodb-1.12.0.zip' successfully
```
the property `libDir` specifies the directory where the third-party libraries are located in the zip file.
```bash theme={null}
./bin/pulsar-admin \
--admin-url "${WEB_SERVICE_URL}" \
--auth-plugin org.apache.pulsar.client.impl.auth.oauth2.AuthenticationOAuth2 \
--auth-params '{"privateKey":"file://${privateKey}","issuerUrl":"${issuerUrl}","audience":"urn:sn:pulsar:${orgName}:${instanceName}}' \
packages upload function://public/default/mongo-connect-zip@v1 \
--path /tmp/mongodb-kafka-connect-mongodb-1.12.0.zip \
--description "mongodb kafka connect in zip format" \
--properties fileName=mongo-kafka-connect.zip \
--properties libDir=mongodb-kafka-connect-mongodb-1.12.0/lib
```
Replace the placeholder variables with the actual values that you can get when [setting up client tools](/cloud/process/pulsar-functions/function-setup#set-up-client-tools).
* `admin-url`: the HTTP service URL of your Pulsar cluster.
* `privateKey`: the path to the downloaded OAuth2 key file.
* `issuerUrl`: the URL of the OAuth2 issuer.
* `audience`: the [Uniform Resource Name (URN)](/cloud/references/glossary#uniform-resource-name-urn), which is a combination of the `urn:sn:pulsar`, your organization name, and your Pulsar instance name.
* `${orgName}`: the name of your [organization](/cloud/references/glossary#organization).
* `${instanceName}`: the name of your [instance](/cloud/references/glossary#instance).
You should see the following output:
```bash theme={null}
The package 'function://public/default/mongo-connect-zip@v1' uploaded from path '/tmp/mongodb-kafka-connect-mongodb-1.12.0.zip' successfully
```
the property `libDir` specifies the directory where the third-party libraries are located in the zip file.
The following example shows how to create a custom mongodb source connect named `mongo-source` on StreamNative Cloud using different tools.
To create a custom mongodb source connect named `mongo-source`, run the following command.
```bash theme={null}
> cat mongo.json
{
"name": "mongo-source",
"config": {
"connector.class": "com.mongodb.kafka.connect.MongoSourceConnector",
"connection.uri": "mongodb://mongo.default.svc.cluster.local:27017/?authSource=admin",
"database": "kafka-mongo",
"collection": "source",
"key.converter.schemas.enable": false,
"value.converter.schemas.enable": false,
"sn.pulsar.package.url": "function://public/default/mongo-connect-zip@v1",
"tasks.max": "1"
}
}
> snctl kafka admin connect apply -f mongo.json --use-service-account
```
The `sn.pulsar.package.url` is the package url you uploaded to the StreamNative Cloud Package service.
You should see the following output:
```bash theme={null}
Created connector mongo-source
```
If you want to verify whether the data generator source connect has been created successfully, run the following command:
```bash theme={null}
snctl kafka admin connect get connectors
```
You should see the following output:
```bash theme={null}
NAME TYPE STATE TASKS
mongo-source source RUNNING 0: RUNNING
```
To create a custom mongodb source connect named `mongo-source`, run the following command.
```bash theme={null}
> cat mongo.json
{
"name": "mongo-source",
"config": {
"connector.class": "com.mongodb.kafka.connect.MongoSourceConnector",
"connection.uri": "mongodb://mongo.default.svc.cluster.local:27017/?authSource=admin",
"database": "kafka-mongo",
"collection": "source",
"key.converter.schemas.enable": false,
"value.converter.schemas.enable": false,
"sn.pulsar.package.url": "function://public/default/mongo-connect-zip@v1",
"tasks.max": "1"
}
}
> kcctl apply -f mongo.json
```
The `sn.pulsar.package.url` is the package url you uploaded to the StreamNative Cloud Package service.
You should see the following output:
```bash theme={null}
Created connector mongo-source
```
If you want to verify whether the data generator source connect has been created successfully, run the following command:
```bash theme={null}
kcctl get connectors
```
You should see the following output:
```bash theme={null}
NAME TYPE STATE TASKS
mongo-source source RUNNING 0: RUNNING
```
To create a custom mongodb source connect named `mongo-source`, run the following command.
```bash theme={null}
> cat mongo.json
{
"name": "mongo-source",
"config": {
"connector.class": "com.mongodb.kafka.connect.MongoSourceConnector",
"connection.uri": "mongodb://mongo.default.svc.cluster.local:27017/?authSource=admin",
"database": "kafka-mongo",
"collection": "source",
"key.converter.schemas.enable": false,
"value.converter.schemas.enable": false,
"sn.pulsar.package.url": "function://public/default/mongo-connect-zip@v1",
"tasks.max": "1"
}
}
> curl -X POST --header "Content-Type: application/json" "https://public%2Fdefault:${APIKEY}@${KAFKA-SERVICE-URL}/admin/kafkaconnect/connectors/" --data @mongo.json
{"name":"mongo-source","config":{"connector.class":"com.mongodb.kafka.connect.MongoSourceConnector","connection.uri":"mongodb://mongo.default.svc.cluster.local:27017/?authSource=admin","database":"kafka-mongo","collection":"source","key.converter.schemas.enable":false,"value.converter.schemas.enable":false,"sn.pulsar.package.url":"function://public/default/mongo-connect-zip","tasks.max":"1"}}
```
If you want to list the submitted connect for a double check, run the following command:
```bash theme={null}
> curl "https://public%2Fdefault:${APIKEY}@${KAFKA-SERVICE-URL}/admin/kafkaconnect/connectors/"
["mongo-source"]
```
## Set resources for kafka connect
You can use below two configs to set the resources for the kafka connect to control the CPU and memory usage of the connector:
* `sn.cpu`: The number of CPU cores to allocate to the connector, default to **0.5**.
* `sn.memory`: The bytes of memory to allocate to the connector, default to **2147483648** (2G).
You need to upgrade your Pulsar cluster to `v3.0.8.4+`, `v3.3.3.4+` or `v4.0.1.3+` to use the `sn.cpu` and `sn.memory` configs.
## Tune Kafka Connect clients
You can tune the Kafka client behavior for an individual connector by adding connector-level override settings. These settings are useful when one connector needs different throughput, latency, or retry behavior than the default Kafka Connect worker settings.
Use the following prefixes in the connector configuration:
* `producer.override.*`: Overrides Kafka producer settings. Use this prefix mainly for source connectors that write records to Kafka topics. Common settings include `compression.type`, `batch.size`, `linger.ms`, and `acks`.
* `consumer.override.*`: Overrides Kafka consumer settings. Use this prefix for sink connectors that read records from Kafka topics. Common settings include `max.poll.records`, `fetch.min.bytes`, `fetch.max.wait.ms`, and `auto.offset.reset`.
* `admin.override.*`: Overrides Kafka administrative client settings. Use this prefix when the connector needs different administrative client behavior, such as for topic creation or dead-letter queue operations. Common settings include `request.timeout.ms`, `retry.backoff.ms`, and `default.api.timeout.ms`.
For example, the following sink connector configuration increases the consumer batch size and adjusts admin client timeouts:
```json theme={null}
{
"name": "jdbc-sink",
"config": {
"connector.class": "io.confluent.connect.jdbc.JdbcSinkConnector",
"topics": "orders",
"tasks.max": "1",
"consumer.override.max.poll.records": "1000",
"consumer.override.fetch.min.bytes": "1048576",
"consumer.override.fetch.max.wait.ms": "500",
"admin.override.request.timeout.ms": "30000",
"admin.override.retry.backoff.ms": "500"
}
}
```
The following source connector example tunes the producer used to write records to Kafka:
```json theme={null}
{
"name": "mongo-source",
"config": {
"connector.class": "com.mongodb.kafka.connect.MongoSourceConnector",
"tasks.max": "1",
"producer.override.compression.type": "gzip",
"producer.override.batch.size": "131072",
"producer.override.linger.ms": "20",
"producer.override.acks": "all"
}
}
```
## Schema Registry Support
Kafka Connect supports using schema registry to save Avro/Protobuf/Json schema for the value and key. And StreamNative has an internal schema registry which can be used without complex configurations.
To use it, you just need to set the following configuration in the connector configuration:
* `value.converter.schema.registry.internal: true`: if you want to use the internal schema registry for the value converter.
* `key.converter.schema.registry.internal: true`: if you want to use the internal schema registry for the key converter.
# Set up Your Environment
Source: https://docs.streamnative.io/cloud/connect/kafka-connect/deploy-kafka-connectors/kafka-connect-setup
This section introduces how to set up a new service account to run kafka connectors. To perform the following operations, you need to be the cluster administrator beforehand.
## Create a service account for Pulsar users
1. On the left navigation pane of StreamNative Cloud Console, click **Service Accounts**.
2. Click **Create Service Account**.
3. Enter a name for the service account, and then click **Confirm**.
You may see the `Role xxxx cannot access topic public/__kafka_connect/__kafka_connect_offset_storage` exception when you create a connector, this is a known issue which uses a wrong namespace `public/__kafka_connect` to create the offset storage topic,
after v3.3.1.5, this issue has been fixed, and will use namespace `public/default` instead.
You can create a **Super Admin** service account or create the `public/__kafka_connect` namespace and grant `produce` permission to this service account you created as the workaround.
## Authorize the service account
To make the service account work, you need to make the service account granted with proper permissions (`packages`, `produce`, and `consume`).
To grant the service account permissions on the namespace level, follow these steps:
1. Navigate to the **Namespace Dashboard** page by [switching to the namespace workspace](/cloud/get-started/cloud-console#switch-a-namespace).
2. On the **Namespace Dashboard** page, click **Configuration** on the left navigation pane.
3. On the **Namespace configuration** page, click **ADD ROLE**, and select the service account that you want to authorize.
4. On the drop-down menu below the service account, select the proper permissions to assign to the service account. There are six permissions in total:
* `consume`: allow the service account to consume messages.
* `produce`: allow the service account to publish messages.
* `functions`: allow the service account to submit and manage functions.
* `sinks`: allow the service account to create and manage sink connectors.
* `sources`: allow the service account to create and manage source connectors.
* `packages`: allow the service account to upload and manage pulsar packages. If you want to submit a customized function/connector, then you will need to upload the function/connector’s JAR/NAR/Python file first, which requires the `packages` permission.
## Grant access to the service account
To grant the underlying infrastructure with access to the newly created service account's OAuth2 key file, you need to create a service account binding via UI.
Go to the `Service Accounts` tab and choose the service account you want to use for running the connector. Clicking on the right button and there will be a `Edit service account bindings` option.
Click the `Edit service account bindings`, choose the desired pool member and confirm.
You can also enable the `Enable IAM Role Creation` option to create a separate IAM role for the service account.
Now your connector is ready to use the service account in StreamNative environments.
## (Optional) Create a separate IAM role for the service account
StreamNative's I/O components (Pulsar Functions, Pulsar Connectors, and Kafka Connectors) run as cloud-native workloads on AWS, GCP, and Azure infrastructures.
Use the cloud providers' native IAM (Identity and Access Management) services to control access to infrastructure resources such as S3, GCS, and Azure Blob Storage. This removes the need for password-based authentication for the service accounts that run connectors in StreamNative Cloud.
By default, StreamNative uses a single service account per `PulsarCluster` for all I/O components (Pulsar Functions, Pulsar Connectors, and Kafka Connectors) to access underlying infrastructure resources. This means all I/O Components in the same cluster share one service account and the same permissions.
Using a single service account for all I/O components means all functions and connectors share the same permissions. If one component is compromised, it could access resources intended for other components.
So it's better to leave the default service account with no permissions and use it for running IO components that do not require access to external resources.
And create separate service accounts with the minimum required permissions for each IO component that need to access external resources.
To enhance security and improve isolation, you can create a separate IAM role for each service account used to run connectors. This let you grant only the permissions each service account needs.
Create a separate IAM role for your service account:
This feature is available in [snctl](/tools/cli/snctl/snctl-overview) v1.3.0 or later.
1. Get the `PoolMember` name and namespace from the `PulsarCluster`
```shell theme={null}
snctl get pulsarcluster -o yaml
```
In the output, find the `poolMemberRef` block, which looks like:
```yaml theme={null}
poolMemberRef:
name:
namespace:
```
Multiple clusters may be located in the same `PoolMember`. You do not need to create separate IAM roles for each cluster within the same `PoolMember`.
2. Create a new `ServiceAccountBinding` that binds the service account to the `PoolMember`
```shell theme={null}
snctl create serviceaccountbinding \
--pool-member / \
--enable-iam-account-creation \
--service-account-name
```
**AWS only:** You can specify one or more `AWS Assume Role ARNs` that can be assumed by the IAM role created for the service account (repeat the flag for each ARN):
```shell theme={null}
snctl create serviceaccountbinding \
--pool-member / \
--enable-iam-account-creation \
--service-account-name \
--aws-assume-role-arns \
--aws-assume-role-arns
```
The IAM role created by StreamNative will include permissions to call `sts:AssumeRole` on `arn1` and `arn2`. You must still add a trust policy on `arn1` and `arn2` to allow the newly created role to assume them, an example likes below:
```json theme={null}
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::[aws-account-id]:role/StreamNative/sncloud-role/authorization.streamnative.io/iamaccounts/IamAccount-[org-id]-sab-[binding-name]"
},
"Action": "sts:AssumeRole"
}
]
}
```
3. (Optional) Update an existing `ServiceAccountBinding` to create the IAM role
```shell theme={null}
snctl edit serviceaccountbinding
```
4. Verify the IAM role was created successfully
```shell theme={null}
snctl get serviceaccountbinding -o yaml
```
Expected output (example):
```yaml theme={null}
apiVersion: cloud.streamnative.io/v1alpha1
kind: ServiceAccountBinding
metadata:
creationTimestamp: "2025-06-25T08:45:35Z"
finalizers:
- serviceaccountbinding.finalizers.cloud.streamnative.io
generation: 1
name: test-admin
namespace: o-lftqu
ownerReferences:
- apiVersion: cloud.streamnative.io/v1alpha1
kind: ServiceAccount
name: admin
uid: 4ef639aa-6278-4863-9a23-f1da50cea448
resourceVersion: "54707713"
uid: 918d40ad-551d-416b-a2ae-d41548d6608e
spec:
enableIamRoleCreation: true
poolMemberRef:
name: azure-eastus-zephyr
namespace: streamnative
serviceAccountName: admin
status:
conditions:
- lastTransitionTime: "2025-06-25T08:45:35Z"
status: "True"
type: IAMAccountReady
- lastTransitionTime: "2025-06-25T08:45:35Z"
status: "True"
type: ServiceAccountReady
- lastTransitionTime: "2025-07-16T13:56:17Z"
status: "True"
type: ResourceExists
- lastTransitionTime: "2025-07-16T13:56:17Z"
status: "True"
type: PoolMemberReady
- lastTransitionTime: "2025-07-16T13:56:17Z"
reason: AllConditionStatusTrue
status: "True"
type: Ready
```
In the output, the `status.conditions` array should include a condition with `type: IAMAccountReady` and `status: "True"`, indicating the IAM role was created successfully.
5. Use the service account when creating I/O components
You can now select this service account in Console (or use its API key with the CLI) when creating I/O components (Pulsar Functions, Pulsar Connectors, and Kafka Connectors). The components will inherit the permissions granted to the IAM role created in the previous step.
You can also create a separate IAM role for your service account via StreamNative Cloud Console. Just enable the `Enable IAM Role Creation` option when creating or editing a service account binding.
**AWS only:** You can specify one or more `AWS Assume Role ARNs` that can be assumed by the IAM role created for the service account (use one line for each ARN)
The IAM role created by StreamNative will include permissions to call `sts:AssumeRole` on `arn1` and `arn2`. You must still add a trust policy on `arn1` and `arn2` to allow the newly created role to assume them, an example likes below:
```json theme={null}
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::[aws-account-id]:role/StreamNative/sncloud-role/authorization.streamnative.io/iamaccounts/IamAccount-[org-id]-sab-[binding-name]"
},
"Action": "sts:AssumeRole"
}
]
}
```
In Azure, a Managed Identity `sab-[binding-name]-[org-id]` is created;
In AWS, an IAM role `role/StreamNative/sncloud-role/authorization.streamnative.io/iamaccounts/IamAccount-[org-id]-sab-[binding-name]` is created;
In GCP, a service account with display name: `IamAccount/[org-id]/sab-[binding-name]` is created.
## Set up client tools
### Using StreamNative Cloud CLI tool `snctl`
Starting from v1.0.0 of the StreamNative Cloud CLI tool `snctl`, it supports to manage Kafka Connectors running on StreamNative Cloud.
Follow the steps below to set up `snctl`:
1. Use `snctl config set --organization $ORG` to set your StreamNative Cloud organization.
2. Use `snctl context use` to select your target StreamNative Cloud cluster interactively.
3. To send Kafka Connect admin requests as a service account, use `snctl kafka admin connect --as-service-account $SERVICE_ACCOUNT_NAME ...` or `snctl kafka admin connect --use-service-account ...`.
4. To run a Kafka connector as a service account, use `--sn-service-account $SERVICE_ACCOUNT_NAME` on `snctl kafka admin connect apply` or `snctl kafka admin connect patch connector`. To select the runtime service account interactively, use `--use-sn-service-account`.
5. Verify the setup using `snctl kafka admin connect info`, it should print something like below.
```shell theme={null}
> snctl kafka admin connect info
URL: https://${KAFKA-SERVICE-URL}/admin/kafkaconnect/
Version: 3.7.0
Commit: 839b886f9b732b15
Kafka Cluster ID: connect
```
`--as-service-account` and `--sn-service-account` set different identities.
Use `--as-service-account` to send the request with the specified service account's credentials. That same service account also becomes the runtime identity of the connector. Therefore, the service account must have permissions to create or update connectors, download packages, and produce or consume messages.
Use `--sn-service-account` to keep the request authenticated as the current caller, but run the connector with the specified service account as its runtime identity. In this case, the caller must have permission to create or update the connector and use the selected service account (see [account-admin](/cloud/security/access/rbac/manage-rbac-roles#account-admin)). The runtime service account only needs the permissions required by the connector itself, such as producing or consuming messages and downloading packages.
You can use `--as-service-account` on Pulsar clusters of any supported version. The `--sn-service-account` and `--use-sn-service-account` flags require Pulsar 4.0.x version 4.0.10.6 or later, or Pulsar 4.2.x version 4.2.1.4 or later.
### Using kcctl
We have tested with the [kcctl](https://github.com/kcctl/kcctl) to manage Kafka Connectors, you can also try other CLI tools you like.
Follow the steps below to set up it:
1. Create an apikey from the service account you created.
You can follow the instructions to [create an API key](/cloud/security/authentication/service-accounts/use-api-keys/api-keys-overview#create-an-cluster-api-key) for the service account you choose to use.
2. Set up the kcctl with the apikey.
```shell theme={null}
kcctl config set-context --bootstrap-servers ${KAFKA-SERVICE-URL}:9093 --cluster=https://${KAFKA-SERVICE-URL}/admin/kafkaconnect/ --username public/default --password "token:${APIKEY}" ${NAME}
kcctl config use-context ${NAME}
```
The KAFKA-SERVICE-URL is the endpoint of the Kafka service, you can find it in the StreamNative Cloud Console.
3. Verify the setup using `kcctl info`, it should print something like below.
```shell theme={null}
> kcctl info
URL: https://${KAFKA-SERVICE-URL}/admin/kafkaconnect/
Version: 3.7.0
Commit: 839b886f9b732b15
Kafka Cluster ID: connect
```
## What’s next?
* [Check kafka connect availability](/cloud/connect/kafka-connect/deploy-kafka-connectors/kafka-connect-check)
* [Create kafka connectors](/cloud/connect/kafka-connect/deploy-kafka-connectors/kafka-connect-create)
# Manage Kafka Connectors
Source: https://docs.streamnative.io/cloud/connect/kafka-connect/kafka-connect-manage
StreamNative Cloud enables you to manage Pulsar IO Connectors by using a variety of tools, including `snctl`, `kcctl`, `restful-api`, and `Console`.
## Update a connect
When you want to modify configurations or update resources for connects, you can update connectors using multiple tools.
The following example shows how to update the tasks.max of the data generator source connector `test` to `2` using different tools.
```bash theme={null}
> cat datagen.json
{
"name": "test",
"config": {
"connector.class": "io.confluent.kafka.connect.datagen.DatagenConnector",
"kafka.topic": "testusers",
"quickstart": "users",
"key.converter": "org.apache.kafka.connect.storage.StringConverter",
"value.converter": "org.apache.kafka.connect.json.JsonConverter",
"value.converter.schemas.enable": "false",
"max.interval": 1000,
"iterations": 10000000,
"tasks.max": "2"
}
}
> snctl kafka admin connect apply -f datagen.json
```
You should see the following output:
```bash theme={null}
Updated connector test
```
And you can further check the status:
```bash theme={null}
snctl kafka admin connect describe connector test
Name: test
Type: source
State: RUNNING
Worker ID: 10.80.161.255:8083
Config:
connector.class: io.confluent.kafka.connect.datagen.DatagenConnector
iterations: 10000000
kafka.topic: testusers
key.converter: org.apache.kafka.connect.storage.StringConverter
max.interval: 1000
name: test
quickstart: users
tasks.max: 2
value.converter: org.apache.kafka.connect.json.JsonConverter
value.converter.schemas.enable: false
Tasks:
0:
State: RUNNING
Worker ID: 10.80.161.255:8083
Config:
connector.class: io.confluent.kafka.connect.datagen.DatagenConnector
quickstart: users
tasks.max: 2
max.interval: 1000
iterations: 10000000
task.class: io.confluent.kafka.connect.datagen.DatagenTask
name: test
value.converter.schemas.enable: false
kafka.topic: testusers
task.id: 0
value.converter: org.apache.kafka.connect.json.JsonConverter
key.converter: org.apache.kafka.connect.storage.StringConverter
1:
State: RUNNING
Worker ID: 10.80.160.255:8083
Config:
connector.class: io.confluent.kafka.connect.datagen.DatagenConnector
quickstart: users
tasks.max: 2
max.interval: 1000
iterations: 10000000
task.class: io.confluent.kafka.connect.datagen.DatagenTask
name: test
value.converter.schemas.enable: false
kafka.topic: testusers
task.id: 0
value.converter: org.apache.kafka.connect.json.JsonConverter
key.converter: org.apache.kafka.connect.storage.StringConverter
Topics:
testusers
```
```bash theme={null}
> cat datagen.json
{
"name": "test",
"config": {
"connector.class": "io.confluent.kafka.connect.datagen.DatagenConnector",
"kafka.topic": "testusers",
"quickstart": "users",
"key.converter": "org.apache.kafka.connect.storage.StringConverter",
"value.converter": "org.apache.kafka.connect.json.JsonConverter",
"value.converter.schemas.enable": "false",
"max.interval": 1000,
"iterations": 10000000,
"tasks.max": "2"
}
}
> kcctl apply -f datagen.json
```
You should see the following output:
```bash theme={null}
Updated connector test
```
And you can further check the status:
```bash theme={null}
kcctl describe connectors test --tasks-config
Name: test
Type: source
State: RUNNING
Worker ID: 10.80.161.255:8083
Config:
connector.class: io.confluent.kafka.connect.datagen.DatagenConnector
iterations: 10000000
kafka.topic: testusers
key.converter: org.apache.kafka.connect.storage.StringConverter
max.interval: 1000
name: test
quickstart: users
tasks.max: 2
value.converter: org.apache.kafka.connect.json.JsonConverter
value.converter.schemas.enable: false
Tasks:
0:
State: RUNNING
Worker ID: 10.80.161.255:8083
Config:
connector.class: io.confluent.kafka.connect.datagen.DatagenConnector
quickstart: users
tasks.max: 2
max.interval: 1000
iterations: 10000000
task.class: io.confluent.kafka.connect.datagen.DatagenTask
name: test
value.converter.schemas.enable: false
kafka.topic: testusers
task.id: 0
value.converter: org.apache.kafka.connect.json.JsonConverter
key.converter: org.apache.kafka.connect.storage.StringConverter
1:
State: RUNNING
Worker ID: 10.80.160.255:8083
Config:
connector.class: io.confluent.kafka.connect.datagen.DatagenConnector
quickstart: users
tasks.max: 2
max.interval: 1000
iterations: 10000000
task.class: io.confluent.kafka.connect.datagen.DatagenTask
name: test
value.converter.schemas.enable: false
kafka.topic: testusers
task.id: 0
value.converter: org.apache.kafka.connect.json.JsonConverter
key.converter: org.apache.kafka.connect.storage.StringConverter
Topics:
testusers
```
```bash theme={null}
> cat datagen.json
{
"name": "test",
"config": {
"connector.class": "io.confluent.kafka.connect.datagen.DatagenConnector",
"kafka.topic": "testusers",
"quickstart": "users",
"key.converter": "org.apache.kafka.connect.storage.StringConverter",
"value.converter": "org.apache.kafka.connect.json.JsonConverter",
"value.converter.schemas.enable": "false",
"max.interval": 1000,
"iterations": 10000000,
"tasks.max": "2"
}
}
> curl -X PUT --header "Content-Type: application/json" "https://public%2Fdefault:${APIKEY}@${KAFKA-SERVICE-URL}/admin/kafkaconnect/connectors/test/config" --data @datagen.json
```
If no error is response, the update is successful.
And you can further check the status:
```bash theme={null}
> curl "https://public%2Fdefault:${APIKEY}@${KAFKA-SERVICE-URL}/admin/kafkaconnect/connectors/test | jq '.'"
{
"name": "datagen-test-offset",
"config": {
"connector.class": "io.confluent.kafka.connect.datagen.DatagenConnector",
"iterations": "10000000",
"kafka.topic": "testusers",
"key.converter": "org.apache.kafka.connect.storage.StringConverter",
"max.interval": "1000",
"name": "datagen-test-offset",
"quickstart": "users",
"tasks.max": "2",
"value.converter": "org.apache.kafka.connect.json.JsonConverter",
"value.converter.schemas.enable": "false"
},
"tasks": [
{
"connector": "datagen-test-offset",
"task": 0
},
{
"connector": "datagen-test-offset",
"task": 1
}
],
"type": "source"
}
```
1. On the left navigation pane of StreamNative Console, under **Resources**, click **Connectors**.
2. On the Connectors page, select the **Kafka Sources** or **Kafka Sinks** tab.
3. Click the ellipsis at the end of the row of the connector, and then click **Edit**.
4. Edit the configuration that you want to change, and click **SUBMIT**.
## Delete a connector
The following example shows how to delete the data generator source connector `test` using different tools.
To delete the source connector `test`, use the following command.
```bash theme={null}
snctl kafka admin connect delete connector test
```
You should see the following output:
```bash theme={null}
Deleted connector test
```
If you want to verify whether the source connector has been deleted successfully, run the following command.
```bash theme={null}
snctl kafka admin connect get connectors
```
You should see the following output:
```bash theme={null}
NAME TYPE STATE TASKS
```
To delete the source connector `test`, use the following command.
```bash theme={null}
kcctl delete connector test
```
You should see the following output:
```bash theme={null}
Deleted connector test
```
If you want to verify whether the source connector has been deleted successfully, run the following command.
```bash theme={null}
kcctl get connectors
```
You should see the following output:
```bash theme={null}
NAME TYPE STATE TASKS
```
To delete the source connector `test`, use the following command.
```bash theme={null}
> curl -X DELETE "https://public%2Fdefault:${APIKEY}@${KAFKA-SERVICE-URL}/admin/kafkaconnect/connectors/test"
```
If no error is response, the delete is successful.
If you want to verify whether the source connector has been deleted successfully, run the following command.
```bash theme={null}
curl -X GET "https://public%2Fdefault:${APIKEY}@${KAFKA-SERVICE-URL}/admin/kafkaconnect/connectors/test"
```
You should see the following output:
```bash theme={null}
{"reason":"This resource doesn't exist, please check the name"}
```
1. On the left navigation pane of StreamNative Console, under **Resources**, click **Connectors**.
2. On the Connectors page, select the **Kafka Sources** or **Kafka Sinks** tab.
3. Click the ellipsis at the end of the row of the connector, and then click **Delete**.
4. Enter the connector name and then click **Confirm**.
## Stop a connector
You can stop a running connector using different tools, after stopped, all resources of the connector will be released.
After stopped, you can restart the connector.
To stop the source connector `test`, use the following command.
```bash theme={null}
snctl kafka admin connect stop test
```
You should see the following output:
```bash theme={null}
Stopped connector test
```
If you want to verify whether the source connector has been stopped successfully, run the following command.
```bash theme={null}
snctl kafka admin connect get connectors
```
You should see the following output:
```bash theme={null}
NAME TYPE STATE TASKS
datagen source STOPPED
```
To stop the source connector `test`, use the following command.
```bash theme={null}
kcctl stop connectors test
```
You should see the following output:
```bash theme={null}
Stopped connector test
```
If you want to verify whether the source connector has been stopped successfully, run the following command.
```bash theme={null}
kcctl get connectors
```
You should see the following output:
```bash theme={null}
NAME TYPE STATE TASKS
datagen source STOPPED
```
To stop the source connector `test`, use the following command.
```bash theme={null}
> curl -X PUT --header 'content-type: application/json' "https://public%2Fdefault:${APIKEY}@${KAFKA-SERVICE-URL}/admin/kafkaconnect/connectors/test/stop"
```
If no error is response, the stop is successful.
If you want to verify whether the source connector has been stopped successfully, run the following command.
```bash theme={null}
curl -X GET "https://public%2Fdefault:${APIKEY}@${KAFKA-SERVICE-URL}/admin/kafkaconnect/connectors/test/status | jq '.'"
```
You should see the following output:
```bash theme={null}
{
"name": "test",
"connector": {
"state": "STOPPED",
"worker_id": "10.80.161.255:8083",
"trace": "Kafka Connector Resource stopped"
},
"tasks": [],
"type": "source"
}
```
1. On the left navigation pane of StreamNative Console, under **Resources**, click **Connectors**.
2. On the Connectors page, select the **Kafka Sources** or **Kafka Sinks** tab.
3. Click the ellipsis at the end of the row of the connector, and then click **Stop**.
## Restart a connector
You can restart a stopped or a running connector using different tools.
To restart the source connector `test`, use the following command.
```bash theme={null}
snctl kafka admin connect restart connector test
```
You should see the following output:
```bash theme={null}
Restarted connector test
```
If you want to verify whether the source connector has been restarted successfully, run the following command.
```bash theme={null}
snctl kafka admin connect get connectors
```
You should see the following output:
```bash theme={null}
NAME TYPE STATE TASKS
datagen source RUNNING
```
To restart the source connector `test`, use the following command.
```bash theme={null}
kcctl restart connectors test
```
You should see the following output:
```bash theme={null}
Restarted connector test
```
If you want to verify whether the source connector has been restarted successfully, run the following command.
```bash theme={null}
kcctl get connectors
```
You should see the following output:
```bash theme={null}
NAME TYPE STATE TASKS
datagen source RUNNING
```
To restart the source connector `test`, use the following command.
```bash theme={null}
> curl -X POST "https://public%2Fdefault:${APIKEY}@${KAFKA-SERVICE-URL}/admin/kafkaconnect/connectors/test/restart"
```
If no error is response, the restart is successful.
If you want to verify whether the source connector has been restarted successfully, run the following command.
```bash theme={null}
curl -X GET "https://public%2Fdefault:${APIKEY}@${KAFKA-SERVICE-URL}/admin/kafkaconnect/connectors/test/status | jq '.'"
```
You should see the following output:
```bash theme={null}
{
"name": "test",
"connector": {
"state": "RUNNING",
"worker_id": "10.80.161.255:8083",
"trace": "",
},
"tasks": [
{
"id": 0,
"state": "RUNNING",
"worker_id": "10.244.0.75:8083"
}
],
"type": "source"
}
```
1. On the left navigation pane of StreamNative Console, under **Resources**, click **Connectors**.
2. On the Connectors page, select the **Kafka Sources** or **Kafka Sinks** tab.
3. Click the ellipsis at the end of the row of the connector, and then click **Restart**.
## Pause a connector
You can pause a running connector using different tools, a paused connector still occupy the resources but just stop processing messages.
To pause the source connector `test`, use the following command.
```bash theme={null}
snctl kafka admin connect pause test
```
You should see the following output:
```bash theme={null}
Paused connector test
```
If you want to verify whether the source connector has been paused successfully, run the following command.
```bash theme={null}
snctl kafka admin connect get connectors
```
You should see the following output:
```bash theme={null}
NAME TYPE STATE TASKS
datagen source PAUSED 0: PAUSED
```
To pause the source connector `test`, use the following command.
```bash theme={null}
kcctl pause connectors test
```
You should see the following output:
```bash theme={null}
Paused connector test
```
If you want to verify whether the source connector has been paused successfully, run the following command.
```bash theme={null}
kcctl get connectors
```
You should see the following output:
```bash theme={null}
NAME TYPE STATE TASKS
datagen source PAUSED 0: PAUSED
```
To pause the source connector `test`, use the following command.
```bash theme={null}
> curl -X PUT --header 'content-type: application/json' "https://public%2Fdefault:${APIKEY}@${KAFKA-SERVICE-URL}/admin/kafkaconnect/connectors/test/pause"
```
If no error is response, the pause is successful.
If you want to verify whether the source connector has been paused successfully, run the following command.
```bash theme={null}
curl -X GET "https://public%2Fdefault:${APIKEY}@${KAFKA-SERVICE-URL}/admin/kafkaconnect/connectors/test/status | jq '.'"
```
You should see the following output:
```bash theme={null}
{
"name": "test",
"connector": {
"state": "PAUSED",
"worker_id": "10.80.161.255:8083",
"trace": "",
},
"tasks": [
{
"id": 0,
"state": "PAUSEd",
"worker_id": "10.244.0.75:8083"
}
],
"type": "source"
}
```
1. On the left navigation pane of StreamNative Console, under **Resources**, click **Connectors**.
2. On the Connectors page, select the **Kafka Sources** or **Kafka Sinks** tab.
3. Click the ellipsis at the end of the row of the connector, and then click **Pause**.
## Resume a connector
You can resume a paused connector using different tools.
To resume the source connector `test`, use the following command.
```bash theme={null}
snctl kafka admin connect resume test
```
You should see the following output:
```bash theme={null}
Resumed connector test
```
If you want to verify whether the source connector has been resumed successfully, run the following command.
```bash theme={null}
snctl kafka admin connect get connectors
```
You should see the following output:
```bash theme={null}
NAME TYPE STATE TASKS
datagen source RUNNING 0: RUNNING
```
To resume the source connector `test`, use the following command.
```bash theme={null}
kcctl resume connectors test
```
You should see the following output:
```bash theme={null}
Resumed connector test
```
If you want to verify whether the source connector has been resumed successfully, run the following command.
```bash theme={null}
kcctl get connectors
```
You should see the following output:
```bash theme={null}
NAME TYPE STATE TASKS
datagen source RUNNING 0: RUNNING
```
To resume the source connector `test`, use the following command.
```bash theme={null}
> curl -X PUT --header 'content-type: application/json' "https://public%2Fdefault:${APIKEY}@${KAFKA-SERVICE-URL}/admin/kafkaconnect/connectors/test/resume"
```
If no error is response, the pause is successful.
If you want to verify whether the source connector has been resumed successfully, run the following command.
```bash theme={null}
curl -X GET "https://public%2Fdefault:${APIKEY}@${KAFKA-SERVICE-URL}/admin/kafkaconnect/connectors/test/status | jq '.'"
```
You should see the following output:
```bash theme={null}
{
"name": "test",
"connector": {
"state": "RESUMED",
"worker_id": "10.80.161.255:8083",
"trace": "",
},
"tasks": [
{
"id": 0,
"state": "RESUMED",
"worker_id": "10.244.0.75:8083"
}
],
"type": "source"
}
```
1. On the left navigation pane of StreamNative Console, under **Resources**, click **Connectors**.
2. On the Connectors page, select the **Kafka Sources** or **Kafka Sinks** tab.
3. Click the ellipsis at the end of the row of the connector, and then click **Resume**.
## What’s next?
* [Monitor and troubleshoot kafka connectors](/cloud/connect/kafka-connect/kafka-connect-monitoring)
* [SMTs(Single Message Transformations)](/cloud/connect/kafka-connect/kafka-connect-smt)
* Discover kafka Connect Ecosystem on [StreamNative Hub](/connect/overview).
# Monitor and Troubleshoot Kafka Connectors
Source: https://docs.streamnative.io/cloud/connect/kafka-connect/kafka-connect-monitoring
StreamNative Cloud allows you to monitor kafka connectors' status and logs.
## View connector status
This section describes how to view connector status using `snctl`, `kcctl`, `Rest API`, and console.
The following example introduces how to view the status of the data generator source connector named `test`.
To check the status of the source connector `test`, run the following command:
```bash theme={null}
snctl kafka admin connect describe connector test
```
```bash theme={null}
Name: test
Type: source
State: RUNNING
Worker ID: 10.80.161.252:8083
Config:
config.action.reload: restart
connector.class: io.confluent.kafka.connect.datagen.DatagenConnector
errors.log.enable: false
errors.log.include.messages: false
errors.retry.delay.max.ms: 60000
errors.retry.timeout: 0
errors.tolerance: none
exactly.once.source.support: disabled
exactly.once.support: requested
header.converter: org.apache.kafka.connect.storage.SimpleHeaderConverter
iterations: -1
kafka.topic: testgen
key.converter: org.apache.kafka.connect.json.JsonConverter
max.interval: 500
name: test
offset.storage.partitions: 25
offset.storage.replication.factor: 3
offset.storage.topic: kafka-connect-offset-storage
quickstart: users
tasks.max: 1
tasks.max.enforce: true
transaction.boundary: poll
value.converter: org.apache.kafka.connect.json.JsonConverter
Tasks:
0:
State: RUNNING
Worker ID: 10.80.161.252:8083
Topics:
testgen
```
To check the status of the source connector `test`, run the following command:
```bash theme={null}
kcctl describe connectors test
```
```bash theme={null}
Name: test
Type: source
State: RUNNING
Worker ID: 10.80.161.252:8083
Config:
config.action.reload: restart
connector.class: io.confluent.kafka.connect.datagen.DatagenConnector
errors.log.enable: false
errors.log.include.messages: false
errors.retry.delay.max.ms: 60000
errors.retry.timeout: 0
errors.tolerance: none
exactly.once.source.support: disabled
exactly.once.support: requested
header.converter: org.apache.kafka.connect.storage.SimpleHeaderConverter
iterations: -1
kafka.topic: testgen
key.converter: org.apache.kafka.connect.json.JsonConverter
max.interval: 500
name: test
offset.storage.partitions: 25
offset.storage.replication.factor: 3
offset.storage.topic: kafka-connect-offset-storage
quickstart: users
tasks.max: 1
tasks.max.enforce: true
transaction.boundary: poll
value.converter: org.apache.kafka.connect.json.JsonConverter
Tasks:
0:
State: RUNNING
Worker ID: 10.80.161.252:8083
Topics:
testgen
```
To check the status of the source connector `test`, run the following command:
```bash theme={null}
curl -X GET "https://public%2Fdefault:${APIKEY}@${KAFKA-SERVICE-URL}/admin/kafkaconnect/connectors/test"
```
You should see the following output:
```bash theme={null}
{
"name": "test",
"config": {
"config.action.reload": "restart",
"connector.class": "io.confluent.kafka.connect.datagen.DatagenConnector",
"errors.log.enable": "false",
"errors.log.include.messages": "false",
"errors.retry.delay.max.ms": "60000",
"errors.retry.timeout": "0",
"errors.tolerance": "none",
"exactly.once.source.support": "disabled",
"exactly.once.support": "requested",
"header.converter": "org.apache.kafka.connect.storage.SimpleHeaderConverter",
"iterations": "-1",
"kafka.topic": "testgen",
"key.converter": "org.apache.kafka.connect.json.JsonConverter",
"max.interval": "500",
"name": "test",
"offset.storage.partitions": "25",
"offset.storage.replication.factor": "3",
"offset.storage.topic": "kafka-connect-offset-storage",
"quickstart": "users",
"tasks.max": "1",
"tasks.max.enforce": "true",
"transaction.boundary": "poll",
"value.converter": "org.apache.kafka.connect.json.JsonConverter"
},
"tasks": [
{
"connector": "test",
"task": 0
}
],
"type": "source"
}
```
1. From the left navigation pane, under **Resources**, click **Connectors**.
2. Select the **Kafka Sources** or **Kafka Sinks** tab and click the connector you want to check, you will see the status of this connector and its tasks, and also the logs and metrics.
## View connector logs
### View the connector logs using `snctl`
This section describes how to view connector logs using `snctl`.
This example assumes you have [installed snctl](/tools/cli/snctl/snctl-overview#install-snctl) and [initialized snctl configurations](/tools/cli/snctl/snctl-overview#initialize-snctl-configuration).
You can run the `snctl logs` command to view logs for a specific connector. This table outlines the configuration options that are used for viewing connector logs. For details about all supported fields, you can use the `snctl logs -h` command to list more information.
| Option | Descriptions |
| ------------------------ | ---------------------------------------------------------------------------------------------------------------- |
| `-c` or `--cluster` | The name of your Pulsar cluster where the connector is created. |
| `-p` or `--component` | The type of component to monitor. Available options are `function`, `sink`, `source` and `kafka-connect`. |
| `-f` or `--follow` | Continuously list the connector log history. |
| `-h` or `--help` | Show usage information about the `snctl logs` command. |
| `-i` or `--instance` | The name of your Pulsar instance where the connector is created. |
| `--name` | The name of your connector. |
| `-o` or `--organization` | The name of your organization where the connector is created. |
| `--previous` | Print the logs that are generated before the configured timestamp. |
| `--pulsar-tenant` | The name of your Pulsar tenant where the connector is created. |
| `--pulsar-namespace` | The name of your Pulsar namespace where the connector is created. |
| `--since` | List logs more recent than the specific time. Available units are `second`, `minute`, and `hour`, such as `24h`. |
| `-s` or `--size` | Specify how many lines of recent logs to display. |
| `--timestamp` | Include timestamps on each line in the log output. |
The following command example shows how to view up to 60 lines of the `data1` sink connector’s logs within the last 5 hours.
```bash theme={null}
snctl logs --since 5h --organization sndev --instance aws --cluster aws --name data1 --pulsar-tenant public --pulsar-namespace default -p kafka-connect -f -s 60
```
You should see the following output:
```bash theme={null}
2024-08-26T04:37:21,290+0000 [SourceTaskOffsetCommitter-1] INFO org.apache.kafka.connect.runtime.WorkerSourceTask - WorkerSourceTask{id=datagen-ui-0} Committing offsets for 241 acknowledged messages
2024-08-26T04:38:21,306+0000 [SourceTaskOffsetCommitter-1] INFO org.apache.kafka.connect.runtime.WorkerSourceTask - WorkerSourceTask{id=datagen-ui-0} Committing offsets for 229 acknowledged messages
2024-08-26T04:39:13,572+0000 [kafka-admin-client-thread | datagen-ui-73c8b112-mesh-admin] INFO org.apache.kafka.clients.NetworkClient - [AdminClient clientId=datagen-ui-73c8b112-mesh-admin] Node 1753251735 disconnected.
2024-08-26T04:39:21,320+0000 [SourceTaskOffsetCommitter-1] INFO org.apache.kafka.connect.runtime.WorkerSourceTask - WorkerSourceTask{id=datagen-ui-0} Committing offsets for 233 acknowledged messages
2024-08-26T04:40:18,606+0000 [kafka-producer-network-thread | connector-producer-datagen-ui-0] INFO org.apache.kafka.clients.NetworkClient - [Producer clientId=connector-producer-datagen-ui-0] Node 1261922880 disconnected.
2024-08-26T04:40:21,334+0000 [SourceTaskOffsetCommitter-1] INFO org.apache.kafka.connect.runtime.WorkerSourceTask - WorkerSourceTask{id=datagen-ui-0} Committing offsets for 261 acknowledged messages
2024-08-26T04:41:21,349+0000 [SourceTaskOffsetCommitter-1] INFO org.apache.kafka.connect.runtime.WorkerSourceTask - WorkerSourceTask{id=datagen-ui-0} Committing offsets for 235 acknowledged messages
2024-08-26T04:42:21,362+0000 [SourceTaskOffsetCommitter-1] INFO org.apache.kafka.connect.runtime.WorkerSourceTask - WorkerSourceTask{id=datagen-ui-0} Committing offsets for 270 acknowledged messages
2024-08-26T04:43:21,381+0000 [SourceTaskOffsetCommitter-1] INFO org.apache.kafka.connect.runtime.WorkerSourceTask - WorkerSourceTask{id=datagen-ui-0} Committing offsets for 235 acknowledged messages
2024-08-26T04:44:13,738+0000 [kafka-admin-client-thread | datagen-ui-73c8b112-mesh-admin] INFO org.apache.kafka.clients.NetworkClient - [AdminClient clientId=datagen-ui-73c8b112-mesh-admin] Node 1261922880 disconnected.
2024-08-26T04:44:21,393+0000 [SourceTaskOffsetCommitter-1] INFO org.apache.kafka.connect.runtime.WorkerSourceTask - WorkerSourceTask{id=datagen-ui-0} Committing offsets for 240 acknowledged messages
2024-08-26T04:45:21,407+0000 [SourceTaskOffsetCommitter-1] INFO org.apache.kafka.connect.runtime.WorkerSourceTask - WorkerSourceTask{id=datagen-ui-0} Committing offsets for 227 acknowledged messages
2024-08-26T04:46:21,421+0000 [SourceTaskOffsetCommitter-1] INFO org.apache.kafka.connect.runtime.WorkerSourceTask - WorkerSourceTask{id=datagen-ui-0} Committing offsets for 234 acknowledged messages
2024-08-26T04:47:21,436+0000 [SourceTaskOffsetCommitter-1] INFO org.apache.kafka.connect.runtime.WorkerSourceTask - WorkerSourceTask{id=datagen-ui-0} Committing offsets for 226 acknowledged messages
2024-08-26T04:48:21,449+0000 [SourceTaskOffsetCommitter-1] INFO org.apache.kafka.connect.runtime.WorkerSourceTask - WorkerSourceTask{id=datagen-ui-0} Committing offsets for 248 acknowledged messages
2024-08-26T04:49:13,883+0000 [kafka-admin-client-thread | datagen-ui-73c8b112-mesh-admin] INFO org.apache.kafka.clients.NetworkClient - [AdminClient clientId=datagen-ui-73c8b112-mesh-admin] Node 1753251735 disconnected.
2024-08-26T04:49:21,462+0000 [SourceTaskOffsetCommitter-1] INFO org.apache.kafka.connect.runtime.WorkerSourceTask - WorkerSourceTask{id=datagen-ui-0} Committing offsets for 231 acknowledged messages
2024-08-26T04:50:21,479+0000 [SourceTaskOffsetCommitter-1] INFO org.apache.kafka.connect.runtime.WorkerSourceTask - WorkerSourceTask{id=datagen-ui-0} Committing offsets for 218 acknowledged messages
2024-08-26T04:51:21,492+0000 [SourceTaskOffsetCommitter-1] INFO org.apache.kafka.connect.runtime.WorkerSourceTask - WorkerSourceTask{id=datagen-ui-0} Committing offsets for 241 acknowledged messages
2024-08-26T04:52:21,509+0000 [SourceTaskOffsetCommitter-1] INFO org.apache.kafka.connect.runtime.WorkerSourceTask - WorkerSourceTask{id=datagen-ui-0} Committing offsets for 247 acknowledged messages
2024-08-26T04:53:21,530+0000 [SourceTaskOffsetCommitter-1] INFO org.apache.kafka.connect.runtime.WorkerSourceTask - WorkerSourceTask{id=datagen-ui-0} Committing offsets for 230 acknowledged messages
2024-08-26T04:54:14,033+0000 [kafka-admin-client-thread | datagen-ui-73c8b112-mesh-admin] INFO org.apache.kafka.clients.NetworkClient - [AdminClient clientId=datagen-ui-73c8b112-mesh-admin] Node 1261922880 disconnected.
2024-08-26T04:54:18,658+0000 [kafka-producer-network-thread | connector-producer-datagen-ui-0] INFO org.apache.kafka.clients.NetworkClient - [Producer clientId=connector-producer-datagen-ui-0] Node 1261922880 disconnected.
2024-08-26T04:54:21,559+0000 [SourceTaskOffsetCommitter-1] INFO org.apache.kafka.connect.runtime.WorkerSourceTask - WorkerSourceTask{id=datagen-ui-0} Committing offsets for 221 acknowledged messages
2024-08-26T04:55:21,585+0000 [SourceTaskOffsetCommitter-1] INFO org.apache.kafka.connect.runtime.WorkerSourceTask - WorkerSourceTask{id=datagen-ui-0} Committing offsets for 238 acknowledged messages
2024-08-26T04:56:21,614+0000 [SourceTaskOffsetCommitter-1] INFO org.apache.kafka.connect.runtime.WorkerSourceTask - WorkerSourceTask{id=datagen-ui-0} Committing offsets for 224 acknowledged messages
2024-08-26T04:57:21,643+0000 [SourceTaskOffsetCommitter-1] INFO org.apache.kafka.connect.runtime.WorkerSourceTask - WorkerSourceTask{id=datagen-ui-0} Committing offsets for 226 acknowledged messages
2024-08-26T04:58:21,655+0000 [SourceTaskOffsetCommitter-1] INFO org.apache.kafka.connect.runtime.WorkerSourceTask - WorkerSourceTask{id=datagen-ui-0} Committing offsets for 236 acknowledged messages
2024-08-26T04:59:14,185+0000 [kafka-admin-client-thread | datagen-ui-73c8b112-mesh-admin] INFO org.apache.kafka.clients.NetworkClient - [AdminClient clientId=datagen-ui-73c8b112-mesh-admin] Node 1753251735 disconnected.
2024-08-26T04:59:21,673+0000 [SourceTaskOffsetCommitter-1] INFO org.apache.kafka.connect.runtime.WorkerSourceTask - WorkerSourceTask{id=datagen-ui-0} Committing offsets for 242 acknowledged messages
2024-08-26T05:00:21,690+0000 [SourceTaskOffsetCommitter-1] INFO org.apache.kafka.connect.runtime.WorkerSourceTask - WorkerSourceTask{id=datagen-ui-0} Committing offsets for 233 acknowledged messages
2024-08-26T05:01:21,715+0000 [SourceTaskOffsetCommitter-1] INFO org.apache.kafka.connect.runtime.WorkerSourceTask - WorkerSourceTask{id=datagen-ui-0} Committing offsets for 244 acknowledged messages
2024-08-26T05:02:21,728+0000 [SourceTaskOffsetCommitter-1] INFO org.apache.kafka.connect.runtime.WorkerSourceTask - WorkerSourceTask{id=datagen-ui-0} Committing offsets for 242 acknowledged messages
2024-08-26T05:03:21,743+0000 [SourceTaskOffsetCommitter-1] INFO org.apache.kafka.connect.runtime.WorkerSourceTask - WorkerSourceTask{id=datagen-ui-0} Committing offsets for 249 acknowledged messages
2024-08-26T05:04:14,338+0000 [kafka-admin-client-thread | datagen-ui-73c8b112-mesh-admin] INFO org.apache.kafka.clients.NetworkClient - [AdminClient clientId=datagen-ui-73c8b112-mesh-admin] Node 1261922880 disconnected.
2024-08-26T05:04:21,758+0000 [SourceTaskOffsetCommitter-1] INFO org.apache.kafka.connect.runtime.WorkerSourceTask - WorkerSourceTask{id=datagen-ui-0} Committing offsets for 226 acknowledged messages
2024-08-26T05:05:21,779+0000 [SourceTaskOffsetCommitter-1] INFO org.apache.kafka.connect.runtime.WorkerSourceTask - WorkerSourceTask{id=datagen-ui-0} Committing offsets for 249 acknowledged messages
2024-08-26T05:06:21,800+0000 [SourceTaskOffsetCommitter-1] INFO org.apache.kafka.connect.runtime.WorkerSourceTask - WorkerSourceTask{id=datagen-ui-0} Committing offsets for 234 acknowledged messages
2024-08-26T05:07:21,812+0000 [SourceTaskOffsetCommitter-1] INFO org.apache.kafka.connect.runtime.WorkerSourceTask - WorkerSourceTask{id=datagen-ui-0} Committing offsets for 249 acknowledged messages
2024-08-26T05:08:21,827+0000 [SourceTaskOffsetCommitter-1] INFO org.apache.kafka.connect.runtime.WorkerSourceTask - WorkerSourceTask{id=datagen-ui-0} Committing offsets for 239 acknowledged messages
2024-08-26T05:09:14,476+0000 [kafka-admin-client-thread | datagen-ui-73c8b112-mesh-admin] INFO org.apache.kafka.clients.NetworkClient - [AdminClient clientId=datagen-ui-73c8b112-mesh-admin] Node 1753251735 disconnected.
2024-08-26T05:09:21,841+0000 [SourceTaskOffsetCommitter-1] INFO org.apache.kafka.connect.runtime.WorkerSourceTask - WorkerSourceTask{id=datagen-ui-0} Committing offsets for 232 acknowledged messages
2024-08-26T05:10:21,855+0000 [SourceTaskOffsetCommitter-1] INFO org.apache.kafka.connect.runtime.WorkerSourceTask - WorkerSourceTask{id=datagen-ui-0} Committing offsets for 252 acknowledged messages
2024-08-26T05:11:21,870+0000 [SourceTaskOffsetCommitter-1] INFO org.apache.kafka.connect.runtime.WorkerSourceTask - WorkerSourceTask{id=datagen-ui-0} Committing offsets for 242 acknowledged messages
2024-08-26T05:12:21,884+0000 [SourceTaskOffsetCommitter-1] INFO org.apache.kafka.connect.runtime.WorkerSourceTask - WorkerSourceTask{id=datagen-ui-0} Committing offsets for 234 acknowledged messages
2024-08-26T05:13:21,897+0000 [SourceTaskOffsetCommitter-1] INFO org.apache.kafka.connect.runtime.WorkerSourceTask - WorkerSourceTask{id=datagen-ui-0} Committing offsets for 237 acknowledged messages
2024-08-26T05:14:14,648+0000 [kafka-admin-client-thread | datagen-ui-73c8b112-mesh-admin] INFO org.apache.kafka.clients.NetworkClient - [AdminClient clientId=datagen-ui-73c8b112-mesh-admin] Node 1261922880 disconnected.
2024-08-26T05:14:21,909+0000 [SourceTaskOffsetCommitter-1] INFO org.apache.kafka.connect.runtime.WorkerSourceTask - WorkerSourceTask{id=datagen-ui-0} Committing offsets for 237 acknowledged messages
2024-08-26T05:15:21,920+0000 [SourceTaskOffsetCommitter-1] INFO org.apache.kafka.connect.runtime.WorkerSourceTask - WorkerSourceTask{id=datagen-ui-0} Committing offsets for 234 acknowledged messages
2024-08-26T05:16:21,934+0000 [SourceTaskOffsetCommitter-1] INFO org.apache.kafka.connect.runtime.WorkerSourceTask - WorkerSourceTask{id=datagen-ui-0} Committing offsets for 248 acknowledged messages
2024-08-26T05:17:21,953+0000 [SourceTaskOffsetCommitter-1] INFO org.apache.kafka.connect.runtime.WorkerSourceTask - WorkerSourceTask{id=datagen-ui-0} Committing offsets for 232 acknowledged messages
2024-08-26T05:18:21,972+0000 [SourceTaskOffsetCommitter-1] INFO org.apache.kafka.connect.runtime.WorkerSourceTask - WorkerSourceTask{id=datagen-ui-0} Committing offsets for 238 acknowledged messages
2024-08-26T05:19:14,802+0000 [kafka-admin-client-thread | datagen-ui-73c8b112-mesh-admin] INFO org.apache.kafka.clients.NetworkClient - [AdminClient clientId=datagen-ui-73c8b112-mesh-admin] Node 1753251735 disconnected.
2024-08-26T05:19:21,991+0000 [SourceTaskOffsetCommitter-1] INFO org.apache.kafka.connect.runtime.WorkerSourceTask - WorkerSourceTask{id=datagen-ui-0} Committing offsets for 226 acknowledged messages
2024-08-26T05:20:22,004+0000 [SourceTaskOffsetCommitter-1] INFO org.apache.kafka.connect.runtime.WorkerSourceTask - WorkerSourceTask{id=datagen-ui-0} Committing offsets for 235 acknowledged messages
2024-08-26T05:21:22,018+0000 [SourceTaskOffsetCommitter-1] INFO org.apache.kafka.connect.runtime.WorkerSourceTask - WorkerSourceTask{id=datagen-ui-0} Committing offsets for 251 acknowledged messages
2024-08-26T05:22:22,033+0000 [SourceTaskOffsetCommitter-1] INFO org.apache.kafka.connect.runtime.WorkerSourceTask - WorkerSourceTask{id=datagen-ui-0} Committing offsets for 238 acknowledged messages
2024-08-26T05:23:22,047+0000 [SourceTaskOffsetCommitter-1] INFO org.apache.kafka.connect.runtime.WorkerSourceTask - WorkerSourceTask{id=datagen-ui-0} Committing offsets for 227 acknowledged messages
2024-08-26T05:24:14,938+0000 [kafka-admin-client-thread | datagen-ui-73c8b112-mesh-admin] INFO org.apache.kafka.clients.NetworkClient - [AdminClient clientId=datagen-ui-73c8b112-mesh-admin] Node 1261922880 disconnected.
2024-08-26T05:24:22,061+0000 [SourceTaskOffsetCommitter-1] INFO org.apache.kafka.connect.runtime.WorkerSourceTask - WorkerSourceTask{id=datagen-ui-0} Committing offsets for 236 acknowledged messages
```
### View the connector logs from log topics
StreamNative Cloud provide a way to send your logs to a Pulsar topic, you can just use config `sn.log.topic` to set it.
Once the connector is deployed with this config, you can configure consumers to consume messages from the log topic.
## What’s next?
* [SMTs(Single Message Transformations)](/cloud/connect/kafka-connect/kafka-connect-smt)
* Discover kafka Connect Ecosystem on [StreamNative Hub](/connect/overview).
# Kafka Connect Overview
Source: https://docs.streamnative.io/cloud/connect/kafka-connect/kafka-connect-overview
The Kafka Connect functionality requires Apache Pulsar version 3.3.1.4 or higher on your StreamNative cluster. If your current version is below 3.3.1.4, please [contact our support team](https://support.streamnative.io/hc/en-us) to upgrade your cluster. Alternatively, you may create a new StreamNative cluster to access Kafka Connect functionality.
Additionally, ensure that the 'Kafka Protocol' and 'Pulsar Function' options are enabled at the cluster level. Without this, the Kafka Source and Kafka Sink tabs will not appear on the Connectors page.
## Introduction to Kafka Connect
### Concept
[Kafka Connect](https://kafka.apache.org/documentation/#connect) is an integration tool that is released with the Apache Kafka project. It provides reliable data streaming between Apache Kafka and external systems and is both scalable and flexible. Kafka Connect works with Kafka on Pulsar (KoP), which is compatible with the Kafka API.
Kafka Connect uses Source and Sink connectors for integration. Source connectors stream data from an external system to Kafka, while Sink connectors stream data from Kafka to an external system.
The following diagram illustrates the data movement among source connectors, Pulsar Kop, sink connectors, and external systems.
### Benefits
* Seamless & Simplified Data Integration: Kafka Connect provide a unified interface for connecting Kop to various external systems and data sources, allowing developers to easily integrate Kop with their existing infrastructure without the need for custom integration code.
* Extensibility: Kafka Connect are designed to be easily extensible, allowing developers to create custom connectors for specific use cases and data sources not covered by the [built-in connectors](#built-in-connectors-on-stream-native-cloud).
* Reduced Development Effort: By leveraging pre-built connectors, developers can save time and effort. They don't have to write and maintain complex integration code from scratch for each external system.
* Reliable and Scalable: Kafka Connect are built to be reliable and scalable, ensuring the data transfers between Kop and external systems are efficient and fault-tolerant.
### Use cases
* Data Ingestion to Pulsar Kop: If you have data coming from various external sources, such as databases, message queues, or cloud storage systems like Amazon S3, you can use Kafka Connect to ingest that data into Kop topics.
* Data Export from Pulsar Kop: Kafka Connect also enable you to export data from Kop topics to other systems or storage solutions. This helps you to synchronize data across different environments, replicate data, or stream data to external services or databases.
* Real-time Data Processing: Kafka Connect facilitate real-time data processing by enabling the seamless movement of data between Kop and other systems. This is particularly useful in event-driven architectures, streaming applications, and microservices-based solutions.
* Extending Kop's Functionality: If you have specific use cases or data sources not directly supported by Kop, you can deploy custom Kafka Connect to extend Kop's functionality and integrate with those systems.
### Connectors Shared Responsibility
StreamNative and our customers have a shared responsibility for maintaining and keeping connectors properly functioning. Outlined below, StreamNative has a responsibility for custom connectors that are maintained by uploading to StreamNative Cloud to maintain connectivity to the Pulsar Kop cluster and for logging and monitoring. Customers who upload their connectors are responsible for all other operations such as configurations, updates, development, support and plugin installation. Partner connectors have similar support but the partners with StreamNative will be responsible for development and connector support. For built in connectors, StreamNative is responsible for everything except connector configuration.
For more details, see below.
## Built-in connectors on StreamNative Cloud
To further reduce the development overhead and time, StreamNative has pre-built a variety of Kafka connect on StreamNative Cloud. With proper configurations, you can integrate the data between your Pulsar Kop cluster on StreamNative Cloud and your data systems effortlessly.
### Built-in source connectors
Currently, StreamNative Cloud supports the following kafka source connectors:
* [MongoDB source connector](/connect/connectors/kafka-connect-mongo-source/current/kafka-connect-mongodb-source)
* [YugabyteDB CDC source connector](/connect/connectors/kafka-connect-yugabyte-cdc-source/current/kafka-connect-yugabyte-cdc-source)
* [Datagen source connector](/connect/connectors/kafka-connect-datagen/current/kafka-connect-datagen-source)
* [Cosmos DB source connector](/connect/connectors/kafka-connect-cosmosdb-source/current/kafka-connect-cosmosdb-source)
* [Debezium MongoDB source connector](/connect/connectors/kafka-connect-debezium-mongodb/current/kafka-connect-debezium-mongodb)
* [Debezium Mysql source connector](/connect/connectors/kafka-connect-debezium-mysql/current/kafka-connect-debezium-mysql)
* [Debezium PostgreSql source connector](/connect/connectors/kafka-connect-debezium-postgresql/current/kafka-connect-debezium-postgresql)
* [Debezium Spanner source connector](/connect/connectors/kafka-connect-debezium-spanner/current/kafka-connect-debezium-spanner)
* [Google Pub/Sub source connector](/connect/connectors/kafka-connect-google-pubsub-source/current/kafka-connect-google-pubsub-source)
* [Google Pub/Sub Lite source connector](/connect/connectors/kafka-connect-google-pubsub-lite-source/current/kafka-connect-google-pubsub-lite-source)
* [Debezium SqlServer source connector](/connect/connectors/kafka-connect-debezium-sqlserver/current/kafka-connect-debezium-sqlserver)
* [JDBC source connector](/connect/connectors/kafka-connect-jdbc-source/current/kafka-connect-jdbc-source)
* [JR source connector](/connect/connectors/kafka-connect-jr-source/current/kafka-connect-jr-source)
### Built-in sink connectors
Currently, StreamNative Cloud supports the following kafka sink connectors.
* [Iceberg sink connector](/connect/connectors/kafka-connect-iceberg/current/kafka-connect-iceberg-sink)
* [Milvus sink connector](/connect/connectors/kafka-connect-milvus-sink/current/kafka-connect-milvus-sink)
* [MongoDB sink connector](/connect/connectors/kafka-connect-mongo-sink/current/kafka-connect-mongodb-sink)
* [BigQuery sink connector](/connect/connectors/kafka-connect-bigquery/current/kafka-connect-bigquery)
* [Cosmos DB sink connector](/connect/connectors/kafka-connect-cosmosdb-sink/current/kafka-connect-cosmosdb-sink)
* [ElasticSearch sink connector](/connect/connectors/kafka-connect-elasticsearch-sink/current/kafka-connect-elasticsearch-sink)
* [Snowflake sink connector](/connect/connectors/kafka-connect-snowflake-sink/current/kafka-connect-snowflake-sink)
* [JDBC sink connector](/connect/connectors/kafka-connect-jdbc-sink/current/kafka-connect-jdbc-sink)
* [Debezium JDBC sink connector](/connect/connectors/kafka-connect-debezium-jdbc-sink/current/kafka-connect-debezium-jdbc-sink)
* [Google Pub/Sub sink connector](/connect/connectors/kafka-connect-google-pubsub-sink/current/kafka-connect-google-pubsub-sink)
* [Google Pub/Sub Lite sink connector](/connect/connectors/kafka-connect-google-pubsub-lite-sink/current/kafka-connect-google-pubsub-lite-sink)
* [Google Cloud Storage sink connector](/connect/connectors/kafka-connect-google-cloud-storage-sink/current/kafka-connect-google-cloud-storage-sink)
* [Google Bigtable sink connector](/connect/connectors/kafka-connect-google-bigtable-sink/current/kafka-connect-google-bigtable-sink)
Currently, the Kafka Connect doesn't support multi-tenancy. All Kafka Connects are deployed to the `public/default` namespace.
And all of configured topics are also under the `public/default` namespace by default, unless you specified topics with the prefix: `${tenant}.${namespace}.`.
For more details about the multi-tenancy support for Kafka topics in StreamNative cloud, please refer to the [Kafka Multi-Tenancy](/cloud/build/kafka-clients/advanced-features/kafka-multi-tenancy).
## Self-hosted Kafka Connect
Despite the fact that StreamNative Cloud supports fully managed Kafka Connect connectors, you can still self-host Kafka Connect connectors in your own environment. See the [Kafka Connect QuickStart](id:cloud-connect-kafka-connect) for how to configure your own Kafka Connect connectors to connect to your StreamNative cluster.
## What’s next?
* [Deploy kafka connectors](/cloud/connect/kafka-connect/deploy-kafka-connectors/deploy-kafka-connect-index)
* [Manage kafka connectors](/cloud/connect/kafka-connect/kafka-connect-manage)
* [Monitor and troubleshoot kafka connectors](/cloud/connect/kafka-connect/kafka-connect-monitoring)
* [SMTs(Single Message Transformations)](/cloud/connect/kafka-connect/kafka-connect-smt)
* Discover kafka Connect Ecosystem on [StreamNative Hub](/connect/overview).
# Kafka Connect SMTs(Single Message Transformations)
Source: https://docs.streamnative.io/cloud/connect/kafka-connect/kafka-connect-smt
## Transformations
StreamNative cloud supports Kafka Connect transformations. You can use the following transformations in your Kafka Connect configurations:
* [InsertField](https://kafka.apache.org/37/documentation.html#org.apache.kafka.connect.transforms.InsertField) - Add a field using either static data or record metadata
* [ReplaceField](https://kafka.apache.org/37/documentation.html#org.apache.kafka.connect.transforms.ReplaceField) - Filter or rename fields
* [MaskField](https://kafka.apache.org/37/documentation.html#org.apache.kafka.connect.transforms.MaskField) - Replace field with valid null value for the type (0, empty string, etc) or custom replacement (non-empty string or numeric value only)
* [ValueToKey](https://kafka.apache.org/37/documentation.html#org.apache.kafka.connect.transforms.ValueToKey) - Replace the record key with a new key formed from a subset of fields in the record value
* [HoistField](https://kafka.apache.org/37/documentation.html#org.apache.kafka.connect.transforms.HoistField) - Wrap the entire event as a single field inside a Struct or a Map
* [ExtractField](https://kafka.apache.org/37/documentation.html#org.apache.kafka.connect.transforms.ExtractField) - Extract a specific field from Struct and Map and include only this field in results
* [SetSchemaMetadata](https://kafka.apache.org/37/documentation.html#org.apache.kafka.connect.transforms.SetSchemaMetadata) - modify the schema name or version
* [TimestampRouter](https://kafka.apache.org/37/documentation.html#org.apache.kafka.connect.transforms.TimestampRouter) - Modify the topic of a record based on original topic and timestamp. Useful when using a sink that needs to write to different tables or indexes based on timestamps
* [RegexRouter](https://kafka.apache.org/37/documentation.html#org.apache.kafka.connect.transforms.RegexRouter) - modify the topic of a record based on original topic, replacement string and a regular expression
* [Flatten](https://kafka.apache.org/37/documentation.html#org.apache.kafka.connect.transforms.Flatten): Flatten a nested data structure, generating names for each field by concatenating the field names at each level with a configurable delimiter character.
* [Cast](https://kafka.apache.org/37/documentation.html#org.apache.kafka.connect.transforms.Cast): Cast fields or the entire key or value to a specific type, e.g. to force an integer field to a smaller width.
* [TimestampConverter](https://kafka.apache.org/37/documentation.html#org.apache.kafka.connect.transforms.TimestampConverter): Convert timestamps between different formats such as Unix epoch, strings, and Connect Date/Timestamp types.
* [Filter](https://kafka.apache.org/37/documentation.html#org.apache.kafka.connect.transforms.Filter) - Removes messages from all further processing. This is used with a predicate to selectively filter certain messages.
* [InsertHeader](https://kafka.apache.org/37/documentation.html#org.apache.kafka.connect.transforms.InsertHeader) - Add a header using static data
* [HeadersFrom](https://kafka.apache.org/37/documentation.html#org.apache.kafka.connect.transforms.HeaderFrom) - Copy or move fields in the key or value to the record headers
* [DropHeaders](https://kafka.apache.org/37/documentation.html#org.apache.kafka.connect.transforms.DropHeaders) - Remove headers by name
Some built-in connectors also has specified transformations:
### YugabyteDB CDC Source
* [YBExtractNewRecordState SMT](https://docs.yugabyte.com/preview/explore/change-data-capture/using-yugabytedb-grpc-replication/debezium-connector-yugabytedb/#ybextractnewrecordstate-smt)
* [ExtractTopic](https://docs.yugabyte.com/preview/explore/change-data-capture/using-yugabytedb-grpc-replication/debezium-connector-yugabytedb/#ybextractnewrecordstate-smt)
* [PGCompatible SMT](https://docs.yugabyte.com/preview/explore/change-data-capture/using-yugabytedb-grpc-replication/debezium-connector-yugabytedb/#ybextractnewrecordstate-smt)
### Iceberg Sink
* [CopyValue](https://github.com/tabular-io/iceberg-kafka-connect/blob/main/kafka-connect-transforms/README.md#copyvalue)
* [DmsTransform](https://github.com/tabular-io/iceberg-kafka-connect/blob/main/kafka-connect-transforms/README.md#dmstransform)
* [DebeziumTransform](https://github.com/tabular-io/iceberg-kafka-connect/blob/main/kafka-connect-transforms/README.md#debeziumtransform)
* [JsonToMapTransform](https://github.com/tabular-io/iceberg-kafka-connect/blob/main/kafka-connect-transforms/README.md#jsontomaptransform)
* [KafkaMetadataTransform](https://github.com/tabular-io/iceberg-kafka-connect/blob/main/kafka-connect-transforms/README.md#kafkametadatatransform)
* [MongoDebeziumTransform](https://github.com/tabular-io/iceberg-kafka-connect/blob/main/kafka-connect-transforms/README.md#mongodebeziumtransform)
## Predicates
StreamNative cloud supports Kafka Connect predicates. You can use the following predicates in your Kafka Connect configurations:
* [TopicNameMatches](https://kafka.apache.org/37/documentation.html#org.apache.kafka.connect.transforms.predicates.TopicNameMatches): matches records in a topic with a name matching a particular Java regular expression.
* [HasHeaderKey](https://kafka.apache.org/37/documentation.html#org.apache.kafka.connect.transforms.predicates.HasHeaderKey): matches records which have a header with the given key.
* [RecordIsTombstone](https://kafka.apache.org/37/documentation.html#org.apache.kafka.connect.transforms.predicates.RecordIsTombstone): matches tombstone records, that is records with a null value.
## What’s next?
* Discover kafka Connect Ecosystem on [StreamNative Hub](/connect/overview).
# Configuration Reference
Source: https://docs.streamnative.io/cloud/connect/pulsar-io/connector-config
This section lists all the common configuration options for the built-in source and sink connectors. For connector-specific configurations, see [StreamNative Hub](/connect/overview).
## Source connector configurations
This table lists all the common configurations for a source connector.
| Field | Description |
| ----------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `-a`, `--archive` | The path to the NAR archive for the source.
It supports the file-URL-path (file://) which assumes that the NAR file already exists on the worker host from which the worker can download the package.
For a built-in connector, it should be set to `builtin//`. |
| `--classname` | The source's class name if the `archive` is set to a file-URL-path (file://). |
| `--cpu` | The CPU (in cores) that needs to be allocated per source instance (applicable only to Docker runtime). |
| `--deserialization-classname` | The SerDe classname for the source. |
| `--destination-topic-name` | The Pulsar topic to which data is sent. |
| `--disk` | The disk (in bytes) that needs to be allocated per source instance (applicable only to Docker runtime). |
| `--name` | The source's name. |
| `--namespace` | The source's namespace. |
| `--parallelism` | The source's parallelism factor, that is, the number of source instances to run. |
| `--processing-guarantees` | The processing guarantees (also named as delivery semantics) applied to the source. A source connector receives messages from the external system and writes messages to a Pulsar topic. The `--processing-guarantees` ensures the processing guarantees for writing messages to the Pulsar topic.
The available values are `ATLEAST_ONCE`, `ATMOST_ONCE`, `EFFECTIVELY_ONCE`. |
| `--ram` | The RAM (in bytes) that needs to be allocated per source instance (applicable only to the process and Docker runtimes). |
| `-st`, `--schema-type` | The schema type.
Either a built-in schema (for example, AVRO and JSON) or a custom schema class name to be used to encode messages emitted from source. |
| `--source-config` | The key/values configurations of the source. For example: '`{"sleepBetweenMessages": 60}`'; For configuration details, refer to the [documentation](/connect/overview) of each connector |
| `--source-config-file` | The path to a YAML config file that specifies the source's configuration. |
| `--sn-service-account` | The StreamNative Cloud service account that the source uses as its runtime identity. This `snctl` flag writes `snServiceAccount` to `custom-runtime-options`. You can use `--use-sn-service-account` to select a runtime service account interactively. You must have the `cloud.serviceaccounts.describe` permission on the specified service account (see [account-admin](/cloud/security/access/rbac/manage-rbac-roles#account-admin)). Only Pulsar 4.0.x clusters running version 4.0.10.6 or later, or Pulsar 4.2.x clusters running version 4.2.1.4 or later, support this config. |
| `-t`, `--source-type` | The source's connector provider. |
| `--tenant` | The source's tenant. |
| `--producer-config` | The custom producer configuration (as a JSON string). |
## Sink connector configurations
This table lists all the common configurations for a sink connector.
| Field | Description |
| ------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `-a`, `--archive` | The path to the archive file for the sink.
It supports the file-URL-path (file://) which assumes that the NAR file already exists on the worker host from which the worker can download the package.
For a built-in connector, it should be set to `builtin//`. |
| `--classname` | The sink's class name if the `archive` is set to a file-URL-path (file://). |
| `--cpu` | The CPU (in cores) that needs to be allocated per sink instance (applicable only to Docker runtime). |
| `--custom-schema-inputs` | The map of input topics to schema types or class names (as a JSON string). |
| `--custom-serde-inputs` | The map of input topics to SerDe class names (as a JSON string). |
| `--disk` | The disk (in bytes) that needs to be allocated per sink instance (applicable only to Docker runtime). |
| `-i, --inputs` | The sink's input topic or topics (multiple topics can be specified as a comma-separated list). |
| `--name` | The sink's name. |
| `--namespace` | The sink's namespace. |
| `--parallelism` | The sink's parallelism factor, that is, the number of sink instances to run. |
| `--processing-guarantees` | The processing guarantees (also known as delivery semantics) applied to the sink. The `--processing-guarantees` implementation in Pulsar also relies on sink implementation.
The available values are `ATLEAST_ONCE`, `ATMOST_ONCE`, `EFFECTIVELY_ONCE`. |
| `--ram` | The RAM (in bytes) that needs to be allocated per sink instance (applicable only to the process and Docker runtimes). |
| `--retain-ordering` | Sink consumes messages in order. |
| `--sink-config` | The key/values configurations of the sink. For example: '`{"sleepBetweenMessages": 60}`'; For configuration details, refer to the [documentation](/connect/overview) of each connector |
| `--sink-config-file` | The path to a YAML config file specifying the sink's configuration. |
| `--sn-service-account` | The StreamNative Cloud service account that the sink uses as its runtime identity. This `snctl` flag writes `snServiceAccount` to `custom-runtime-options`. You can use `--use-sn-service-account` to select a runtime service account interactively. |
| `-t`, `--sink-type` | The sink's connector provider. The `sink-type` parameter of the currently built-in connectors is determined by the setting of the `name` parameter. You can use the `pulsar-admin sinks available-sinks` command to get all built-in sink connectors. |
| `--subs-name` | Pulsar source subscription name if you want to specify a subscription name for the input-topic consumer. |
| `--tenant` | The sink's tenant. |
| `--timeout-ms` | The message timeout in milliseconds. |
| `--topics-pattern` | The topic pattern to consume from a list of topics under a namespace that matches the pattern.
`--input` and `--topics-Pattern` are mutually exclusive.
Add SerDe class name for a pattern in `--customSerdeInputs`. |
## StreamNative Cloud custom runtime options
To facilitate submitting Pulsar functions based on your requirements, Function on Cloud service provides some custom options via `custom-runtime-options`.
When update functions/sinks/sources with custom runtime options, the original custom runtime options will be replaced by the new ones, so make sure all the wanted fields are passed in the custom runtime options when you do the update.
This table lists all fields available for custom options.
| Name | Type | Default | Description |
| ------------------------------- | --------------------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `clusterName` | String | N/A | The Pulsar cluster of a Pulsar function, source, or sink. |
| `inputTypeClassName` | String | `[B` | The map of input topics to Java class names. |
| `outputTypeClassName` | String | `[B` | The map of output topics to Java class names. |
| `maxReplicas` | Integer | `0` | The maximum number of Pulsar instances that you want to run for this Pulsar Function. When the value of the `maxReplicas` parameter is greater than the value of `replicas`, it indicates that the Functions controller automatically scales the Pulsar Functions based on the CPU usage. By default, `maxReplicas` is set to 0, which indicates that auto-scaling is disabled. |
| `env` | `Map` | N/A | The environment variables being attached to a Pod that is created by the Function Mesh Operator for the cluster. |
| `imagePullSecrets` | `List` | N/A | A list of references to secrets in the same namespace for pulling any of the images used by a Pod. |
| `logLevel` | String | info | The log levels for Pulsar functions. For details, see [log levels](https://functionmesh.io/docs/next/reference/crd-config/function-crd#log-levels). |
| `logRotationPolicy` | String | N/A | The log rotation policies for Pulsar functions. You can set the log rotation policies based on the time or the log file size. For details, see [log rotation policies](https://functionmesh.io/docs/next/reference/crd-config/function-crd#log-rotation-policies). |
| `runnerImageTag` | String | N/A | The tag of the [runner image](https://functionmesh.io/docs/next/reference/crd-config/function-crd#runner-images) that is used to submit a function, source, or sink. |
| `hpaSpec` (Preview) | HPASpec | N/A | The Kubernetes HorizontalPodAutoscaler settings. For details, see [Kubernetes documentation](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/). This feature may not ready for your cluster enviroment, please file a ticket if you want this feature enabled. |
| `logFormat` | String | text | The log format that defines how the content of a log file should be interpreted. Available options are ` json` and `text`. The log format configurations are only available for the Java and Python runtimes. |
| `logTopic` | String | N/A | Used for sinks/sources since they don't have a log topic argument like functions |
| `logTopicAgent` | String | runtime | The log agent that defines how StreamNative cloud redirects your functions / connectors log into a Pulsar topic. Available options are `runtime` and `sidecar`. When use `sidecar` all logs (including instance logs) will be sent to the log topic by filebeat (better performance than `runtime`), else will use the Pulsar Functions runtime's log-topic implementation instead. |
| `genericKind` | String | N/A | Used for functions written in languages other than Java and Python, available values are `executable`, `nodejs`, `wasm` |
| `snServiceAccount` | String | N/A | The StreamNative Cloud service account that the function, source, or sink uses as its runtime identity. You must have the `cloud.serviceaccounts.describe` permission on the specified service account (see [account-admin](/cloud/security/access/rbac/manage-rbac-roles#account-admin)). Only Pulsar 4.0.x clusters running version 4.0.10.6 or later, or Pulsar 4.2.x clusters running version 4.2.1.4 or later, support this config. |
| `terminationGracePeriodSeconds` | Long | N/A | The amount of time that kubernetes will give for a pod before terminating it. |
| `pauseRollout` | Boolean | N/A | Whether to pause the rollout of functions/connectors, when set to true, running functions\&connectors will not restart during the upgrade of backend function-mesh operator. |
| `enableStateStore` | Boolean | N/A | Whether to enable stateful backend for this function, default to false, only available for **Java** function |
You can compose the custom runtime options as a JSON string and pass it to the `custom-runtime-options` field. For example:
```json theme={null}
{
"inputTypeClassName": "java.lang.String",
"logTopic": "log-topic-name"
}
```
Then it could be passed to `custom-runtime-options` field as follows:
```bash theme={null}
snctl pulsar admin sinks create --custom-runtime-options '{"inputTypeClassName":"java.lang.String","logTopic":"log-topic-name"}' --as-service-account $SERVICE_ACCOUNT ...
```
```bash theme={null}
pulsarctl sinks create --custom-runtime-options '{"inputTypeClassName":"java.lang.String","logTopic":"log-topic-name"}' ...
```
# Manage Connectors
Source: https://docs.streamnative.io/cloud/connect/pulsar-io/connector-manage
StreamNative Cloud enables you to manage Pulsar IO Connectors by using a variety of tools, including `snctl`, `pulsarctl`, `pulsar-admin`, and `Terraform`.
If you want to update or delete connectors using `snctl`, `pulsarctl` or `pulsar-admin`, make sure you have set up your client tool. For more information, see [set up client tools](/cloud/connect/pulsar-io/deploy-connectors/connector-setup#set-up-client-tools).
## Update a connector
When you want to modify configurations or update resources for connectors, you can update connectors using multiple tools.
The following example shows how to update the parallelism of the data generator source connector `test` to `2` using different tools.
```bash theme={null}
snctl pulsar admin sources update \
--name test \
--parallelism 2
```
You should see the following output:
```bash theme={null}
Updated successfully
```
And you can further check the status:
```bash theme={null}
snctl pulsar admin sources status --name test
{
"numInstances": 2,
"numRunning": 2,
"instances": [
{
"instanceId": 0,
"status": {
"running": true,
"error": "",
"numRestarts": 0,
"numReceivedFromSource": 1799,
"numSystemExceptions": 0,
"latestSystemExceptions": [],
"numSourceExceptions": 0,
"latestSourceExceptions": [],
"numWritten": 1799,
"lastReceivedTime": 1693946327331,
"workerId": "test"
}
},
{
"instanceId": 1,
"status": {
"running": true,
"error": "",
"numRestarts": 0,
"numReceivedFromSource": 689,
"numSystemExceptions": 0,
"latestSystemExceptions": [],
"numSourceExceptions": 0,
"latestSourceExceptions": [],
"numWritten": 689,
"lastReceivedTime": 1693946327129,
"workerId": "test"
}
}
]
}
```
```bash theme={null}
pulsarctl sources update \
--name test \
--parallelism 2
```
You should see the following output:
```bash theme={null}
Updated successfully
```
And you can further check the status:
```bash theme={null}
pulsarctl sources status --name test
{
"numInstances": 2,
"numRunning": 2,
"instances": [
{
"instanceId": 0,
"status": {
"running": true,
"error": "",
"numRestarts": 0,
"numReceivedFromSource": 1799,
"numSystemExceptions": 0,
"latestSystemExceptions": [],
"numSourceExceptions": 0,
"latestSourceExceptions": [],
"numWritten": 1799,
"lastReceivedTime": 1693946327331,
"workerId": "test"
}
},
{
"instanceId": 1,
"status": {
"running": true,
"error": "",
"numRestarts": 0,
"numReceivedFromSource": 689,
"numSystemExceptions": 0,
"latestSystemExceptions": [],
"numSourceExceptions": 0,
"latestSourceExceptions": [],
"numWritten": 689,
"lastReceivedTime": 1693946327129,
"workerId": "test"
}
}
]
}
```
```bash theme={null}
pulsar-admin \
--admin-url "${WEB_SERVICE_URL}" \
--auth-plugin org.apache.pulsar.client.impl.auth.oauth2.AuthenticationOAuth2 \
--auth-params '{"privateKey":"file:///YOUR-KEY-FILE-PATH",
"issuerUrl":"https://auth.streamnative.cloud/",
"audience":"urn:sn:pulsar:${orgName}:${instanceName}}'
sources update \
--name test \
--parallelism 2
```
Replace the placeholder variables with the actual values, which you can get when you set up client tools.
* `admin-url`: the HTTP service URL of your Pulsar cluster.
* `private_key`: the path to the downloaded OAuth2 key file.
* `audience`: the [Uniform Resource Name (URN)](/cloud/references/glossary#uniform-resource-name-urn), which is a combination of the `urn:sn:pulsar`, your organization name, and your Pulsar instance name.
* `${orgName}`: the name of your [organization](/cloud/references/glossary#organization).
* `${instanceName}`: the name of your [instance](/cloud/references/glossary#instance).
You should see the following output:
```bash theme={null}
Updated successfully
```
And you can further check the status:
```bash theme={null}
pulsar-admin sources status --name test
{
"numInstances" : 2,
"numRunning" : 2,
"instances" : [ {
"instanceId" : 0,
"status" : {
"running" : true,
"error" : "",
"numRestarts" : 0,
"numReceivedFromSource" : 1287,
"numSystemExceptions" : 0,
"latestSystemExceptions" : [ ],
"numSourceExceptions" : 0,
"latestSourceExceptions" : [ ],
"numWritten" : 1287,
"lastReceivedTime" : 1693946605095,
"workerId" : "test"
}
}, {
"instanceId" : 1,
"status" : {
"running" : true,
"error" : "",
"numRestarts" : 0,
"numReceivedFromSource" : 909,
"numSystemExceptions" : 0,
"latestSystemExceptions" : [ ],
"numSourceExceptions" : 0,
"latestSourceExceptions" : [ ],
"numWritten" : 909,
"lastReceivedTime" : 1693946605023,
"workerId" : "test"
}
} ]
}
```
To update the submitted connector, you only need to update the Terraform file and then call the following command.
```bash theme={null}
# update the main.tf file
terraform apply
# output
pulsar_source.test: Refreshing state... [id=public/default/dg-test-tf]
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
~ update in-place
Terraform will perform the following actions:
# pulsar_source.test will be updated in-place
~ resource "pulsar_source" "test" {
~ archive = "connectors/pulsar-io-data-generator-2.9.2.17.nar" -> "builtin://data-generator"
- custom_runtime_options = jsonencode(
{
- clusterName = "test"
- managed = true
- maxReplicas = 0
- outputTypeClassName = "org.apache.pulsar.io.datagenerator.Person"
- serviceAccountName = "test-function-pulsarcluster"
}
) -> null
id = "public/default/dg-test-tf"
name = "dg-test-tf"
~ parallelism = 1 -> 2
# (10 unchanged attributes hidden)
}
Plan: 0 to add, 1 to change, 0 to destroy.
Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value: yes
pulsar_source.test: Modifying... [id=public/default/dg-test-tf]
pulsar_source.test: Modifications complete after 1s [id=public/default/dg-test-tf]
Apply complete! Resources: 0 added, 1 changed, 0 destroyed.
```
1. On the left navigation pane of StreamNative Console, under **Resources**, click **Connectors**.
2. On the Connectors page, select the **Created Sources** tab.
3. Click the ellipsis at the end of the row of the connector, and then click **Edit**.
4. Edit the configuration that you want to change, and click **SUBMIT**.
```bash theme={null}
curl -X PUT https://${WEB_SERVICE_URL}/admin/v3/sources/{tenant}/{namespace}/test \
-H 'Authorization: Bearer ' \
-H "Content-Type: multipart/form-data" \
-F 'sourceConfig={"name": "test", "tenant": "public", "namespace": "default", "parallelism": 2};type=application/json'
```
If no error is response, the update is successful.
And you can further check the status:
```bash theme={null}
curl -X GET https://${WEB_SERVICE_URL}/admin/v3/sources/public/default/test/status \
--header 'Authorization: Bearer ' | jq '.'
{
"numInstances": 2,
"numRunning": 2,
"instances": [
{
"instanceId": 0,
"status": {
"running": true,
"error": "",
"numRestarts": 0,
"numReceivedFromSource": 1799,
"numSystemExceptions": 0,
"latestSystemExceptions": [],
"numSourceExceptions": 0,
"latestSourceExceptions": [],
"numWritten": 1799,
"lastReceivedTime": 1693946327331,
"workerId": "test"
}
},
{
"instanceId": 1,
"status": {
"running": true,
"error": "",
"numRestarts": 0,
"numReceivedFromSource": 689,
"numSystemExceptions": 0,
"latestSystemExceptions": [],
"numSourceExceptions": 0,
"latestSourceExceptions": [],
"numWritten": 689,
"lastReceivedTime": 1693946327129,
"workerId": "test"
}
}
]
}
```
## Delete a connector
The following example shows how to delete the data generator source connector `test` using different tools.
To delete the source connector `test`, use the following command.
```bash theme={null}
snctl pulsar admin sources delete --tenant public --namespace default --name test
```
You should see the following output:
```bash theme={null}
Deleted test successfully
```
If you want to verify whether the source connector has been deleted successfully, run the following command.
```bash theme={null}
snctl pulsar admin sources get --tenant public --namespace default --name test
```
You should see the following output:
```bash theme={null}
[✖] code: 500 reason: failed to perform the request: responseCode: 404, responseMessage: sources.compute.functionmesh.io "test-XXXXX" not found
```
To delete the source connector `test`, use the following command.
```bash theme={null}
pulsarctl sources delete --tenant public --namespace default --name test
```
You should see the following output:
```bash theme={null}
Deleted test successfully
```
If you want to verify whether the source connector has been deleted successfully, run the following command.
```bash theme={null}
pulsarctl sources get --tenant public --namespace default --name test
```
You should see the following output:
```bash theme={null}
[✖] code: 500 reason: failed to perform the request: responseCode: 404, responseMessage: sources.compute.functionmesh.io "test-XXXXX" not found
```
To delete the source connector `test`, run the following command.
```bash theme={null}
./bin/pulsar-admin sources delete --tenant public --namespace default --name test
```
You should see the following output:
```bash theme={null}
Delete source successfully
```
To verify the source connector has been deleted, run the following command.
```bash theme={null}
./bin/pulsar-admin sources get --tenant public --namespace default --name test
```
You should see the following output:
```bash theme={null}
failed to perform the request: responseCode: 404, responseMessage: sources.compute.functionmesh.io "test-e9ef0ca6" not found
```
To delete the source connector `test` with terraform, run the following command and type `yes` on the prompt.
```bash theme={null}
terraform destroy
# output
pulsar_source.test: Refreshing state... [id=public/default/dg-test-tf]
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
- destroy
Terraform will perform the following actions:
# pulsar_source.test will be destroyed
- resource "pulsar_source" "test" {
- archive = "connectors/pulsar-io-data-generator-2.9.2.17.nar" -> null
- classname = "org.apache.pulsar.io.datagenerator.DataGeneratorSource" -> null
- configs = jsonencode(
{
- sleepBetweenMessages = "60"
}
) -> null
- cpu = 1 -> null
- custom_runtime_options = jsonencode(
{
- clusterName = "test"
- managed = true
- maxReplicas = 0
- outputTypeClassName = "org.apache.pulsar.io.datagenerator.Person"
- serviceAccountName = "test-function-pulsarcluster"
}
) -> null
- destination_topic_name = "public/default/dg-test" -> null
- disk_mb = 10240 -> null
- id = "public/default/dg-test-tf" -> null
- name = "dg-test-tf" -> null
- namespace = "default" -> null
- parallelism = 2 -> null
- processing_guarantees = "ATMOST_ONCE" -> null
- ram_mb = 1024 -> null
- tenant = "public" -> null
- use_thread_local_producers = false -> null
}
Plan: 0 to add, 0 to change, 1 to destroy.
Do you really want to destroy all resources?
Terraform will destroy all your managed infrastructure, as shown above.
There is no undo. Only 'yes' will be accepted to confirm.
Enter a value: yes
pulsar_source.test: Destroying... [id=public/default/dg-test-tf]
pulsar_source.test: Destruction complete after 1s
Destroy complete! Resources: 1 destroyed.
```
1. On the left navigation pane of StreamNative Console, under **Resources**, click **Connectors**.
2. On the Connectors page, select the **Created Sources** tab.
3. Click the ellipsis at the end of the row of the connector, and then click **Delete**.
4. Enter the connector name and then click **Confirm**.
To delete the source connector `test`, use the following command.
```bash theme={null}
curl -X DELETE https://${WEB_SERVICE_URL}/admin/v3/sources/public/default/test \
--header 'Authorization: Bearer '
```
If no error is response, the delete is successful.
If you want to verify whether the source connector has been deleted successfully, run the following command.
```bash theme={null}
curl -X GET https://${WEB_SERVICE_URL}/admin/v3/sources/public/default/test/status \
--header 'Authorization: Bearer ' | jq '.'
```
You should see the following output:
```bash theme={null}
{"reason":"failed to perform the request: responseCode: 404, responseMessage: sources.compute.functionmesh.io \"test-6b51d8ef\" not found"}%
```
# Monitor and Troubleshoot Connectors
Source: https://docs.streamnative.io/cloud/connect/pulsar-io/connector-monitoring
StreamNative Cloud allows you to monitor connectors status, logs, and exceptions that are thrown when a source or sink connector fails to be created, updated, or cannot work.
## View connector status
This section describes how to view connector status using `snctl`, `pulsarctl`, `pulsar-admin`, `Rest API`, and console.
If you want to monitor connectors using `snctl`, `pulsarctl` or `pulsar-admin`, `Rest API`, make sure you have set up your client tool. For more information, see set up client tools.
The following example introduces how to view the status of the data generator source connector named `test`.
To check the status of the source connector `test`, run the following command:
```bash theme={null}
snctl pulsar admin sources status --tenant public --namespace default --name test
```
```bash theme={null}
{
"numInstances": 1,
"numRunning": 1,
"instances": [
{
"instanceId": 0,
"status": {
"running": true,
"error": "",
"numRestarts": 0,
"numReceivedFromSource": 2622,
"numSystemExceptions": 0,
"latestSystemExceptions": [],
"numSourceExceptions": 0,
"latestSourceExceptions": [],
"numWritten": 2622,
"lastReceivedTime": 1691532145625,
"workerId": "test"
}
]
}
```
To check the status of the source connector `test`, run the following command:
```bash theme={null}
pulsarctl sources status --tenant public --namespace default --name test
```
```bash theme={null}
{
"numInstances": 1,
"numRunning": 1,
"instances": [
{
"instanceId": 0,
"status": {
"running": true,
"error": "",
"numRestarts": 0,
"numReceivedFromSource": 2622,
"numSystemExceptions": 0,
"latestSystemExceptions": [],
"numSourceExceptions": 0,
"latestSourceExceptions": [],
"numWritten": 2622,
"lastReceivedTime": 1691532145625,
"workerId": "test"
}
]
}
```
To check the status of the source connector `test`, run the following command:
```bash theme={null}
./bin/pulsar-admin sources status --tenant public --namespace default --name test
```
You should see the following output:
```bash theme={null}
{
"numInstances" : 1,
"numRunning" : 1,
"instances" : [ {
"instanceId" : 0,
"status" : {
"running" : true,
"error" : "",
"numRestarts" : 0,
"numReceivedFromSource" : 433,
"numSystemExceptions" : 0,
"latestSystemExceptions" : [ ],
"numSourceExceptions" : 0,
"latestSourceExceptions" : [ ],
"numWritten" : 433,
"lastReceivedTime" : 1691452485845,
"workerId" : "test"
}
} ]
}
```
1. From the left navigation pane, under **Resources**, click **Connectors**.
2. Select the **Created Sinks** tab or the **Created Sources** tab to view the status and exceptions of the connector, as well as the system exceptions.
To check the status of the source connector `test`, run the following command:
```bash theme={null}
curl -X GET https://${WEB_SERVICE_URL}/admin/v3/sources/public/default/test/status \
--header 'Authorization: Bearer ' | jq '.'
```
You should see the following output:
```bash theme={null}
{
"numInstances" : 1,
"numRunning" : 1,
"instances" : [ {
"instanceId" : 0,
"status" : {
"running" : true,
"error" : "",
"numRestarts" : 0,
"numReceivedFromSource" : 433,
"numSystemExceptions" : 0,
"latestSystemExceptions" : [ ],
"numSourceExceptions" : 0,
"latestSourceExceptions" : [ ],
"numWritten" : 433,
"lastReceivedTime" : 1691452485845,
"workerId" : "test"
}
} ]
}
```
## View connector logs
### View the connector logs using `snctl`
This section describes how to view connector logs using `snctl`.
This example assumes you have [installed snctl](/tools/cli/snctl/snctl-overview#install-snctl) and [initialized snctl configurations](/tools/cli/snctl/snctl-overview#initialize-snctl-configuration).
You can run the `snctl logs` command to view logs for a specific connector. This table outlines the configuration options that are used for viewing connector logs. For details about all supported fields, you can use the `snctl logs -h` command to list more information.
| Option | Descriptions |
| ------------------------ | ---------------------------------------------------------------------------------------------------------------- |
| `-c` or `--cluster` | The name of your Pulsar cluster where the connector is created. |
| `-p` or `--component` | The type of component to monitor. Available options are `function`, `sink`, and `source`. |
| `-f` or `--follow` | Continuously list the connector log history. |
| `-h` or `--help` | Show usage information about the `snctl logs` command. |
| `-i` or `--instance` | The name of your Pulsar instance where the connector is created. |
| `--name` | The name of your connector. |
| `-o` or `--organization` | The name of your organization where the connector is created. |
| `--previous` | Print the logs that are generated before the configured timestamp. |
| `--pulsar-tenant` | The name of your Pulsar tenant where the connector is created. |
| `--pulsar-namespace` | The name of your Pulsar namespace where the connector is created. |
| `--since` | List logs more recent than the specific time. Available units are `second`, `minute`, and `hour`, such as `24h`. |
| `-s` or `--size` | Specify how many lines of recent logs to display. |
| `--timestamp` | Include timestamps on each line in the log output. |
The following command example shows how to view up to 60 lines of the `data1` sink connector’s logs within the last 5 hours.
```bash theme={null}
snctl logs --since 5h --organization sndev --instance aws --cluster aws --name data1 --pulsar-tenant public --pulsar-namespace default -p sink -f -s 60
```
You should see the following output:
```bash theme={null}
2023-03-23T02:18:43,075+0000 [pulsar-client-io-1-1] INFO org.apache.pulsar.client.impl.ConsumerImpl - [public/default/my-topic][11] Subscribed to topic on aws-broker-0.aws-broker-headless.sndev.svc.cluster.local/172.16.239.82:6650 -- consumer: 0
2023-03-23T02:18:43,075+0000 [pulsar-client-io-1-1] INFO org.apache.pulsar.client.impl.ConsumerImpl - [public/default/my-topic][11] Subscribed to topic on aws-broker-0.aws-broker-headless.sndev.svc.cluster.local/172.16.239.82:6650 -- consumer: 0
2023-03-23T02:18:43,028+0000 [pulsar-client-io-1-1] INFO org.apache.pulsar.client.impl.ConsumerImpl - [public/default/my-topic][11] Subscribing to topic on cnx [id: 0xd4f91768, L:/172.16.136.145:53364 - R:aws-broker-0.aws-broker-headless.sndev.svc.cluster.local/172.16.239.82:6650], consumerId 0
2023-03-23T02:18:43,028+0000 [pulsar-client-io-1-1] INFO org.apache.pulsar.client.impl.ConsumerImpl - [public/default/my-topic][11] Subscribing to topic on cnx [id: 0xd4f91768, L:/172.16.136.145:53364 - R:aws-broker-0.aws-broker-headless.sndev.svc.cluster.local/172.16.239.82:6650], consumerId 0
2023-03-23T02:18:43,026+0000 [pulsar-client-io-1-1] INFO org.apache.pulsar.client.impl.ConnectionPool - [[id: 0xd4f91768, L:/172.16.136.145:53364 - R:aws-broker-0.aws-broker-headless.sndev.svc.cluster.local/172.16.239.82:6650]] Connected to server
2023-03-23T02:18:43,026+0000 [pulsar-client-io-1-1] INFO org.apache.pulsar.client.impl.ConnectionPool - [[id: 0xd4f91768, L:/172.16.136.145:53364 - R:aws-broker-0.aws-broker-headless.sndev.svc.cluster.local/172.16.239.82:6650]] Connected to server
2023-03-23T02:18:42,951+0000 [pulsar-client-io-1-1] INFO org.apache.pulsar.client.impl.ConsumerStatsRecorderImpl - Pulsar client config: {"serviceUrl":"pulsar://aws-broker.sndev.svc.cluster.local:6650","authPluginClassName":"org.apache.pulsar.client.impl.auth.oauth2.AuthenticationOAuth2","authParams":"*****","authParamMap":null,"operationTimeoutMs":30000,"lookupTimeoutMs":30000,"statsIntervalSeconds":60,"numIoThreads":1,"numListenerThreads":1,"connectionsPerBroker":1,"useTcpNoDelay":true,"useTls":false,"tlsTrustCertsFilePath":null,"tlsAllowInsecureConnection":true,"tlsHostnameVerificationEnable":false,"concurrentLookupRequest":5000,"maxLookupRequest":50000,"maxLookupRedirects":20,"maxNumberOfRejectedRequestPerConnection":50,"keepAliveIntervalSeconds":30,"connectionTimeoutMs":10000,"requestTimeoutMs":60000,"initialBackoffIntervalNanos":100000000,"maxBackoffIntervalNanos":60000000000,"enableBusyWait":false,"listenerName":null,"useKeyStoreTls":false,"sslProvider":null,"tlsTrustStoreType":"JKS","tlsTrustStorePath":null,"tlsTrustStorePassword":null,"tlsCiphers":[],"tlsProtocols":[],"memoryLimitBytes":0,"proxyServiceUrl":null,"proxyProtocol":null,"enableTransaction":false,"socks5ProxyAddress":null,"socks5ProxyUsername":null,"socks5ProxyPassword":null}
2023-03-23T02:18:42,951+0000 [pulsar-client-io-1-1] INFO org.apache.pulsar.client.impl.ConsumerStatsRecorderImpl - Pulsar client config: {"serviceUrl":"pulsar://aws-broker.sndev.svc.cluster.local:6650","authPluginClassName":"org.apache.pulsar.client.impl.auth.oauth2.AuthenticationOAuth2","authParams":"*****","authParamMap":null,"operationTimeoutMs":30000,"lookupTimeoutMs":30000,"statsIntervalSeconds":60,"numIoThreads":1,"numListenerThreads":1,"connectionsPerBroker":1,"useTcpNoDelay":true,"useTls":false,"tlsTrustCertsFilePath":null,"tlsAllowInsecureConnection":true,"tlsHostnameVerificationEnable":false,"concurrentLookupRequest":5000,"maxLookupRequest":50000,"maxLookupRedirects":20,"maxNumberOfRejectedRequestPerConnection":50,"keepAliveIntervalSeconds":30,"connectionTimeoutMs":10000,"requestTimeoutMs":60000,"initialBackoffIntervalNanos":100000000,"maxBackoffIntervalNanos":60000000000,"enableBusyWait":false,"listenerName":null,"useKeyStoreTls":false,"sslProvider":null,"tlsTrustStoreType":"JKS","tlsTrustStorePath":null,"tlsTrustStorePassword":null,"tlsCiphers":[],"tlsProtocols":[],"memoryLimitBytes":0,"proxyServiceUrl":null,"proxyProtocol":null,"enableTransaction":false,"socks5ProxyAddress":null,"socks5ProxyUsername":null,"socks5ProxyPassword":null}
2023-03-23T02:18:42,939+0000 [pulsar-client-io-1-1] INFO org.apache.pulsar.client.impl.ConsumerStatsRecorderImpl - Starting Pulsar consumer status recorder with config: {"topicNames":["public/default/my-topic"],"topicsPattern":null,"subscriptionName":"11","subscriptionType":"Shared","subscriptionMode":"Durable","receiverQueueSize":1000,"acknowledgementsGroupTimeMicros":100000,"negativeAckRedeliveryDelayMicros":60000000,"maxTotalReceiverQueueSizeAcrossPartitions":50000,"consumerName":null,"ackTimeoutMillis":0,"tickDurationMillis":1000,"priorityLevel":0,"maxPendingChunkedMessage":10,"autoAckOldestChunkedMessageOnQueueFull":false,"expireTimeOfIncompleteChunkedMessageMillis":60000,"cryptoFailureAction":"FAIL","properties":{"application":"pulsar-sink","id":"public/default/data1-cc47863d","instance_hostname":"data1-cc47863d-sink-0","instance_id":"0"},"readCompacted":false,"subscriptionInitialPosition":"Latest","patternAutoDiscoveryPeriod":60,"regexSubscriptionMode":"PersistentOnly","deadLetterPolicy":null,"retryEnable":false,"autoUpdatePartitions":true,"autoUpdatePartitionsIntervalSeconds":60,"replicateSubscriptionState":false,"resetIncludeHead":false,"keySharedPolicy":null,"batchIndexAckEnabled":false,"ackReceiptEnabled":false,"poolMessages":false,"maxPendingChuckedMessage":10}
2023-03-23T02:18:42,939+0000 [pulsar-client-io-1-1] INFO org.apache.pulsar.client.impl.ConsumerStatsRecorderImpl - Starting Pulsar consumer status recorder with config: {"topicNames":["public/default/my-topic"],"topicsPattern":null,"subscriptionName":"11","subscriptionType":"Shared","subscriptionMode":"Durable","receiverQueueSize":1000,"acknowledgementsGroupTimeMicros":100000,"negativeAckRedeliveryDelayMicros":60000000,"maxTotalReceiverQueueSizeAcrossPartitions":50000,"consumerName":null,"ackTimeoutMillis":0,"tickDurationMillis":1000,"priorityLevel":0,"maxPendingChunkedMessage":10,"autoAckOldestChunkedMessageOnQueueFull":false,"expireTimeOfIncompleteChunkedMessageMillis":60000,"cryptoFailureAction":"FAIL","properties":{"application":"pulsar-sink","id":"public/default/data1-cc47863d","instance_hostname":"data1-cc47863d-sink-0","instance_id":"0"},"readCompacted":false,"subscriptionInitialPosition":"Latest","patternAutoDiscoveryPeriod":60,"regexSubscriptionMode":"PersistentOnly","deadLetterPolicy":null,"retryEnable":false,"autoUpdatePartitions":true,"autoUpdatePartitionsIntervalSeconds":60,"replicateSubscriptionState":false,"resetIncludeHead":false,"keySharedPolicy":null,"batchIndexAckEnabled":false,"ackReceiptEnabled":false,"poolMessages":false,"maxPendingChuckedMessage":10}
```
### View the connector logs from log topics
StreamNative Cloud provide an alternative implementation of the Pulsar Functions log topic(see [Pulsar Functions log topic](https://pulsar.apache.org/docs/en/functions-debug-log-topic)) feature called `sidecar` mode, which supports using such feature in Connectors.
To enable the `sidecar` mode, user should provide the following configurations when deploying the connector:
```yaml theme={null}
pulsarctl sinks/sources create --custom-runtime-options '{"logTopic":"LOG-TOPIC", "logTopicAgent":"sidecar"}' ...
```
For more details about the `custom-runtime-options`, see [Custom runtime options](/cloud/connect/pulsar-io/connector-config#stream-native-cloud-custom-runtime-options).
Once the connector is deployed with the `sidecar` mode, you can configure consumers to consume messages from the log topic.
# Connector Overview
Source: https://docs.streamnative.io/cloud/connect/pulsar-io/connector-overview
## Introduction to Pulsar IO Connectors
### Concept
Pulsar IO connectors allow you to integrate Pulsar with various external systems and data sources for both inbound and outbound data movement. For example, you can use Pulsar IO Connectors to ingest data from external sources into Pulsar topics or export data from Pulsar topics to other external systems.
Pulsar IO Connectors can be further categorized as source connectors or sink connectors:
* A source connector ingests data from an external system into Pulsar.
* A sink connector egresses data from Pulsar to an external system.
The following diagram illustrates the data movement among source connectors, Pulsar, sink connectors, and external systems.
### Benefits
* Seamless & Simplified Data Integration: Pulsar IO Connectors provide a unified interface for connecting Pulsar to various external systems and data sources, allowing developers to easily integrate Pulsar with their existing infrastructure without the need for custom integration code.
* Extensibility: Pulsar IO Connectors are designed to be easily extensible, allowing developers to create custom connectors for specific use cases and data sources not covered by the [built-in connectors](#built-in-connectors-on-streamnative-cloud).
* Reduced Development Effort: By leveraging pre-built connectors, developers can save time and effort. They don't have to write and maintain complex integration code from scratch for each external system.
* Reliable and Scalable: Pulsar IO Connectors are built to be reliable and scalable, ensuring the data transfers between Pulsar and external systems are efficient and fault-tolerant.
### Use cases
* Data Ingestion to Pulsar: If you have data coming from various external sources, such as Apache Kafka, databases, message queues, or cloud storage systems like Amazon S3, you can use Pulsar IO Connectors to ingest that data into Pulsar topics.
* Data Export from Pulsar: Pulsar IO Connectors also enable you to export data from Pulsar topics to other systems or storage solutions. This helps you to synchronize data across different environments, replicate data, or stream data to external services or databases.
* Real-time Data Processing: Pulsar IO Connectors facilitate real-time data processing by enabling the seamless movement of data between Pulsar and other systems. This is particularly useful in event-driven architectures, streaming applications, and microservices-based solutions.
* Extending Pulsar's Functionality: If you have specific use cases or data sources not directly supported by Pulsar, you can deploy custom Pulsar IO Connectors to extend Pulsar's functionality and integrate with those systems.
### Connectors Shared Responsibility
StreamNative and our customers have a shared responsibility for maintaining and keeping connectors properly functioning. Outlined below, StreamNative has a responsibility for custom connectors that are maintained by uploading to StreamNative Cloud to maintain connectivity to the Pulsar cluster and for logging and monitoring. Customers who upload their connectors are responsible for all other operations such as configurations, updates, development, support and plugin installation. Partner connectors have similar support but the partners with StreamNative will be responsible for development and connector support. For built in connectors, StreamNative is responsible for everything except connector configuration.
For more details, see below.
## Built-in connectors on StreamNative Cloud
To further reduce the development overhead and time, StreamNative has pre-built a variety of Pulsar IO connectors on StreamNative Cloud. With proper configurations, you can integrate the data between your Pulsar cluster on StreamNative Cloud and your data systems effortlessly.
### Built-in source connectors
Currently, StreamNative Cloud supports the following source connectors:
* [AMQP1\_0 source connector](/connect/connectors/amqp-1-0-source/current/amqp-1-0-source)
* [AWS SQS source connector](/connect/connectors/sqs-source/current/sqs-source)
* [Google BigQuery source connector](/connect/connectors/google-bigquery-source/current/google-bigquery-source)
* [Debezium Microsoft SQL Server source connector](/connect/connectors/debezium-mssql-source/current/debezium-mssql-source)
* [Debezium MongoDB source connector](/connect/connectors/debezium-mongodb-source/current/debezium-mongodb-source)
* [Debezium MySQL source connector](/connect/connectors/debezium-mysql-source/current/debezium-MySQL-source)
* [Debezium PostgreSQL source connector](/connect/connectors/debezium-postgres-source/current/debezium-postgres-source)
* [Kafka source connector](/connect/connectors/kafka-source/current/kafka-source)
* [Kinesis source connector](/connect/connectors/kinesis-source/current/kinesis-source)
* Data generator source connector (for internal testing purposes only)
### Built-in sink connectors
Currently, StreamNative Cloud supports the following sink connectors.
* [AMQP1\_0 sink connector](/connect/connectors/amqp-1-0-sink/current/amqp-1-0-sink)
* [AWS EventBridge sink connector](/connect/connectors/aws-eventbridge-sink/current/aws-eventbridge-sink)
* [AWS Lambda sink connector](/connect/connectors/aws-lambda-sink/current/aws-lambda-sink)
* [AWS SQS sink connector](/connect/connectors/sqs-sink/current/sqs-sink)
* [AWS S3 Sink Connector](/connect/connectors/aws-s3-sink/current/aws-s3-sink)
* [Google Cloud Storage Sink Connector](/connect/connectors/google-cloud-storage-sink/current/google-cloud-storage-sink)
* [Azure Blob Storage Sink Connector](/connect/connectors/azure-blob-storage-sink/current/azure-blob-storage-sink)
* [Elasticsearch sink connector](/connect/connectors/elasticsearch-sink/current/elasticsearch-sink)
* [Google BigQuery sink connector](/connect/connectors/google-bigquery-sink/current/google-bigquery-sink)
* [Kinesis sink connector](/connect/connectors/kinesis-sink/current/kinesis-sink)
* [Snowflake Streaming sink connector](/connect/connectors/snowflake-streaming-sink/current/snowflake-streaming)
* [Snowflake sink connector](/connect/connectors/snowflake-sink/current/snowflake-sink)
* Data generator sink connector (for internal testing purposes only)
## What’s next?
* Learn how to [deploy connectors](/cloud/connect/pulsar-io/deploy-connectors/deploy-connector-index).
* Learn how to [manage connectors](/cloud/connect/pulsar-io/connector-manage).
* Learn how to [monitor connectors](/cloud/connect/pulsar-io/connector-monitoring).
* Reference [common configurations](/cloud/connect/pulsar-io/connector-config).
* Discover Pulsar Ecosystem on [StreamNative Hub](/connect/overview).
* Watch the [playlist for deploying connectors on StreamNative Cloud](https://www.youtube.com/playlist?list=PL7-BmxsE3q4WIhP4EISejpJ12YaTd6Y3h).
# Check Connector Availability
Source: https://docs.streamnative.io/cloud/connect/pulsar-io/deploy-connectors/connector-check
You can check the latest availabiltiy of built-in connectors on StreamNative Cloud using `snctl`, `pulsarctl` or `pulsar-admin`.
## Check Source Connector Availability
```
snctl pulsar admin sources available-sources
+-------------------+-----------------------------------------+--------------------------------------------------------------+
| NAME | DESCRIPTION | CLASSNAME |
+-------------------+-----------------------------------------+--------------------------------------------------------------+
| amqp1_0 | AMQP1_0 connectors@2.8.2.4 | org.apache.pulsar.ecosystem.io.amqp.AmqpSource |
| bigquery | Google BigQuery connectors@2.10.1.12 | org.apache.pulsar.ecosystem.io.bigquery.BigQuerySource |
| data-generator | Test data generator connector@2.9.2.17 | org.apache.pulsar.io.datagenerator.DataGeneratorSource |
| debezium-mongodb | Debezium MongoDb Source@2.9.2.17 | org.apache.pulsar.io.debezium.mongodb.DebeziumMongoDbSource |
| debezium-mssql | Debezium Microsoft SQL Server@2.9.2.17 | org.apache.pulsar.io.debezium.mssql.DebeziumMsSqlSource |
| debezium-mysql | Debezium MySql Source@2.9.2.17 | org.apache.pulsar.io.debezium.mysql.DebeziumMysqlSource |
| debezium-postgres | Debezium Postgres Source@2.9.2.17 | org.apache.pulsar.io.debezium.postgres.DebeziumPostgresSource|
| kafka | Kafka Source@2.9.2.17 | org.apache.pulsar.io.kafka.KafkaBytesSource |
| kinesis | Kinesis connectors@2.9.2.17 | org.apache.pulsar.io.kinesis.KinesisSource |
| sqs | SQS connectors@2.9.2.18 | org.apache.pulsar.ecosystem.io.sqs.SQSSource |
+-------------------+-----------------------------------------+--------------------------------------------------------------+
```
```
pulsarctl sources available-sources
+-------------------+-----------------------------------------+--------------------------------------------------------------+
| NAME | DESCRIPTION | CLASSNAME |
+-------------------+-----------------------------------------+--------------------------------------------------------------+
| amqp1_0 | AMQP1_0 connectors@2.8.2.4 | org.apache.pulsar.ecosystem.io.amqp.AmqpSource |
| bigquery | Google BigQuery connectors@2.10.1.12 | org.apache.pulsar.ecosystem.io.bigquery.BigQuerySource |
| data-generator | Test data generator connector@2.9.2.17 | org.apache.pulsar.io.datagenerator.DataGeneratorSource |
| debezium-mongodb | Debezium MongoDb Source@2.9.2.17 | org.apache.pulsar.io.debezium.mongodb.DebeziumMongoDbSource |
| debezium-mssql | Debezium Microsoft SQL Server@2.9.2.17 | org.apache.pulsar.io.debezium.mssql.DebeziumMsSqlSource |
| debezium-mysql | Debezium MySql Source@2.9.2.17 | org.apache.pulsar.io.debezium.mysql.DebeziumMysqlSource |
| debezium-postgres | Debezium Postgres Source@2.9.2.17 | org.apache.pulsar.io.debezium.postgres.DebeziumPostgresSource|
| kafka | Kafka Source@2.9.2.17 | org.apache.pulsar.io.kafka.KafkaBytesSource |
| kinesis | Kinesis connectors@2.9.2.17 | org.apache.pulsar.io.kinesis.KinesisSource |
| sqs | SQS connectors@2.9.2.18 | org.apache.pulsar.ecosystem.io.sqs.SQSSource |
+-------------------+-----------------------------------------+--------------------------------------------------------------+
```
```
./bin/pulsar-admin \
--admin-url "${WEB_SERVICE_URL}" \
--auth-plugin org.apache.pulsar.client.impl.auth.oauth2.AuthenticationOAuth2 \
--auth-params '{"privateKey":"file:///YOUR-KEY-FILE-PATH",
"issuerUrl":"https://auth.streamnative.cloud/",
"audience":"urn:sn:pulsar:${orgName}:${instanceName}}'
sources available-sources
amqp1_0
AMQP1_0 connectors@2.8.2.4
----------------------------------------
bigquery
Google BigQuery connectors@2.10.1.12
sidebarTitle: Check Connector Availability
----------------------------------------
data-generator
Test data generator connector@2.9.2.17
----------------------------------------
debezium-mongodb
Debezium MongoDb Source@2.9.2.17
sidebarTitle: Check Connector Availability
----------------------------------------
debezium-mssql
Debezium Microsoft SQL Server Source@2.9.2.17
----------------------------------------
debezium-mysql
Debezium MySql Source@2.9.2.17
sidebarTitle: Check Connector Availability
----------------------------------------
debezium-postgres
Debezium Postgres Source@2.9.2.17
----------------------------------------
kafka
Kafka Source@2.9.2.17
sidebarTitle: Check Connector Availability
----------------------------------------
kinesis
Kinesis connectors@2.9.2.17
----------------------------------------
sqs
SQS connectors@2.9.2.18
sidebarTitle: Check Connector Availability
----------------------------------------
```
```
curl -X GET https://${WEB_SERVICE_URL}/admin/v3/sources/builtinsources \
--header 'Authorization: Bearer ' | jq '.'
[
{
"name": "amqp1_0",
"description": "AMQP1_0 connectors",
"sourceClass": "org.apache.pulsar.ecosystem.io.amqp.AmqpSource",
"sinkClass": "org.apache.pulsar.ecosystem.io.amqp.AmqpSink",
"sourceConfigClass": "org.apache.pulsar.ecosystem.io.amqp.AmqpSourceConfig",
"sinkConfigClass": "org.apache.pulsar.ecosystem.io.amqp.AmqpSinkConfig",
"id": "pulsar-io-amqp1_0",
"version": "2.8.2.4",
"imageRepository": "streamnative/pulsar-io-amqp-1-0",
"imageTag": "2.8.2.4",
"typeClassName": "java.nio.ByteBuffer",
"sourceTypeClassName": "java.nio.ByteBuffer",
"sinkTypeClassName": "java.nio.ByteBuffer",
"defaultSchemaType": "org.apache.pulsar.client.impl.schema.ByteBufferSchema",
"jar": "connectors/pulsar-io-amqp1_0-2.8.2.4.nar"
},
{
"name": "bigquery",
"description": "Google BigQuery connectors",
"sourceClass": "org.apache.pulsar.ecosystem.io.bigquery.BigQuerySource",
"sinkClass": "org.apache.pulsar.ecosystem.io.bigquery.BigQuerySink",
"sourceConfigClass": "org.apache.pulsar.ecosystem.io.bigquery.BigQuerySourceConfig",
"sinkConfigClass": "org.apache.pulsar.ecosystem.io.bigquery.BigQueryConfig",
"id": "pulsar-io-bigquery",
"version": "3.0.1.6",
"imageRepository": "streamnative/pulsar-io-bigquery",
"imageTag": "3.0.1.6",
"sourceTypeClassName": "org.apache.pulsar.client.api.schema.GenericRecord",
"sinkTypeClassName": "org.apache.pulsar.client.api.schema.GenericObject",
"jarFullName": "pulsar-io-bigquery-3.0.1.6.jar",
"jar": "connectors/pulsar-io-bigquery-3.0.1.6.jar"
},
{
"name": "data-generator",
"description": "Test data generator connector",
"sourceClass": "org.apache.pulsar.io.datagenerator.DataGeneratorSource",
"sinkClass": "org.apache.pulsar.io.datagenerator.DataGeneratorPrintSink",
"sourceConfigClass": "org.apache.pulsar.io.datagenerator.DataGeneratorSourceConfig",
"id": "pulsar-io-data-generator",
"version": "2.9.2.17",
"imageRepository": "streamnative/pulsar-io-data-generator",
"imageTag": "2.9.2.17",
"typeClassName": "org.apache.pulsar.io.datagenerator.Person",
"sourceTypeClassName": "org.apache.pulsar.io.datagenerator.Person",
"sinkTypeClassName": "org.apache.pulsar.io.datagenerator.Person",
"jar": "connectors/pulsar-io-data-generator-2.9.2.17.nar"
},
{
"name": "debezium-mongodb",
"description": "Debezium MongoDb Source",
"sourceClass": "org.apache.pulsar.io.debezium.mongodb.DebeziumMongoDbSource",
"id": "pulsar-io-debezium-mongodb",
"version": "2.9.2.17",
"imageRepository": "streamnative/pulsar-io-debezium-mongodb",
"imageTag": "2.9.2.17",
"typeClassName": "org.apache.pulsar.common.schema.KeyValue",
"sourceTypeClassName": "org.apache.pulsar.common.schema.KeyValue",
"sinkTypeClassName": "org.apache.pulsar.common.schema.KeyValue",
"jar": "connectors/pulsar-io-debezium-mongodb-2.9.2.17.nar"
}
// omitting...
]
```
## Check Sink Connector Availability
```
snctl pulsar admin sinks available-sinks
+-----------------+----------------------------------------+------------------------------------------------------------------+
| NAME | DESCRIPTION | CLASSNAME |
+-----------------+----------------------------------------+------------------------------------------------------------------+
| amqp1_0 | AMQP1_0 connectors @2.8.2.4 | org.apache.pulsar.ecosystem.io.amqp.AmqpSink |
| aws-eventbridge | AWS EventBridge Sink @2.10.4.3 | org.apache.pulsar.io.eventbridge.sink.EventBridgeSink |
| aws-lambda | AWS Lambda Sink @2.9.2.17 | org.apache.pulsar.ecosystem.io.aws.lambda.AWSLambdaBytesSink |
| bigquery | Google BigQuery connectors @2.10.1.12 | org.apache.pulsar.ecosystem.io.bigquery.BigQuerySink |
| cloud-storage | Cloud storage Sink @2.9.4.3 | org.apache.pulsar.io.jcloud.sink.CloudStorageGenericRecordSink |
| data-generator | Test data generator connector @2.9.2.17| org.apache.pulsar.io.datagenerator.DataGeneratorPrintSink |
| elasticsearch | Elasticsearch Sink @2.10.0.3 | org.apache.pulsar.io.elasticsearch.ElasticSearchSink |
| kinesis | Kinesis connectors @2.9.2.17 | org.apache.pulsar.io.kinesis.KinesisSink |
| snowflake | Snowflake Sink @2.10.3.4 | org.apache.pulsar.ecosystem.io.snowflake.SnowflakeSinkConnector |
| sqs | SQS connectors @2.9.2.18 | org.apache.pulsar.ecosystem.io.sqs.SQSSink |
+-----------------+----------------------------------------+------------------------------------------------------------------+
```
```
pulsarctl sinks available-sinks
+-----------------+----------------------------------------+------------------------------------------------------------------+
| NAME | DESCRIPTION | CLASSNAME |
+-----------------+----------------------------------------+------------------------------------------------------------------+
| amqp1_0 | AMQP1_0 connectors @2.8.2.4 | org.apache.pulsar.ecosystem.io.amqp.AmqpSink |
| aws-eventbridge | AWS EventBridge Sink @2.10.4.3 | org.apache.pulsar.io.eventbridge.sink.EventBridgeSink |
| aws-lambda | AWS Lambda Sink @2.9.2.17 | org.apache.pulsar.ecosystem.io.aws.lambda.AWSLambdaBytesSink |
| bigquery | Google BigQuery connectors @2.10.1.12 | org.apache.pulsar.ecosystem.io.bigquery.BigQuerySink |
| cloud-storage | Cloud storage Sink @2.9.4.3 | org.apache.pulsar.io.jcloud.sink.CloudStorageGenericRecordSink |
| data-generator | Test data generator connector @2.9.2.17| org.apache.pulsar.io.datagenerator.DataGeneratorPrintSink |
| elasticsearch | Elasticsearch Sink @2.10.0.3 | org.apache.pulsar.io.elasticsearch.ElasticSearchSink |
| kinesis | Kinesis connectors @2.9.2.17 | org.apache.pulsar.io.kinesis.KinesisSink |
| snowflake | Snowflake Sink @2.10.3.4 | org.apache.pulsar.ecosystem.io.snowflake.SnowflakeSinkConnector |
| sqs | SQS connectors @2.9.2.18 | org.apache.pulsar.ecosystem.io.sqs.SQSSink |
+-----------------+----------------------------------------+------------------------------------------------------------------+
```
```
./bin/pulsar-admin \
--admin-url "${WEB_SERVICE_URL}" \
--auth-plugin org.apache.pulsar.client.impl.auth.oauth2.AuthenticationOAuth2 \
--auth-params '{"privateKey":"file:///YOUR-KEY-FILE-PATH",
"issuerUrl":"https://auth.streamnative.cloud/",
"audience":"urn:sn:pulsar:${orgName}:${instanceName}}'
sinks available-sinks
amqp1_0
AMQP1_0 connectors@2.8.2.4
----------------------------------------
aws-eventbridge
AWS EventBridge Sink@2.10.4.3
sidebarTitle: Check Connector Availability
----------------------------------------
aws-lambda
AWS Lambda Sink@2.9.2.17
----------------------------------------
bigquery
Google BigQuery connectors@2.10.1.12
sidebarTitle: Check Connector Availability
----------------------------------------
cloud-storage
Cloud storage Sink@2.8.4.3
----------------------------------------
data-generator
Test data generator connector@2.9.2.17
sidebarTitle: Check Connector Availability
----------------------------------------
elasticsearch
Elasticsearch Sink@2.10.0.3
----------------------------------------
kinesis
Kinesis connectors@2.9.2.17
sidebarTitle: Check Connector Availability
----------------------------------------
snowflake
Snowflake Sink@2.10.3.4
----------------------------------------
sqs
SQS connectors@2.9.2.18
sidebarTitle: Check Connector Availability
----------------------------------------
```
```
curl -X GET https://${WEB_SERVICE_URL}/admin/v3/sinks/builtinsinks \
--header 'Authorization: Bearer ' | jq '.'
[
{
"name": "aws-eventbridge",
"description": "AWS EventBridge Sink",
"sinkClass": "org.apache.pulsar.io.eventbridge.sink.EventBridgeSink",
"sinkConfigClass": "org.apache.pulsar.io.eventbridge.sink.EventBridgeConfig",
"id": "pulsar-io-aws-eventbridge",
"version": "2.10.4.3",
"imageRepository": "streamnative/pulsar-io-aws-eventbridge",
"imageTag": "2.10.4.3",
"typeClassName": "org.apache.pulsar.client.api.schema.GenericObject",
"sourceTypeClassName": "org.apache.pulsar.client.api.schema.GenericObject",
"sinkTypeClassName": "org.apache.pulsar.client.api.schema.GenericObject",
"jar": "connectors/pulsar-io-aws-eventbridge-2.10.4.3.nar"
},
{
"name": "aws-lambda",
"description": "AWS Lambda Sink",
"sinkClass": "org.apache.pulsar.ecosystem.io.aws.lambda.AWSLambdaBytesSink",
"sinkConfigClass": "org.apache.pulsar.ecosystem.io.aws.lambda.AWSLambdaConnectorConfig",
"id": "pulsar-io-aws-lambda",
"version": "2.9.2.17",
"imageRepository": "streamnative/pulsar-io-aws-lambda",
"imageTag": "2.9.2.17",
"sourceTypeClassName": "[B",
"sinkTypeClassName": "[B",
"jar": "connectors/pulsar-io-aws-lambda-2.9.2.17.nar"
},
{
"name": "bigquery",
"description": "Google BigQuery connectors",
"sourceClass": "org.apache.pulsar.ecosystem.io.bigquery.BigQuerySource",
"sinkClass": "org.apache.pulsar.ecosystem.io.bigquery.BigQuerySink",
"sourceConfigClass": "org.apache.pulsar.ecosystem.io.bigquery.BigQuerySourceConfig",
"sinkConfigClass": "org.apache.pulsar.ecosystem.io.bigquery.BigQueryConfig",
"id": "pulsar-io-bigquery",
"version": "3.0.1.6",
"imageRepository": "streamnative/pulsar-io-bigquery",
"imageTag": "3.0.1.6",
"sourceTypeClassName": "org.apache.pulsar.client.api.schema.GenericRecord",
"sinkTypeClassName": "org.apache.pulsar.client.api.schema.GenericObject",
"jarFullName": "pulsar-io-bigquery-3.0.1.6.jar",
"jar": "connectors/pulsar-io-bigquery-3.0.1.6.jar"
},
{
"name": "cloud-storage",
"description": "Cloud storage Sink",
"sinkClass": "org.apache.pulsar.io.jcloud.sink.CloudStorageGenericRecordSink",
"sinkConfigClass": "org.apache.pulsar.io.jcloud.sink.CloudStorageSinkConfig",
"id": "pulsar-io-cloud-storage",
"version": "2.10.2.4",
"imageRepository": "streamnative/pulsar-io-cloud-storage",
"imageTag": "2.10.2.4",
"typeClassName": "org.apache.pulsar.client.api.schema.GenericRecord",
"sourceTypeClassName": "org.apache.pulsar.client.api.schema.GenericRecord",
"sinkTypeClassName": "org.apache.pulsar.client.api.schema.GenericRecord",
"jar": "connectors/pulsar-io-cloud-storage-2.10.2.4.nar"
}
// omitting...
]
```
## What’s next?
* [Create connectors](/cloud/connect/pulsar-io/deploy-connectors/connector-create)
# Create Connectors
Source: https://docs.streamnative.io/cloud/connect/pulsar-io/deploy-connectors/connector-create
## Prerequisites
Before deploying a connector to StreamNative Cloud, make sure the following prerequisites have been met:
* A running external data system service.
* A running [Pulsar Cluster](/cloud/clusters/manage-clusters/cluster#create-a-cluster) on StreamNative Cloud and the [required environment](/cloud/connect/pulsar-io/deploy-connectors/connector-setup) has been set up.
* At least one of the required tools: [snctl](/tools/cli/snctl/snctl-overview), [pulsarctl](/tools/cli/pulsarctl/pulsarctl-overview), `pulsar-admin` , or the Terraform module. For a quickstart of setting up `pulsarctl` and `pulsar-admin`, see [set up client tools](/cloud/connect/pulsar-io/deploy-connectors/connector-setup#set-up-client-tools).
## Create a built-in connector
Before creating a connector, it's highly recommended to do the following:
1. [Check connector availability](/cloud/connect/pulsar-io/deploy-connectors/connector-check) to ensure the version number of the connector you want to create is supported on StreamNative Cloud.
2. Go to [StreamNative Hub](/connect/overview) and find the connector-specific docs of your version for configuration reference.
The following example shows how to create a data generator source connector named `test` on StreamNative Cloud using different tools.
The `builtin://` is followed by the name of the built-in connector, such as `builtin://data-generator`.
To create a data generator source connector named `test`, run the following command.
```bash theme={null}
snctl pulsar admin sources create --archive builtin://data-generator --destination-topic-name public/default/dg-test --source-config '{"sleepBetweenMessages": 60}' --name test --sn-service-account $SERVICE_ACCOUNT
```
Replace `$SERVICE_ACCOUNT` with the StreamNative Cloud service account that the connector uses as its runtime identity. To select the runtime service account interactively, use `--use-sn-service-account`.
Only Pulsar 4.0.x clusters running version 4.0.10.6 or later, or Pulsar 4.2.x clusters running version 4.2.1.4 or later, support the `--sn-service-account` flag.
You can use `--as-service-account` instead of `--sn-service-account` if you are using other versions of Pulsar clusters.
You should see the following output:
```bash theme={null}
Created test successfully
```
If you want to verify whether the data generator source connector has been created successfully, run the following command:
```bash theme={null}
snctl pulsar admin sources list
```
You should see the following output:
```bash theme={null}
+---------------------+
| PULSAR SOURCES NAME |
+---------------------+
| test |
+---------------------+
```
If you want to create a sink connector, use the `snctl pulsar admin sinks create` command.
To create a data generator source connector named `test`, run the following command.
```bash theme={null}
pulsarctl sources create --archive builtin://data-generator --destination-topic-name public/default/dg-test --source-config '{"sleepBetweenMessages": 60}' --name test
```
You should see the following output:
```bash theme={null}
Created test successfully
```
If you want to verify whether the data generator source connector has been created successfully, run the following command:
```bash theme={null}
pulsarctl sources list
```
You should see the following output:
```bash theme={null}
+---------------------+
| PULSAR SOURCES NAME |
+---------------------+
| test |
+---------------------+
```
If you want to create a sink connector, use the `pulsarctl sinks create` command.
To create a data generator source connector named `test`, run the following command.
```bash theme={null}
./bin/pulsar-admin \
--admin-url "${WEB_SERVICE_URL}" \
--auth-plugin org.apache.pulsar.client.impl.auth.oauth2.AuthenticationOAuth2 \
--auth-params '{"privateKey":"file:///YOUR-KEY-FILE-PATH",
"issuerUrl":"https://auth.streamnative.cloud/",
"audience":"urn:sn:pulsar:${orgName}:${instanceName}}'
sources create --archive builtin://data-generator --destination-topic-name public/default/dg-test --source-config '{"sleepBetweenMessages": 60}' --name test
```
Replace the placeholder variables with the actual values that you can get when [setting up client tools](/cloud/connect/pulsar-io/deploy-connectors/connector-setup#set-up-client-tools).
* `admin-url`: the HTTP service URL of your Pulsar cluster.
* `private_key`: the path to the downloaded OAuth2 key file.
* `audience`: the [Uniform Resource Name (URN)](/cloud/references/glossary#uniform-resource-name-urn), which is a combination of the `urn:sn:pulsar`, your organization name, and your Pulsar instance name.
* `${orgName}`: the name of your [organization](/cloud/references/glossary#organization).
* `${instanceName}`: the name of your [instance](/cloud/references/glossary#instance).
If you want to list the submitted connector for a double check, run the following command:
```bash theme={null}
./bin/pulsar-admin sources list
```
You should see the following output:
```bash theme={null}
[
"test"
]
```
To reduce the complexity of your command, you can add the above parameters with values into the `conf/client.conf` file under the downloaded Pulsar release. Once it's configured, you can run a simple command instead:
```bash theme={null}
./bin/pulsar-admin sources create --archive builtin://data-generator --destination-topic-name public/default/dg-test --source-config '{"sleepBetweenMessages": 60}' --name test
```
1. Add the following content to your Terraform file:
```bash theme={null}
terraform {
required_providers {
pulsar = {
version = "0.2.0"
source = "registry.terraform.io/streamnative/pulsar"
}
}
}
provider "pulsar" {
web_service_url = "${WEB_SERVICE_URL}"
audience = "urn:sn:pulsar:${orgName}:${instanceName}"
issuer_url = "https://auth.streamnative.cloud/"
key_file_path = "file:///YOUR-KEY-FILE-PATH"
api_version = 3
}
resource "pulsar_source" "test" {
provider = pulsar
name = "dg-test-tf"
tenant = "public"
namespace = "default"
archive = "builtin://data-generator"
destination_topic_name = "public/default/dg-test"
processing_guarantees = "ATMOST_ONCE"
configs = "{\"sleepBetweenMessages\":\"60\"}"
}
```
2. Call the following commands in your Terraform file directory:
```bash theme={null}
terraform init
# output
Terraform has been successfully initialized!
```
```bash theme={null}
terraform apply
# output
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
+ create
Terraform will perform the following actions:
# pulsar_source.test will be created
+ resource "pulsar_source" "test" {
+ archive = "builtin://data-generator"
+ classname = (known after apply)
+ configs = jsonencode(
{
+ sleepBetweenMessages = "60"
}
)
+ cpu = 1
+ destination_topic_name = "public/default/dg-test"
+ disk_mb = 10240
+ id = (known after apply)
+ name = "dg-test-tf"
+ namespace = "default"
+ parallelism = 1
+ processing_guarantees = "ATMOST_ONCE"
+ ram_mb = 1024
+ tenant = "public"
}
Plan: 1 to add, 0 to change, 0 to destroy.
Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value: yes
pulsar_source.test: Creating...
pulsar_source.test: Creation complete after 1s [id=public/default/dg-test-tf]
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
```
You can use `snctl`, `pulsarctl` or `pulsar-admin` to list the source connector submitted using Terraform.
To create a data generator source connector named `test`, run the following command.
```bash theme={null}
curl -X POST https://${WEB_SERVICE_URL}/admin/v3/sources/{tenant}/{namespace}/test \
-H 'Authorization: Bearer ' \
-H "Content-Type: multipart/form-data" \
-F 'sourceConfig={"name": "test", "tenant": "public", "namespace": "default", "archive": "builtin://data-generator", "topicName": "public/default/dg-test", "configs": {"sleepBetweenMessages": "60"}};type=application/json'
```
If you want to list the submitted connector for a double check, run the following command:
```bash theme={null}
curl -X GET https://pc-ae474868.aws-use2-dixie-snc.streamnative.test.aws.sn2.dev/admin/v3/sources/public/default \
--header 'Authorization: Bearer '
["test"]
```
For all the common configurations of built-in connectors, see [Configuration reference](/cloud/connect/pulsar-io/connector-config).
## Pass sensitive configs to connector
Some connectors require sensitive information, such as passwords, token, to be passed to the connector. And you may not want to expose these sensitive information in the connector configuration.
To solve this problem, you can use the following methods to pass sensitive information to the connector:
* **Create a secret**
For example, the AWS lambda sink connector requires the AWS access key and secret key to be passed to the connector.
You can create a secret in the console UI and pass the secret name to the connector configuration.
The `location` should be the same as the region of your Pulsar cluster.
The `awsAccessKey` and `awsSecretKey` is the field name, and the `lambda-sink-secret` can be any unique name you want to give to the secret.
Only "sensitive" fields are able to load from secrets. You can get the list of sensitive fields from the connector configuration reference.
E.g. [AWS lambda sink configurations](https://docs.streamnative.io/hub/connector-aws-lambda-sink-v3.1#configuration-properties)
* **Pass secrets to the connector configuration**
The following example shows how to create an AWS lambda sink connector named `test` on StreamNative Cloud using different tools.
The `builtin://` is followed by the name of the built-in connector, such as `builtin://data-generator`.
To create an AWS lambda sink connector named `test`, run the following command.
```bash theme={null}
snctl pulsar admin sinks create --archive builtin://aws-lambda --inputs public/default/lambda-sink-test --sink-config '{"awsRegion": "us-west-2","lambdaFunctionName": "test-hello","payloadFormat": "V2"}' --secrets '{"awsAccessKey":{"path":"lambda-sink-secret","key":"awsAccessKey"},"awsSecretKey":{"path":"lambda-sink-secret","key":"awsSecretKey"}}' --name test --sn-service-account $SERVICE_ACCOUNT
```
You should see the following output:
```bash theme={null}
Created test successfully
```
The `awsAccessKey` and `awsSecretKey` is the field name, and the `lambda-sink-secret` is the secret name you created in UI.
If you want to verify whether the AWS lambda sink connector has been created successfully, run the following command:
```bash theme={null}
snctl pulsar admin sinks list
```
You should see the following output:
```bash theme={null}
+---------------------+
| PULSAR SINKS NAME |
+---------------------+
| test |
+---------------------+
```
To create an AWS lambda sink connector named `test`, run the following command.
```bash theme={null}
pulsarctl sinks create --archive builtin://aws-lambda --inputs public/default/lambda-sink-test --sink-config '{"awsRegion": "us-west-2","lambdaFunctionName": "test-hello","payloadFormat": "V2"}' --secrets '{"awsAccessKey":{"path":"lambda-sink-secret","key":"awsAccessKey"},"awsSecretKey":{"path":"lambda-sink-secret","key":"awsSecretKey"}}' --name test
```
You should see the following output:
```bash theme={null}
Created test successfully
```
The `awsAccessKey` and `awsSecretKey` is the field name, and the `lambda-sink-secret` is the secret name you created in UI.
If you want to verify whether the AWS lambda sink connector has been created successfully, run the following command:
```bash theme={null}
pulsarctl sinks list
```
You should see the following output:
```bash theme={null}
+---------------------+
| PULSAR SINKS NAME |
+---------------------+
| test |
+---------------------+
```
To create an AWS lambda sink connector named `test`, run the following command.
```bash theme={null}
./bin/pulsar-admin \
--admin-url "${WEB_SERVICE_URL}" \
--auth-plugin org.apache.pulsar.client.impl.auth.oauth2.AuthenticationOAuth2 \
--auth-params '{"privateKey":"file:///YOUR-KEY-FILE-PATH",
"issuerUrl":"https://auth.streamnative.cloud/",
"audience":"urn:sn:pulsar:${orgName}:${instanceName}}'
sinks create --archive builtin://aws-lambda --inputs public/default/lambda-sink-test --sink-config '{"awsRegion": "us-west-2","lambdaFunctionName": "test-hello","payloadFormat": "V2"}' --secrets '{"awsAccessKey":{"path":"lambda-sink-secret","key":"awsAccessKey"},"awsSecretKey":{"path":"lambda-sink-secret","key":"awsSecretKey"}}' --name test
```
Replace the placeholder variables with the actual values that you can get when [setting up client tools](/cloud/connect/pulsar-io/deploy-connectors/connector-setup#set-up-client-tools).
* `admin-url`: the HTTP service URL of your Pulsar cluster.
* `private_key`: the path to the downloaded OAuth2 key file.
* `audience`: the [Uniform Resource Name (URN)](/cloud/references/glossary#uniform-resource-name-urn), which is a combination of the `urn:sn:pulsar`, your organization name, and your Pulsar instance name.
* `${orgName}`: the name of your [organization](/cloud/references/glossary#organization).
* `${instanceName}`: the name of your [instance](/cloud/references/glossary#instance).
If you want to list the submitted connector for a double check, run the following command:
```bash theme={null}
./bin/pulsar-admin sinks list
```
You should see the following output:
```bash theme={null}
[
"test"
]
```
The `awsAccessKey` and `awsSecretKey` is the field name, and the `lambda-sink-secret` is the secret name you created in UI.
To reduce the complexity of your command, you can add the above parameters with values into the `conf/client.conf` file under the downloaded Pulsar release. Once it's configured, you can run a simple command instead:
```bash theme={null}
./bin/pulsar-admin sinks create --archive builtin://aws-lambda --inputs public/default/lambda-sink-test --sink-config '{"awsRegion": "us-west-2","lambdaFunctionName": "test-hello","payloadFormat": "V2"}' --secrets '{"awsAccessKey":{"path":"lambda-sink-secret","key":"awsAccessKey"},"awsSecretKey":{"path":"lambda-sink-secret","key":"awsSecretKey"}}' --name test
```
* **Add the following content to your Terraform file:**
```bash theme={null}
terraform {
required_providers {
pulsar = {
version = "0.2.0"
source = "registry.terraform.io/streamnative/pulsar"
}
}
}
provider "pulsar" {
web_service_url = "${WEB_SERVICE_URL}"
audience = "urn:sn:pulsar:${orgName}:${instanceName}"
issuer_url = "https://auth.streamnative.cloud/"
key_file_path = "file:///YOUR-KEY-FILE-PATH"
api_version = 3
}
resource "pulsar_sink" "test" {
provider = pulsar
name = "lambda-sink-test-tf"
tenant = "public"
namespace = "default"
archive = "builtin://aws-lambda"
auto_ack = true
cleanup_subscription = true
destination_topic_name = "public/default/lambda-sink-test"
processing_guarantees = "ATMOST_ONCE"
configs = "{\"awsRegion\":\"us-west-2\",\"lambdaFunctionName\":\"test-hello\",\"payloadFormat\":\"V2\"}"
secrets = "{\"awsAccessKey\":{\"path\":\"lambda-sink-secret\",\"key\":\"awsAccessKey\"},\"awsSecretKey\":{\"path\":\"lambda-sink-secret\",\"key\":\"awsSecretKey\"}}"
}
```
* **Call the following commands in your Terraform file directory:**
```bash theme={null}
terraform init
# output
Terraform has been successfully initialized!
```
```bash theme={null}
terraform apply
# output
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
+ create
Terraform will perform the following actions:
# pulsar_sink.test will be created
+ resource "pulsar_sink" "test" {
+ archive = "builtin://aws-lambda"
+ auto_ack = true
+ classname = (known after apply)
+ cleanup_subscription = true
+ configs = jsonencode(
{
+ awsRegion = "us-west-2"
+ lambdaFunctionName = "test-hello"
+ payloadFormat = "V2"
}
)
+ cpu = 1
+ disk_mb = 10240
+ id = (known after apply)
+ inputs = [
+ "public/default/lambda-sink-test",
]
+ name = "lambda-sink-test-tf"
+ namespace = "default"
+ parallelism = 1
+ processing_guarantees = "ATMOST_ONCE"
+ ram_mb = 1024
+ retain_ordering = true
+ secrets = jsonencode(
{
+ awsAccessKey = {
+ key = "awsAccessKey"
+ path = "lambda-sink-secret"
}
+ awsSecretKey = {
+ key = "awsSecretKey"
+ path = "lambda-sink-secret"
}
}
)
+ subscription_position = "Earliest"
+ tenant = "public"
}
Plan: 1 to add, 0 to change, 0 to destroy.
Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value: yes
pulsar_sink.test: Creating...
pulsar_sink.test: Creation complete after 5s [id=public/default/lambda-sink-test-tf]
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
```
The `awsAccessKey` and `awsSecretKey` is the field name, and the `lambda-sink-secret` is the secret name you created in UI.
You can use `snctl`, `pulsarctl` or `pulsar-admin` to list the source connector submitted using Terraform.
To create an AWS lambda sink connector named `test`, run the following command.
```bash theme={null}
curl -X POST https://${WEB_SERVICE_URL}/admin/v3/sinks/{tenant}/{namespace}/test \
-H 'Authorization: Bearer ' \
-H "Content-Type: multipart/form-data" \
-F 'sinkConfig={"name": "test", "tenant": "public", "namespace": "default", "archive": "builtin://aws-lambda", "inputs": ["public/default/lambda-sink-test"], "configs": {"awsRegion": "us-west-2","lambdaFunctionName": "test-hello", "payloadFormat": "V2"}, "secrets": {"awsAccessKey":{"path":"lambda-sink-secret","key":"awsAccessKey"},"awsSecretKey":{"path":"lambda-sink-secret","key":"awsSecretKey"}}};type=application/json'
```
If you want to list the submitted connector for a double check, run the following command:
```bash theme={null}
curl -X GET https://pc-ae474868.aws-use2-dixie-snc.streamnative.test.aws.sn2.dev/admin/v3/sinks/public/default \
--header 'Authorization: Bearer '
["test"]
```
The `awsAccessKey` and `awsSecretKey` is the field name, and the `lambda-sink-secret` is the secret name you created in UI.
For all the common configurations of built-in connectors, see [Configuration reference](/cloud/connect/pulsar-io/connector-config).
## Create a custom connector
Before creating a connector, it's highly recommended to do the following:
1. [Check connector availability](/cloud/connect/pulsar-io/deploy-connectors/connector-check) to ensure the version number of the connector you want to create is supported on StreamNative Cloud.
2. Go to [StreamNative Hub](/connect/overview) and find the connector-specific docs of your version for configuration reference.
To create a custom Pulsar Connector, you need to upload the connector jar/nar file to the StreamNative Cloud Package service first. Below are the steps:
### Upload your connector file to Pulsar
Upload packages
```bash theme={null}
snctl pulsar admin packages upload sink://public/default/custom-connect@v1 \
--path /tmp/your-connector.jar \
--description "custom connector" \
--properties fileName=your-connector.jar
```
You should see the following output:
```bash theme={null}
The package 'sink://public/default/custom-connect@v1' uploaded from path '/tmp/your-connector.jar' successfully
```
You can also upload your package to `source://${tenant}/${namespace}/${name}@{$version}`, currently Pulsar Package Service supports below protocols:
* `source://`
* `sink://`
* `function://`
You need to set the context for Pulsarctl first:
```bash theme={null}
# create a context
pulsarctl context set ${context-name} \
--admin-service-url ${admin-service-url} \
--issuer-endpoint ${issuerUrl} \
--audience urn:sn:pulsar:${orgName}:${instanceName} \
--key-file ${privateKey}
# activate oauth2
pulsarctl oauth2 activate
```
Replace the placeholder variables with the actual values that you can get when [setting up client tools](/cloud/process/pulsar-functions/function-setup#set-up-client-tools).
* `context-name`: any name you want
* `admin-service-url`: the HTTP service URL of your Pulsar cluster.
* `privateKey`: the path to the downloaded OAuth2 key file.
* `issuerUrl`: the URL of the OAuth2 issuer.
* `audience`: the [Uniform Resource Name (URN)](/cloud/references/glossary#uniform-resource-name-urn), which is a combination of the `urn:sn:pulsar`, your organization name, and your Pulsar instance name.
* `${orgName}`: the name of your [organization](/cloud/references/glossary#organization).
* `${instanceName}`: the name of your [instance](/cloud/references/glossary#instance).
Upload packages
```bash theme={null}
pulsarctl packages upload sink://public/default/custom-connect@v1 \
--path /tmp/your-connector.jar \
--description "custom connector" \
--properties fileName=your-connector.jar
```
You should see the following output:
```bash theme={null}
The package 'sink://public/default/custom-connect@v1' uploaded from path '/tmp/your-connector.jar' successfully
```
You can also upload your package to `source://${tenant}/${namespace}/${name}@{$version}`, currently Pulsar Package Service supports below protocols:
* `source://`
* `sink://`
* `function://`
```bash theme={null}
./bin/pulsar-admin \
--admin-url "${WEB_SERVICE_URL}" \
--auth-plugin org.apache.pulsar.client.impl.auth.oauth2.AuthenticationOAuth2 \
--auth-params '{"privateKey":"file://${privateKey}","issuerUrl":"${issuerUrl}","audience":"urn:sn:pulsar:${orgName}:${instanceName}}' \
packages upload sink://public/default/custom-connect@v1 \
--path /tmp/your-connector.jar \
--description "custom connector" \
--properties fileName=your-connector.jar
```
Replace the placeholder variables with the actual values that you can get when [setting up client tools](/cloud/process/pulsar-functions/function-setup#set-up-client-tools).
* `admin-url`: the HTTP service URL of your Pulsar cluster.
* `privateKey`: the path to the downloaded OAuth2 key file.
* `issuerUrl`: the URL of the OAuth2 issuer.
* `audience`: the [Uniform Resource Name (URN)](/cloud/references/glossary#uniform-resource-name-urn), which is a combination of the `urn:sn:pulsar`, your organization name, and your Pulsar instance name.
* `${orgName}`: the name of your [organization](/cloud/references/glossary#organization).
* `${instanceName}`: the name of your [instance](/cloud/references/glossary#instance).
You should see the following output:
```bash theme={null}
The package 'sink://public/default/custom-connect@v1' uploaded from path '/tmp/your-connector.jar' successfully
```
You can also upload your package to `source://${tenant}/${namespace}/${name}@{$version}`, currently Pulsar Package Service supports below protocols:
* `source://`
* `sink://`
* `function://`
To create a custom connector, just replace the `archive` argument to the package URL(like `sink://public/default/custom-connect@v1`) you uploaded.
# Set up Your Environment
Source: https://docs.streamnative.io/cloud/connect/pulsar-io/deploy-connectors/connector-setup
This section introduces how to set up a new service account with the minimum permissions to run connectors. To perform the following operations, you need to be the cluster administrator beforehand.
## Create a service account for Pulsar users
1. On the left navigation pane of StreamNative Cloud Console, click **Service Accounts**.
2. Click **Create Service Account**.
3. Enter a name for the service account, and then click **Confirm**.
Do **NOT** check the **Super Admin** option when creating this service account.
## Authorize the service account
To make the service account work, you need to make the service account granted with proper permissions (`sinks`, `sources`, `packages`, `produce`, and `consume`).
To grant the service account permissions on the namespace level, follow these steps:
1. Navigate to the **Namespace Dashboard** page by [switching to the namespace workspace](/cloud/get-started/cloud-console#switch-a-namespace).
2. On the **Namespace Dashboard** page, click **Configuration** on the left navigation pane.
3. On the **Namespace configuration** page, click **ADD ROLE**, and select the service account that you want to authorize.
4. On the drop-down menu below the service account, select the proper permissions to assign to the service account. There are six permissions in total:
* `consume`: allow the service account to consume messages.
* `produce`: allow the service account to publish messages.
* `functions`: allow the service account to submit and manage functions.
* `sinks`: allow the service account to create and manage sink connectors.
* `sources`: allow the service account to create and manage source connectors.
* `packages`: allow the service account to upload and manage pulsar packages. If you want to submit a customized function/connector, then you will need to upload the function/connector’s JAR/NAR/Python file first, which requires the `packages` permission.
## Grant access to the service account
To grant the underlying infrastructure with access to the newly created service account's OAuth2 key file, you need to create a service account binding via UI.
Go to the `Service Accounts` tab and choose the service account you want to use for running the connector. Clicking on the right button and there will be a `Edit service account bindings` option.
Click the `Edit service account bindings`, choose the desired pool member and confirm.
You can also enable the `Enable IAM Role Creation` option to create a separate IAM role for the service account.
Now your connector is ready to use the service account in StreamNative environments.
## (Optional) Create a separate IAM role for the service account
StreamNative's I/O components (Pulsar Functions, Pulsar Connectors, and Kafka Connectors) run as cloud-native workloads on AWS, GCP, and Azure infrastructures.
Use the cloud providers' native IAM (Identity and Access Management) services to control access to infrastructure resources such as S3, GCS, and Azure Blob Storage. This removes the need for password-based authentication for the service accounts that run connectors in StreamNative Cloud.
By default, StreamNative uses a single service account per `PulsarCluster` for all I/O components (Pulsar Functions, Pulsar Connectors, and Kafka Connectors) to access underlying infrastructure resources. This means all I/O Components in the same cluster share one service account and the same permissions.
Using a single service account for all I/O components means all functions and connectors share the same permissions. If one component is compromised, it could access resources intended for other components.
So it's better to leave the default service account with no permissions and use it for running IO components that do not require access to external resources.
And create separate service accounts with the minimum required permissions for each IO component that need to access external resources.
To enhance security and improve isolation, you can create a separate IAM role for each service account used to run connectors. This let you grant only the permissions each service account needs.
Create a separate IAM role for your service account:
This feature is available in [snctl](/tools/cli/snctl/snctl-overview) v1.3.0 or later.
1. Get the `PoolMember` name and namespace from the `PulsarCluster`
```shell theme={null}
snctl get pulsarcluster -o yaml
```
In the output, find the `poolMemberRef` block, which looks like:
```yaml theme={null}
poolMemberRef:
name:
namespace:
```
Multiple clusters may be located in the same `PoolMember`. You do not need to create separate IAM roles for each cluster within the same `PoolMember`.
2. Create a new `ServiceAccountBinding` that binds the service account to the `PoolMember`
```shell theme={null}
snctl create serviceaccountbinding \
--pool-member / \
--enable-iam-account-creation \
--service-account-name
```
**AWS only:** You can specify one or more `AWS Assume Role ARNs` that can be assumed by the IAM role created for the service account (repeat the flag for each ARN):
```shell theme={null}
snctl create serviceaccountbinding \
--pool-member / \
--enable-iam-account-creation \
--service-account-name \
--aws-assume-role-arns \
--aws-assume-role-arns
```
The IAM role created by StreamNative will include permissions to call `sts:AssumeRole` on `arn1` and `arn2`. You must still add a trust policy on `arn1` and `arn2` to allow the newly created role to assume them, an example likes below:
```json theme={null}
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::[aws-account-id]:role/StreamNative/sncloud-role/authorization.streamnative.io/iamaccounts/IamAccount-[org-id]-sab-[binding-name]"
},
"Action": "sts:AssumeRole"
}
]
}
```
3. (Optional) Update an existing `ServiceAccountBinding` to create the IAM role
```shell theme={null}
snctl edit serviceaccountbinding
```
4. Verify the IAM role was created successfully
```shell theme={null}
snctl get serviceaccountbinding -o yaml
```
Expected output (example):
```yaml theme={null}
apiVersion: cloud.streamnative.io/v1alpha1
kind: ServiceAccountBinding
metadata:
creationTimestamp: "2025-06-25T08:45:35Z"
finalizers:
- serviceaccountbinding.finalizers.cloud.streamnative.io
generation: 1
name: test-admin
namespace: o-lftqu
ownerReferences:
- apiVersion: cloud.streamnative.io/v1alpha1
kind: ServiceAccount
name: admin
uid: 4ef639aa-6278-4863-9a23-f1da50cea448
resourceVersion: "54707713"
uid: 918d40ad-551d-416b-a2ae-d41548d6608e
spec:
enableIamRoleCreation: true
poolMemberRef:
name: azure-eastus-zephyr
namespace: streamnative
serviceAccountName: admin
status:
conditions:
- lastTransitionTime: "2025-06-25T08:45:35Z"
status: "True"
type: IAMAccountReady
- lastTransitionTime: "2025-06-25T08:45:35Z"
status: "True"
type: ServiceAccountReady
- lastTransitionTime: "2025-07-16T13:56:17Z"
status: "True"
type: ResourceExists
- lastTransitionTime: "2025-07-16T13:56:17Z"
status: "True"
type: PoolMemberReady
- lastTransitionTime: "2025-07-16T13:56:17Z"
reason: AllConditionStatusTrue
status: "True"
type: Ready
```
In the output, the `status.conditions` array should include a condition with `type: IAMAccountReady` and `status: "True"`, indicating the IAM role was created successfully.
5. Use the service account when creating I/O components
You can now select this service account in Console (or use its API key with the CLI) when creating I/O components (Pulsar Functions, Pulsar Connectors, and Kafka Connectors). The components will inherit the permissions granted to the IAM role created in the previous step.
You can also create a separate IAM role for your service account via StreamNative Cloud Console. Just enable the `Enable IAM Role Creation` option when creating or editing a service account binding.
**AWS only:** You can specify one or more `AWS Assume Role ARNs` that can be assumed by the IAM role created for the service account (use one line for each ARN)
The IAM role created by StreamNative will include permissions to call `sts:AssumeRole` on `arn1` and `arn2`. You must still add a trust policy on `arn1` and `arn2` to allow the newly created role to assume them, an example likes below:
```json theme={null}
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::[aws-account-id]:role/StreamNative/sncloud-role/authorization.streamnative.io/iamaccounts/IamAccount-[org-id]-sab-[binding-name]"
},
"Action": "sts:AssumeRole"
}
]
}
```
In Azure, a Managed Identity `sab-[binding-name]-[org-id]` is created;
In AWS, an IAM role `role/StreamNative/sncloud-role/authorization.streamnative.io/iamaccounts/IamAccount-[org-id]-sab-[binding-name]` is created;
In GCP, a service account with display name: `IamAccount/[org-id]/sab-[binding-name]` is created.
## Set up client tools
### Use `snctl` to manage Pulsar IO connectors with a service account
The StreamNative CLI `snctl` includes Pulsar admin commands that connect directly to your StreamNative Cloud cluster. You can use a service account for the admin request, the connector runtime identity, or both.
1. Use `snctl config set --organization $ORG` to set your StreamNative Cloud organization.
2. Use `snctl context use` to select your target StreamNative Cloud cluster interactively.
3. To send the admin request as a service account, use `snctl pulsar admin --as-service-account $SERVICE_ACCOUNT_NAME ...` or `snctl pulsar admin --use-service-account ...`.
4. To run a connector as a service account, use `--sn-service-account $SERVICE_ACCOUNT_NAME` on `snctl pulsar admin sources create`, `snctl pulsar admin sources update`, `snctl pulsar admin sinks create`, or `snctl pulsar admin sinks update`. To select the runtime service account interactively, use `--use-sn-service-account`.
`--as-service-account` and `--sn-service-account` set different identities.
Use `--as-service-account` to send the request with the specified service account's credentials. That same service account also becomes the runtime identity of the connector. Therefore, the service account must have permissions to create or update connectors, download packages, and produce or consume messages.
Use `--sn-service-account` to keep the request authenticated as the current caller, but run the connector with the specified service account as its runtime identity. In this case, the caller must have permission to create or update the connector and use the selected service account (see [account-admin](/cloud/security/access/rbac/manage-rbac-roles#account-admin)). The runtime service account only needs the permissions required by the connector itself, such as producing or consuming messages and downloading packages.
You can use `--as-service-account` on Pulsar clusters of any supported version. The `--sn-service-account` and `--use-sn-service-account` flags require Pulsar 4.0.x version 4.0.10.6 or later, or Pulsar 4.2.x version 4.2.1.4 or later.
### Use `pulsarctl`, `pulsar-admin`, or the REST API to manage Pulsar IO connectors with a service account
StreamNative Cloud Console provides a step-by-step wizard to walk you through the basic client setup process. You can connect your Pulsar client that uses the previously created service account to interact with your Pulsar cluster.
1. On the left navigation pane of StreamNative Cloud Console, in the **Admin** section, click **Pulsar Clients**.
2. Select the **CLI Tools** tab and follow the wizard to generate the sample code you need for connecting to your Pulsar cluster. The steps may vary depending on the tool you use.
a. Select `pulsarctl`, `pulsar-admin`, or the REST API.
b. Download the selected CLI tool.
c. Select the service account you created.
d. Select **OAuth2** as the authentication type and download the key file to your local machine.
e. Set up your CLI tool with that key file, and the steps vary depending on the CLI tool you use.
f. Copy the command for setting client configurations to your terminal, update the path of the OAuth2 key file, and run it.
g. Select the target tenant, namespace and topic, and copy the sample command to run.
f. Select the target tenant, namespace and topic, and copy the sample command to your terminal and update the path of the OAuth2 key file before running.
f. Select the target tenant, namespace and topic, and copy the sample `curl` command to your terminal and update the path of the OAuth2 key file before running.
## What’s next?
* [Check connector availability](/cloud/connect/pulsar-io/deploy-connectors/connector-check)
# Deploy connectors
Source: https://docs.streamnative.io/cloud/connect/pulsar-io/deploy-connectors/deploy-connector-index
Pulsar provides a pluggable architecture for connectors, allowing you to deploy pre-built connectors and develop custom connectors for external systems, such as databases, messaging systems, block storage, cloud services, or any other system capable of producing or consuming data.
To deploy connectors on StreamNative Cloud, follow the following instructions.
* [Set up your environment](/cloud/connect/pulsar-io/deploy-connectors/connector-setup)
* [Check connector availability](/cloud/connect/pulsar-io/deploy-connectors/connector-check)
* [Create connectors](/cloud/connect/pulsar-io/deploy-connectors/connector-create)
# Connect to your cluster using Kafka Connect
Source: https://docs.streamnative.io/cloud/connect/self-host-connectors/cloud-connect-elasticsearch
* This QuickStart assumes that you have created a StreamNative cluster with the Kafka protocol enabled, created a service account, and granted the service account `produce` and `consume` permissions to a namespace for the target topic.
* This QuickStart is developed on a MAC Operating System (OS) environment. If you choose another OS, the commands might vary.
This document shows how to connect to your StreamNative cluster using [Kafka Connect](https://docs.confluent.io/platform/current/connect/index.html) with OAuth2 authentication.
## Before you begin
* Get the OAuth2 credential file.
1. On the left navigation pane, click **Service Accounts**.
2. In the row of the service account you want to use, in the **Key File** column, click the **Download** icon to download the OAuth2 credential file to your local directory.
* Get the service URL of your StreamNative cluster.
1. On the left navigation pane, in the **Admin** area, click **Pulsar Clusters**.
2. Select the **Details** tab, and in the **Access Points** area, click **Copy** at the end of the row of the **Kafka Service URL (TCP)**.
- Install a recent version of [Docker](https://docs.docker.com/get-docker/).
- [Download the `jq` CLI JSON processor](https://stedolan.github.io/jq/download/), which provides a JSON-format output.
## Configure Elasticsearch
1. Open a terminal, and run the command below to start an Elasticsearch instance with ports `9200` and `9300`.
```bash theme={null}
docker run --name elastic-1 \
-p 9200:9200 -p 9300:9300 -it \
-e "discovery.type=single-node" \
-e "xpack.security.enabled=false" \
docker.elastic.co/elasticsearch/elasticsearch:7.17.2
```
You should see the following output:
```bash theme={null}
...output omitted...
{"@timestamp":"2022-04-15T15:13:17.067Z", "log.level": "INFO", "message":"successfully loaded geoip database file [GeoLite2-Country.mmdb]", "ecs.version": "1.2.0","service.name":"ES_ECS","event.dataset":"elasticsearch.server","process.thread.name":"elasticsearch[efb7b3360ba3][generic][T#7]","log.logger":"org.elasticsearch.ingest.geoip.DatabaseNodeService","elasticsearch.cluster.uuid":"ocHgh5mAQROAlUofYHE3Cg","elasticsearch.node.id":"0aWiWmaBTgC0vdp6Zw_ZnQ","elasticsearch.node.name":"efb7b3360ba3","elasticsearch.cluster.name":"docker-cluster"}
{"@timestamp":"2022-04-15T15:13:17.118Z", "log.level": "INFO", "message":"successfully loaded geoip database file [GeoLite2-City.mmdb]", "ecs.version": "1.2.0","service.name":"ES_ECS","event.dataset":"elasticsearch.server","process.thread.name":"elasticsearch[efb7b3360ba3][generic][T#13]","log.logger":"org.elasticsearch.ingest.geoip.DatabaseNodeService","elasticsearch.cluster.uuid":"ocHgh5mAQROAlUofYHE3Cg","elasticsearch.node.id":"0aWiWmaBTgC0vdp6Zw_ZnQ","elasticsearch.node.name":"efb7b3360ba3","elasticsearch.cluster.name":"docker-cluster"}
```
2. Verify that the Elasticsearch instance is started successfully.
```bash theme={null}
curl 'http://localhost:9200'
```
You should see the following output:
```json theme={null}
{
"name": "eaf2be7fe2d6",
"cluster_name": "docker-cluster",
"cluster_uuid": "jolOS3_VRGq2-LpZbkT1kw",
"version": {
"number": "7.17.2",
"build_flavor": "default",
"build_type": "docker",
"build_hash": "de7261de50d90919ae53b0eff9413fd7e5307301",
"build_date": "2022-03-28T15:12:21.446567561Z",
"build_snapshot": false,
"lucene_version": "8.11.1",
"minimum_wire_compatibility_version": "6.8.0",
"minimum_index_compatibility_version": "6.0.0-beta1"
},
"tagline": "You Know, for Search"
}
```
## Configure Kafka Connect
[Kafka Connect](https://docs.confluent.io/platform/current/connect/index.html) is an integration tool that is released with the Apache Kafka project. It provides reliable data streaming between Apache Kafka and external systems and is both scalable and flexible. Kafka Connect works with Kafka on Pulsar (KoP), which is compatible with the Kafka API.
Kafka Connect uses Source and Sink connectors for integration. Source connectors stream data from an external system to Kafka, while Sink connectors stream data from Kafka to an external system.
1. Navigate to the [Apache downloads page for Kafka](https://www.apache.org/dyn/closer.cgi?path=/kafka/3.1.0/kafka_2.13-3.1.0.tgz), and click the suggested download link for the Kafka 3.1.0 binary package.
2. Extract the Kafka binaries folder in the `_YOUR_HOME_DIRECTORY_/kafka_2.13-3.1.0` directory that you created earlier.
### Download the StreamNative OAuth dependency
```bash theme={null}
# download supplementary libraries
curl -O https://repo1.maven.org/maven2/io/streamnative/pulsar/handlers/oauth-client/3.1.0.1/oauth-client-3.1.0.1.jar --output-dir ./libs
```
### Download the Elasticsearch Sink connector
1. Create a `connectors` folder to store all Kafka connectors.
```bash theme={null}
# switch to your kafka folder
cd kafka_2.13-3.1.0
# create a connector folder to store all Kafka connectors
mkdir connectors
```
2. Navigate to the [Elasticsearch Sink connector](https://www.confluent.io/hub/confluentinc/kafka-connect-elasticsearch) and click **Download** to download the archived binaries.
3. Extract the file and copy the unzipped folder into the `connectors` directory.
### Configure Kafka Connect
1. Create a configuration file (named `connect-sn-kop.properties`).
```bash theme={null}
# switch to your kafka folder
cd kafka_2.13-3.1.0
# create a connect configuration file
# which contains information of Kafka server (StreamNative KoP cluster)
vim conf/connect-sn-kop.properties
```
2. Add the following content to the `connect-sn-kop.properties` file.
```conf theme={null}
# add the information of StreamNative KoP cluster
bootstrap.servers="SERVER-URL"
sasl.login.callback.handler.class=io.streamnative.pulsar.handlers.kop.security.oauth.OauthLoginCallbackHandler
security.protocol=SASL_SSL
sasl.mechanism=OAUTHBEARER
sasl.jaas.config=org.apache.kafka.common.security.oauthbearer.OAuthBearerLoginModule \
required oauth.issuer.url="https://auth.streamnative.cloud/"\
oauth.credentials.url="file://YOUR-KEY-FILE-PATH"\
oauth.audience="YOUR-AUDIENCE-STRING";
producer.sasl.login.callback.handler.class=io.streamnative.pulsar.handlers.kop.security.oauth.OauthLoginCallbackHandler
producer.security.protocol=SASL_SSL
producer.sasl.mechanism=OAUTHBEARER
producer.sasl.jaas.config=org.apache.kafka.common.security.oauthbearer.OAuthBearerLoginModule \
required oauth.issuer.url="https://auth.streamnative.cloud/"\
oauth.credentials.url="file://YOUR-KEY-FILE-PATH"\
oauth.audience="YOUR-AUDIENCE-STRING";
consumer.sasl.login.callback.handler.class=io.streamnative.pulsar.handlers.kop.security.oauth.OauthLoginCallbackHandler
consumer.security.protocol=SASL_SSL
consumer.sasl.mechanism=OAUTHBEARER
consumer.sasl.jaas.config=org.apache.kafka.common.security.oauthbearer.OAuthBearerLoginModule \
required oauth.issuer.url="https://auth.streamnative.cloud/"\
oauth.credentials.url="file://YOUR-KEY-FILE-PATH"\
oauth.audience="YOUR-AUDIENCE-STRING";
#Cluster level converters
#These apply when the connectors don't define any converter
key.converter=org.apache.kafka.connect.json.JsonConverter
value.converter=org.apache.kafka.connect.json.JsonConverter
#JSON schemas enabled to false in cluster level
key.converter.schemas.enable=true
value.converter.schemas.enable=true
#Where to keep the Connect topic offset configurations
offset.storage.file.filename=/tmp/connect.offsets
offset.flush.interval.ms=10000
#Plugin path to put the connector binaries
plugin.path=YOUR-FULL-PATH/connectors/
```
* `oauth.credentials.url`: the path to your downloaded OAuth2 credential file.
* `bootstrap.servers`: the Kafka service URL of your StreamNative cluster.
* `oauth.audience`: the `audience` parameter is a combination of the `urn:sn:pulsar`, your organization name, and your Pulsar instance name.
* `key.converter` and `value.converter`: the converter that sends JSON-format messages to Kafka.
* `plugin.path`: the full path of the `connectors` folder that is created in the previous step.
For details about the security of Kafka Connect, see the [Confluent documentation](https://docs.confluent.io/platform/current/kafka/authentication_sasl/authentication_sasl_scram.html#kconnect-long).
### Configure the Elasticsearch Sink connector
Add the following content to the `elasticsearch-sink-connector.properties` file.
```conf theme={null}
name=elasticsearch-sink
connector.class=io.confluent.connect.elasticsearch.ElasticsearchSinkConnector
tasks.max=1
# Topic name to get data from
topics=test-elasticsearch-sink
key.ignore=true
# The key converter for this connector
key.converter=org.apache.kafka.connect.storage.StringConverter
# The value converter for this connector
value.converter=org.apache.kafka.connect.json.JsonConverter
# Identify if the value contains a schema.
# Required value converter is `org.apache.kafka.connect.json.JsonConverter`.
value.converter.schemas.enable=false
schema.ignore=true
# Elasticsearch server url
connection.url=http://localhost:9200
type.name=kafka-connect
```
### Run Kafka Connect
Open a new terminal and navigate to the Kafka folder, run the following command in the directory:
```bash theme={null}
cd kafka_2.13-3.1.0
bin/connect-standalone.sh config/connect-sn-kop.properties config/elasticsearch-sink-connector.properties
```
You should see the following output:
```bash theme={null}
...output omitted...
[2023-02-07 23:11:37,102] INFO [elasticsearch-sink|task-0] [Consumer clientId=connector-consumer-elasticsearch-sink-0, groupId=connect-elasticsearch-sink] Discovered group coordinator kopyhshen-broker-0-3d0a2d7c-2875-4caf-b74e-7d3260027a9a.gcp-shared-gcp-usce1-martin.streamnative.g.snio.cloud:9093 (id: 1865975191 rack: null) (org.apache.kafka.clients.consumer.internals.ConsumerCoordinator:853)
[2023-02-07 23:11:37,106] INFO [elasticsearch-sink|task-0] [Consumer clientId=connector-consumer-elasticsearch-sink-0, groupId=connect-elasticsearch-sink] (Re-)joining group (org.apache.kafka.clients.consumer.internals.ConsumerCoordinator:535)
[2023-02-07 23:11:42,233] INFO [elasticsearch-sink|task-0] [Consumer clientId=connector-consumer-elasticsearch-sink-0, groupId=connect-elasticsearch-sink] Successfully joined group with generation Generation{generationId=3, memberId='connector-consumer-elasticsearch-sink-0-1718e62d-b638-419b-8376-2ee14a19d23d', protocol='range'} (org.apache.kafka.clients.consumer.internals.ConsumerCoordinator:595)
[2023-02-07 23:11:42,237] INFO [elasticsearch-sink|task-0] [Consumer clientId=connector-consumer-elasticsearch-sink-0, groupId=connect-elasticsearch-sink] Finished assignment for group at generation 3: {connector-consumer-elasticsearch-sink-0-1718e62d-b638-419b-8376-2ee14a19d23d=Assignment(partitions=[test-elasticsearch-sink-0])} (org.apache.kafka.clients.consumer.internals.ConsumerCoordinator:652)
```
## Index data on the Elasticsearch server
This example shows how to send five JSON-format messages to the `test-elasticsearch-sink` topic. These messages will be forwarded to the local Elasticsearch server.
1. Start a Kafka producer and send five JSON-format messages to the `test-elasticsearch-sink` topic.
```bash theme={null}
echo '{"reporterId": 8824, "reportId": 10000, "content": "Was argued independent 2002 film, The Slaughter Rule.", "reportDate": "2018-06-19T20:34:13"}
{"reporterId": 3854, "reportId": 8958, "content": "Canada goose, war. Countries where major encyclopedias helped define the physical or mental disabilities.", "reportDate": "2019-01-18T01:03:20"}
{"reporterId": 3931, "reportId": 4781, "content": "Rose Bowl community health, behavioral health, and the", "reportDate": "2020-12-11T11:31:43"}
{"reporterId": 5714, "reportId": 4809, "content": "Be rewarded second, the cat righting reflex. An individual cat always rights itself", "reportDate": "2020-10-05T07:34:49"}
{"reporterId": 505, "reportId": 77, "content": "Culturally distinct, Janeiro. In spite of the crust is subducted", "reportDate": "2018-01-19T01:53:09"}' | ./bin/kafka-console-producer.sh \
--bootstrap-server "your-pulsar-service-url" \
--producer.config ./kafka.properties \
--topic test-elasticsearch-sink
```
If everything goes well, the command will exit normally and output nothing. The records are sent to an Elasticsearch index called `test-elasticsearch-sink`. The name of the index is the same as the name of the Kafka topic. By default, the Elasticsearch Sink connector creates the index with the same name.
For details about how to configure the Kafka configuration properties file, see [get started with Kafka protocol](/cloud/get-started/quickstart-kafka).
2. Verify that data is indexed on the Elasticsearch server.
```bash theme={null}
curl 'http://localhost:9200/test-elasticsearch-sink/_search' | jq
```
Ten records should be returned.
```json theme={null}
{
"took": 10,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 5,
"relation": "eq"
},
...output omitted...
{
"_index": "test-elasticsearch-sink",
"_type": "_doc",
"_id": "test-elasticsearch-sink+0+9",
"_score": 1,
"_source": {
"reportId": 4781,
"reportDate": "2020-12-11T11:31:43",
"reporterId": 3931,
"content": "Rose Bowl community health, behavioral health, and the"
}
}
]
}
}
```
3. Check the record count in the `test-elasticsearch-sink` index.
```bash theme={null}
curl 'http://localhost:9200/test-elasticsearch-sink/_count'
```
You should see the following output:
```
{"count":5,"_shards":{"total":1,"successful":1,"skipped":0,"failed":0}}
```
You can see that the number of received records is identical to the number of sent messages.
4. Verify the connectivity between Kafka and Pulsar by searching a keyword in the `test-elasticsearch-sink` index.
This example shows how to search the keyword `health` in the `test-elasticsearch-sink` index.
```bash theme={null}
curl 'http://localhost:9200/test-elasticsearch-sink/_search?q=content:health' | jq
```
You should see the following output:
```json theme={null}
{
"took": 9,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 1,
"relation": "eq"
},
"max_score": 3.2154756,
"hits": [
{
"_index": "test-elasticsearch-sink",
"_type": "_doc",
"_id": "test-elasticsearch-sink+0+11",
"_score": 3.2154756,
"_source": {
"reportId": 4781,
"reportDate": "2020-12-11T11:31:43",
"reporterId": 3931,
"content": "Rose Bowl community health, behavioral health, and the"
}
}
]
}
}
```
You can see that all records have the word `health` listed in their `content` field.
# StreamNative Cloud Console Basics
Source: https://docs.streamnative.io/cloud/get-started/cloud-console
The StreamNative Cloud Console enables you to view and manage [instances](/cloud/clusters/manage-instances/instance), [clusters](/cloud/clusters/manage-clusters/cluster), [tenants](/cloud/manage-data-streams/tenant), [namespaces](/cloud/manage-data-streams/namespace), [topics](/cloud/manage-data-streams/topic), view your account billing information, and more. This page describes some common tasks you can complete in the Cloud Console.
## Use the Cloud Console
Access the Cloud Console at the following URL:
[https://console.streamnative.cloud](https://console.streamnative.cloud)
To access the console, you will be required to sign in to your StreamNative Cloud account. If you don't have an account, you can [sign up](/cloud/security/access/resource-hierarchy/organizations#create-an-organization) for one with \$200 in credits.
## Console Layout
There are 5 elements in the Cloud Console:
* **Breadcrumb**: At the top of the console, there is a Breadcrumb-based Navigation Bar. You can use the Breadcrumb to navigate the structure of StreamNative Cloud.
* **Navigation Pane**: On the left side of the console, there is a Navigation Pane that contains the resources available to you at the current level of navigation. The resources at each level are different based on the level of navigation.
* **Main Workspace**: To the right of the Navigation Pane is the Main Workspace. This area displays the content and functionality related to the resource you've selected in the Navigation Pane, allowing you to view, manage, and interact with your chosen resources.
* **User Menu**: In the top-right corner is the User Menu. This menu contains options for managing your account settings, viewing organization details and resources, accessing documentation, and logging out. It also displays your current user information.
* **Chat Dialog**: In the bottom-right corner of the Main Workspace, you can find a Chat Dialog. This dialog allows you to interact directly with the StreamNative support team.
## Breadcrumb
Use the Breadcrumb in the StreamNative Console to navigate the structure of StreamNative Cloud. You can switch between different instances, clusters, tenants, and namespaces by selecting your desired location from the dropdown menu.
### Breadcrumb Structure
The breadcrumb contains four values that correspond to resources within a StreamNative organization:
* [Instance](/cloud/clusters/manage-instances/instance)
* [Cluster](/cloud/clusters/manage-clusters/cluster)
* [Tenant](/cloud/manage-data-streams/tenant)
* [Namespace](/cloud/manage-data-streams/namespace)
Selecting an item in the breadcrumb will take you to the corresponding workspace to work on different levels of resources. The left Navigation Pane will show different resources based on the level of navigation.
## Organization Workspace
The Organization Workspace is the landing page when you log into the StreamNative Console. It offers a comprehensive overview of your instances and users, and provides a step-by-step guide to set up and manage your first StreamNative cluster.
To return to the Organization Workspace from any level of navigation, simply click the **Organization** button located to the right of the StreamNative logo.
In the Organization Workspace, the left Navigation Pane displays the following resources:
* **Organization Dashboard**: This central hub presents an overview of your instances and users. It also guides you through the entire process of setting up and managing your first Pulsar cluster.
* **Instances**: This section allows you to view and manage all instances associated with your organization.
### Organization Dashboard
The **Organization Dashboard** page provides an overview of the instances and users, and guides you through the complete process of setting up and managing your Pulsar cluster.
For users who don't have a cluster yet, the **Organization Dashboard** page serves as a prompt for moving forward in the provisioning process. For users who already have a cluster, the **Organization Dashboard** page encourages them to broaden their usage of StreamNative Cloud.
After logging in to the StreamNative Console, you can go to the **Organization Dashboard** page by clicking it on the left navigation pane. The **Organization Dashboard** page consists of three parts:
* The **Instance** card
You can create, view, and manage your instances on this card. For details, see [work with instances](/cloud/clusters/manage-instances/instance).
* The **Users** card
You can invite, view, and manage users on this card. For details, see [work with users](/cloud/security/authentication/user-accounts).
* The **Setup guide** area
This section walks you through the basic setup and configuration process, such as adding payment methods, creating service accounts, creating your Pulsar instances and clusters, viewing your tenants and namespaces, creating your topics, setting up your client, and so on. When an operation is completed, the related checkbox is checked.
### Navigating to the Cluster Workspace
You can access the Cluster Workspace using either of these methods:
1. Utilize the Breadcrumb navigation:
* First, select your desired instance.
* Then, choose the specific cluster you want to access.
2. Direct navigation from the Instances page:
* Navigate to the **Instances** page.
* Click on the row of the instance that contains your desired cluster.
## Cluster Workspace
The Cluster Workspace is where you view and manage all the cluster-level resources, including Tenants and Secrets, and manage the cluster configuration. It also provides guides on how you can connect to the clusters using various clients, including Kafka, Pulsar, and MQTT. Additionally, it provides instructions on how to use our cloud metrics API to monitor the cluster.
### Switch a Cluster
You can use the Breadcrumb to switch to a different cluster within the same instance. If you want to switch to a different instance, you can go back to the **Organization Workspace** first and select a different instance from the dropdown menu.
### Left Navigation Pane
The left Navigation Pane displays the following resources:
* **Cluster Dashboard**: This page provides a dashboard of the cluster, including the number of topics, number of messages, number of subscriptions, storage & backlog size and throughput, and more. Additionally, it includes a details tab providing the cluster details and its access points.
* **Resources**:
* **Tenants**: This page allows you to view and manage all the tenants available in this cluster.
* **Secrets**: This page allows you to view and manage all secrets associated with your cluster.
* **Monitor**:
* **Metrics API**: This page provides instructions on how to use the metrics API to monitor the cluster.
* **Clients**:
* **Pulsar Clients**: This page provides instructions on how to connect to the cluster using Pulsar clients.
* **Kafka Clients**: This page provides instructions on how to connect to the cluster using Kafka clients.
* **MQTT Clients**: This page provides instructions on how to connect to the cluster using MQTT clients.
* **Admin**:
* **Configuration**: This page allows you to view and manage the cluster configuration.
### Navigating to the Tenant Workspace
You can access the Tenant Workspace using either of these methods:
1. Utilize the Breadcrumb navigation:
* First, select your desired instance.
* Then, choose the specific cluster that contains your desired tenant.
* Finally, click on the name of the tenant you want to access.
2. Direct navigation from the Tenants page:
* Navigate to the **Tenants** page.
* Click on the row of the tenant you want to access.
## Tenant Workspace
The Tenant Workspace is where you view and manage all the tenant-level resources, including namespaces, topics, and more. It also provides shortcuts to connect to the clusters using various clients, including Kafka, Pulsar, and MQTT.
### Switch a Tenant
You can use the **Tenant selector** in the Breadcrumb to switch to a different tenant within the same cluster. If you want to switch to a different cluster, you can use the **Cluster selector** in the Breadcrumb to navigate to a different Cluster's workspace.
### Left Navigation Pane
The left Navigation Pane of a Tenant Workspace displays the following resources:
* **Tenant Dashboard**: This page provides a dashboard of the tenant, including the number of topics, number of messages, number of subscriptions, storage & backlog size, throughput, and more.
* **Resources**:
* **Namespaces**: This page allows you to view and manage all the namespaces in this tenant.
* **Clients**:
* **Pulsar Clients**: This page provides instructions on how to connect to the cluster using Pulsar clients.
* **Kafka Clients**: This page provides instructions on how to connect to the cluster using Kafka clients.
* **MQTT Clients**: This page provides instructions on how to connect to the cluster using MQTT clients.
* **Admin**:
* **Configuration**: This page allows you to view and manage the tenant configuration.
### Navigating to the Namespace Workspace
You can access the Namespace Workspace using either of these methods:
1. Utilize the Breadcrumb navigation:
* First, select your desired instance.
* Then, choose the specific cluster that contains your desired tenant.
* Next, click on the name of the tenant you want to access.
* Finally, click on the name of the namespace you want to access.
2. Direct navigation from the Namespaces page:
* Navigate to the **Namespaces** page.
* Click on the row of the namespace you want to access.
## Namespace Workspace
The Namespace Workspace is where you view and manage all the namespace-level resources, including topics, functions, connectors, and more. It also provides shortcuts to connect to the clusters using various clients, including Kafka, Pulsar, and MQTT.
### Switch a Namespace
You can use the **Namespace selector** in the Breadcrumb to switch to a different namespace within the same tenant. If you want to switch to a different tenant, you can use the **Tenant selector** in the Breadcrumb to navigate to a different Tenant's workspace.
### Left Navigation Pane
The left Navigation Pane of a Namespace Workspace displays the following resources:
* **Namespace Dashboard**: This page provides a dashboard of the namespace, including the number of topics, number of messages, number of subscriptions, storage & backlog size, throughput, and more.
* **Resources**:
* **Topics**: This page allows you to view and manage all the topics in this namespace.
* **Connectors**: This page allows you to view and manage all the connectors in this namespace.
* **Functions**: This page allows you to view and manage all the functions in this namespace.
* **pfSQL**: This page allows you to view and manage all the pfSQL queries in this namespace.
* **Clients**:
* **Pulsar Clients**: This page provides instructions on how to connect to the cluster using Pulsar clients.
* **Kafka Clients**: This page provides instructions on how to connect to the cluster using Kafka clients.
* **MQTT Clients**: This page provides instructions on how to connect to the cluster using MQTT clients.
* **Admin**:
* **Bundles**: This page allows you to view and manage all the bundles in this namespace.
* **Configuration**: This page allows you to view and manage the namespace configuration.
## User Menu
The User Menu is located in the top-right corner of the StreamNative Console. It contains the following options:
* **Organization**: This option allows you to view and manage your organizations. You can use it to switch between organizations.
* **Organization Usage**: This page shows the billing usage of your organization, broken down by billing cycles across different billing dimensions.
* **Accounts & Accesses**: This page displays the accounts and accesses of your organization. You can access it for any account-related operations.
* **Cloud Environments**: This page is for managing the BYOC infrastructure. It is the central place for you to view and manage the [Cloud Connections](/cloud/clusters/byoc/create-cloud-connection) and [Cloud Environments](/cloud/clusters/byoc/create-cloud-environment) of your organization.
* **Billing & Payment**: This page shows the billing information of your organization, including your payment methods, invoices, and more.
* **Support**: This option allows you to submit a ticket to the StreamNative support portal.
* **Documentation**: This option provides access to the StreamNative documentation site.
* **Sign out**: This option allows you to log out of your StreamNative Cloud account.
# Quick Start for BYOC Cost Optimized Cluster
Source: https://docs.streamnative.io/cloud/get-started/quickstart-byoc-costprofile
StreamNative Cloud is a resilient, scalable, data streaming service , delivered as a fully managed Pulsar and Kafka service.
StreamNative Cloud provides multiple interfaces for management and interaction:
1. **StreamNative Cloud Console**: A user-friendly web-based interface for managing cluster resources, configuring settings, and handling billing.
2. **Command-Line Interface (CLI)**:
* [StreamNative CLI (`snctl`)](/tools/cli/snctl/snctl-overview): The unified command-line interface for deploying and managing StreamNative Cloud infrastructure and interacting directly with your Pulsar clusters and Kafka-protocol endpoints.
* [Pulsar CLI (`pulsarctl`)](/tools/cli/pulsarctl/pulsarctl-overview): For managing cluster-specific resources, such as tenants, namespaces, topics, functions, connectors, and more.
3. **REST APIs**: For programmatic access and integration with other systems.
* [StreamNative Cloud API](/api-references/cloudapi/cloud-api)
* [Pulsar Admin REST API](https://pulsar.apache.org/docs/en/admin-api-overview/)
* [Kafka Admin API](https://kafka.apache.org/documentation/#adminapi)
4. **Terraform Providers**:
* [StreamNative Terraform Provider](https://registry.terraform.io/providers/streamnative/streamnative/latest/docs)
* [Pulsar Terraform Provider](https://registry.terraform.io/providers/streamnative/pulsar/latest/docs)
These tools provide flexibility in how you interact with and manage your StreamNative Cloud environment, catering to different user preferences and use cases.
[Sign up for StreamNative Cloud](https://console.streamnative.cloud/?defaultMethod=signup) and get \$200 of free credits. No credit card required.
This quick start guides you through getting started with StreamNative [BYOC](/cloud/clusters/cluster-types#byoc-clusters). It demonstrates how to use a StreamNative BYOC cluster to create topics, produce data to the cluster, and consume data from it.
This QuickStart assumes you are familiar with the [basics concepts of StreamNative Cloud Clusters](/cloud/clusters/streamnative-cluster-overview).
## Prerequisites
* Access to [StreamNative Cloud](https://console.streamnative.cloud/?defaultMethod=signup).
* Internet connectivity.
* Access to Your AWS Account for provisioning the BYOC infrastructure.
* Install [Java 17](https://www.oracle.com/java/technologies/downloads/#java17). For details, see [overview of JDK installation](https://docs.oracle.com/en/java/javase/17/install/overview-jdk-installation.html).
* Install Maven. For details, see [installing Apache Maven](https://maven.apache.org/install.html).
## Step 1: Sign up
If you have an email account configured for using Single Sign-On (SSO) with StreamNative Cloud, use that email address and password when signing up.
To sign up, navigate to the [StreamNative Cloud Console signup page](https://console.streamnative.cloud/?defaultMethod=signup). Follow the prompts to create an account.
After you click **Finish**, you might have to wait briefly for your first organization to be created. After your new organization is created, continue on to creating your first instance and cluster.
## Step 2: Grant StreamNative Vendor Access
Before deploying a StreamNative cluster within your cloud account, you must first grant StreamNative vendor access. Follow the instructions in [Account Access for BYOC on AWS](/cloud/clusters/byoc/grant-vendor-access/byoc-on-aws/byoc-aws-access#provision-aws-access) to provision AWS access for StreamNative Cloud. This step ensures StreamNative has the necessary permissions to manage resources in your AWS account.
Once completed, please note the account ID of the AWS account you have granted access to StreamNative Cloud. You will use this account ID to create a Cloud Connection.
## Step 3: Create a Cloud Connection
1. In the upper-right corner of the StreamNative Cloud Console, click your Profile and select **Cloud Environments**.
2. Select **Cloud Connections** tab and click **New Cloud Connection**.
3. In the **Create connection** dialog, enter the following information:
* **Name**: Enter a name for the cloud connection. For example, `my-aws-connection`.
* **Connection provider**: Select **AWS** as the connection provider.
* **AWS Account ID**: Enter the account ID of the AWS account you noted in the previous step.
* Check **Confirm if vendor access Terraform module is executed**.
4. Click **Submit**.
5. The cloud connection creation process will start. Once completed, you can see the status of the cloud connection turned to `Connected` in the **Cloud Connections** tab.
## Step 4: Create a Cloud Environment
Once you have created a cloud connection, you can create a cloud environment and provision a BYOC instance.
1. Navigate to [Organization Dashboard](/cloud/get-started/cloud-console#organization-dashboard).
2. Select **Instances** at the left navigation pane.
3. On the **Instances** page, click **+ New Instance**.
4. On the **Choose the deployment type for your instance** page, click **Deploy BYOC**.
5. You will see a dialog "Cloud Environment required". Click **Create** button to create a cloud environment.
6. On the **Cloud Connection** page, select the cloud connection you created in the previous step. In this case, it is `my-aws-connection`. Then click **Environment setup**.
7. Then fill out the information for the cloud environment.
* **Region**: Select the region where you want to deploy the BYOC cluster. In this example, it is `us-west-2`.
* **Environment tag**: Enter a tag for the cloud environment. For example, `poc`.
* **Configure StreamNative Managed VPC Network**:
* **Network CIDR**: By default, it creates a StreamNative Managed VPC with a CIDR of `10.0.0.0/16`. If you need to specify a different CIDR, you can enter it here.
* **Default Gateway**: You can configure how do you want to expose your BYOC cluster, whether it is **public** or **private**. By default, it is **public**.
8. Click **Create**.
The provisioning process of a cloud environment usually takes about 40 minutes to complete. You can safely close the page and come back later. You will also receive an email notification when the cloud environment is ready.
For more information about provisioning BYOC infrastructure, see [Provision BYOC Infrastructure](/cloud/clusters/byoc/byoc-overview).
## Step 5: Create a StreamNative Instance & Cluster
Once the cloud environment is ready, you can create a Pulsar instance.
1. Navigate to [Organization Dashboard](/cloud/get-started/cloud-console#organization-dashboard).
2. Select **Instances** at the left navigation pane.
3. On the **Instances** page, click **+ New Instance**.
4. On the **Choose the deployment type for your instance** page, click **Deploy BYOC** again. You will not see the dialog "Cloud Environment required" this time.
5. On the **Instance Configuration** page, fill out the information for the Pulsar instance. Then, click **Cluster Location** to start the cluster creation process.
* **Instance Name**: Enter a name for the instance. For example, `my-instance`.
* **Cloud Connection**: Select the cloud connection you created in the previous step. In this example, it is `my-aws-connection`.
6. On the **Cluster Location** page, fill out the information for the cluster.
* **Cluster Name**: Enter a name for the cluster. For example, `my-cluster`.
* **Cloud Environment**: Select the cloud environment you created in the previous step. In this example, it is `aws-usw2-poc-`.
* **Cluster Profile**: Select the cluster profile. In this example, it is 'Cost Optimized'
* **Availability Zone**: Select the Availability Zone. In this example, it is 'Multi AZ'
7. Click **Cluster Size** to configure the cluster size.
* You can use the slider to adjust the throughput accordingly.
* You can also manually configure the number of brokers and its corresponding resources in the **Advanced** section.
* There is no bookie in the cluster based on Cost Optimized profile.
At the right navigation pane, you can see the estimated cost for the cluster.
8. Click **Finish** to start the cluster creation process.
The cluster page appears, displaying the cluster creation process. Depending on the chosen cloud provider and other settings, it may take several minutes to provision the cluster.
Once the cluster has been provisioned, the page will show "Cluster Provisioned successfully" and you can click **Go To The Dashboard** to access the **Cluster Dashboard** page.
Now you can get started configuring apps and data on your new cluster.
## Step 6: Create a service account
To interact with your cluster by producing and consuming messages, you need to set up authentication and authorization. This is done by creating a [Service Account](/cloud/security/authentication/service-accounts/service-accounts), which serves as an identity for authenticating and authorizing access to the cluster. The service account will provide the necessary credentials for your applications to securely connect and perform operations on the Pulsar cluster.
1. In the upper-right corner of the StreamNative Cloud Console, click your Profile and select **Accounts & Accesses**.
2. On the left navigation pane, click **Service Accounts**.
3. On the **Service Account** page, click **+ New**.
4. On the **Create Service Account** dialog, enter a name for the service account, and then click **Confirm**.
5. On the **Service Account** page, in the row of the service account you just created, click the **...** icon, and select **Create API Key** in the dropdown menu.
6. On the **New API Key** dialog:
* Enter a name for the API key
* Set the expiration date
* Select the instance you created in previous step
* Write a description for the API key
* Click **Confirm**
An API key and associated secret apply to the active StreamNative instance. If you add a new instance, you must create a new API key for producers and consumers on the new Pulsar instance. For more information, see [Use API Keys to Authenticate to StreamNative Cloud](/cloud/security/authentication/service-accounts/use-api-keys/api-keys-overview).
7. After the API key is created, you can see the API key shown in the **New API Key** dialog. Click the **Copy and close** button to copy the API key to your clipboard. **Please note that you cannot retrieve the API key later after closing the dialog.**
## Step 7: Create Tenant and Namespace, and Authorize the Service Account
After creating the service account and obtaining the API key, the next crucial step is to authorize the service account. This process grants the necessary permissions for the service account to interact with your StreamNative Cloud cluster.
Authorization involves setting up Access Control Lists (ACLs) that define what actions the service account can perform. Typically, you'll want to grant permissions for producing and consuming messages on specific topics or namespaces.
For more information about authorization, see [Authorization and ACLs](/cloud/security/access/access-control-lists/authorization-and-acls).
1. Go back to the **Cluster Dashboard** page.
2. On the left navigation pane, click **Instances**.
3. On the **Instances** page, click the name of the instance you created in Step 2.
4. On the **Cluster Dashboard** page, click **Tenants** on the left navigation pane.
5. On the **Tenants** page, click **+ New Tenant**.
6. On the **New Tenant** dialog:
* Enter a name for the tenant
* Select your user account as the **Admin role**
* Select the cluster created in Step 2 as **Allowed clusters**
* Click **Confirm**
7. On the **Tenants** page, click the name of the tenant you just created. You will be directed to the **Tenant Dashboard** page.
8. On the **Tenant Dashboard** page, click **Namespaces** on the left navigation pane.
9. On the **Namespaces** page, click **New Namespace**.
10. On the **New Namespace** dialog:
* Enter a name for the namespace
* Select the cluster created in Step 2 as **Allowed clusters** and **Replication clusters**
* Click **Confirm**
11. On the **Namespaces** page, click the name of the namespace you just created. You will be directed to the **Namespace Dashboard** page.
12. On the **Namespace Dashboard** page, click **Configuration** on the left navigation pane.
13. On the **Namespace configuration** page, click **ADD ROLE**. Select the name of the service account you just created, and choose the **consume** and **produce** permissions. This grants your service account the `produce` and `consume` permissions for this namespace.
## Step 8: Grant permission to access Kafka Schema Registry
This quick start uses AVRO to produce the message. You need to grant the service account to access the Kafka Schema registry.
You can do this by granting the service account the `produce` permission to the `public/__kafka_schemaregistry/__schema-registry` topic. This is required because the current implementation of Kafka Schema Registry uses this topic's ACL to authorize access to the schema registry.
1. Navigate to the **Namespace Dashboard** page of `public / __kafka_schemaregistry` namepsace.
2. On the left navigation pane, click **Topics**.
3. On the **Topics** page, click the topic `__schema-registry`.
4. On the topic details page, click **Policy** tab.
5. Click **+ Add** button and, in the dropdown menu, select the name of the service account you just created and choose the **produce** permission.
Now you have created a tenant, namespace, and granted the service account the `produce` and `consume` permissions for this namespace. You also grant the service account permission to access the Kafka Schema Registry. You can now continue on to building a Python app, connecting to the cluster, and producing and consuming messages.
## Step 9: Produce and consume messages
This QuickStart provides you with an example Java app to get you up and running with consuming and producing messages. This is a simple example and is not intended for production environments.
### Create a producer/consumer
1. Return to the StreamNative Cloud Console and go to the "Cluster Dashboard" page.
2. On the left navigation pane, click **Kafka Clients**.
3. On the **Kafka client setup** page, click the **Code libraries** tab, follow the setup wizard to get the sample codes for your producer and consumer.
a. Select **Java** as the client library and click **Next**.
b. Select the service account you created and click **Next**.
c. Select **API Key** as the authentication type and click **Next**. If you already have an API key, you can use the API key noted in Step 6. Otherwise, you can create a new API key.
d. Check **Kafka Schema Registry** and click **Next**.
d. Copy the required dependencies to your `pom.xml` file, and click **Next**.
e. Select the target tenant, namespace, topic, and subscription.
f. You are now ready to copy the auto-generated sample codes.
4. Build your project.
a. Create a new file named `pom.xml` and add the following content:
```xml theme={null}
4.0.0
org.example
kafka-examples
1.0-SNAPSHOT
jar
2.17.1
UTF-8
UTF-8
org.apache.kafka
kafka-clients
3.4.0
io.confluent
kafka-avro-serializer
7.5.0
io.streamnative.pulsar.handlers
oauth-client
3.1.0.4
org.apache.kafka
kafka-streams
3.4.0
org.apache.logging.log4j
log4j-slf4j-impl
${log4j.version}
org.apache.logging.log4j
log4j-core
${log4j.version}
org.slf4j
slf4j-log4j12
1.7.30
confluent
https://packages.confluent.io/maven/
```
b. Create a folder `src/main/java/org/example`.
c. Under `src/main/java/org/example`, create a file named `SNCloudTokenProducer.java`. Copy and paste the producer code to this file.
d. Under `src/main/java/org/example`, create a file named `SNCloudTokenConsumer.java`. Copy and paste the consumer code to this file.
e. In both files, replace **``** with the API key you copied from the Service Account page.
c. Go to the root folder of your project and run the following command to build your project:
```bash theme={null}
mvn clean install
```
### Run the clients to produce and consume your first message
1. Open a terminal window, navigate to the root folder of your project, and run the following command:
```bash theme={null}
mvn exec:java -Dexec.mainClass="org.example.SNCloudTokenConsumer"
```
2. Open a second terminal window, navigate to the root folder of your project, and run the following command:
```bash theme={null}
mvn exec:java -Dexec.mainClass="org.example.SNCloudTokenProducer"
```
You will see a message like the following:
```bash theme={null}
Send hello to -0@0
```
3. Return to the first terminal window. You should see the following:
```bash theme={null}
Receive record: {"name": "jwt-sr", "age": 20} from -0@0
```
You can continue to produce and consume messages by repeating the above steps.
For example, you can run the producer in a loop to produce 100 messages:
```bash theme={null}
for i in {1..100}; do
mvn exec:java -Dexec.mainClass="org.example.SNCloudTokenProducer"
done
```
## Step 10: Check the storage bucket
Since the Cost Optimized Profile currently uses S3 as the storage layer, you can check the storage bucket to verify the data is persisted.
1. Navigate to the **Cluster Dashboard** page.
2. Click **Details** tab.
3. On the **Details** page, you can find the S3 bucket name listed in the **Storage Bucket** field under the **Access Points** section.
4. Navigate to your AWS account and check the S3 bucket to verify the data is persisted.
5. You should be able to see the data persisted in the S3 bucket under folder `---ursa`. There are two sub folders: `storage` and `compaction`. The `storage` folder contains the raw WAL files and the `compaction` folder contains the compacted lakehouse tables. Those lakehouse tables are organized by `//`.
## Step 11: Query the compacted lakehouse tables using DuckDB
1. Install DuckDB. For details, see [DuckDB Installation](https://duckdb.org/docs/installation).
2. Run DuckDB.
```bash theme={null}
duckdb
```
3. Load the lakehouse table into DuckDB.
```sql theme={null}
CREATE SECRET (
TYPE S3,
PROVIDER CREDENTIAL_CHAIN
);
```
```sql theme={null}
SELECT COUNT(*) FROM delta_scan('s3://path/to/compacted/lakehouse/table')
```
You should be able to see the output like the following:
```sql theme={null}
┌──────────────┐
│ count_star() │
│ int64 │
├──────────────┤
│ 101 │
└──────────────┘
```
## Next steps
* After you have successfully provisioned a **BYOC** cluster and connected to the cluster, you can learn more about working with StreamNative Cloud by reading through [Cloud Console basics](/cloud/get-started/cloud-console).
* If you want to learn more about Kafka and StreamNative Cloud, take our developer courses at the [StreamNative Developer Portal](https://streamnative.io/dev-portal).
# Quick Start for BYOC Latency Optimized Cluster
Source: https://docs.streamnative.io/cloud/get-started/quickstart-byoc-latencyprofile
StreamNative Cloud is a resilient, scalable, data streaming service , delivered as a fully managed Pulsar and Kafka service.
StreamNative Cloud provides multiple interfaces for management and interaction:
1. **StreamNative Cloud Console**: A user-friendly web-based interface for managing cluster resources, configuring settings, and handling billing.
2. **Command-Line Interface (CLI)**:
* [StreamNative CLI (`snctl`)](/tools/cli/snctl/snctl-overview): The unified command-line interface for deploying and managing StreamNative Cloud infrastructure and interacting directly with your Pulsar clusters and Kafka-protocol endpoints.
* [Pulsar CLI (`pulsarctl`)](/tools/cli/pulsarctl/pulsarctl-overview): For managing cluster-specific resources, such as tenants, namespaces, topics, functions, connectors, and more.
3. **REST APIs**: For programmatic access and integration with other systems.
* [StreamNative Cloud API](/api-references/cloudapi/cloud-api)
* [Pulsar Admin REST API](https://pulsar.apache.org/docs/en/admin-api-overview/)
* [Kafka Admin API](https://kafka.apache.org/documentation/#adminapi)
4. **Terraform Providers**:
* [StreamNative Terraform Provider](https://registry.terraform.io/providers/streamnative/streamnative/latest/docs)
* [Pulsar Terraform Provider](https://registry.terraform.io/providers/streamnative/pulsar/latest/docs)
These tools provide flexibility in how you interact with and manage your StreamNative Cloud environment, catering to different user preferences and use cases.
[Sign up for StreamNative Cloud](https://console.streamnative.cloud/?defaultMethod=signup) and get \$200 of free credits. No credit card required.
This quick start guides you through getting started with StreamNative [BYOC](/cloud/clusters/cluster-types#byoc-clusters). It demonstrates how to use a StreamNative BYOC cluster to create topics, produce data to the cluster, and consume data from it.
This QuickStart assumes you are familiar with the [basics concepts of StreamNative Cloud Clusters](/cloud/clusters/streamnative-cluster-overview).
## Prerequisites
* Access to [StreamNative Cloud](https://console.streamnative.cloud/?defaultMethod=signup).
* Internet connectivity.
* Access to Your AWS Account for provisioning the BYOC infrastructure.
* Ensure you have installed Python 3.0 or higher versions and the Pulsar Python client.
```bash theme={null}
python -m pip install pulsar-client
```
## Step 1: Sign up
If you have an email account configured for using Single Sign-On (SSO) with StreamNative Cloud, use that email address and password when signing up.
To sign up, navigate to the [StreamNative Cloud Console signup page](https://console.streamnative.cloud/?defaultMethod=signup). Follow the prompts to create an account.
After you click **Finish**, you might have to wait briefly for your first organization to be created. After your new organization is created, continue on to creating your first instance and cluster.
## Step 2: Grant StreamNative Vendor Access
Before deploying a StreamNative cluster within your cloud account, you must first grant StreamNative vendor access. Follow the instructions in [Account Access for BYOC on AWS](/cloud/clusters/byoc/grant-vendor-access/byoc-on-aws/byoc-aws-access#provision-aws-access) to provision AWS access for StreamNative Cloud. This step ensures StreamNative has the necessary permissions to manage resources in your AWS account.
Once completed, please note the account ID of the AWS account you have granted access to StreamNative Cloud. You will use this account ID to create a Cloud Connection.
## Step 3: Create a Cloud Connection
1. In the upper-right corner of the StreamNative Cloud Console, click your Profile and select **Cloud Environments**.
2. Select **Cloud Connections** tab and click **New Cloud Connection**.
3. In the **Create connection** dialog, enter the following information:
* **Name**: Enter a name for the cloud connection. For example, `my-aws-connection`.
* **Connection provider**: Select **AWS** as the connection provider.
* **AWS Account ID**: Enter the account ID of the AWS account you noted in the previous step.
* Check **Confirm if vendor access Terraform module is executed**.
4. Click **Submit**.
5. The cloud connection creation process will start. Once completed, you can see the status of the cloud connection turned to `Connected` in the **Cloud Connections** tab.
## Step 4: Create a Cloud Environment
Once you have created a cloud connection, you can create a cloud environment and provision a BYOC instance.
1. Navigate to [Organization Dashboard](/cloud/get-started/cloud-console#organization-dashboard).
2. Select **Instances** at the left navigation pane.
3. On the **Instances** page, click **+ New Instance**.
4. On the **Choose the deployment type for your instance** page, click **Deploy BYOC**.
5. You will see a dialog "Cloud Environment required". Click **Create** button to create a cloud environment.
6. On the **Cloud Connection** page, select the cloud connection you created in the previous step. In this case, it is `my-aws-connection`. Then click **Environment setup**.
7. Then fill out the information for the cloud environment.
* **Region**: Select the region where you want to deploy the BYOC cluster. In this example, it is `us-west-2`.
* **Environment tag**: Enter a tag for the cloud environment. For example, `poc`.
* **Configure StreamNative Managed VPC Network**:
* **Network CIDR**: By default, it creates a StreamNative Managed VPC with a CIDR of `10.0.0.0/16`. If you need to specify a different CIDR, you can enter it here.
* **Default Gateway**: You can configure how do you want to expose your BYOC cluster, whether it is **public** or **private**. By default, it is **public**.
8. Click **Create**.
The provisioning process of a cloud environment usually takes about 40 minutes to complete. You can safely close the page and come back later. You will also receive an email notification when the cloud environment is ready.
For more information about provisioning BYOC infrastructure, see [Provision BYOC Infrastructure](/cloud/clusters/byoc/byoc-overview).
## Step 5: Create a StreamNative Instance & Cluster
Once the cloud environment is ready, you can create a Pulsar instance.
1. Navigate to [Organization Dashboard](/cloud/get-started/cloud-console#organization-dashboard).
2. Select **Instances** at the left navigation pane.
3. On the **Instances** page, click **+ New Instance**.
4. On the **Choose the deployment type for your instance** page, click **Deploy BYOC** again. You will not see the dialog "Cloud Environment required" this time.
5. On the **Instance Configuration** page, fill out the information for the Pulsar instance. Then, click **Cluster Location** to start the cluster creation process.
* **Instance Name**: Enter a name for the Pulsar instance. For example, `my-pulsar-instance`.
* **Cloud Connection**: Select the cloud connection you created in the previous step. In this example, it is `my-aws-connection`.
6. On the **Cluster Location** page, fill out the information for the cluster.
* **Cluster Name**: Enter a name for the cluster. For example, `my-byoc-cluster`.
* **Cloud Environment**: Select the cloud environment you created in the previous step. In this example, it is `aws-usw2-poc-`.
* **Cluster Profile**: Select the cluster profile. In this example, it is 'Latency Optimized'
* **Availability Zone**: Select the Availability Zone. In this example, it is 'Multi AZ'
7. Click **Cluster Operations** to choose the release channel for the cluster and configure the cluster.
* **Release Channel**: Select the release channel for the cluster. In this example, it is `LTS`.
* **Features**: Select the features for the cluster. You can keep the default features or customize it.
* **Maintenance Window**: If you have a Enterprise or Production support plan, you can customize the maintenance window for the cluster. Otherwise, you can skip this step.
* **Custom Configuration**: If you need to customize the cluster configuration, you can expand the **Add optional custom configuration** section.
8. Click **Cluster Size** to configure the cluster size.
* You can use the slider to adjust the throughput accordingly.
* You can also manually configure the number of brokers, bookies, and their corresponding resources in the **Advanced** section.
At the right navigation pane, you can see the estimated cost for the cluster.
9. Click **Finish** to start the cluster creation process.
The cluster page appears, displaying the cluster creation process. Depending on the chosen cloud provider and other settings, it may take several minutes to provision the cluster.
Once the cluster has been provisioned, the page will show "Cluster Provisioned successfully" and you can click **Go To The Dashboard** to access the **Cluster Dashboard** page.
Now you can get started configuring apps and data on your new cluster.
## Step 6: Create a service account
To interact with your cluster by producing and consuming messages, you need to set up authentication and authorization. This is done by creating a [Service Account](/cloud/security/authentication/service-accounts/service-accounts), which serves as an identity for authenticating and authorizing access to the cluster. The service account will provide the necessary credentials for your applications to securely connect and perform operations on the Pulsar cluster.
1. In the upper-right corner of the StreamNative Cloud Console, click your Profile and select **Accounts & Accesses**.
2. On the left navigation pane, click **Service Accounts**.
3. On the **Service Account** page, click **+ New**.
4. On the **Create Service Account** dialog, enter a name for the service account, and then click **Confirm**.
5. On the **Service Account** page, in the row of the service account you just created, click the **...** icon, and select **Create API Key** in the dropdown menu.
6. On the **New API Key** dialog:
* Enter a name for the API key
* Set the expiration date
* Select the instance you created in previous step
* Write a description for the API key
* Click **Confirm**
An API key and associated secret apply to the active StreamNative instance. If you add a new instance, you must create a new API key for producers and consumers on the new Pulsar instance. For more information, see [Use API Keys to Authenticate to StreamNative Cloud](/cloud/security/authentication/service-accounts/use-api-keys/api-keys-overview).
7. After the API key is created, you can see the API key shown in the **New API Key** dialog. Click the **Copy and close** button to copy the API key to your clipboard. **Please note that you cannot retrieve the API key later after closing the dialog.**
## Step 7: Create Tenant and Namespace, and Authorize the Service Account
After creating the service account and obtaining the API key, the next crucial step is to authorize the service account. This process grants the necessary permissions for the service account to interact with your StreamNative Cloud cluster.
Authorization involves setting up Access Control Lists (ACLs) that define what actions the service account can perform. Typically, you'll want to grant permissions for producing and consuming messages on specific topics or namespaces.
For more information about authorization, see [Authorization and ACLs](/cloud/security/access/access-control-lists/authorization-and-acls).
1. Go back to the **Cluster Dashboard** page.
2. On the left navigation pane, click **Instances**.
3. On the **Instances** page, click the name of the instance you created in Step 2.
4. On the **Cluster Dashboard** page, click **Tenants** on the left navigation pane.
5. On the **Tenants** page, click **+ New Tenant**.
6. On the **New Tenant** dialog:
* Enter a name for the tenant
* Select your user account as the **Admin role**
* Select the cluster created in Step 2 as **Allowed clusters**
* Click **Confirm**
7. On the **Tenants** page, click the name of the tenant you just created. You will be directed to the **Tenant Dashboard** page.
8. On the **Tenant Dashboard** page, click **Namespaces** on the left navigation pane.
9. On the **Namespaces** page, click **New Namespace**.
10. On the **New Namespace** dialog:
* Enter a name for the namespace
* Select the cluster created in Step 2 as **Allowed clusters** and **Replication clusters**
* Click **Confirm**
11. On the **Namespaces** page, click the name of the namespace you just created. You will be directed to the **Namespace Dashboard** page.
12. On the **Namespace Dashboard** page, click **Configuration** on the left navigation pane.
13. On the **Namespace configuration** page, click **ADD ROLE**. Select the name of the service account you just created, and choose the **consume** and **produce** permissions. This grants your service account the `produce` and `consume` permissions for this namespace.
Now you have created a tenant, namespace, and granted the service account the `produce` and `consume` permissions for this namespace. You can now continue on to building a Python app, connecting to the cluster, and producing and consuming messages.
## Step 8: Produce and consume messages
This QuickStart provides you with an example Python app to get you up and running with consuming and producing messages. This is a simple example and is not intended for production environments.
### Create a producer/consumer
1. Return to the StreamNative Cloud Console and go to the "Cluster Dashboard" page.
2. On the left navigation pane, click **Pulsar Clients**.
3. On the **Pulsar client setup** page, click the **Code libraries** tab, follow the setup wizard to get the sample codes for your producer and consumer.
a. Select **Python** as the client library and click **Next**.
b. Select the service account you created and click **Next**.
c. Select **API Key** as the authentication type and click **Next**.
d. Install `pulsar-client` python client library.
```bash theme={null}
pip3 install pulsar-client
```
e. Select the target tenant, namespace, topic, and subscription.
f. You are now ready to copy the auto-generated sample codes.
4. Return to your text editor and create two new files: `producer.py` and `consumer.py`. Copy and paste the sample code for the producer into `producer.py` and the sample code for the consumer into `consumer.py`. In both files, replace **``** with the API key you copied from the Service Account page.
### Run the clients to produce and consume your first message
1. Open a terminal window, navigate to the folder containing the `consumer.py` file, and run the following command:
```bash theme={null}
python3 consumer.py
```
2. Open a second terminal window, navigate to the folder containing the `producer.py` file, and run the following command:
```bash theme={null}
python3 producer.py
```
3. Return to the first terminal window. You should see the following:
```bash theme={null}
Received message 'Hello-0' id=''
Received message 'Hello-1' id=''
Received message 'Hello-2' id=''
Received message 'Hello-3' id=''
Received message 'Hello-4' id=''
Received message 'Hello-5' id=''
Received message 'Hello-6' id=''
Received message 'Hello-7' id=''
Received message 'Hello-8' id=''
Received message 'Hello-9' id=''
```
You have now produced and consumed your first 10 messages.
## Next steps
* After you have successfully provisioned a **BYOC** cluster and connected to the cluster, you can learn more about working with StreamNative Cloud by reading through [Cloud Console basics](/cloud/get-started/cloud-console).
* If you want to learn more about Pulsar, Kafka, and StreamNative Cloud, take our developer courses at the [StreamNative Developer Portal](https://streamnative.io/dev-portal).
# Quick Start for StreamNative Cloud
Source: https://docs.streamnative.io/cloud/get-started/quickstart-console
StreamNative Cloud is a resilient, scalable, data streaming service , delivered as a fully managed Pulsar and Kafka service.
StreamNative Cloud provides multiple interfaces for management and interaction:
1. **StreamNative Cloud Console**: A user-friendly web-based interface for managing cluster resources, configuring settings, and handling billing.
2. **Command-Line Interface (CLI)**:
* [StreamNative CLI (`snctl`)](/tools/cli/snctl/snctl-overview): The unified command-line interface for deploying and managing StreamNative Cloud infrastructure and interacting directly with your Pulsar clusters and Kafka-protocol endpoints.
* [Pulsar CLI (`pulsarctl`)](/tools/cli/pulsarctl/pulsarctl-overview): For managing cluster-specific resources, such as tenants, namespaces, and topics.
3. **REST APIs**: For programmatic access and integration with other systems.
* [StreamNative Cloud API](/api-references/cloudapi/cloud-api)
* [Pulsar Admin REST API](https://pulsar.apache.org/docs/en/admin-api-overview/)
* [Kafka Admin API](https://kafka.apache.org/documentation/#adminapi)
These tools provide flexibility in how you interact with and manage your StreamNative Cloud environment, catering to different user preferences and use cases.
[Sign up for StreamNative Cloud](https://console.streamnative.cloud/?defaultMethod=signup) and get \$200 of free credits. No credit card required.
This quick start guides you through getting started with StreamNative Cloud using a [Serverless cluster](/cloud/clusters/cluster-types#serverless-clusters). It demonstrates how to use StreamNative Cloud to create topics, produce data to the cluster, and consume data from it.
This QuickStart assumes you are familiar with the [basics concepts of Apache Pulsar](/cloud/references/glossary).
## Prerequisites
* Access to [StreamNative Cloud](https://console.streamnative.cloud/?defaultMethod=signup).
* Internet connectivity.
* Ensure you have installed Python 3.0 or higher versions and the Pulsar Python client.
```bash theme={null}
python -m pip install pulsar-client
```
## Step 1: Sign up
If you have an email account configured for using Single Sign-On (SSO) with StreamNative Cloud, use that email address and password when signing up.
To sign up, navigate to the [StreamNative Cloud Console login page](https://console.streamnative.cloud/?defaultMethod=signup). Follow the prompts to create an account.
After you click **Finish**, you might have to wait briefly for your first organization to be created.
After your new organization is created, continue on to creating your first instance and cluster.
## Step 2: Create a StreamNative instance and cluster
You first need to create an [instance](/cloud/references/glossary#instance) and a [cluster](/cloud/references/glossary#cluster).
1. In the upper-right corner of the StreamNative Cloud Console, click your Profile and select **Organizations** to list your created organizations.
2. Click the name of your first organization. In the figure below, the organization name is `Demos`.
3. On the **Select an Instance** card of the **Organization Dashboard** page, click the `+` button.
4. On the **Choose the deployment type for your instance**, click **Deploy Serverless** to start the instance creation process.
5. On the **Instance Configuration** page, enter a name for your instance, and select a Cloud Provider. The instance name starts with a lowercase letter, contains any combination of lowercase letters (a-z), numbers (0-9), and hyphens (-), and must be 4-10 characters.
6. Click **Cluster Location** to start the cluster creation process.
7. On the **Cluster Location** page, enter a name for your cluster, select the cluster location, and then click **Finish**. The cluster name starts with a lowercase letter, contains any combination of lowercase letters (a-z), numbers (0-9), and hyphens (-), and must be 4-10 characters.
The cluster page appears, displaying the cluster creation process. Depending on the chosen cloud provider and other settings, it may take a few seconds to several minutes to provision the cluster. Once the cluster has been provisioned, the **Cluster Dashboard** page will be displayed.
Now you can get started configuring apps and data on your new cluster.
## Step 3: Create a service account
To interact with your cluster by producing and consuming messages, you need to set up authentication and authorization. This is done by creating a [Service Account](/cloud/security/authentication/service-accounts/service-accounts), which serves as an identity for authenticating and authorizing access to the cluster. The service account will provide the necessary credentials for your applications to securely connect and perform operations on the Pulsar cluster.
Currently, you can't edit a service account. If you need a service account to have Super Admin access, make sure to enable it when creating the service account. By default, service accounts do not have Super Admin enabled.
1. In the upper-right corner of the StreamNative Cloud Console, click your Profile and select **Accounts & Accesses**.
2. On the left navigation pane, click **Service Accounts**.
3. On the **Service Account** page, click **+ New Service Account**.
4. On the **Create Service Account** dialog, enter a name for the service account, and then click **Confirm**.
5. On the **Service Account** page, in the row of the service account you just created, click the **...** icon, and select **Create API Key** in the dropdown menu.
6. On the **New API Key** dialog:
* Enter a name for the API key
* Set the expiration date
* Select the instance you created in Step 2
* Write a description for the API key
* Click **Confirm**
An API key and associated secret apply to the active StreamNative instance. If you add a new instance, you must create a new API key for producers and consumers on the new Pulsar instance. For more information, see [Use API Keys to Authenticate to StreamNative Cloud](/cloud/security/authentication/service-accounts/use-api-keys/api-keys-overview).
7. After the API key is created, you can see the API key shown in the **New API Key** dialog. Click the **Copy and close** button to copy the API key to your clipboard. **Please note that you cannot retrieve the API key later after closing the dialog.**
## Step 4: Create Tenant and Namespace, and Authorize the Service Account
After creating the service account and obtaining the API key, the next crucial step is to authorize the service account. This process grants the necessary permissions for the service account to interact with your StreamNative Cloud cluster.
Authorization involves setting up Access Control Lists (ACLs) that define what actions the service account can perform. Typically, you'll want to grant permissions for producing and consuming messages on specific topics or namespaces.
For more information about authorization, see [Authorization and ACLs](/cloud/security/access/access-control-lists/authorization-and-acls).
1. Go back to the **Cluster Dashboard** page.
2. On the left navigation pane, click **Instances**.
3. On the **Instances** page, click the name of the instance you created in Step 2.
4. On the **Cluster Dashboard** page, click **Tenants** on the left navigation pane.
5. On the **Tenants** page, click **+ New Tenant**.
6. On the **New Tenant** dialog:
* Enter a name for the tenant
* Select your user account as the **Admin role**
* Select the cluster created in Step 2 as **Allowed clusters**
* Click **Confirm**
7. On the **Tenants** page, click the name of the tenant you just created. You will be directed to the **Tenant Dashboard** page.
8. On the **Tenant Dashboard** page, click **Namespaces** on the left navigation pane.
9. On the **Namespaces** page, click **New Namespace**.
10. On the **New Namespace** dialog:
* Enter a name for the namespace
* Select the cluster created in Step 2 as **Allowed clusters** and **Replication clusters**
* Click **Confirm**
11. On the **Namespaces** page, click the name of the namespace you just created. You will be directed to the **Namespace Dashboard** page.
12. On the **Namespace Dashboard** page, click **Configuration** on the left navigation pane.
13. On the **Namespace configuration** page, click **ADD ROLE**. Select the name of the service account you just created, and choose the **consume** and **produce** permissions. This grants your service account the `produce` and `consume` permissions for this namespace.
Now you have created a tenant, namespace, and granted the service account the `produce` and `consume` permissions for this namespace. You can now continue on to building a Python app, connecting to the cluster, and producing and consuming messages.
## Step 5: Produce and consume messages
This QuickStart provides you with an example Python app to get you up and running with consuming and producing messages. This is a simple example and is not intended for production environments.
### Create a producer/consumer
1. Return to the StreamNative Cloud Console and go to the "Cluster Dashboard" page.
2. On the left navigation pane, click **Pulsar Clients**.
3. On the **Pulsar client setup** page, click the **Code libraries** tab, follow the setup wizard to get the sample codes for your producer and consumer.
a. Select **Python** as the client library and click **Next**.
b. Select the service account you created and click **Next**.
c. Select **API Key** as the authentication type and click **Next**.
d. Install `pulsar-client` python client library.
```bash theme={null}
pip3 install pulsar-client
```
e. Select the target tenant, namespace, topic, and subscription.
f. You are now ready to copy the auto-generated sample codes.
4. Return to your text editor and create two new files: `producer.py` and `consumer.py`. Copy and paste the sample code for the producer into `producer.py` and the sample code for the consumer into `consumer.py`. In both files, replace **``** with the API key you copied from the Service Account page.
### Run the clients to produce and consume your first message
1. Open a terminal window, navigate to the folder containing the `consumer.py` file, and run the following command:
```bash theme={null}
python3 consumer.py
```
2. Open a second terminal window, navigate to the folder containing the `producer.py` file, and run the following command:
```bash theme={null}
python3 producer.py
```
3. Return to the first terminal window. You should see the following:
```bash theme={null}
Received message 'Hello-0' id=''
Received message 'Hello-1' id=''
Received message 'Hello-2' id=''
Received message 'Hello-3' id=''
Received message 'Hello-4' id=''
Received message 'Hello-5' id=''
Received message 'Hello-6' id=''
Received message 'Hello-7' id=''
Received message 'Hello-8' id=''
Received message 'Hello-9' id=''
```
You have now produced and consumed your first 10 messages.
## Next steps
* After you have successfully provisioned a **Serverless** cluster and connected to the cluster, you can learn more about working with StreamNative Cloud by reading through [Cloud Console basics](/cloud/get-started/cloud-console).
* If you want to learn more about Pulsar, Kafka, and StreamNative Cloud, take our developer courses at the [StreamNative Developer Portal](https://streamnative.io/dev-portal).
* If you want to create multiple Pulsar clusters replicating messages with geo-replication mechanism, you can learn more by reading through the [Geo Replication on StreamNative Cloud](/cloud/clusters/cloud-geo-replication).
# Overview of StreamNative Catalogs
Source: https://docs.streamnative.io/cloud/lakehouse/catalogs/catalog-overview
The StreamNative Catalog feature allows you to create connections to external catalog providers, such as Databricks Unity Catalog, Snowflake Open Catalog, Snowflake Horizon (Polaris) Catalog, Google BigLake metastore, and Amazon S3 Tables, to stream topic data from StreamNative Cloud as Iceberg tables.
You can register a catalog by selecting a provider, entering the required catalog details, and completing the registration process. StreamNative Cloud supports registering multiple catalogs per cluster, so a single Pulsar or Kafka cluster can land topics into different governance domains across BigQuery and Snowflake.
StreamNative Catalog is scoped at the organization level within StreamNative Cloud. Once a catalog is registered, it can be accessed and used across multiple StreamNative Clusters, enabling centralized catalog management and streamlined data access for streaming workloads.
# Manage StreamNative Catalogs
Source: https://docs.streamnative.io/cloud/lakehouse/catalogs/manage-catalogs
**View Catalogs**
On the **Catalogs** page, you can view a list of all catalogs that have been registered in StreamNative Cloud. The **Catalogs** page displays the following information for each registered catalog: Name, Catalog Type, Table Format, Status, and an Actions menu.
**Catalog Actions**
Each catalog listed on the **Catalogs** page includes an actions menu with the following options: **View Details** and **Delete**.
**Catalog Details**
Clicking on a catalog listed on the **Catalogs** page navigates you to the **Catalog Details** page, where you can view detailed information about the selected catalog.
# Private Networking for Catalog Integration
Source: https://docs.streamnative.io/cloud/lakehouse/catalogs/private-networking/overview
When integrating StreamNative Cloud with external catalog providers in production environments, you may need to configure private network connections to ensure that traffic between StreamNative Cloud and your catalog and storage services does not traverse the public internet.
Private networking for lakehouse catalog integration involves two components:
* **Storage connectivity** — Private network connections between StreamNative Cloud and your object storage (S3, GCS, or Azure Blob Storage).
* **Catalog connectivity** — Private network connections between StreamNative Cloud and your catalog provider.
The following diagram shows the network path between StreamNative Cloud and the catalog and storage services over private connectivity.
```mermaid theme={null}
flowchart TB
subgraph BYOC["StreamNative BYOC VPC"]
Cluster["BYOC Cluster"]
subgraph Endpoints["Private Endpoints"]
StorageEP["Storage Private Endpoint"]
CatalogEP["Catalog Private Endpoint"]
end
end
Storage["Object Storage"]
Catalog["Catalog Provider"]
Cluster -->|"storage traffic"| StorageEP --> Storage
Cluster -->|"catalog traffic"| CatalogEP --> Catalog
classDef byoc fill:#dbeafe,stroke:#2563eb,color:#1e3a8a
classDef edge fill:#fde68a,stroke:#b45309,color:#451a03
classDef ext fill:#ede9fe,stroke:#7c3aed,color:#4c1d95
class Cluster byoc
class StorageEP,CatalogEP edge
class Storage,Catalog ext
style Endpoints fill:#fffbeb,stroke:#f59e0b,color:#92400e
```
## Prerequisites
* A StreamNative BYOC cluster deployed on AWS, GCP, or Azure.
* A registered catalog in StreamNative Cloud. See [Register Catalog](/cloud/lakehouse/catalogs/register-catalog).
* An active integration with a supported catalog provider. See the [External Tables Integrations](/cloud/lakehouse/external-tables/external-tables-overview) for setup guides.
## Storage private connectivity
Private network connections between StreamNative Cloud and object storage are handled differently depending on the cloud provider.
On AWS, StreamNative configures private network connections to Amazon S3 endpoints by default in all StreamNative environments. The S3 VPC endpoint is configured per VPC.
**No action is required on your side.** All traffic between your StreamNative BYOC cluster and S3 stays within the AWS private network automatically.
On GCP, StreamNative configures private network connections to Google Cloud Storage (GCS) endpoints by default in all StreamNative environments. The GCS private endpoint is configured per network.
**No action is required on your side** in most cases. All traffic between your StreamNative BYOC cluster and GCS stays within the Google private network automatically.
**Exception — Shared VPC:** If your BYOC cluster runs in a [Shared VPC](https://cloud.google.com/vpc/docs/shared-vpc), StreamNative cannot modify the network in the host project. You must configure private connectivity to GCS yourself by either:
* Enabling [Private Google Access](https://cloud.google.com/vpc/docs/configure-private-google-access) on the subnets used by the cluster, or
* Creating a [Private Service Connect endpoint for Google APIs](https://cloud.google.com/vpc/docs/configure-private-service-connect-apis) (see [Shared VPC deployment patterns](https://cloud.google.com/vpc/docs/private-service-connect-deployments) for host-project guidance).
On Azure, you must configure a private endpoint for your Azure Storage account to enable private connectivity between StreamNative Cloud and your storage.
To set up a private endpoint for your storage account, follow the instructions in the Azure documentation:
[Configure Azure Storage private endpoints](https://learn.microsoft.com/en-us/azure/storage/common/storage-private-endpoints).
## Catalog private connectivity
To establish private network connections between StreamNative Cloud and your catalog provider, follow the guide for your catalog provider:
Configure private connectivity to Snowflake Open Catalog using AWS PrivateLink, GCP Private Service Connect, or Azure Private Link.
Configure private connectivity to Snowflake Horizon Catalog using AWS PrivateLink, GCP Private Service Connect, or Azure Private Link.
Configure private connectivity to Databricks Unity Catalog for Delta Lake using AWS PrivateLink, GCP Private Service Connect, or Azure Private Link.
Configure private connectivity to Databricks Unity Catalog for Iceberg using AWS PrivateLink, GCP Private Service Connect, or Azure Private Link.
Private connectivity for Amazon S3 Tables on AWS. Configured by default — no action required.
Private connectivity for Google BigLake on GCP. Configured by default — no action required.
# Register Catalog
Source: https://docs.streamnative.io/cloud/lakehouse/catalogs/register-catalog
To register a catalog in StreamNative Cloud, navigate to the **Catalogs** page and click **Register Catalog**.
On the **Register Catalog** form, provide the required details based on the selected Catalog Provider.
### Databricks Unity Catalog (Delta Lake and Iceberg)
* **Name** – Enter a unique name for the catalog in StreamNative Cloud.
* **Catalog Provider** – Select the catalog provider where you want to ingest data.
* **Catalog Name** – Enter the name of the catalog that exists in Databricks Unity Catalog.
* **URI** – Provide the URI of the catalog.
* **Authentication Type** – Select the appropriate authentication method for connecting to the catalog provider.
### Snowflake Open Catalog
* **Name** – Enter a unique name for the catalog in StreamNative Cloud.
* **Catalog Provider** – Select the catalog provider where you want to ingest data.
* **Warehouse** – Enter the name of the warehouse that exists in Snowflake Open Catalog.
* **URI** – Provide the URI of the catalog.
* **Authentication Type** – Select the appropriate authentication method for connecting to the catalog provider.
### Amazon S3 Tables
* **Name** – Enter a unique name for the catalog in StreamNative Cloud.
* **Catalog Provider** – Select the catalog provider where you want to ingest data.
* **S3 Table Bucket** – Enter the ARN of the S3 Table bucket.
### Google BigLake metastore
The Google BigLake metastore is an Iceberg REST catalog for Google Cloud that integrates with BigQuery, so streamed tables are queryable from BigQuery without an extra import step.
* **Name** – Enter a unique name for the catalog in StreamNative Cloud.
* **Catalog Provider** – Select Google BigLake as the catalog provider.
* **Google Project** – Enter the name of the Google project.
* **Warehouse** – Enter the name of the Google Cloud Storage Warehouse.
### Snowflake Horizon (Polaris) Catalog
The Snowflake Horizon Catalog is an Iceberg REST catalog hosted on Snowflake. Access is governed by Snowflake roles, so existing Snowflake RBAC policies apply to streamed tables.
* **Name** – Enter a unique name for the catalog in StreamNative Cloud.
* **Catalog Provider** – Select Snowflake Horizon as the catalog provider.
* **Account** – Enter the Snowflake account identifier hosting the Horizon catalog.
* **Warehouse** – Enter the name of the warehouse that exists in Snowflake Horizon.
* **URI** – Provide the URI of the Polaris REST catalog endpoint.
* **Authentication Type** – Select the appropriate authentication method (for example, OAuth2 client credentials) for connecting to Snowflake Horizon.
## Register multiple catalogs per cluster
A single StreamNative cluster can be associated with multiple registered catalogs. This lets you route different topics to different catalogs — for example, landing some topics into BigLake for BigQuery analytics and others into Snowflake Horizon for governed Snowflake access — all from one Pulsar or Kafka cluster. Repeat the registration steps above for each catalog you want to make available to the cluster.
# Enable Lakehouse Table
Source: https://docs.streamnative.io/cloud/lakehouse/enable-lakehouse-integration
You can enable the Lakehouse Table for a cluster, a namespace, or a single topic from the StreamNative Cloud Console. Once enabled, topic data is delivered to the configured external lakehouse catalog automatically.
> Currently, only the **Deliver to External Table** mode is supported. The **Expose Internal Table** option is coming soon.
## Prerequisites
* A cluster (Pulsar or Kafka) running on a profile that supports Lakehouse Table delivery. See [Lakehouse Table Overview](/cloud/lakehouse/lakehouse-table-overview) for the supported cluster types and profiles.
* A registered catalog in your organization. If you have not registered a catalog yet, see [Register Catalog](/cloud/lakehouse/catalogs/register-catalog).
## Enable Lakehouse Table at the cluster level
You can enable the Lakehouse Table at the cluster level either when you create a new cluster or for an existing cluster.
### Enable when creating a new cluster
When you create a new cluster, the cluster wizard includes a **Lakehouse Table** configuration step.
1. Toggle on **Enable Lakehouse Table**.
2. Select a **Catalog Provider**. StreamNative Cloud supports the following providers:
* Databricks Unity Catalog for Iceberg (Iceberg)
* Databricks Unity Catalog for Delta Lake (Delta Lake)
* Snowflake Open Catalog (Iceberg)
* Snowflake Horizon Catalog (Iceberg)
* Amazon S3Table (Iceberg)
* Google BigLake (Iceberg) -- can only be configured **after** the cluster is created. Skip the Lakehouse Table step at cluster creation and enable it later from the existing cluster page.
3. Select the target **Catalog** that belongs to the catalog provider you selected. If the catalog you need is not registered yet, click **Register new catalog** to open the registration page. See [Register Catalog](/cloud/lakehouse/catalogs/register-catalog).
4. (Optional) Enable **Apply lakehouse setting to all topics** to automatically deliver every existing and new topic in the cluster to the lakehouse table. If this option is disabled, you can enable Lakehouse delivery later at the namespace or topic level.
### Enable for an existing cluster
For an existing Pulsar cluster (latency-optimized profile or cost-optimized profile), open the cluster page and click **Enable Lakehouse Table**.
In the dialog, select a target catalog from the dropdown. If the catalog is not registered yet, click **Register new catalog** to register one.
After you confirm, every topic in the cluster begins delivering data to the lakehouse table automatically.
## Enable Lakehouse Table at the namespace level
You can also enable the Lakehouse Table at the namespace level. Open the namespace and click **Enable Lakehouse Table**, then select a registered target catalog. If the catalog you need is not registered, click **Register new catalog** to register one.
> Namespace-level enablement is supported only on Pulsar clusters (latency-optimized and cost-optimized profiles). Kafka clusters do not support namespace-level enablement; for Kafka clusters, enable Lakehouse Table at the cluster level instead.
After you confirm, every topic in the namespace begins delivering data to the lakehouse table automatically.
## Enable Lakehouse Table at the topic level
You can enable the Lakehouse Table for a single topic. Open the topic and click **Enable Lakehouse Table**, then select a registered target catalog. If the catalog you need is not registered, click **Register new catalog** to register one.
> Topic-level enablement is supported only on Pulsar clusters (latency-optimized and cost-optimized profiles). Kafka clusters do not support topic-level enablement; for Kafka clusters, enable Lakehouse Table at the cluster level instead.
After you confirm, the topic data is delivered to the lakehouse table automatically.
## Configuration override priority
When the same setting is configured at multiple levels, the most specific level wins:
```
Topic settings
↓ (override)
Namespace settings
↓ (override)
Cluster settings
```
For example, if Lakehouse delivery is enabled at the cluster level but disabled at a specific topic, that topic's data is not delivered.
### Per-namespace and per-topic catalog selection
Different namespaces in the same cluster can deliver data to **different catalogs**, and individual topics within a namespace can also override the namespace's catalog and deliver to a different one. For example, namespace `analytics/finance` can be configured to use a Snowflake Open Catalog, namespace `analytics/marketing` in the same cluster can use a Databricks Unity Catalog, and a single topic `analytics/marketing/realtime-events` inside `analytics/marketing` can be redirected to an Amazon S3Tables catalog. To assign different catalogs, enable the Lakehouse Table separately on each namespace or topic and select the desired catalog.
### Catalog override order
The catalog used for a topic is resolved in the same most-specific-wins order:
```
Topic catalog
↓ (overrides)
Namespace catalog
↓ (overrides)
Cluster catalog
```
If a catalog is set on the topic, that catalog is used regardless of the namespace or cluster catalog. If only the namespace catalog is set, every topic in that namespace uses the namespace's catalog. If neither is set, the cluster catalog is used.
## Next Steps
* Monitor data delivery progress for a topic from the Cloud Console: [Lakehouse Observability -- Monitor data delivery progress in the Cloud Console](/cloud/lakehouse/lakehouse-observability#monitor-data-delivery-progress-in-the-cloud-console).
* See how Pulsar topic names are mapped to lakehouse namespace and table names: [Lakehouse Table Overview -- Topic to lakehouse identifier mapping](/cloud/lakehouse/lakehouse-table-overview#topic-to-lakehouse-identifier-mapping).
* Explore features:
* [Schema Evolution](/cloud/lakehouse/features/schema-evolution)
* [Variant Type](/cloud/lakehouse/features/variant-type)
* [Partition Key](/cloud/lakehouse/features/iceberg-partition-key)
* [Upsert](/cloud/lakehouse/features/iceberg-upsert)
* [Persist Key](/cloud/lakehouse/features/persist-key)
* [Persist Extra Metadata](/cloud/lakehouse/features/persist-extra-metadata)
# Overview - External Tables
Source: https://docs.streamnative.io/cloud/lakehouse/external-tables/external-tables-overview
**External Tables**
External Tables are tables backed by StreamNative topics but represented in open table formats, such as Apache Iceberg or Delta Lake, with both data and metadata stored directly in user-managed object storage.
**Key Characteristics**
* **Open Table Formats** -
Data is written as Parquet files and managed using Iceberg or Delta metadata logs.
* **Object Storage–Backed** -
Tables reside in S3, GCS, Azure Blob, or other object storage systems.
Externally Managed
StreamNative Cloud materializes the data, but table lifecycle, optimization, schema governance, and cataloging are typically managed by a Lakehouse vendor, such as:
* Databricks Unity Catalog
* Snowflake Open Catalog
* Amazon S3 Tables
**High Interoperability**
External Tables are fully queryable by external compute platforms, BI tools, and SQL engines.
**When to Use External Tables**
* You want deep integration with an existing Lakehouse platform.
* You require open, interoperable formats for analytics, AI/ML, or downstream workloads.
* You prefer to manage optimization (compaction, vacuum, retention) in systems like Databricks, Snowflake, or Polaris.
# Partition Key
Source: https://docs.streamnative.io/cloud/lakehouse/features/iceberg-partition-key
Partition keys control how data is organized into partitions within the Iceberg table. Partitioning improves query performance by enabling partition pruning.
`partition.key` is a [dynamic configuration](../dynamic-configuration) key that takes effect **only at the topic level**. Setting it at the cluster or namespace level has no effect.
> **Cluster-name prefix:** All dynamic configuration keys must be prefixed with the cluster name (for example, `.partition.key`). The cluster name is the value of `clusterName` in `conf/broker.conf` -- see [Finding the Cluster Name](../dynamic-configuration#finding-the-cluster-name). The examples below use `private-cloud` as the cluster name; replace it with the name of your cluster.
> **Cardinality limit:** Keep the **total number of partition values across all levels under 10** (the cardinality of `key1 × key2 × ... × keyN` should not exceed 10). If the partitioning would produce more than 10 distinct partition values, use the `bucket[N]` transform to bound it. Excessive partitions cause many small files, which degrade write throughput and query performance.
## Configuration Format
The partition key is specified as a JSON array. Each element has three fields:
| Field | Required | Description |
| -------------- | -------- | ------------------------------------------------------------- |
| `sourceColumn` | Yes | The field name from the topic schema |
| `transform` | No | Iceberg partition transform function. Defaults to `identity`. |
| `targetName` | No | Custom name for the transformed partition column |
### Supported Iceberg Transforms
| Transform | Description |
| ------------- | -------------------------------- |
| `identity` | Use the field value as-is |
| `bucket[N]` | Hash into N buckets |
| `truncate[N]` | Truncate strings to N characters |
| `year` | Extract year from timestamp |
| `month` | Extract month from timestamp |
| `day` | Extract day from timestamp |
| `hour` | Extract hour from timestamp |
For full semantics, see the [Iceberg partition transforms specification](https://iceberg.apache.org/spec/#partition-transforms).
## Apply at Topic Level
```bash theme={null}
bin/pulsar-admin topics update-properties \
-p private-cloud.partition.key='[{\"sourceColumn\":\"\",\"transform\":\"\",\"targetName\":\"\"}]' \
persistent:////
```
> Setting `partition.key` at the cluster or namespace level has no effect. Apply it on the topic only.
## Example
Configure two partition keys on a topic:
* `timestamp` -- bucketed by hour, named `ts_hour`
* `address` -- truncated to 7 characters, named `t_address`
```bash theme={null}
bin/pulsar-admin topics update-properties \
-p private-cloud.partition.key="[{\"sourceColumn\":\"timestamp\",\"transform\":\"hour\",\"targetName\":\"ts_hour\"},{\"sourceColumn\":\"address\",\"transform\":\"truncate[7]\",\"targetName\":\"t_address\"}]" \
persistent://public/default/events
```
## Important Notes
1. The `sourceColumn` value must reference a field that exists in the topic schema.
2. The `targetName` is the name produced after applying the transform; it does not need to exist in the topic schema.
3. The JSON value must be a valid JSON array. When passing it on the shell, escape inner double quotes (`\"`).
4. If the JSON cannot be parsed, the system falls back to a non-partitioned table.
5. **Keep the total cardinality of partition values under 10.** If a column has high cardinality, wrap it with `bucket[N]` to bound the number of partitions (for example, `{"sourceColumn":"userId","transform":"bucket[8]"}`). High partition counts produce many small files and degrade performance.
## Related
* [Dynamic Configuration Guide](../dynamic-configuration) -- Cluster-name prefix, override priority, and apply procedure
* [Upsert](/cloud/lakehouse/features/iceberg-upsert) -- Combining partition keys with upsert has compatibility constraints
# Upsert
Source: https://docs.streamnative.io/cloud/lakehouse/features/iceberg-upsert
Upsert mode enables deduplication of records based on a primary key. When multiple records with the same key arrive, only the latest value is retained in the lakehouse table.
`upsert.mode.enabled` and `identifier.fields` are [dynamic configuration](../dynamic-configuration) keys.
> **Cluster-name prefix:** All dynamic configuration keys must be prefixed with the cluster name (for example, `.upsert.mode.enabled`). The cluster name is the value of `clusterName` in `conf/broker.conf` -- see [Finding the Cluster Name](../dynamic-configuration#finding-the-cluster-name). The examples below use `private-cloud` as the cluster name; replace it with the name of your cluster.
## Configuration Keys
| Key | Scope | Description | Default |
| ------------------------------------ | --------------------------- | --------------------------------------------------------------------------------------------------------------------- | ------- |
| `.upsert.mode.enabled` | Cluster / Namespace / Topic | Enable upsert mode (`true` / `false`). More-specific scopes override broader ones. | `false` |
| `.identifier.fields` | Topic only | Comma-separated list of fields used as the primary key. Setting this at the cluster or namespace level has no effect. | -- |
## How Upsert Works
StreamNative Ursa implements upsert using **Iceberg equal-delete** files. For each upsert write, the compaction service emits an equal-delete entry that matches the previous record by the configured identifier fields, followed by the new record. Readers reconcile the delete and the new value at query time.
### Catalog Compatibility
Because upsert depends on equal-delete files, the underlying catalog and query engine must support reading Iceberg equal deletes. Catalogs differ in their delete-file support:
| Catalog | Equal Delete | Upsert Support |
| -------------------------------------------- | ------------------------- | ------------------ |
| Snowflake Open Catalog (Polaris) | No (position delete only) | Not supported |
| Snowflake Horizon Catalog | No (position delete only) | Not supported |
| Databricks Unity Catalog (Managed Iceberg) | No (position delete only) | Not supported |
| AWS S3Table | Yes | Supported |
| Google BigLake | Under confirmation | Under confirmation |
| Iceberg Hadoop catalog (no external catalog) | Yes | Supported |
If you need upsert with a catalog that only supports position deletes, the recommended approach is to use the Hadoop catalog or AWS S3Table for the affected tables.
## Apply at Cluster Level
Cluster-level properties are stored in the `sn/system` namespace. Cluster-level upsert applies as the default for every namespace and topic that does not override it.
```bash theme={null}
bin/pulsar-admin namespaces set-properties \
-p private-cloud.cluster.upsert.mode.enabled=true \
sn/system
```
## Apply at Namespace Level
```bash theme={null}
bin/pulsar-admin namespaces set-properties \
-p private-cloud.upsert.mode.enabled=true \
/
```
## Apply at Topic Level
`identifier.fields` must be set on the topic; setting `upsert.mode.enabled` on the topic is also valid and overrides any namespace or cluster default.
```bash theme={null}
bin/pulsar-admin topics update-properties \
-p private-cloud.upsert.mode.enabled=true \
-p private-cloud.identifier.fields=, \
persistent:////
```
## Example
Enable upsert on `persistent://public/default/users` with `userId` and `email` as the primary key:
```bash theme={null}
bin/pulsar-admin topics update-properties \
-p private-cloud.upsert.mode.enabled=true \
-p private-cloud.identifier.fields=userId,email \
persistent://public/default/users
```
## Requirements
* Identifier fields **must exist** in the topic schema.
* Identifier fields **must be marked as `required`** in the schema (not nullable).
* The catalog and query engine must support reading Iceberg equal-delete files. See [Catalog Compatibility](#catalog-compatibility).
## Commit Behavior
* **Append-only writes** (default) are batch-committed: multiple Parquet files are grouped and committed to the catalog in a single commit.
* **Upsert writes** are committed one-by-one to ensure correct data ordering. This may slightly reduce throughput compared to append-only mode.
## Limitations
* When upsert is combined with a [partition key](/cloud/lakehouse/features/iceberg-partition-key), identifier fields only deduplicate within the same partition. For example, if the table has `partition.key=region` and `identifier.fields=userId`, two records with the same `userId` but different `region` values are both kept.
* Upsert is supported only for External Tables (SDT).
## Related
* [Dynamic Configuration Guide](../dynamic-configuration) -- Cluster-name prefix, override priority, and apply procedure
* [Partition Key](/cloud/lakehouse/features/iceberg-partition-key) -- Combining partition keys with upsert has compatibility constraints
# Persist Extra Metadata
Source: https://docs.streamnative.io/cloud/lakehouse/features/persist-extra-metadata
The **Persist Extra Metadata** feature injects a `__meta` column into the lakehouse table that contains additional message metadata captured at write time. Use it when downstream queries need access to information that is part of the message envelope but not part of the message body -- for example, the message offset, publish time, event time, or producer-side properties.
## What Gets Persisted
When the feature is enabled, every record written to the lakehouse table includes a `__meta` column populated with the following fields:
| Field | Description |
| ----------------- | ---------------------------------------------------------------------------------- |
| `__messageOffset` | The original Pulsar / Kafka message ID or offset |
| `__publishTime` | Pulsar publish timestamp (epoch ms) |
| `__eventTime` | Pulsar event time (epoch ms), if set by the producer |
| `__schemaVersion` | Numeric schema version of the source message |
| `__properties` | Producer-supplied key/value properties (Pulsar message properties / Kafka headers) |
The column is stored as an Iceberg / Delta **Variant** value. This keeps the schema stable when properties evolve (new keys, removed keys) and lets downstream engines extract individual fields with standard Variant accessors (for example, `__meta.__publishTime` in Spark SQL).
## Configuration
| Property | Default | Description |
| ---------------------- | ------- | ----------------------------------------------------------------------------------------------------- |
| `persistExtraMetadata` | `false` | Master switch. When `true`, the `__meta` column is added to the table and populated for every record. |
### Required Companion Settings
Because `__meta` is a Variant column, the feature shares the [Variant type](/cloud/lakehouse/features/variant-type) prerequisites:
| Property | Default | Required When |
| -------------------------- | ------- | --------------------------------------------------------------------------- |
| `variantTypeEnabled` | `false` | Always (master switch for Variant support) |
| `tableEvolveSchemaEnabled` | `true` | Always (the column is added by schema evolution) |
| `allowIcebergV3` | `false` | Required for Iceberg (Variant is an Iceberg V3 feature). Ignored for Delta. |
> **Important:** Variant support is gated by a feature flag. Contact the StreamNative Support Team to enable it before turning on `persistExtraMetadata`.
### Iceberg
Add the following to the compaction service `custom` config:
```yaml theme={null}
persistExtraMetadata: "true"
variantTypeEnabled: "true"
tableEvolveSchemaEnabled: "true" # default; only override if previously disabled
allowIcebergV3: "true"
```
> **Downstream query engine compatibility:** When `allowIcebergV3` is enabled, your readers (Spark, Trino, Athena, etc.) must support Iceberg V3 to read tables that contain Variant columns. See [Variant Type](/cloud/lakehouse/features/variant-type#iceberg) for details.
### Delta Lake
```yaml theme={null}
persistExtraMetadata: "true"
variantTypeEnabled: "true"
tableEvolveSchemaEnabled: "true"
```
Delta does not require `allowIcebergV3`.
## Querying the Metadata
Once enabled, the `__meta` column appears in the lakehouse table alongside the user-defined fields. Examples:
**Spark SQL (Iceberg):**
```sql theme={null}
SELECT __meta:__publishTime AS publish_time,
__meta:__messageOffset AS offset,
__meta:__properties:trace_id AS trace_id,
*
FROM iceberg_catalog.namespace.events
WHERE __meta:__publishTime >= 1700000000000
LIMIT 10;
```
**Spark SQL (Delta):**
```sql theme={null}
SELECT variant_get(__meta, '$.__publishTime', 'long') AS publish_time,
variant_get(__meta, '$.__messageOffset', 'string') AS offset,
*
FROM delta.`s3://bucket/path/events`
LIMIT 10;
```
The exact Variant accessor syntax depends on your engine version; consult the engine's Variant documentation for the canonical form.
## Behavior Notes
* **Adding metadata to existing tables.** Because the column is added through schema evolution (`tableEvolveSchemaEnabled=true`), enabling the flag on a topic that already has a lakehouse table appends the `__meta` column on the next compaction. Records written before the flag was enabled will have a `null` value in the column.
* **Disabling the feature.** Setting `persistExtraMetadata` back to `false` stops new records from receiving metadata, but the column itself is not removed. Older rows retain their values.
* **Performance impact.** The `__meta` column is small per-row but increases storage and write throughput slightly. The Variant encoding is efficient and supports predicate pushdown when the engine extracts a specific field.
## Related
* [Variant Type](/cloud/lakehouse/features/variant-type) -- Prerequisite feature for `persistExtraMetadata`
* [Schema Evolution](/cloud/lakehouse/features/schema-evolution) -- The mechanism by which the `__meta` column is added to the table
* [Persist Key](/cloud/lakehouse/features/persist-key) -- Companion feature that persists the message key as a separate column
# Persist Key
Source: https://docs.streamnative.io/cloud/lakehouse/features/persist-key
The **Persist Key** feature injects a `__key` column into the lakehouse table that contains the original message key from the source topic. Use it when downstream queries need access to the partition key produced by the application -- for example, joining the lakehouse table with another dataset on the producer's key, computing per-key aggregations, or auditing message routing.
## What Gets Persisted
When the feature is enabled, every record written to the lakehouse table includes a `__key` column populated with the source message's key:
| Source | Key value persisted |
| --------------- | --------------------------------------------------------------------------------------------- |
| Pulsar producer | The Pulsar message key (`MessageBuilder.key(...)`), or `null` if the producer did not set one |
| Kafka producer | The Kafka record key bytes, or `null` if the producer did not set one |
The column is added to the table by schema evolution and stored as a `binary` value, preserving the exact bytes the producer sent.
## Configuration
| Property | Default | Description |
| ------------ | ------- | ---------------------------------------------------------------------------------------------------- |
| `persistKey` | `false` | Master switch. When `true`, the `__key` column is added to the table and populated for every record. |
### Required Companion Settings
The `__key` column is added through schema evolution, so schema evolution must remain enabled:
| Property | Default | Description |
| -------------------------- | ------- | ----------------------------------------------------------------------------------------- |
| `tableEvolveSchemaEnabled` | `true` | Required (the column is added by schema evolution). Only override if previously disabled. |
`persistKey` does **not** require Variant support, Iceberg V3, or any other feature flag.
### Configuration
Add the following to the compaction service `custom` config:
```yaml theme={null}
persistKey: "true"
tableEvolveSchemaEnabled: "true" # default; only override if previously disabled
```
The same configuration applies to both Iceberg and Delta Lake.
## Querying the Key
Once enabled, the `__key` column appears in the lakehouse table alongside the user-defined fields. Examples:
**Spark SQL:**
```sql theme={null}
SELECT CAST(__key AS STRING) AS key,
*
FROM iceberg_catalog.namespace.events
WHERE CAST(__key AS STRING) = 'user-42'
LIMIT 10;
```
```sql theme={null}
-- Per-key counts
SELECT CAST(__key AS STRING) AS key, COUNT(*) AS message_count
FROM iceberg_catalog.namespace.events
GROUP BY CAST(__key AS STRING)
ORDER BY message_count DESC;
```
If your producer keys are UTF-8 strings, cast the column to `STRING` for readability. For binary keys, query the column directly as `BINARY`.
## Behavior Notes
* **Adding the key column to existing tables.** Because the column is added through schema evolution (`tableEvolveSchemaEnabled=true`), enabling the flag on a topic that already has a lakehouse table appends the `__key` column on the next compaction. Records written before the flag was enabled will have a `null` value in the column.
* **Disabling the feature.** Setting `persistKey` back to `false` stops new records from receiving the key, but the column itself is not removed. Older rows retain their values.
* **Null keys.** Messages without a key are written with `null` in the `__key` column.
* **Combining with upsert.** The `__key` column is independent of [identifier fields](/cloud/lakehouse/features/iceberg-upsert) used for upsert. It records the producer-side key as-is and is not used for deduplication.
## Related
* [Persist Extra Metadata](/cloud/lakehouse/features/persist-extra-metadata) -- Companion feature that persists message envelope metadata (offset, publish time, properties) as a Variant column
* [Schema Evolution](/cloud/lakehouse/features/schema-evolution) -- The mechanism by which the `__key` column is added to the table
* [Upsert](/cloud/lakehouse/features/iceberg-upsert) -- For deduplication semantics on a primary key, which is a different concern from persisting the source message key
# Schema Evolution
Source: https://docs.streamnative.io/cloud/lakehouse/features/schema-evolution
Schema evolution is enabled by default (`tableEvolveSchemaEnabled=true`). When a producer changes the schema of a topic, the lakehouse table is automatically updated to match.
> **Recommendation:** For topics that have Lakehouse integration enabled, set the Pulsar schema compatibility strategy to **`BACKWARD_TRANSITIVE`**. This guarantees that every reader (including downstream Iceberg / Delta consumers) can read data written with all previous schema versions, which aligns with how the lakehouse table is evolved. See the [Pulsar schema compatibility documentation](https://pulsar.apache.org/docs/2.10.x/schema-evolution-compatibility/#backward-and-backward_transitive) for details on `BACKWARD` vs `BACKWARD_TRANSITIVE`.
>
> Apply with `pulsar-admin` at the namespace or topic level:
>
> ```bash theme={null}
> # Namespace level
> bin/pulsar-admin namespaces set-schema-compatibility-strategy \
> --compatibility BACKWARD_TRANSITIVE \
> /
>
> # Topic level
> bin/pulsar-admin topicPolicies set-schema-compatibility-strategy \
> --strategy BACKWARD_TRANSITIVE \
> //
> ```
## How It Works
Schema evolution is triggered automatically during the compaction process when the compaction service encounters messages with a schema version newer than what the lakehouse table currently has.
### Step 1: Detection
When processing messages, the compaction service extracts the schema version from each message. If the version is newer than the latest version recorded in the table's schema mapping, evolution is triggered.
### Step 2: Retrieve All Schema Versions
The compaction service retrieves all schema versions from the schema registry (Pulsar or Confluent) up to the current version. This ensures that intermediate schema versions are not skipped.
### Step 3: Convert Schemas
Each source schema (Avro, JSON, ProtobufNative(Pulsar) or Protobuf(Kafka)) is converted to the target table format:
* **Avro** is converted directly to Iceberg Schema or Delta StructType
* **JSON** is first converted to Avro, then to the target format (Pulsar internally represents JSON schemas using Avro)
* **ProtobufNative(Pulsar)** is converted via the Protobuf descriptor to Avro, then to the target format
* **Protobuf(Kafka)** is converted via the Protobuf descriptor to Avro, then to the target format
### Step 4: Apply Changes
Schema changes are applied to the table iteratively, version by version in ascending order. Each version is processed as a transaction.
For **Iceberg** tables, the following operations are supported:
* **Add columns** -- new fields are always added as optional for backward compatibility
* **Delete columns** -- field is removed from the schema (or made optional in soft-delete mode)
* **Type promotion** -- `int` to `long`, `float` to `double`, and other compatible promotions
* **Nullability changes** -- required fields can be made optional (reverse is not supported)
* **Nested struct evolution** -- the same rules apply recursively to nested fields
For **Delta** tables:
* Column Mapping mode (`NAME`) is automatically enabled to support safe renames and deletes
* Each column receives a unique physical ID for safe schema evolution
* Schema changes are committed as Delta transactions
### Step 5: Record Schema Mapping
After each successful evolution, a mapping from the source schema version to the table's internal schema ID is recorded as a table property (`streamnative.schema.mapping`). This prevents re-processing the same version.
## Supported Operations
| Operation | Iceberg | Delta |
| -------------------------------------------------------------------- | ------------- | ------------- |
| Add optional columns | Supported | Supported |
| Delete columns | Supported | Supported |
| Type promotion (`int` -> `long`, `float` -> `double`) | Supported | Supported |
| Required -> Optional | Supported | Supported |
| Optional -> Required | Not supported | Not supported |
| Nested struct evolution | Supported | Supported |
| Type category changes (`struct` \<-> `list`, `primitive` \<-> `map`) | Not supported | Not supported |
## Limitations
* **Adding required fields:** New fields added to existing tables are automatically converted to optional. Required fields can only be defined at table creation time.
* **Type category changes:** Changing a field from one type category to another (e.g., struct to list, primitive to map) is not supported.
* **Backward incompatibility:** If the table schema has been evolved beyond the message's schema version, the message cannot be processed. Update the producer to use the latest schema.
* **Soft-delete mode:** Enable `schema.evolution.soft-delete.enabled=true` to make deleted fields optional instead of removing them entirely. This preserves backward compatibility for readers.
## Configuration
| Property | Description | Default |
| -------------------------------------- | ------------------------------------------------ | ------- |
| `tableEvolveSchemaEnabled` | Enable automatic schema evolution | `true` |
| `schema.evolution.soft-delete.enabled` | Make deleted fields optional instead of removing | `false` |
| `dlt.suffix` | Suffix appended to Dead Letter Table name | `_dlt` |
## Dead Letter Table (DLT)
When a message cannot be successfully processed into the lakehouse table, it is routed to a **Dead Letter Table (DLT)** instead of failing the entire compaction job. This allows the pipeline to continue processing valid messages while preserving failed records for investigation.
### When Are Messages Routed to DLT?
Messages are routed to DLT in the following scenarios:
| Scenario | Example |
| ------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Schema incompatibility** | 1) Schema evolution is disabled and the record schema does not match the table schema; 2) New topic schema is incompatible with the Lakehouse table schema |
| **Unsupported schema changes** | Evolving a non-Variant field to Variant, or a Variant field to another type |
| **Type conversion errors** | Record cannot be serialized to the target lakehouse format (Iceberg/Delta/Parquet) |
| **Null values** | Null payload/record values from Kafka entries |
| **Deserialization errors** | Failures deserializing Pulsar or Kafka source data |
| **Parsing failures** | Schema parsing errors for Pulsar message format |
> **Note:** Fatal errors (such as catalog connectivity issues, permission errors, or infrastructure failures) are **not** routed to DLT -- they cause the compaction task to fail and retry.
### DLT Table Naming
The DLT table name is derived from the original topic name by appending the configurable DLT suffix (default: `_dlt`).
**Format:**
```
```
**Example:**
| Original Topic | DLT Table |
| ------------------------------------------------- | --------------------------------------------------------- |
| `persistent://my-tenant/my-namespace/user-events` | `user-events_dlt` (in namespace `my-tenant/my-namespace`) |
| `persistent://public/default/orders` | `orders_dlt` (in namespace `public/default`) |
For Iceberg tables, the DLT table is created in the same namespace as the original table. For Delta tables, the DLT topic is `//_dlt`.
### DLT Schema
Both Iceberg and Delta DLT tables use a consistent 3-field schema:
| Field | Type | Nullable | Description |
| --------------- | ------ | -------- | -------------------------------------------------- |
| `messageId` | String | No | The original Pulsar or Kafka message ID |
| `payload` | String | Yes | Base64-encoded original message payload |
| `failureReason` | String | Yes | The error message explaining why the record failed |
This allows you to:
* Identify which messages failed and why
* Replay or reprocess the failed messages after fixing the underlying issue
* Debug schema or serialization problems
### Configuring the DLT Suffix
The default DLT suffix is `_dlt`. To customize it, set the `dlt.suffix` property in the compaction service configuration:
```yaml theme={null}
compactionScheduler:
config:
custom:
dlt.suffix: "_deadletter"
```
With this configuration, the DLT table for topic `user-events` would be `user-events-deadletter`.
### Monitoring DLT Activity
When the compaction writer closes, it logs a summary of DLT activity including:
* Total number of records routed to DLT
* Breakdown by failure reason (up to 100 distinct reasons tracked)
* Up to 10 sample message IDs per failure reason
Example log output:
```
WARN Sent 42 record(s) to DLT for topic: persistent://public/default/events, partition: 0,
failure reasons with messageIds: {"Schema evolution is disabled...": ["msgId1", "msgId2", ...]}
```
Use this information to diagnose schema mismatches, invalid data, or other data quality issues upstream.
# Variant Type
Source: https://docs.streamnative.io/cloud/lakehouse/features/variant-type
The Variant type allows a single column to hold values of different data types, enabling flexible handling of semi-structured data without defining a rigid schema upfront.
StreamNative Ursa supports the Variant type for both **Apache Iceberg (V3)** and **Delta Lake** tables.
> **Important:** Variant type support is disabled by default. Contact the StreamNative Support Team to enable the feature flag before using Variant types.
## Enabling Variant Support
Variant support is gated by a small set of broker properties. The required combination depends on the target table format.
| Property | Default | Description |
| -------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------- |
| `variantTypeEnabled` | `false` | Master switch for Variant support. Required for both Iceberg and Delta. |
| `tableEvolveSchemaEnabled` | `true` | Schema evolution must remain enabled so Variant fields can be added/removed during writes. Required for both Iceberg and Delta. |
| `allowIcebergV3` | `false` | Enables Iceberg V3 features (including Variant). **Required for Iceberg**, ignored for Delta. |
### Iceberg
Set the following properties on the compaction service `custom` config:
```yaml theme={null}
variantTypeEnabled: "true"
tableEvolveSchemaEnabled: "true" # default; only override if previously disabled
allowIcebergV3: "true"
```
> **Downstream query engine compatibility:** When `allowIcebergV3` is enabled, the downstream query engine reading the table must also support Iceberg V3. Older Spark / Trino / Athena versions that only support Iceberg V2 will fail to read tables that use Variant or other V3-only features. Verify your engine's Iceberg support level before enabling.
### Delta Lake
Delta Lake's Variant type is not gated by an Iceberg version flag. Only the master switch and schema evolution are required:
```yaml theme={null}
variantTypeEnabled: "true"
tableEvolveSchemaEnabled: "true" # default; only override if previously disabled
```
## Supported Data Types
* **Primitives:** `string`, `int`, `long`, `float`, `double`, `boolean`, `bytes`
* **Complex types:** `map`, `list / array`, `set`
* **Nested POJOs** and **entire POJOs**
## Configure Variant in Pulsar
### Avro Schema
Use the `@AvroSchema` annotation with `logicalType: "variant"`:
```java theme={null}
@Data
public class Event {
private String name;
// Variant for primitive type
@AvroSchema("{\"type\": \"string\", \"logicalType\": \"variant\"}")
private String flexibleField;
// Variant for Map
@AvroSchema("{\"type\": \"map\", \"values\": \"string\", \"logicalType\": \"variant\"}")
private Map metadata;
// Variant for List
@AvroSchema("{\"type\": \"array\", \"items\": \"string\", \"logicalType\": \"variant\"}")
private List tags;
// Variant for nested POJO with metadata fields for query optimization
@AvroSchema("{\"type\": \"record\", \"name\": \"Address\", \"fields\": ["
+ " {\"name\": \"city\", \"type\": \"string\"},"
+ " {\"name\": \"zip\", \"type\": \"int\"}"
+ "],"
+ "\"logicalType\": \"variant\","
+ "\"variant-metadata-fields\": \"[\\\"zip\\\", \\\"city\\\"]\" "
+ "}")
private Address address;
}
```
### JSON Schema
Use `@JsonPropertyDescription` with the Variant annotation:
```java theme={null}
@Data
public class Event {
private String name;
@JsonPropertyDescription("logicalType: variant")
private String flexibleField;
@JsonPropertyDescription("logicalType: variant")
private Map metadata;
@JsonPropertyDescription("logicalType: variant")
private List tags;
@JsonPropertyDescription("logicalType: variant")
private Address address;
}
```
### ProtobufNative Schema
Define a custom field option named `logical_type`:
```protobuf theme={null}
syntax = "proto3";
import "google/protobuf/descriptor.proto";
extend google.protobuf.FieldOptions {
string logical_type = 1001;
}
message Event {
string name = 1;
string flexible_field = 2 [(logical_type) = "variant"];
map metadata = 3 [(logical_type) = "variant"];
repeated string tags = 4 [(logical_type) = "variant"];
Address address = 5 [(logical_type) = "variant"];
}
message Address {
string city = 1;
int32 zip = 2;
}
```
## Configure Variant in Ursa (Kafka Protocol)
### Avro Schema -- POJO Annotation
Same `@AvroSchema` annotations as Pulsar. Produce data using `ReflectionAvroSerializer` (do not use `KafkaAvroSerializer`).
### Avro Schema -- Inline Definition
Define `logicalType: "variant"` directly in the Avro schema:
```json theme={null}
{
"type": "record",
"name": "Event",
"fields": [
{
"name": "id",
"type": ["null", "string"],
"default": null
},
{
"name": "score",
"type": {
"type": "double",
"logicalType": "variant"
}
},
{
"name": "tags",
"type": {
"type": "array",
"items": "string",
"logicalType": "variant"
},
"default": []
},
{
"name": "attributes",
"type": {
"type": "map",
"values": "string",
"logicalType": "variant"
},
"default": {}
},
{
"name": "address",
"type": {
"type": "record",
"name": "Address",
"fields": [
{"name": "street", "type": "string"},
{"name": "city", "type": "string"}
],
"logicalType": "variant",
"variant-metadata-fields": "[\"street\", \"city\"]"
}
}
]
}
```
### JSON Schema
Same `@JsonPropertyDescription("logicalType: variant")` annotations as Pulsar.
### Protobuf Schema
Protobuf is supported via the same `logical_type` custom field option as Pulsar's ProtobufNative schema. Define the option once in your `.proto` file and tag each Variant field:
```protobuf theme={null}
syntax = "proto3";
import "google/protobuf/descriptor.proto";
extend google.protobuf.FieldOptions {
string logical_type = 1001;
}
message Event {
string name = 1;
string flexible_field = 2 [(logical_type) = "variant"];
map metadata = 3 [(logical_type) = "variant"];
repeated string tags = 4 [(logical_type) = "variant"];
Address address = 5 [(logical_type) = "variant"];
}
message Address {
string city = 1;
int32 zip = 2;
}
```
## Performance Optimization
Use `variant-metadata-fields` to specify fields that should be extracted as top-level columns. This accelerates query performance by enabling predicate pushdown on those fields:
```json theme={null}
"variant-metadata-fields": "[\"zip\", \"city\"]"
```
## Schema Evolution Rules for Variant
| Operation | Supported |
| ---------------------------------------- | --------------------------------------- |
| Adding new Variant fields | Yes |
| Removing existing Variant fields | Yes |
| Converting non-Variant field to Variant | No (messages sent to Dead Letter Table) |
| Converting Variant field to another type | No (messages sent to Dead Letter Table) |
For more information about the Dead Letter Table (DLT), see [Schema Evolution -- Dead Letter Table](/cloud/lakehouse/features/schema-evolution#dead-letter-table-dlt).
# Overview - Internal Tables
Source: https://docs.streamnative.io/cloud/lakehouse/internal-tables/internal-tables-overview
**Internal Tables (Coming Soon)**
Internal Tables are topics inside StreamNative Cloud that store data in Ursa Format, the native, high-performance storage layer used by StreamNative’s Cost Optimized Clusters. This capability is currently not available and will be released in an upcoming version of StreamNative Cloud.
**Key Characteristics**
* **Stored in Ursa Format** -
Data is written using a compact, high-throughput format optimized for streaming and low-latency access.
* **Fully Managed by StreamNative** -
StreamNative will handle all storage lifecycle operations — retention, compaction, indexing, and metadata.
* **StreamNative-Native Performance** -
Designed for fast ingestion, low latency, and operational efficiency within the StreamNative cloud environment.
* **Not Externally Queryable via Open Table Formats** -
Internal Tables are optimized for streaming workloads, not external analytics engines.
**When to Use Internal Tables**
* You need low-latency ingestion and high-throughput streaming.
* You prefer StreamNative to manage all storage operations end-to-end.
* You don’t require external interoperability with Iceberg/Delta or an external Lakehouse system.
Note: Internal Tables are under development and will be introduced soon. The feature description above outlines planned capabilities.
# Lakehouse Features Overview
Source: https://docs.streamnative.io/cloud/lakehouse/lakehouse-features
## Feature Matrix
| Feature | Iceberg (SDT) | Delta (SDT) | Iceberg (SBT) | Delta (SBT) |
| ---------------- | -------------- | ------------ | ------------- | ----------- |
| Schema Evolution | Supported | Supported | Coming Soon | Coming Soon |
| Partition Key | Configurable | Configurable | Coming Soon | Coming Soon |
| Upsert | Supported | Supported | Coming Soon | Coming Soon |
| Variant Type | Supported (V3) | Supported | Coming Soon | Coming Soon |
| Streaming Read | -- | -- | Coming Soon | Coming Soon |
| Analytical Query | Supported | Supported | Coming Soon | Coming Soon |
## Supported Cloud Vendors
| Provider | WAL Storage | Lakehouse Table |
| -------------------- | ----------- | --------------- |
| AWS S3 | Supported | Supported |
| Google Cloud Storage | Supported | Supported |
| Azure Blob Storage | Supported | Supported |
## Supported Schemas
| Schema Format | Supported |
| ----------------------- | --------- |
| Avro | Yes |
| JSON | Yes |
| ProtobufNative (Pulsar) | Yes |
| Protobuf (Kafka) | Yes |
Supported schema registries:
* StreamNative Kafka Schema Registry
* Confluent Schema Registry
## Feature Guides
Each feature has its own detailed guide:
* [Schema Evolution](/cloud/lakehouse/features/schema-evolution) -- How the lakehouse table evolves when the topic schema changes, including Dead Letter Table (DLT) behavior
* [Variant Type](/cloud/lakehouse/features/variant-type) -- Handle semi-structured data with Iceberg / Delta Variant type
* [Partition Key](/cloud/lakehouse/features/iceberg-partition-key) -- Configure table partitioning with Iceberg transforms
* [Upsert](/cloud/lakehouse/features/iceberg-upsert) -- Deduplication and primary key-based updates
* [Persist Extra Metadata](/cloud/lakehouse/features/persist-extra-metadata) -- Persist message-envelope metadata (offset, publish time, properties) as a `__meta` Variant column
* [Persist Key](/cloud/lakehouse/features/persist-key) -- Persist the source message key as a `__key` column
## Next Steps
* [Observability](/cloud/lakehouse/lakehouse-observability) -- Monitor lakehouse tables with metrics and Grafana dashboards
# Lakehouse Table Overview
Source: https://docs.streamnative.io/cloud/lakehouse/lakehouse-table-overview
Lakehouse Table is a zero-ETL integration that automatically converts streaming data from Apache Pulsar topics into open table formats -- Apache Iceberg and Delta Lake -- stored directly on object storage (AWS S3, GCS, Azure Blob Storage). This enables unified streaming and analytics access to the same data without building or maintaining separate data pipelines.
## Architecture
```
┌──────────────────┐
│ Pulsar Broker │
└────────┬─────────┘
│
┌───────────────┴────────────────┐
│ WAL Storage │
│ ┌──────────────────────────┐ │
│ │ Latency-Optimized: │ │
│ │ Apache BookKeeper │ │
│ ├──────────────────────────┤ │
│ │ Cost-Optimized: │ │
│ │ Object Storage │ │
│ │ (S3 / GCS / Azure) │ │
│ └──────────────────────────┘ │
└───────────────┬────────────────┘
│ Reads from both
▼
┌─────────────────────────────┐
│ Compaction Service │
│ (WAL → Parquet conversion) │
└────────────┬────────────────┘
│ Commit
▼
┌─────────────────────────────┐
│ Lakehouse Table │
│ (Iceberg / Delta Lake) │
└─────────────────────────────┘
│
┌────────────┴────────────┐
▼ ▼
External Catalog Query Engines
(Unity Catalog, S3Table, (Spark, Trino,
BigLake, Snowflake) DuckDB, Athena)
```
### WAL Storage Options
Lakehouse Table supports two WAL storage tiers:
* **Latency-optimized (Apache BookKeeper):** Low-latency writes for performance-sensitive workloads
* **Cost-optimized (Object Storage):** Direct writes to AWS S3, GCS, or Azure Blob Storage for cost efficiency
The **Compaction Service reads from both** BookKeeper and Object Storage, converts the data to Parquet format, and commits snapshots to the lakehouse catalog.
### Coordination
**Oxia** serves as the metadata store for coordination, leader election, schema storage, and offset index management.
The Compaction Service operates with a leader-worker architecture: the leader publishes compaction tasks and commits results to the lakehouse catalog, while workers perform the WAL-to-Parquet conversion.
## Table Modes
### External Table (SDT -- Stream Delivered Table)
An External Table delivers data from Pulsar topics into an external lakehouse catalog (such as Databricks Unity Catalog, Snowflake, AWS S3Table, or Google BigLake). A **separate copy** of the topic data is written to the Lakehouse table — the Pulsar topic and the Lakehouse table hold independent copies of the same records. In this mode:
* Data is written to Iceberg or Delta Lake tables managed by the external catalog as a separate copy from the Pulsar topic
* Analytical access via standard table APIs (Spark, Trino, DuckDB, Athena, etc.)
* Supports **upsert**, **partition key**, and **schema evolution**
* The external catalog governs data lifecycle (retention, deletion) for the Lakehouse copy independently of the Pulsar topic
* Streaming reads with offset semantics are **not** supported on the delivered data
**Use External Tables when:** you want to deliver streaming data into curated lakehouse tables for analytics, integrate with existing data platforms, or need upsert/deduplication capabilities.
### Internal Table (SBT -- Stream Backed Table)
> **Coming Soon** -- Internal Table support is under active development.
An Internal Table is managed entirely by Ursa Storage. The Pulsar topic and the Lakehouse table **share the same single copy of data** — there is no separate write to the Lakehouse table. The same physical data supports both streaming reads (with offset tracking and replay) and analytical queries -- true stream-table duality with zero data duplication.
## Supported Cluster Profiles and Protocols
StreamNative Private Cloud offers two cluster types (Pulsar and Kafka), each with two performance profiles (latency-optimized and cost-optimized). Lakehouse delivery support depends on the combination of cluster type, profile, and producer protocol.
| Cluster Type | Profile | Producer Protocol | Lakehouse Delivery |
| ------------ | ----------------- | ----------------- | ------------------ |
| Pulsar | Latency-optimized | Pulsar | Supported |
| Pulsar | Latency-optimized | Kafka | Coming Soon |
| Pulsar | Cost-optimized | Kafka | Supported |
| Pulsar | Cost-optimized | Pulsar | Not yet supported |
| Kafka | Cost-optimized | Kafka | Supported |
| Kafka | Latency-optimized | Kafka | Coming Soon |
Notes:
* A **Pulsar latency-optimized** cluster uses Apache BookKeeper as the WAL tier. Topic data produced via the Pulsar protocol can be delivered to Lakehouse today; Kafka-protocol delivery is on the roadmap.
* A **Pulsar cost-optimized** cluster uses object storage as the WAL tier. Topic data produced via the Kafka protocol is delivered to Lakehouse; the Pulsar protocol is not yet supported on this profile.
* A **Kafka cost-optimized** cluster delivers Kafka topic data to Lakehouse today.
* A **Kafka latency-optimized** cluster will support Lakehouse delivery in a future release.
## Supported Formats
| Format | Status |
| -------------- | --------- |
| Apache Iceberg | Supported |
| Delta Lake | Supported |
## Supported Cloud Storage
| Provider | WAL Storage | Lakehouse Table |
| -------------------- | ----------- | --------------- |
| AWS S3 | Supported | Supported |
| Google Cloud Storage | Supported | Supported |
| Azure Blob Storage | Supported | Supported |
## Supported Catalogs
Catalog support varies by cloud provider:
| Catalog | Table Format | AWS | GCP | Azure |
| ------------------------------------------ | ------------ | --------- | --------- | --------- |
| Databricks Unity Catalog (Managed Iceberg) | Iceberg | Supported | Supported | Supported |
| Databricks Unity Catalog (Delta Lake) | Delta Lake | Supported | Supported | Supported |
| Snowflake Horizon Catalog | Iceberg | Supported | Supported | Supported |
| Snowflake Open Catalog (Polaris) | Iceberg | Supported | Supported | Supported |
| AWS S3Table | Iceberg | Supported | -- | -- |
| Google BigLake | Iceberg | -- | Supported | -- |
## Topic to lakehouse identifier mapping
Each Pulsar topic maps to exactly **one** Lakehouse table. The mapping is 1:1 regardless of how many partitions the topic has — data from all partitions of a partitioned topic is consolidated into a single Lakehouse table.
When data is delivered from a Pulsar topic to a lakehouse table, the topic's tenant, namespace, and topic name are mapped to a catalog **namespace** and a **table name**. The mapping rules differ by catalog type because Pulsar allows characters (`/`, `.`, `-`, `:`) that are not valid in many catalog identifiers.
The compaction service applies the following rules.
### Iceberg with hierarchical catalogs (Snowflake Open Catalog, Snowflake Horizon, Iceberg REST, Iceberg Hadoop)
The original Pulsar identifiers are used unchanged:
* Catalog namespace: `.` (two-level)
* Table name: the topic local name (the part after the namespace)
For example, the topic `persistent://my-tenant/my-namespace/orders` is mapped to namespace `my-tenant.my-namespace` and table `orders`.
### Iceberg with flat-namespace catalogs (AWS S3Tables, Google BigLake, Hive)
These catalogs only accept a single-level namespace, so the tenant and namespace are flattened into one identifier with a cluster-name prefix. Each component is escaped to remove invalid characters:
| Source character | Replacement |
| ---------------- | ------------------------- |
| `/` | `___` (three underscores) |
| `.` | `_` (one underscore) |
| `-` | `__` (two underscores) |
| `:` | `____` (four underscores) |
* Catalog namespace: `__` (default cluster prefix is `pulsar`)
* Table name (S3Tables): the topic local name with the same character escapes applied
* Table name (BigLake, Hive): the topic local name as-is
For example, with the default cluster prefix `pulsar`, topic `persistent://public-v1/default.v2/test-table-v1`:
* On **AWS S3Tables**: namespace `pulsar_public__v1_default_v2`, table `test__table__v1`
* On **Google BigLake**: namespace `pulsar_public__v1_default_v2`, table `test-table-v1`
### Databricks Unity Catalog (Iceberg or Delta Lake)
Unity Catalog uses a three-level identifier (`catalog.schema.table`). The compaction service writes all topics into a single schema and encodes the full Pulsar topic path into the **table name**, so each catalog table maps 1:1 to a Pulsar topic. The full topic path `//` is flattened with these escapes:
| Source character | Replacement |
| ---------------- | ------------------------- |
| `/` | `__` (two underscores) |
| `.` | `____` (four underscores) |
| `-` | `___` (three underscores) |
For example, topic `persistent://public/default/test-topic` is mapped to table name `public__default__test___topic`. Topic `persistent://public/default/v1.events` is mapped to `public__default__v1____events`.
## Limitations
### Schema limitations
The following topic schema constructs are not supported when delivering data to a Lakehouse Table:
* **Recursive schemas:** Schemas that reference themselves -- directly or indirectly -- are not supported. For example, a record with a field whose type is the same record (such as a tree node that holds a list of child nodes of the same type). Iceberg and Delta Lake require a fixed, finite column structure, which cannot represent a self-referential schema. Topics that use a recursive schema cannot be delivered to a Lakehouse Table.
## Next Steps
* [Deploy Lakehouse Table](/cloud/lakehouse/deploy-lakehouse-table) -- Set up the infrastructure with `private-cloud.yaml`
* [Prepare Lakehouse Catalogs](/cloud/lakehouse/prepare-lakehouse-catalogs) -- Set up your external catalog service
* [Dynamic Configuration Guide](/cloud/lakehouse/dynamic-configuration) -- Cluster-name prefix, override priority, and the full set of dynamic configuration keys
* [Register Lakehouse Catalogs](/cloud/lakehouse/catalogs/register-catalog) -- Connect catalogs to the compaction service
* [Enable Lakehouse Integration](/cloud/lakehouse/enable-lakehouse-integration) -- Enable at cluster, namespace, or topic level
* Features:
* [Schema Evolution](/cloud/lakehouse/features/schema-evolution)
* [Variant Type](/cloud/lakehouse/features/variant-type)
* [Partition Key](/cloud/lakehouse/features/iceberg-partition-key)
* [Upsert](/cloud/lakehouse/features/iceberg-upsert)
* [Persist Key](/cloud/lakehouse/features/persist-key)
* [Persist Extra Metadata](/cloud/lakehouse/features/persist-extra-metadata)
* [Observability](/cloud/lakehouse/lakehouse-observability) -- Metrics, alerts, and Grafana dashboard
# Overview - Lakehouse Tables
Source: https://docs.streamnative.io/cloud/lakehouse/lakehouse-tables-overview
**StreamNative Lakehouse Tables**
StreamNative Lakehouse Tables provide a unified way to expose streaming topics as open table format objects—such as Apache Iceberg and Delta Lake—directly within StreamNative Cloud. With Lakehouse Tables, data produced to Pulsar or Kafka-compatible topics can be automatically stored in object storage in a transactional, analytics-ready table format. This enables seamless integration between real-time data streams and downstream analytics, AI/ML, and governance systems.
**Overview**
StreamNative Lakehouse Tables bridge the gap between streaming and batch systems by converting message data from topics into table-backed datasets. Each Lakehouse Table maintains:
* Metadata (schema, manifest lists, snapshots)
* Data files (Parquet/columnar format)
* Transaction logs (for table evolution)
These components reside in user-controlled object storage, ensuring low cost, high durability, and interoperability with a broad ecosystem of tools.
**Key Capabilities**
**1. Open Table Format Support**
StreamNative Lakehouse Tables support industry-standard formats:
* Apache Iceberg
* Delta Lake (Delta 2.0 and above)
This ensures compatibility with engines such as Databricks, Snowflake, Spark, Trino, Flink, BigQuery, StarTree, and more.
**2. Native Topic-to-Table Mapping**
Each table is backed by one or more StreamNative topics. Data is automatically:
* Ingested from the streaming topic
* Serialized into Parquet files
* Committed into the table as immutable snapshots
* Made available for SQL queries and analytical engines
This provides a streaming-first lakehouse architecture without external ingestion pipelines.
**3. Object Storage as the Source of Truth**
All table artifacts are stored in object storage such as:
* Amazon S3
* Google Cloud Storage
* Azure Blob Storage
This enables low-cost storage, independent scaling, and easy interoperability.
**4. Schema-Aware and Schema-Safe**
Lakehouse Tables use StreamNative’s schema registry to ensure:
* Schema inference from topics
* Backward/forward compatible evolution
* Safe writes with schema enforcement
* Automatic mapping to Iceberg/Delta schemas
* Users retain full control over table evolution policies.
**5. Transactional Guarantees**
Using open table format guarantees, Lakehouse Tables support:
* ACID transactions
* Snapshot isolation
* Time travel (via historical snapshots)
* Incremental reads
This brings reliability and consistency to streaming data workflows.
6. Full Interoperability with Data and AI Platforms
Once a table is materialized in Iceberg or Delta Lake format, it is fully queryable by:
* Databricks
* Snowflake
* BigQuery Managed Tables
* Apache Spark, Flink, and Trino
* StarTree and Pinot
* DuckDB
* pandas & PyArrow
No connectors or intermediate ETL is required.
# BigLake for Iceberg
Source: https://docs.streamnative.io/cloud/lakehouse/prepare-catalogs/biglake/iceberg
This guide describes how to prepare a Google BigLake metastore for use with StreamNative Ursa as an Iceberg REST catalog.
For background, see the Google Cloud documentation: [Use the BigLake metastore Iceberg REST catalog](https://docs.cloud.google.com/biglake/docs/blms-rest-catalog).
## Prerequisites
* A GCP project with permissions to create BigLake catalogs and modify IAM roles
* A StreamNative Ursa cluster running on GCP
## 1. Create a BigLake Catalog
In the Google Cloud Console, search for **BigLake**.
Create a new catalog by selecting a Cloud Storage bucket.
> **Important:**
>
> * The bucket must be in the **same region** as your StreamNative Ursa cluster, otherwise cross-region traffic and latency are introduced.
> * BigLake does not support sub-directories within a bucket. Each BigLake catalog maps to exactly one bucket (1:1 mapping).
In the **Authentication** section, choose **Credential vending mode**.
After the catalog is created, view the catalog details to obtain the **REST Catalog URI**, **GCS Warehouse**, and **Project**.
Click **Set bucket permissions** to grant the BigLake service account access to the bucket.
## 2. Grant IAM Roles to the Ursa Broker Service Account
Locate the StreamNative Ursa broker service account (the format is typically `iamaccount-@.iam.gserviceaccount.com`).
In the GCP IAM console, grant the broker service account the following roles:
* **BigLake Editor**
* **Storage Object User**
* **Service Usage Consumer**
## Catalog Information Summary
When the steps above are complete, collect the following values for the StreamNative Ursa compaction service. Several values are fixed for any BigLake catalog -- copy them as-is.
| Value | Description |
| -------------------------------------------- | -------------------------------------------------------------------------------------------------------- |
| `iceberg.catalog-backend` | `BIGLAKE` |
| `iceberg.type` | `rest` |
| `iceberg.uri` | The **REST Catalog URI** from step 1 (typically `https://biglake.googleapis.com/iceberg/v1/restcatalog`) |
| `iceberg.warehouse` | The **GCS Warehouse** from step 1 (e.g., `gs://`) |
| `iceberg.header.x-goog-user-project` | The **Project** from step 1 |
| `iceberg.rest.auth.type` | `org.apache.iceberg.gcp.auth.GoogleAuthManager` (fixed) |
| `iceberg.io-impl` | `org.apache.iceberg.gcp.gcs.GCSFileIO` (fixed) |
| `iceberg.rest-metrics-reporting-enabled` | `false` (fixed -- BigLake does not yet support REST metrics reporting) |
| `iceberg.header.X-Iceberg-Access-Delegation` | `vended-credentials` (fixed) |
For the next steps, see [Register Lakehouse Catalogs](/cloud/lakehouse/catalogs/register-catalog).
# Horizon Catalog for Iceberg on AWS
Source: https://docs.streamnative.io/cloud/lakehouse/prepare-catalogs/horizon-catalog/iceberg/aws
This guide describes how to prepare a Snowflake Horizon Catalog for use with StreamNative Ursa as an Iceberg catalog on AWS.
For background, see the Snowflake documentation: [Write to Apache Iceberg tables using an external query engine through Snowflake Horizon Catalog](https://docs.snowflake.com/en/LIMITEDACCESS/iceberg/tables-iceberg-write-using-external-write-engine-snowflake-horizon).
## Prerequisites
* A Snowflake account with Horizon Catalog enabled
* An AWS account with permissions to create S3 buckets and IAM roles
* The `ACCOUNTADMIN` role in Snowflake (required for several SQL operations below)
## 1. Create an External Volume
The Horizon Catalog uses a Snowflake **External Volume** to access object storage. Reference: [Tutorial: Create your first Apache Iceberg table](https://docs.snowflake.com/en/user-guide/tutorials/create-your-first-iceberg-table#create-a-table).
### 1.1 Identify the Snowflake Account Region
Find the region of your Snowflake account so the S3 bucket can be created in the same region.
### 1.2 Create an S3 Bucket
Create an S3 bucket in the AWS console, in the same region as your Snowflake account.
### 1.3 Create an IAM Policy
Create an IAM policy granting access to the bucket. Replace `` with the bucket name from step 1.2.
```json theme={null}
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:GetObject",
"s3:GetObjectVersion",
"s3:DeleteObject",
"s3:DeleteObjectVersion"
],
"Resource": "arn:aws:s3:::/*"
},
{
"Effect": "Allow",
"Action": [
"s3:ListBucket",
"s3:GetBucketLocation"
],
"Resource": "arn:aws:s3:::",
"Condition": {
"StringLike": {
"s3:prefix": ["*"]
}
}
}
]
}
```
### 1.4 Create an IAM Role
Create an IAM role with an External ID (for example, `iceberg_table_external_id`). The trust policy will be updated in step 1.6.
Attach the policy from step 1.3 to the role.
### 1.5 Create the External Volume in Snowflake
Switch to the `ACCOUNTADMIN` role and run the following SQL, substituting your values:
```sql theme={null}
CREATE OR REPLACE EXTERNAL VOLUME
STORAGE_LOCATIONS = (
(
NAME = ''
STORAGE_PROVIDER = 'S3'
STORAGE_BASE_URL = 's3:///'
STORAGE_AWS_ROLE_ARN = 'arn:aws:iam:::role/'
STORAGE_AWS_EXTERNAL_ID = ''
)
)
ALLOW_WRITES = TRUE;
```
If the command fails with a permission error, ensure you are using the `ACCOUNTADMIN` role:
### 1.6 Configure the Trust Relationship
After the external volume is created, retrieve the Snowflake-generated IAM user ARN:
```sql theme={null}
DESC EXTERNAL VOLUME ;
```
The `STORAGE_AWS_IAM_USER_ARN` field contains the value (for example, `arn:aws:iam:::user/`).
Return to the AWS IAM console and update the trust policy of the role created in step 1.4 to allow `STORAGE_AWS_IAM_USER_ARN` to assume the role.
## 2. Configure Access Control
> **Note:** If you already have roles configured with access to the Iceberg tables you want to use, you can skip this section.
For details, see [Configuring access control](https://docs.snowflake.com/en/user-guide/security-access-control-configure).
```sql theme={null}
GRANT ROLE ACCOUNTADMIN, SYSADMIN TO USER ;
```
## 3. Create the Catalog Database
Switch to `ACCOUNTADMIN` and create the catalog database in the Snowflake UI. Then bind the database to the external volume:
```sql theme={null}
ALTER DATABASE SET CATALOG = 'SNOWFLAKE';
ALTER DATABASE SET EXTERNAL_VOLUME = '';
```
## 4. Obtain an Access Token
Snowflake Horizon supports three authentication methods: External OAuth, Key-pair authentication, and Programmatic Access Token (PAT). This guide uses **PAT**.
### 4.1 Create an Authentication Policy
Switch to `ACCOUNTADMIN` and run:
```sql theme={null}
USE ;
CREATE AUTHENTICATION POLICY
PAT_POLICY=(NETWORK_POLICY_EVALUATION = ENFORCED_NOT_REQUIRED);
ALTER ACCOUNT SET AUTHENTICATION POLICY ;
ALTER AUTHENTICATION POLICY
SET AUTHENTICATION_METHODS = ('OAUTH', 'PASSWORD', 'PROGRAMMATIC_ACCESS_TOKEN');
ALTER AUTHENTICATION POLICY
SET PAT_POLICY = (MAX_EXPIRY_IN_DAYS=365, DEFAULT_EXPIRY_IN_DAYS=365);
ALTER USER IF EXISTS ADD PROGRAMMATIC ACCESS TOKEN
DAYS_TO_EXPIRY = 365
COMMENT = 'PAT for StreamNative Ursa';
```
Record the generated PAT.
### 4.2 Verify the Endpoint
Generate an OAuth access token using the PAT and verify the Horizon REST endpoint:
```bash theme={null}
curl -i --fail -X POST \
"https://.snowflakecomputing.com/polaris/api/catalog/v1/oauth/tokens" \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'grant_type=client_credentials' \
--data-urlencode 'scope=session:role:' \
--data-urlencode 'client_secret='
curl -i --fail -X GET \
"https://.snowflakecomputing.com/polaris/api/catalog/v1/config?warehouse=" \
-H "Authorization: Bearer " \
-H "Content-Type: application/json"
```
### 4.3 Grant Permissions
```sql theme={null}
GRANT ROLE PUBLIC TO USER ;
GRANT USAGE ON DATABASE TO ROLE PUBLIC;
GRANT USAGE ON EXTERNAL VOLUME TO ROLE PUBLIC;
```
## Catalog Information Summary
When the steps above are complete, collect the following values for the StreamNative Ursa compaction service:
```sql theme={null}
-- Determine the URI prefix
SELECT CURRENT_ORGANIZATION_NAME() || '-' || CURRENT_ACCOUNT_NAME();
```
| Value | Description |
| -------------------- | ----------------------------------------------------------------------------- |
| `iceberg.uri` | `https://-.snowflakecomputing.com/polaris/api/catalog` |
| `iceberg.warehouse` | The catalog database name created in step 3 |
| `iceberg.credential` | The PAT generated in step 4.1 |
| `iceberg.scope` | `session:role:` (e.g., `session:role:PUBLIC`) |
For the next steps, see [Register Lakehouse Catalogs](/cloud/lakehouse/catalogs/register-catalog).
# Open Catalog for Iceberg on AWS
Source: https://docs.streamnative.io/cloud/lakehouse/prepare-catalogs/open-catalog/iceberg/aws
This guide describes how to prepare a Snowflake Open Catalog (Polaris) for use with StreamNative Ursa as an Iceberg catalog on AWS.
> **Important:** Polaris does not support reading buckets from a different region. The StreamNative Ursa cluster, the storage bucket, and the Polaris catalog must all reside in the **same AWS region**.
## Prerequisites
* A Snowflake standard account
* An AWS account with permissions to create S3 buckets and IAM roles
* Access to the Snowflake Open Catalog feature (request via your Snowflake account team if not yet enabled)
## 1. Create a Snowflake Open Catalog Account
The Snowflake Open Catalog console requires a dedicated **Open Catalog** account. From the standard Snowflake console, navigate to **Admin -> Accounts** and use the toggle to **Create Snowflake Open Catalog Account**.
Configure the account with:
* **Cloud:** AWS
* **Region:** the region in which your S3 bucket resides (for example, `US East (Ohio)`)
* **Edition:** any
Provide an admin username and password.
After creation, click the **Account URL** to sign in to the Open Catalog console.
## 2. Create an S3 Bucket
Create an S3 bucket in the same region as the Open Catalog account.
## 3. Create an IAM Policy
Navigate to **AWS IAM -> Policies -> Create policy**.
Paste the following policy, replacing the bucket name and subpath with your values:
```json theme={null}
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:GetObject",
"s3:GetObjectVersion",
"s3:DeleteObject",
"s3:DeleteObjectVersion"
],
"Resource": "arn:aws:s3::://*"
},
{
"Effect": "Allow",
"Action": [
"s3:ListBucket",
"s3:GetBucketLocation"
],
"Resource": "arn:aws:s3:::/",
"Condition": {
"StringLike": {
"s3:prefix": ["*"]
}
}
}
]
}
```
## 4. Create an IAM Role
Navigate to **AWS IAM -> Roles -> Create role** and configure:
* **Trusted entity type:** AWS account
* **An AWS account:** This account
* **Enable External ID** with a unique value (you will reference this when creating the Polaris catalog)
Attach the policy created in step 4.
Provide a role name and create the role.
Record the role ARN (for example, `arn:aws:iam:::role/`).
## 5. Create the Polaris Catalog
In the Snowflake Open Catalog console, create a new catalog.
Configure the catalog with:
* **External:** disabled
* **Storage provider:** S3
* **Default base location:** `s3:///` (the path from step 3)
* **S3 role ARN:** the role ARN recorded in step 5
* **External ID:** the External ID configured in step 5
Open the catalog details and record the **IAM user ARN** that Polaris uses to access AWS. You will use this in step 7 to update the trust policy of the IAM role.
## 6. Update the IAM Role Trust Policy
Return to the AWS IAM console, open the role created in step 5, and edit the trust relationship.
Update `Principal.AWS` to the Polaris IAM user ARN recorded in step 6.
Click **Update policy**.
## 7. Create a Connection (Service Principal)
In the Open Catalog console, create a new connection that StreamNative Ursa will use to authenticate.
Configure with:
* **Name:** any name
* **Create new principal role:** enabled
* **Principal Role Name:** any name
After creation, record the **Client ID** and **Client Secret** -- the secret cannot be retrieved later.
## 8. Create a Catalog Role and Grant Privileges
Navigate to **Catalogs -> \[your catalog] -> Roles -> + Catalog Role** and create a role with the following privileges:
* `NAMESPACE_CREATE`
* `NAMESPACE_LIST`
* `NAMESPACE_READ_PROPERTIES`
* `NAMESPACE_WRITE_PROPERTIES`
* `TABLE_LIST`
* `TABLE_CREATE`
* `TABLE_WRITE_DATA`
* `TABLE_READ_DATA`
* `TABLE_READ_PROPERTIES`
* `TABLE_WRITE_PROPERTIES`
Click **Grant to Principals Role** and grant the catalog role to the principal role created in step 8.
For background on the relationship between catalogs, catalog roles, principal roles, and principals, see the [Polaris Quick Start](https://polaris.io/#section/Quick-Start/Defining-a-Catalog).
## Catalog Information Summary
When the steps above are complete, collect the following values for the StreamNative Ursa compaction service:
| Value | Description |
| -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `iceberg.uri` | Polaris REST endpoint (e.g., `https://..aws.snowflakecomputing.com/polaris/api/catalog`). The format follows the URL of your Polaris console. |
| `iceberg.warehouse` | The Polaris catalog name created in step 6 |
| `iceberg.credential` | `:` from step 8 |
| `iceberg.scope` | `PRINCIPAL_ROLE:ALL` |
## Table Maintenance
Snowflake Open Catalog (Polaris) and the Hadoop catalog do **not** run table maintenance on your behalf. Streaming writes from the StreamNative Ursa compaction service produce many small Parquet files and accumulate snapshot history over time, which degrades query performance and inflates storage costs. You are responsible for scheduling and running maintenance against every Iceberg table written by Ursa.
Run the maintenance operations below on a regular schedule. They are provided as [Apache Iceberg Spark stored procedures](https://iceberg.apache.org/docs/latest/spark-procedures/) and can be triggered from any Spark cluster (Databricks, AWS EMR, AWS Glue, GCP Dataproc, or self-managed Spark) that has the Iceberg Spark runtime, catalog credentials, and IAM access to the warehouse bucket.
**Maintenance operations**
| Operation | Purpose | Suggested cadence |
| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------- |
| `rewrite_data_files` | Compact small Parquet files into fewer, larger files. Reduces file-listing overhead and improves scan performance. | Hourly to daily, depending on ingestion rate |
| `expire_snapshots` | Drop snapshots older than the retention window so their data and manifest files can be cleaned up. | Daily; retain at least 1–7 days so in-flight readers and time-travel queries keep working |
| `remove_orphan_files` | Delete files in the table location that are no longer referenced by any snapshot (typically left behind by failed or partial writes). | Weekly |
| `rewrite_manifests` | Rewrite manifest files so they align with the current partition layout. Improves query planning time. | Weekly, or after large schema or partition changes |
**Example: run maintenance from Spark**
The following examples assume the catalog has been registered in Spark as ``. Replace ``, ``, and `` with your values.
```sql theme={null}
-- Compact small files. Iceberg targets files smaller than the default 512 MB.
CALL .system.rewrite_data_files(table => '.');
-- Expire snapshots older than 3 days; keep the 5 most recent snapshots.
CALL .system.expire_snapshots(
table => '.',
older_than => TIMESTAMP '2026-05-20 00:00:00',
retain_last => 5
);
-- Remove orphan files older than 7 days.
CALL .system.remove_orphan_files(
table => '.',
older_than => TIMESTAMP '2026-05-20 00:00:00'
);
-- Rewrite manifests to match the current partition layout.
CALL .system.rewrite_manifests(table => '.');
```
**Operational guidance**
* **Credentials.** The principal that runs maintenance must have catalog privileges to read and write the target table (for example, the same `TABLE_READ_DATA`, `TABLE_WRITE_DATA`, `TABLE_READ_PROPERTIES`, and `TABLE_WRITE_PROPERTIES` privileges configured for the Ursa compaction service) and IAM access to the warehouse bucket so it can read and rewrite the underlying data files. With the Hadoop catalog there is no catalog service to authenticate against — only the bucket IAM access is required.
* **Concurrency.** Iceberg uses optimistic concurrency control. If maintenance commits race with the Ursa compaction writer, one of them retries. Schedule heavy operations (`rewrite_data_files`, `rewrite_manifests`) during low-write windows when possible.
* **Retention vs. time travel.** `expire_snapshots` and `remove_orphan_files` permanently delete files. Choose a retention window that exceeds the longest expected read query and your time-travel SLA.
* **Schedule the workload.** Most teams orchestrate these procedures from Databricks Jobs, AWS EMR steps, Airflow, Dagster, or a Kubernetes `CronJob`. Pick a scheduler that fits your existing operational stack.
* **Reference.** See the [Iceberg Spark procedures](https://iceberg.apache.org/docs/latest/spark-procedures/#metadata-management) documentation for the full parameter list, including options for partial rewrites (`where`), file-size targets, and merge-on-read delete file compaction.
For the next steps, see [Register Lakehouse Catalogs](/cloud/lakehouse/catalogs/register-catalog).
# Open Catalog for Iceberg on Azure
Source: https://docs.streamnative.io/cloud/lakehouse/prepare-catalogs/open-catalog/iceberg/azure
This guide describes how to prepare a Snowflake Open Catalog (Polaris) for use with StreamNative Ursa as an Iceberg catalog on Microsoft Azure.
## Prerequisites
* A Snowflake standard account
* An Azure subscription with permissions to create storage accounts and configure trusted apps
* Access to the Snowflake Open Catalog feature
## 1. Create a Snowflake Open Catalog Account
The Snowflake Open Catalog console requires a dedicated **Open Catalog** account. From the standard Snowflake console, navigate to **Admin -> Accounts** and use the toggle to **Create Snowflake Open Catalog Account**.
Configure the account with:
* **Cloud:** AWS or Azure (per Polaris availability)
* **Region:** the region in which your storage container resides
* **Edition:** any
Provide an admin username and password.
After creation, click the **Account URL** to sign in to the Open Catalog console.
## 2. Collect Azure Account Information
### 2.1 Azure Tenant ID
In the Azure portal, search for **Tenant properties** and record the **Tenant ID**.
### 2.2 Storage Service Endpoint
In the Azure portal, navigate to **Storage accounts**, open the target storage account, and click **Settings -> Endpoints**. Record the **Blob service** primary endpoint (for example, `https://.blob.core.windows.net/`).
### 2.3 Create a Container
In the storage account, navigate to **Data storage -> Containers -> + Container** and create a new container.
## 3. Create the Polaris Catalog
In the Snowflake Open Catalog console, create a new catalog.
> **Important:** The StreamNative compaction service writes data using the AzureDFS protocol, so the Polaris catalog must use the same protocol. Use `abfss://@.dfs.core.windows.net` (note `dfs`, not `blob`).
Configure the catalog with:
* **External:** disabled
* **Storage provider:** AZURE
* **Default base location:** `abfss://@.dfs.core.windows.net`
* **Azure tenant ID:** the value from step 2.1
## 4. Create a Trusted App in Azure
Open the catalog details and record the values of `AZURE_CONSENT_URL` and `AZURE_MULTI_TENANT_APP_NAME`.
Open the `AZURE_CONSENT_URL` in a browser and click **Accept**. This redirects to Snowflake and creates a trusted app in Azure. The trusted app name is the portion of `AZURE_MULTI_TENANT_APP_NAME` before the underscore.
> **Note:** Provisioning the trusted app in Azure can take several minutes.
## 5. Grant Container Permissions to the Trusted App
In the Azure portal, navigate to the storage account's **Access Control (IAM) -> + Add -> Add role assignment**.
Search for **Storage Blob Data** and select **Storage Blob Data Contributor**.
Click **Select members**, search for the trusted app name from step 4, select it, and click **Review + assign**.
## 6. Create a Connection (Service Principal)
In the Open Catalog console, create a new connection that StreamNative Ursa will use to authenticate.
Configure with:
* **Name:** any name
* **Create new principal role:** enabled
* **Principal Role Name:** any name
After creation, record the **Client ID** and **Client Secret** -- the secret cannot be retrieved later.
## 7. Create a Catalog Role and Grant Privileges
Navigate to **Catalogs -> \[your catalog] -> Roles -> + Catalog Role** and create a role with the following privileges:
* `NAMESPACE_CREATE`
* `NAMESPACE_READ_PROPERTIES`
* `TABLE_CREATE`
* `TABLE_WRITE_DATA`
* `TABLE_READ_DATA`
Click **Grant to Principals Role** and grant the catalog role to the principal role created in step 6.
## Catalog Information Summary
When the steps above are complete, collect the following values for the StreamNative Ursa compaction service:
| Value | Description |
| -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `iceberg.uri` | Polaris REST endpoint (e.g., `https://..snowflakecomputing.com/polaris/api/catalog`). The format follows the URL of your Polaris console. |
| `iceberg.warehouse` | The Polaris catalog name created in step 3 |
| `iceberg.credential` | `:` from step 6 |
| `iceberg.scope` | `PRINCIPAL_ROLE:ALL` |
## Table Maintenance
Snowflake Open Catalog (Polaris) and the Hadoop catalog do **not** run table maintenance on your behalf. Streaming writes from the StreamNative Ursa compaction service produce many small Parquet files and accumulate snapshot history over time, which degrades query performance and inflates storage costs. You are responsible for scheduling and running maintenance against every Iceberg table written by Ursa.
Run the maintenance operations below on a regular schedule. They are provided as [Apache Iceberg Spark stored procedures](https://iceberg.apache.org/docs/latest/spark-procedures/) and can be triggered from any Spark cluster (Databricks, AWS EMR, AWS Glue, GCP Dataproc, or self-managed Spark) that has the Iceberg Spark runtime, catalog credentials, and IAM access to the warehouse bucket.
**Maintenance operations**
| Operation | Purpose | Suggested cadence |
| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------- |
| `rewrite_data_files` | Compact small Parquet files into fewer, larger files. Reduces file-listing overhead and improves scan performance. | Hourly to daily, depending on ingestion rate |
| `expire_snapshots` | Drop snapshots older than the retention window so their data and manifest files can be cleaned up. | Daily; retain at least 1–7 days so in-flight readers and time-travel queries keep working |
| `remove_orphan_files` | Delete files in the table location that are no longer referenced by any snapshot (typically left behind by failed or partial writes). | Weekly |
| `rewrite_manifests` | Rewrite manifest files so they align with the current partition layout. Improves query planning time. | Weekly, or after large schema or partition changes |
**Example: run maintenance from Spark**
The following examples assume the catalog has been registered in Spark as ``. Replace ``, ``, and `` with your values.
```sql theme={null}
-- Compact small files. Iceberg targets files smaller than the default 512 MB.
CALL .system.rewrite_data_files(table => '.');
-- Expire snapshots older than 3 days; keep the 5 most recent snapshots.
CALL .system.expire_snapshots(
table => '.',
older_than => TIMESTAMP '2026-05-20 00:00:00',
retain_last => 5
);
-- Remove orphan files older than 7 days.
CALL .system.remove_orphan_files(
table => '.',
older_than => TIMESTAMP '2026-05-20 00:00:00'
);
-- Rewrite manifests to match the current partition layout.
CALL .system.rewrite_manifests(table => '.');
```
**Operational guidance**
* **Credentials.** The principal that runs maintenance must have catalog privileges to read and write the target table (for example, the same `TABLE_READ_DATA`, `TABLE_WRITE_DATA`, `TABLE_READ_PROPERTIES`, and `TABLE_WRITE_PROPERTIES` privileges configured for the Ursa compaction service) and IAM access to the warehouse bucket so it can read and rewrite the underlying data files. With the Hadoop catalog there is no catalog service to authenticate against — only the bucket IAM access is required.
* **Concurrency.** Iceberg uses optimistic concurrency control. If maintenance commits race with the Ursa compaction writer, one of them retries. Schedule heavy operations (`rewrite_data_files`, `rewrite_manifests`) during low-write windows when possible.
* **Retention vs. time travel.** `expire_snapshots` and `remove_orphan_files` permanently delete files. Choose a retention window that exceeds the longest expected read query and your time-travel SLA.
* **Schedule the workload.** Most teams orchestrate these procedures from Databricks Jobs, AWS EMR steps, Airflow, Dagster, or a Kubernetes `CronJob`. Pick a scheduler that fits your existing operational stack.
* **Reference.** See the [Iceberg Spark procedures](https://iceberg.apache.org/docs/latest/spark-procedures/#metadata-management) documentation for the full parameter list, including options for partial rewrites (`where`), file-size targets, and merge-on-read delete file compaction.
For the next steps, see [Register Lakehouse Catalogs](/cloud/lakehouse/catalogs/register-catalog).
# Open Catalog for Iceberg on GCP
Source: https://docs.streamnative.io/cloud/lakehouse/prepare-catalogs/open-catalog/iceberg/gcp
This guide describes how to prepare a Snowflake Open Catalog (Polaris) for use with StreamNative Ursa as an Iceberg catalog on Google Cloud Platform (GCP).
> **Important:** Polaris does not support reading buckets from a different region. The StreamNative Ursa cluster, the GCS bucket, and the Polaris catalog must all reside in the **same region**.
## Prerequisites
* A Snowflake standard account
* A GCP project with permissions to create GCS buckets and IAM roles
* Access to the Snowflake Open Catalog feature
## 1. Create a Snowflake Open Catalog Account
The Snowflake Open Catalog console requires a dedicated **Open Catalog** account. From the standard Snowflake console, navigate to **Admin -> Accounts** and use the toggle to **Create Snowflake Open Catalog Account**.
Configure the account with:
* **Cloud:** GCP
* **Region:** the region in which your GCS bucket resides
* **Edition:** any
Provide an admin username and password.
After creation, click the **Account URL** to sign in to the Open Catalog console.
## 2. Create the Polaris Catalog
In the Snowflake Open Catalog console, create a new catalog.
Configure the catalog with:
* **External:** disabled
* **Storage provider:** GCS
* **Default base location:** the GCS path used by the Ursa cluster (`gs:///`)
Open the catalog details and record the **GCP\_SERVICE\_ACCOUNT** value. Polaris uses this service account to access GCS, so it must be granted permission on the bucket.
## 3. Grant Bucket Permissions to the Polaris Service Account
### 3.1 Create a Custom IAM Role
In the GCP console, navigate to **IAM & Admin -> Roles -> Create role** and add the following permissions:
* `storage.buckets.get`
* `storage.objects.create`
* `storage.objects.delete`
* `storage.objects.get`
* `storage.objects.list`
### 3.2 Assign the Role to the Polaris Service Account
Open the bucket, navigate to **PERMISSIONS -> View BY PRINCIPALS -> GRANT ACCESS**.
Add the **GCP\_SERVICE\_ACCOUNT** from step 3, choose the role created in step 4.1, and click **SAVE**.
## 4. Create a Connection (Service Principal)
In the Open Catalog console, create a new connection that StreamNative Ursa will use to authenticate.
Configure with:
* **Name:** any name
* **Create new principal role:** enabled
* **Principal Role Name:** any name
After creation, record the **Client ID** and **Client Secret** -- the secret cannot be retrieved later.
## 5. Create a Catalog Role and Grant Privileges
Navigate to **Catalogs -> \[your catalog] -> Roles -> + Catalog Role** and create a role with the following privileges:
* `NAMESPACE_CREATE`
* `NAMESPACE_LIST`
* `NAMESPACE_READ_PROPERTIES`
* `NAMESPACE_WRITE_PROPERTIES`
* `TABLE_LIST`
* `TABLE_CREATE`
* `TABLE_WRITE_DATA`
* `TABLE_READ_DATA`
* `TABLE_READ_PROPERTIES`
* `TABLE_WRITE_PROPERTIES`
Click **Grant to Principals Role** and grant the catalog role to the principal role created in step 5.
For background on the relationship between catalogs, catalog roles, principal roles, and principals, see the [Polaris Quick Start](https://polaris.io/#section/Quick-Start/Defining-a-Catalog).
## Catalog Information Summary
When the steps above are complete, collect the following values for the StreamNative Ursa compaction service:
| Value | Description |
| -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `iceberg.uri` | Polaris REST endpoint (e.g., `https://..gcp.snowflakecomputing.com/polaris/api/catalog`). The format follows the URL of your Polaris console. |
| `iceberg.warehouse` | The Polaris catalog name created in step 3 |
| `iceberg.credential` | `:` from step 5 |
| `iceberg.scope` | `PRINCIPAL_ROLE:ALL` |
## Table Maintenance
Snowflake Open Catalog (Polaris) and the Hadoop catalog do **not** run table maintenance on your behalf. Streaming writes from the StreamNative Ursa compaction service produce many small Parquet files and accumulate snapshot history over time, which degrades query performance and inflates storage costs. You are responsible for scheduling and running maintenance against every Iceberg table written by Ursa.
Run the maintenance operations below on a regular schedule. They are provided as [Apache Iceberg Spark stored procedures](https://iceberg.apache.org/docs/latest/spark-procedures/) and can be triggered from any Spark cluster (Databricks, AWS EMR, AWS Glue, GCP Dataproc, or self-managed Spark) that has the Iceberg Spark runtime, catalog credentials, and IAM access to the warehouse bucket.
**Maintenance operations**
| Operation | Purpose | Suggested cadence |
| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------- |
| `rewrite_data_files` | Compact small Parquet files into fewer, larger files. Reduces file-listing overhead and improves scan performance. | Hourly to daily, depending on ingestion rate |
| `expire_snapshots` | Drop snapshots older than the retention window so their data and manifest files can be cleaned up. | Daily; retain at least 1–7 days so in-flight readers and time-travel queries keep working |
| `remove_orphan_files` | Delete files in the table location that are no longer referenced by any snapshot (typically left behind by failed or partial writes). | Weekly |
| `rewrite_manifests` | Rewrite manifest files so they align with the current partition layout. Improves query planning time. | Weekly, or after large schema or partition changes |
**Example: run maintenance from Spark**
The following examples assume the catalog has been registered in Spark as ``. Replace ``, ``, and `` with your values.
```sql theme={null}
-- Compact small files. Iceberg targets files smaller than the default 512 MB.
CALL .system.rewrite_data_files(table => '.');
-- Expire snapshots older than 3 days; keep the 5 most recent snapshots.
CALL .system.expire_snapshots(
table => '.',
older_than => TIMESTAMP '2026-05-20 00:00:00',
retain_last => 5
);
-- Remove orphan files older than 7 days.
CALL .system.remove_orphan_files(
table => '.',
older_than => TIMESTAMP '2026-05-20 00:00:00'
);
-- Rewrite manifests to match the current partition layout.
CALL .system.rewrite_manifests(table => '.');
```
**Operational guidance**
* **Credentials.** The principal that runs maintenance must have catalog privileges to read and write the target table (for example, the same `TABLE_READ_DATA`, `TABLE_WRITE_DATA`, `TABLE_READ_PROPERTIES`, and `TABLE_WRITE_PROPERTIES` privileges configured for the Ursa compaction service) and IAM access to the warehouse bucket so it can read and rewrite the underlying data files. With the Hadoop catalog there is no catalog service to authenticate against — only the bucket IAM access is required.
* **Concurrency.** Iceberg uses optimistic concurrency control. If maintenance commits race with the Ursa compaction writer, one of them retries. Schedule heavy operations (`rewrite_data_files`, `rewrite_manifests`) during low-write windows when possible.
* **Retention vs. time travel.** `expire_snapshots` and `remove_orphan_files` permanently delete files. Choose a retention window that exceeds the longest expected read query and your time-travel SLA.
* **Schedule the workload.** Most teams orchestrate these procedures from Databricks Jobs, AWS EMR steps, Airflow, Dagster, or a Kubernetes `CronJob`. Pick a scheduler that fits your existing operational stack.
* **Reference.** See the [Iceberg Spark procedures](https://iceberg.apache.org/docs/latest/spark-procedures/#metadata-management) documentation for the full parameter list, including options for partial rewrites (`where`), file-size targets, and merge-on-read delete file compaction.
For the next steps, see [Register Lakehouse Catalogs](/cloud/lakehouse/catalogs/register-catalog).
# S3Table for Iceberg
Source: https://docs.streamnative.io/cloud/lakehouse/prepare-catalogs/s3table/iceberg
This guide describes how to prepare an AWS S3Table catalog for use with StreamNative Ursa as an Iceberg catalog.
> **Important:** The StreamNative Ursa cluster must run in the **same region** as the S3Table bucket. Cross-region access is not supported and will fail with an AWS client error.
## Prerequisites
* An AWS account with permissions to create S3Table buckets and modify IAM roles
* A StreamNative Ursa cluster (the cluster's IAM role will be granted access to the S3Table bucket)
## 1. Create an S3Table Bucket
In the AWS S3 console, create an **S3Table bucket** in the same region as the Ursa cluster. Record the bucket ARN, which has the form:
```
arn:aws:s3tables:::bucket/
```
## 2. Grant S3Table Permissions via a Table Bucket Policy
Apply a [table bucket policy](https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-tables-bucket-policy.html) on the S3Table bucket so that the StreamNative Ursa cluster's IAM role can read and write tables in the bucket.
### 2.1 Find the StreamNative cluster role ARN
The role ARN to grant access to is the IAM role bound to the broker pods of the StreamNative cluster. When you enable Lakehouse Table for **Amazon S3 Tables** at the cluster, namespace, or topic level in the StreamNative Cloud Console, the dialog displays the exact IAM role ARN that needs access to your S3Table bucket. Copy that ARN.
For details on enabling S3 Tables, see [Enable Lakehouse Table](/cloud/lakehouse/enable-lakehouse-integration).
### 2.2 Apply the table bucket policy
In the AWS S3 console, open your S3Table bucket and go to the **Permissions** tab. Choose **Edit** under **Table bucket policy** and paste the following JSON, replacing `` with the ARN you copied in the previous step and ``, ``, and `` with the values for your bucket.
```json theme={null}
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "S3ListTableBucket",
"Effect": "Allow",
"Principal": {
"AWS": ""
},
"Action": [
"s3tables:ListTableBuckets"
],
"Resource": ["*"]
},
{
"Sid": "DataAccessPermissionsForS3TableBucket",
"Effect": "Allow",
"Principal": {
"AWS": ""
},
"Action": [
"s3tables:GetTableBucket",
"s3tables:CreateNamespace",
"s3tables:GetNamespace",
"s3tables:ListNamespaces",
"s3tables:CreateTable",
"s3tables:GetTable",
"s3tables:ListTables",
"s3tables:UpdateTableMetadataLocation",
"s3tables:GetTableMetadataLocation",
"s3tables:GetTableData",
"s3tables:PutTableData"
],
"Resource": [
"arn:aws:s3tables:::bucket/",
"arn:aws:s3tables:::bucket//*"
]
}
]
}
```
The policy panel is on the **Permissions** tab of the table bucket, as shown below:
## 3. Adjust S3Table Maintenance Settings (Recommended)
By default, S3 Tables retains snapshots for 120 hours (5 days). For production workloads, StreamNative recommends shortening this window to **6 hours**.
| Setting | Default | Recommended |
| -------------------- | ------------------ | ----------- |
| `MaximumSnapshotAge` | 120 hours (5 days) | 6 hours |
**Why this matters.** S3 Tables enforces a fixed 5 MB cap on the Iceberg metadata file size. Long retention windows cause many unexpired snapshots to accumulate in the metadata file. When the metadata file grows beyond 5 MB, **subsequent snapshot commits will fail**, which stops new data from being written into the lakehouse table. A shorter `MaximumSnapshotAge` keeps the metadata file under the cap.
You can update the snapshot management settings from the S3 Table bucket console or via the AWS CLI after the bucket is created. See [S3 Tables maintenance -- Snapshot management](https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-tables-maintenance.html#s3-tables-maintenance-snapshot) for the full list of maintenance settings.
## 4. (Optional) Configure AWS Athena Access
If you intend to query the S3Table data via AWS Athena, you must integrate it with AWS Lake Formation.
### 4.1 Prerequisites
Refer to [S3 Tables integration prerequisites](https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-tables-integrating-aws.html#table-integration-prerequisites). In summary:
* Attach `AWSLakeFormationDataAdmin` to your IAM principal
* Add `glue:PassConnection` and `lakeformation:RegisterResource` permissions
* Use the latest version of the AWS CLI
When the S3Table bucket is created with AWS analytics services enabled, AWS automatically provisions a role (for example, `S3TablesRoleForLakeFormation_1`).
Add the following inline policy to your IAM principal to grant Lake Formation operations:
```json theme={null}
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AWSLakeFormationDataAdminAllow",
"Effect": "Allow",
"Action": [
"lakeformation:*",
"cloudtrail:DescribeTrails",
"cloudtrail:LookupEvents",
"glue:CreateCatalog", "glue:UpdateCatalog", "glue:DeleteCatalog",
"glue:GetCatalog", "glue:GetCatalogs",
"glue:GetDatabase", "glue:GetDatabases",
"glue:CreateDatabase", "glue:UpdateDatabase", "glue:DeleteDatabase",
"glue:GetConnections", "glue:SearchTables",
"glue:GetTable", "glue:CreateTable", "glue:UpdateTable", "glue:DeleteTable",
"glue:GetTableVersions", "glue:GetPartitions", "glue:GetTables",
"glue:ListWorkflows", "glue:BatchGetWorkflows", "glue:DeleteWorkflow",
"glue:GetWorkflowRuns", "glue:StartWorkflowRun", "glue:GetWorkflow",
"glue:PassConnection",
"s3:ListBucket", "s3:GetBucketLocation", "s3:ListAllMyBuckets", "s3:GetBucketAcl",
"iam:ListUsers", "iam:ListRoles", "iam:GetRole", "iam:GetRolePolicy"
],
"Resource": "*"
},
{
"Sid": "AWSLakeFormationDataAdminDeny",
"Effect": "Deny",
"Action": ["lakeformation:PutDataLakeSettings"],
"Resource": "*"
}
]
}
```
### 4.2 Create a Resource Link
A resource link provides a Glue Data Catalog reference to your S3Table namespace. See [Creating a resource link](https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-tables-integrating-aws.html#database-link-tables).
```bash theme={null}
aws glue create-database --region --catalog-id "" --database-input '{
"Name": "",
"TargetDatabase": {
"CatalogId": ":s3tablescatalog/",
"DatabaseName": ""
},
"CreateTableDefaultPermissions": []
}'
```
### 4.3 Grant Lake Formation Permissions
#### On the Table
In the AWS Lake Formation console, navigate to **Data permissions -> Grant** and configure:
1. **Principals**: the IAM user, role, or SAML group that will run queries.
2. **LF-Tags or catalog resources**: choose **Named Data Catalog resources**.
3. **Catalogs**: the Glue Data Catalog created when the table bucket was integrated (`:s3tablescatalog/`).
4. **Databases**: the S3Table namespace.
5. **Tables**: the S3Table table.
6. **Table permissions**: **Super**.
#### On the Resource Link
Resource links require their own grants in addition to the underlying namespace/table grants:
1. **Principals**: the IAM user/role/group.
2. **Catalogs**: your account's default catalog.
3. **Databases**: the resource link from step 4.2.
4. **Resource link permissions**: **Describe**.
## Catalog Information Summary
When the steps above are complete, collect the following values for the StreamNative Ursa compaction service:
| Value | Description |
| ----------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `iceberg.catalog-backend` | `s3table` |
| `iceberg.uri` | `https://s3tables..amazonaws.com/iceberg` (region-specific endpoint -- see the [S3 Tables regions list](https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-tables-regions-quotas.html#s3-tables-regions)) |
| `iceberg.warehouse` | The S3Table bucket ARN: `arn:aws:s3tables:::bucket/` |
| `iceberg.rest.signing-region` | The region of the S3Table bucket |
For the next steps, see [Register Lakehouse Catalogs](/cloud/lakehouse/catalogs/register-catalog).
# Unity Catalog for Delta Lake on AWS
Source: https://docs.streamnative.io/cloud/lakehouse/prepare-catalogs/unity-catalog/delta-lake/aws
This guide describes how to prepare a Databricks Unity Catalog for use with StreamNative Ursa as a Delta Lake catalog on AWS.
## Prerequisites
* An AWS account with permissions to create S3 buckets and IAM roles
* A Databricks account with permissions to create workspaces
## 1. Create a Databricks Workspace
> Skip this step if you already have the Databricks Workspace
In the Databricks account console, create a new workspace. The workspace creation flow uses an AWS CloudFormation stack, so you must be logged into AWS in the same browser session.
Click **Create workspace**.
Choose **Quickstart**.
Enter a workspace name and select the AWS region in which your S3 bucket resides (for example, `us-east-2`). Click **Start Quickstart**.
In the AWS console, acknowledge the IAM resource creation and click **Create Stack**.
When the stack reaches `CREATE_COMPLETE`, return to the Databricks console and open the workspace.
## 2. (Recommend) Generate an OAuth2 Service Principal
If you prefer OAuth2 over a personal access token, create a service principal:
Navigate to **Developer -> Identity and access -> Service principals -> Manage**.
Click **Add service principal -> Add new**, give it a name, and click **Add**.
Open the service principal, click **Secrets -> Generate secret**, choose an expiration period, and **Generate**.
Record the **Client ID** and **Client Secret** -- the secret cannot be retrieved later.
## 3. (Alternative) Generate a User Token
A Databricks user token can be used by StreamNative Ursa to authenticate against Unity Catalog.
Open **User Settings**.
Navigate to **Developer -> Access tokens -> Manage** and generate a new token. Record the token value -- it cannot be retrieved later.
## 4. Configure Unity Catalog Access
Navigate to **Catalog -> Settings -> Metastore**.
Enable **External data access** on the metastore.
Grant privileges on the catalog with the following settings:
* **Principal:** All accounts (or the specific user/service principal)
* **Privilege presets:** Data Editor (selects related privileges automatically)
* **EXTERNAL USE SCHEMA:** Enabled
If you use OAuth2 authentication, set the **Principal** to the service principal name created in step 3.
## 5. Create an S3 Bucket
In your AWS account, create an S3 bucket for the Unity Catalog managed location (for example, `delta-unity-catalog-bucket`).
## 6. Create an IAM Policy
Navigate to **AWS IAM -> Policies -> Create policy**, choose JSON, and paste the following (replace ``):
```json theme={null}
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:GetObject",
"s3:GetObjectVersion",
"s3:DeleteObject",
"s3:DeleteObjectVersion"
],
"Resource": "arn:aws:s3:::/*"
},
{
"Effect": "Allow",
"Action": [
"s3:ListBucket",
"s3:GetBucketLocation"
],
"Resource": "arn:aws:s3:::",
"Condition": {
"StringLike": {
"s3:prefix": ["*"]
}
}
}
]
}
```
## 7. Create an IAM Role
Navigate to **AWS IAM -> Roles -> Create role** and configure:
* **Trusted entity type:** AWS account
* **An AWS account:** This account
* **Enable External ID** with placeholder value `0000` (will be updated in step 9)
Attach the policy from step 6.
Record the role ARN (for example, `arn:aws:iam:::role/`).
## 8. Create a Storage Credential in Unity Catalog
Navigate to **Catalog -> Settings -> Credentials**.
Configure with:
* **Credential:** Storage Credential
* **Type:** AWS IAM Role
* **Name:** any name
* **Role ARN:** the ARN recorded in step 7
Databricks generates a trust relationship policy. Copy it.
## 9. Update the IAM Role Trust Policy
Return to the AWS IAM console, open the role created in step 7, and replace the trust policy with the one generated by Databricks.
Click **Validate** in the Unity Catalog console to verify the credential.
## 10. Create an External Location
Navigate to **Catalog -> Settings -> External Locations**.
Choose **Manual** (the AWS Quickstart creates a new bucket).
Configure:
* **External location name:** any name
* **URL:** `s3://`
* **Storage credential:** the credential from step 8
After creation, click **Test connection** to verify access.
If you use OAuth2, grant **ALL PRIVILEGES** on the external location to the service principal:
## 11. Create the Catalog
In Databricks, create a new catalog and bind it to the external location created in step 10.
## Catalog Information Summary
When the steps above are complete, collect the following values for the StreamNative Ursa compaction service:
| Value | Description |
| --------------------------------------------------- | ------------------------------------------------------------------------ |
| `unityCatalogUri` | Databricks workspace URL (e.g., `https://dbc-xxxx.cloud.databricks.com`) |
| `unityCatalogName` | The Unity Catalog name created in step 11 |
| `unityCatalogToken` | Personal access token from step 2, **or** |
| `unityCatalogClientId` / `unityCatalogClientSecret` | OAuth2 credentials from step 3 |
For the next steps, see [Register Lakehouse Catalogs](/cloud/lakehouse/catalogs/register-catalog).
# Unity Catalog for Delta Lake on Azure
Source: https://docs.streamnative.io/cloud/lakehouse/prepare-catalogs/unity-catalog/delta-lake/azure
This guide describes how to prepare a Databricks Unity Catalog for use with StreamNative Ursa as a Delta Lake catalog on Microsoft Azure.
## Prerequisites
* An Azure subscription with permissions to create storage accounts and Access Connectors
* A Databricks workspace on Azure
## 1. Create an Access Connector for Azure Databricks
In the Azure Marketplace, search for **Access Connector for Azure Databricks** and click **Create**.
Choose the resource group, provide a connector name (for example, `unity-catalog-access-connector`), and click **Next**.
In the **Managed Identity** panel, enable **System assigned identity**, then click **Next** -> **Create**.
Record the connector **Resource ID**:
## 2. Grant `Storage Blob Data Contributor` to the Connector
Open the storage account that will hold the Delta tables, navigate to **Access Control (IAM) -> Add -> Add role assignment**.
Search for and select **Storage Blob Data Contributor**, then click **Next**.
Choose **Managed identity** and select the Access Connector created in step 1.
Click **Next -> Review + assign**.
## 3. Grant `Storage Queue Data Contributor` to the Connector
Repeat the process from step 2 with the **Storage Queue Data Contributor** role.
Both roles are now assigned to the Access Connector.
## 4. Create a Storage Credential in Unity Catalog
In the Databricks Catalog console, navigate to **Catalog -> Settings -> Credentials**.
Click **Create Credential**, provide a name, and paste the Access Connector **Resource ID** from step 1.
## 5. Create an External Location
In the Databricks Catalog console, create a new external location.
Configure with:
* **Storage type:** Azure Data Lake Storage
* **URL:** `abfss://@.dfs.core.windows.net`
* **Storage credential:** the credential created in step 4
Click **Test Connection** to verify the credential.
> **Troubleshooting:** If the test fails with a `Hierarchical Namespace Enabled` error, ensure that **Hierarchical namespace** is enabled on the storage account.
## 6. Create a Service Principal
Navigate to **User -> Settings -> Identity and access -> Service principals -> Manage**.
Click **Add service principal -> Add new**.
Choose **Databricks managed** and provide a name.
Open the service principal, click **Secrets**, choose an expiration period, and **Generate**.
Record both the **Client ID** and **Client Secret** -- the secret cannot be retrieved later.
## 7. Create the Catalog
Create a new Catalog with **Type: Standard** and select the **storage location** created in step 5.
## 8. Grant Permissions to the Service Principal
### 8.1 Catalog Permissions
Navigate to the new catalog and click **Permissions -> Grant**.
Configure:
* **Principals:** the service principal from step 6
* **Privilege presets:** Data Editor
* **EXTERNAL USE SCHEMA:** Enabled
### 8.2 External Location Permissions
Open the external location from step 5.
Click **Grant**, choose the service principal, select **ALL PRIVILEGES**, and click **Confirm**.
## Catalog Information Summary
When the steps above are complete, collect the following values for the StreamNative Ursa compaction service:
| Value | Description |
| --------------------------------------------------- | --------------------------------------------------------------------------------- |
| `unityCatalogUri` | Databricks workspace URL (e.g., `https://adb-.azuredatabricks.net`) |
| `unityCatalogName` | The Unity Catalog name created in step 7 |
| `unityCatalogClientId` / `unityCatalogClientSecret` | OAuth2 credentials from step 6 |
For the next steps, see [Register Lakehouse Catalogs](/cloud/lakehouse/catalogs/register-catalog).
# Unity Catalog for Delta Lake on GCP
Source: https://docs.streamnative.io/cloud/lakehouse/prepare-catalogs/unity-catalog/delta-lake/gcp
This guide describes how to prepare a Databricks Unity Catalog for use with StreamNative Ursa as a Delta Lake catalog on Google Cloud Platform (GCP).
## Prerequisites
* A GCP project with permissions to create GCS buckets and IAM roles
* A Databricks account with permissions to create workspaces
## 1. Create a Databricks Workspace
> Skip this step if you already have the Databricks Workspace in GCP
In the GCP Databricks account console, click **Create workspace**.
Enter the workspace name, choose the region, and provide your GCP project ID.
Click **Save**. The workspace status shows **Provisioning** while initialization is in progress.
When the status changes to **Running**, the workspace is ready.
Open the workspace to enter the Unity Catalog console.
## 2. (Recommend) Generate an OAuth2 Service Principal
For OAuth2 authentication, navigate to **Identity and access -> Service principals -> Manage**.
Click **Add service principal -> Add new** and provide a name.
Open the service principal, click **Secrets -> Generate secret**, choose an expiration period, and **Generate**.
Record both the **Client ID** and **Client Secret** -- the secret cannot be retrieved later.
## 3. (Alternative) Generate a User Token
A Databricks user token can be used by StreamNative Ursa to authenticate against Unity Catalog.
Open **User Settings**.
Navigate to **Developer -> Access tokens -> Manage** and generate a new token. Record the token value -- it cannot be retrieved later.
## 4. Configure Unity Catalog Access
Navigate to **Catalog -> Settings -> Metastore**.
Enable **External data access** on the metastore.
Grant catalog privileges with the following settings:
* **Principal:** All accounts (or the specific user/service principal)
* **Privilege presets:** Data Editor (selects related privileges automatically)
* **EXTERNAL USE SCHEMA:** Enabled
## 5. Grant Bucket Permissions to the Databricks Service Account
When the Databricks workspace is initialized, a service account is created for Unity Catalog.
Navigate to **Catalog -> Settings -> Credentials** to find the service account.
Example service account name:
```
db-uc-credential-@uc-uswest1.iam.gserviceaccount.com
```
### 5.1 Create a Custom IAM Role
In the GCP console, navigate to **IAM & Admin -> Roles -> Create role** and add the following permissions:
* `storage.buckets.get`
* `storage.objects.create`
* `storage.objects.delete`
* `storage.objects.get`
* `storage.objects.list`
### 5.2 Assign the Role to the Databricks Service Account
Open your bucket, click **PERMISSIONS -> View BY PRINCIPALS -> GRANT ACCESS**.
Add the Databricks service account, select the role created in step 6.1, and click **SAVE**.
## 6. Create an External Location in Unity Catalog
Navigate to **Catalog -> Settings -> External Locations** and create a new external location.
Configure with:
* **External location name:** any name
* **URL:** the GCS bucket path
* **Storage credential:** the Unity Catalog credential
Click **Test connection** to verify access.
Grant **ALL PRIVILEGES** on the external location to the service principal.
## Catalog Information Summary
When the steps above are complete, collect the following values for the StreamNative Ursa compaction service:
| Value | Description |
| --------------------------------------------------- | ------------------------------------------------------------------------- |
| `unityCatalogUri` | Databricks workspace URL (e.g., `https://.gcp.databricks.com`) |
| `unityCatalogName` | The Unity Catalog name |
| `unityCatalogToken` | Personal access token from step 2, **or** |
| `unityCatalogClientId` / `unityCatalogClientSecret` | OAuth2 credentials from step 3 |
For the next steps, see [Register Lakehouse Catalogs](/cloud/lakehouse/catalogs/register-catalog).
# Unity Catalog Managed Iceberg Table on AWS
Source: https://docs.streamnative.io/cloud/lakehouse/prepare-catalogs/unity-catalog/iceberg/aws
This guide describes how to prepare a Databricks Unity Catalog for use with StreamNative Ursa as a managed Iceberg table catalog on AWS.
## Prerequisites
* A Databricks account with Unity Catalog and Iceberg Managed Table enabled
* An AWS account with permissions to create S3 buckets and IAM roles
## 1. Create an S3 Bucket
In your AWS account, create an S3 bucket to use as the Unity Catalog storage location (for example, `aws-unitycatalog-iceberg-bucket`).
## 2. Create the IAM Role
### 2.1 Create the Role with a Placeholder Trust Policy
Create an IAM role that allows the Unity Catalog master role to assume it. Use the following trust policy with a placeholder `External ID` of `0000` (you will replace it with the value generated by Databricks in step 3):
```json theme={null}
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": ["arn:aws:iam::414351767826:role/unity-catalog-prod-UCMasterRole-14S5ZJVKOTYTL"]
},
"Action": "sts:AssumeRole",
"Condition": {
"StringEquals": {
"sts:ExternalId": "0000"
}
}
}
]
}
```
Skip the permissions policy on this screen -- it will be added in the next steps.
### 2.2 Attach the S3 Access Policy
Create the following policy and attach it to the role. Replace `` and `` with your values.
```json theme={null}
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:PutObject",
"s3:DeleteObject",
"s3:ListBucket",
"s3:GetBucketLocation",
"s3:ListBucketMultipartUploads",
"s3:ListMultipartUploadParts",
"s3:AbortMultipartUpload"
],
"Resource": [
"arn:aws:s3:::/*",
"arn:aws:s3:::"
]
},
{
"Effect": "Allow",
"Action": ["sts:AssumeRole"],
"Resource": ["arn:aws:iam:::role/"]
}
]
}
```
### 2.3 Attach the File Events Policy
Create a second policy for managed file events (S3 notifications, SNS, SQS) and attach it to the same role:
```json theme={null}
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "ManagedFileEventsSetupStatement",
"Effect": "Allow",
"Action": [
"s3:GetBucketNotification",
"s3:PutBucketNotification",
"sns:ListSubscriptionsByTopic",
"sns:GetTopicAttributes",
"sns:SetTopicAttributes",
"sns:CreateTopic",
"sns:TagResource",
"sns:Publish",
"sns:Subscribe",
"sqs:CreateQueue",
"sqs:DeleteMessage",
"sqs:ReceiveMessage",
"sqs:SendMessage",
"sqs:GetQueueUrl",
"sqs:GetQueueAttributes",
"sqs:SetQueueAttributes",
"sqs:TagQueue",
"sqs:ChangeMessageVisibility",
"sqs:PurgeQueue"
],
"Resource": [
"arn:aws:s3:::",
"arn:aws:sqs:*:*:csms-*",
"arn:aws:sns:*:*:csms-*"
]
},
{
"Sid": "ManagedFileEventsListStatement",
"Effect": "Allow",
"Action": [
"sqs:ListQueues",
"sqs:ListQueueTags",
"sns:ListTopics"
],
"Resource": [
"arn:aws:sqs:*:*:csms-*",
"arn:aws:sns:*:*:csms-*"
]
},
{
"Sid": "ManagedFileEventsTeardownStatement",
"Effect": "Allow",
"Action": [
"sns:Unsubscribe",
"sns:DeleteTopic",
"sqs:DeleteQueue"
],
"Resource": [
"arn:aws:sqs:*:*:csms-*",
"arn:aws:sns:*:*:csms-*"
]
}
]
}
```
Verify that both policies are attached to the role.
## 3. Create an External Location in Unity Catalog
In the Databricks Catalog console, create a new external location pointing to the S3 bucket and the IAM role created above.
When you submit the form, Databricks generates an **External ID** and a trust policy. Copy these values.
## 4. Update the IAM Role Trust Policy
Return to the AWS IAM console and replace the role's trust policy with the one generated by Databricks in step 3, using the new External ID.
After saving the trust policy, click **IAM role configured** in the Databricks catalog console and then **Test connection** to verify the credential.
## 5. Create the Unity Catalog
Create a new catalog in Databricks bound to the external location created in step 3:
* **Type:** Standard
* **Storage location:** the external location created above
## 6. Grant Catalog Permissions
Grant permissions on the catalog. The `EXTERNAL_USE_SCHEMA` permission is **required** for Iceberg Managed Tables in Unity Catalog.
## 7. Create OAuth2 Credentials
Create an OAuth2 service principal that StreamNative Ursa will use to authenticate against Unity Catalog.
Generate a secret for the principal and record both the **Client ID** and **Client Secret**.
## 8. Enable External Data Access on the Metastore
This step is **required** for Unity Catalog Iceberg Managed Tables. Enable **External data access** on the metastore in Databricks.
## Catalog Information Summary
When the steps above are complete, collect the following values for the StreamNative Ursa compaction service:
| Value | Description |
| ---------- | ----------------------------------------------------------------------------------------------------------- |
| URI | Databricks workspace URL (e.g., `https://dbc-xxxx.cloud.databricks.com/api/2.1/unity-catalog/iceberg-rest`) |
| Warehouse | The Unity Catalog name created in step 5 |
| Credential | `:` from step 7 |
For the next steps, see [Register Lakehouse Catalogs](/cloud/lakehouse/catalogs/register-catalog).
# Unity Catalog Managed Iceberg Table on Azure
Source: https://docs.streamnative.io/cloud/lakehouse/prepare-catalogs/unity-catalog/iceberg/azure
This guide describes how to prepare a Databricks Unity Catalog for use with StreamNative Ursa as a managed Iceberg table catalog on Microsoft Azure.
## Prerequisites
* A Databricks workspace on Azure with Unity Catalog and Iceberg Managed Table enabled
* An Azure subscription with permissions to create storage accounts and Access Connectors
## 1. Create an Azure Storage Container
Create a storage container in your Azure Storage Account (for example, `unity-catalog-iceberg`). The container path will follow the format:
```
abfss://@.dfs.core.windows.net
```
## 2. Create an Access Connector for Azure Databricks
Refer to the [Azure Databricks Managed Identities documentation](https://learn.microsoft.com/en-us/azure/databricks/connect/unity-catalog/cloud-storage/azure-managed-identities) for the canonical procedure.
In the Azure Portal, create an **Access Connector for Azure Databricks**.
Record the connector **Resource ID**, which has the form:
```
/subscriptions//resourceGroups//providers/Microsoft.Databricks/accessConnectors/
```
## 3. Grant Storage Permissions to the Access Connector
The Access Connector identity requires the following roles:
| Scope | Role |
| --------------- | ----------------------------------------- |
| Storage Account | `Storage Blob Data Contributor` |
| Storage Account | `Storage Queue Data Contributor` |
| Resource Group | `EventGrid EventSubscription Contributor` |
### 3.1 Grant `Storage Blob Data Contributor`
### 3.2 Grant `Storage Queue Data Contributor`
### 3.3 Grant `EventGrid EventSubscription Contributor`
## 4. Create the Unity Catalog Metastore
Create the Unity Catalog metastore in Databricks.
## 5. Create a Storage Credential
In the Databricks Catalog console, create a storage credential linked to the Access Connector created in step 2.
## 6. Create the External Location
Create an external location pointing to the Azure storage container:
* **URL:** `abfss://@.dfs.core.windows.net`
* **Storage credential:** the credential created in step 5
## 7. Create the Unity Catalog
Create a new Catalog and bind it to the external location created in step 6.
## 8. Grant Catalog Permissions
Grant permissions on the catalog. The `EXTERNAL_USE_SCHEMA` permission is **required** for Iceberg Managed Tables in Unity Catalog.
## 9. Enable External Data Access on the Metastore
> **Note:** This action requires **Azure Account Admin** privileges; without them, the **Metastore** entry is not visible.
Enable **External data access** on the metastore. This step is **required** for Unity Catalog Iceberg Managed Tables.
## 10. Create OAuth2 Credentials
Create an OAuth2 service principal that StreamNative Ursa will use to authenticate.
Generate a secret for the principal and record both the **Client ID** and **Client Secret**.
## Catalog Information Summary
When the steps above are complete, collect the following values for the StreamNative Ursa compaction service:
| Value | Description |
| ---------- | -------------------------------------------------------------------------------------------------------------------- |
| URI | Databricks workspace URL (e.g., `https://adb-.azuredatabricks.net/api/2.1/unity-catalog/iceberg-rest`) |
| Warehouse | The Unity Catalog name created in step 7 |
| Credential | `:` from step 10 |
For the next steps, see [Register Lakehouse Catalogs](/cloud/lakehouse/catalogs/register-catalog).
# Unity Catalog Managed Iceberg Table on GCP
Source: https://docs.streamnative.io/cloud/lakehouse/prepare-catalogs/unity-catalog/iceberg/gcp
This guide describes how to prepare a Databricks Unity Catalog for use with StreamNative Ursa as a managed Iceberg table catalog on Google Cloud Platform (GCP).
## Prerequisites
* A Databricks workspace on GCP with Unity Catalog and Iceberg Managed Table enabled
* A GCP project with permissions to create GCS buckets
## 1. Create a GCS Bucket
Create a GCS bucket to use as the Unity Catalog storage location (for example, `unity-catalog-iceberg-bucket`).
> **Important:** The bucket must be located in the **same region** as your Databricks workspace and your StreamNative Ursa cluster. Cross-region access introduces additional network traffic and latency.
For additional details, see the [Databricks GCP Unity Catalog documentation](https://docs.databricks.com/gcp/en/data-governance/unity-catalog/create-metastore).
## 2. Create a Storage Credential in Unity Catalog
In the Databricks Catalog console, create a new storage credential. Databricks generates a service account that needs permissions on the bucket.
After creation, record the generated service account name. Example:
```
db-uc-credential-@uc-uswest1.iam.gserviceaccount.com
```
## 3. Grant GCS Permissions to the Service Account
In the GCP console, navigate to the bucket's **Permissions** tab and click **Grant access**.
Grant the following roles to the service account from step 2:
* **Storage Legacy Bucket Reader**
* **Storage Object Admin**
## 4. Create the External Location
In the Databricks Catalog console, create an external location with the following settings:
* **External location name:** any name
* **URL:** the GCS bucket path created in step 1
* **Storage credential:** the credential created in step 2
Use **Test connection** to verify the credential has sufficient permissions.
## 5. Create the Unity Catalog
Create a new Catalog with:
* **Type:** Standard
* **Storage location:** the external location created in step 4 (a sub-path within this location may be specified)
## 6. Grant Catalog Permissions
Grant permissions on the catalog. The `EXTERNAL_USE_SCHEMA` permission is **required** for Iceberg Managed Tables in Unity Catalog.
## 7. Enable External Data Access on the Metastore
> **Note:** This action requires **Databricks Account Admin** privileges; without them, the **Metastore** entry is not visible.
Enable **External data access** on the metastore. This step is **required** for Unity Catalog Iceberg Managed Tables.
## 8. Create OAuth2 Credentials
Create an OAuth2 service principal that StreamNative Ursa will use to authenticate.
Generate a secret for the principal and record both the **Client ID** and **Client Secret**.
## Catalog Information Summary
When the steps above are complete, collect the following values for the StreamNative Ursa compaction service:
| Value | Description |
| ---------- | ------------------------------------------------------------------------------------------------------------ |
| URI | Databricks workspace URL (e.g., `https://.gcp.databricks.com/api/2.1/unity-catalog/iceberg-rest`) |
| Warehouse | The Unity Catalog name created in step 5 |
| Credential | `:` from step 8 |
For the next steps, see [Register Lakehouse Catalogs](/cloud/lakehouse/catalogs/register-catalog).
# Prepare Lakehouse Catalogs
Source: https://docs.streamnative.io/cloud/lakehouse/prepare-lakehouse-catalogs
Preparing an external catalog is **optional**. StreamNative Ursa supports the following catalog modes:
* **Iceberg with the Hadoop catalog (no external catalog).** Iceberg metadata and data files are written directly to the configured object storage path. No external catalog service is required, and downstream engines can read the table by pointing at the storage location.
* **Delta Lake without a catalog.** Delta tables are written directly to the configured storage path; readers point at the path (`s3://...`, `gs://...`, or `abfss://...`) to query them.
* **External catalog.** Use a managed catalog service (Databricks Unity Catalog, Snowflake Open Catalog, Snowflake Horizon Catalog, AWS S3Table, or Google BigLake) to register the tables. This is required if you want governance, discoverability, or integration with managed query engines (Databricks SQL, Snowflake, Athena, BigQuery, etc.).
If you choose to use an external catalog, this page is the index for the catalog preparation guides. Each guide focuses solely on provisioning the catalog itself and its supporting cloud resources (storage bucket, IAM role or service principal, and credentials). Once the catalog is ready, see [Register Lakehouse Catalogs](/cloud/lakehouse/catalogs/register-catalog) for how to wire it into the compaction service.
> **Skip this page if you are using the Hadoop catalog (Iceberg) or no catalog (Delta).** Go directly to [Register Lakehouse Catalogs](/cloud/lakehouse/catalogs/register-catalog), which describes the no-catalog configuration.
## Catalog Support Matrix
| Catalog | Table Format | AWS | GCP | Azure |
| ------------------------------------------ | ------------ | --------------------------------------------------------------------- | --------------------------------------------------------------------- | ------------------------------------------------------------------------- |
| Databricks Unity Catalog (Managed Iceberg) | Iceberg | [AWS](/cloud/lakehouse/prepare-catalogs/unity-catalog/iceberg/aws) | [GCP](/cloud/lakehouse/prepare-catalogs/unity-catalog/iceberg/gcp) | [Azure](/cloud/lakehouse/prepare-catalogs/unity-catalog/iceberg/azure) |
| Databricks Unity Catalog (Delta Lake) | Delta Lake | [AWS](/cloud/lakehouse/prepare-catalogs/unity-catalog/delta-lake/aws) | [GCP](/cloud/lakehouse/prepare-catalogs/unity-catalog/delta-lake/gcp) | [Azure](/cloud/lakehouse/prepare-catalogs/unity-catalog/delta-lake/azure) |
| Snowflake Open Catalog (Polaris) | Iceberg | [AWS](/cloud/lakehouse/prepare-catalogs/open-catalog/iceberg/aws) | [GCP](/cloud/lakehouse/prepare-catalogs/open-catalog/iceberg/gcp) | [Azure](/cloud/lakehouse/prepare-catalogs/open-catalog/iceberg/azure) |
| Snowflake Horizon Catalog | Iceberg | [AWS](/cloud/lakehouse/prepare-catalogs/horizon-catalog/iceberg/aws) | -- | -- |
| AWS S3Table | Iceberg | [Iceberg](/cloud/lakehouse/prepare-catalogs/s3table/iceberg) | -- | -- |
| Google BigLake | Iceberg | -- | [Iceberg](/cloud/lakehouse/prepare-catalogs/biglake/iceberg) | -- |
## Choosing a Catalog
| Use case | Recommended catalog |
| ------------------------------------------------------------------- | -------------------------------------------------------------------------- |
| Manage Iceberg tables alongside Databricks workloads | [Unity Catalog (Iceberg)](#databricks-unity-catalog-managed-iceberg-table) |
| Manage Delta Lake tables alongside Databricks workloads | [Unity Catalog (Delta Lake)](#databricks-unity-catalog-delta-lake) |
| Cloud-portable Iceberg REST catalog from Snowflake | [Snowflake Open Catalog (Polaris)](#snowflake-open-catalog-polaris) |
| Governed Iceberg tables managed by Snowflake Horizon | [Snowflake Horizon Catalog](#snowflake-horizon-catalog) |
| AWS-native Iceberg tables with built-in Athena/Redshift integration | [AWS S3Table](#aws-s3table) |
| GCP-native Iceberg with BigQuery/BigLake integration | [Google BigLake](#google-biglake) |
## Catalog Preparation Guides
### Databricks Unity Catalog (Managed Iceberg Table)
Use Unity Catalog to manage Iceberg tables governed by Databricks. The compaction service writes to Iceberg Managed Tables; downstream readers query them via the Unity Catalog Iceberg REST endpoint.
| Cloud | Guide |
| ----- | ------------------------------------------------------------------------------------------------------------- |
| AWS | [Unity Catalog Managed Iceberg Table on AWS](/cloud/lakehouse/prepare-catalogs/unity-catalog/iceberg/aws) |
| GCP | [Unity Catalog Managed Iceberg Table on GCP](/cloud/lakehouse/prepare-catalogs/unity-catalog/iceberg/gcp) |
| Azure | [Unity Catalog Managed Iceberg Table on Azure](/cloud/lakehouse/prepare-catalogs/unity-catalog/iceberg/azure) |
### Databricks Unity Catalog (Delta Lake)
Use Unity Catalog to manage Delta Lake tables. The compaction service writes Delta Lake files governed by Unity Catalog and queryable from Databricks SQL or external Spark sessions.
| Cloud | Guide |
| ----- | --------------------------------------------------------------------------------------------------------- |
| AWS | [Unity Catalog for Delta Lake on AWS](/cloud/lakehouse/prepare-catalogs/unity-catalog/delta-lake/aws) |
| GCP | [Unity Catalog for Delta Lake on GCP](/cloud/lakehouse/prepare-catalogs/unity-catalog/delta-lake/gcp) |
| Azure | [Unity Catalog for Delta Lake on Azure](/cloud/lakehouse/prepare-catalogs/unity-catalog/delta-lake/azure) |
### Snowflake Open Catalog (Polaris)
Snowflake Open Catalog (Polaris) is a cloud-agnostic Iceberg REST catalog operated by Snowflake. It can be used as the catalog for Iceberg tables hosted on AWS, GCP, or Azure object storage.
| Cloud | Guide |
| ----- | ------------------------------------------------------------------------------------------------- |
| AWS | [Open Catalog for Iceberg on AWS](/cloud/lakehouse/prepare-catalogs/open-catalog/iceberg/aws) |
| GCP | [Open Catalog for Iceberg on GCP](/cloud/lakehouse/prepare-catalogs/open-catalog/iceberg/gcp) |
| Azure | [Open Catalog for Iceberg on Azure](/cloud/lakehouse/prepare-catalogs/open-catalog/iceberg/azure) |
### Snowflake Horizon Catalog
Snowflake Horizon provides governed Iceberg tables with native Snowflake integration. The catalog uses a Snowflake **External Volume** backed by an S3 bucket and authenticates via a Programmatic Access Token (PAT).
| Cloud | Guide |
| ----- | --------------------------------------------------------------------------------------------------- |
| AWS | [Horizon Catalog for Iceberg on AWS](/cloud/lakehouse/prepare-catalogs/horizon-catalog/iceberg/aws) |
### AWS S3Table
AWS S3Table is the AWS-native Iceberg catalog with first-class integration into AWS analytics services such as Athena, Redshift, and EMR.
| Cloud | Guide |
| ----- | ------------------------------------------------------------------------ |
| AWS | [S3Table for Iceberg](/cloud/lakehouse/prepare-catalogs/s3table/iceberg) |
> **Important:** The Ursa cluster must run in the **same region** as the S3Table bucket. Cross-region access is not supported.
### Google BigLake
Google BigLake provides an Iceberg REST catalog tightly integrated with BigQuery and Google Cloud Storage.
| Cloud | Guide |
| ----- | ------------------------------------------------------------------------ |
| GCP | [BigLake for Iceberg](/cloud/lakehouse/prepare-catalogs/biglake/iceberg) |
> **Important:** The Ursa cluster, GCS bucket, and BigLake catalog must all be in the same region. Each BigLake catalog maps to exactly one GCS bucket (1:1 mapping; sub-paths are not supported).
## Next Steps
After preparing your catalog, proceed to:
1. [Dynamic Configuration Guide](/cloud/lakehouse/dynamic-configuration) -- Reference for all dynamic configuration keys and the cluster-name prefix requirement.
2. [Register Lakehouse Catalogs](/cloud/lakehouse/catalogs/register-catalog) -- Connect the prepared catalog to the StreamNative Ursa compaction service.
3. [Enable Lakehouse Integration](/cloud/lakehouse/enable-lakehouse-integration) -- Enable SDT (External Table) at the cluster, namespace, or topic level.
# Manage Data Streams in StreamNative Cloud
Source: https://docs.streamnative.io/cloud/manage-data-streams/data-streams-overview
StreamNative Cloud leverages Apache Pulsar, a multi-tenant messaging and data streaming platform. Within Apache Pulsar, data streams are organized into Topics, which are grouped into Tenants and Namespaces. Tenants can span multiple [clusters](/cloud/clusters/manage-clusters/cluster) within a [StreamNative Instance](/cloud/clusters/manage-instances/instance), and each tenant serves as an administrative unit where storage quotas, message TTL (Time to Live), isolation policies and etc. are managed.
The structure of topic URLs in Pulsar, which highlights its multi-tenant architecture, is as follows:
```
[persistent|non-persistent]://tenant/namespace/topic
```
In this structure, the tenant is the primary categorization unit for topics, more fundamental than the namespace or topic name itself.
You can create and manage tenants, namespaces, topics, and their configurations and policies through the [StreamNative Cloud console](https://console.streamnative.cloud), the StreamNative CLI[ (`snctl`)](/tools/cli/snctl/snctl-overview),the [Pulsar CLI (`pulsarctl`)](/tools/cli/pulsarctl/pulsarctl-overview), or [Pulsar Admin APIs](https://pulsar.apache.org/docs/admin-api-overview/).
## Tenants
A [Pulsar tenant](/cloud/manage-data-streams/tenant) is an administrative entity used for capacity allocation and implementing authentication or authorization schemes. Each tenant in a Pulsar instance can have:
* An assigned authorization scheme
* A defined set of clusters where the tenant's configurations are applicable
## Namespace
A [namespace](/cloud/manage-data-streams/namespace) in Pulsar is a logical grouping of topics. It serves as an administrative segment within a tenant, where configuration policies set at the namespace level apply to all topics within that namespace. A tenant can establish multiple namespaces to accommodate different applications, for example:
```bash theme={null}
persistent://tenant/app1/topic-1
persistent://tenant/app2/topic-2
persistent://tenant/app3/topic-3
```
## Topic
A [topic](/cloud/manage-data-streams/topic) in Pulsar is a storage unit that organizes messages into a stream. Similar to other publish-subscribe systems, topics in Pulsar act as named channels that facilitate message transmission from producers to consumers. The naming convention for topics follows a specific URL pattern:
```bash theme={null}
{persistent|non-persistent}://tenant/namespace/topic
```
The components of a topic name are defined as:
| Topic name component | Description |
| ----------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `persistent / non-persistent` | Indicates the type of topic. Pulsar supports both persistent and non-persistent topics. Persistent topics save all messages on disk, ensuring durability (messages are stored on multiple disks unless the broker is standalone). Non-persistent topics do not save data on disks. |
| `tenant` | Represents the tenant within the instance, highlighting Pulsar's support for multi-tenancy. |
| `namespace` | Acts as a grouping mechanism for related topics, with most configuration done at this level. Each tenant may have one or more namespaces. |
| `topic` | The specific name of the topic within a namespace. Topic names in Pulsar do not carry intrinsic meanings beyond their hierarchical organization. |
## Relate topics
This section could include links or references to further reading on related topics or advanced configurations in Pulsar.
# Work with Namespaces in StreamNative Cloud
Source: https://docs.streamnative.io/cloud/manage-data-streams/namespace
This document introduces the instructions for working with namespaces on StreamNative Console. The details may vary depending on the specific product and version number that you use.
A **namespace** is a logical grouping of topics. After creating a tenant, you can create one or more namespaces for the tenant.
## Namespace Overview
A namespace represents an administrative unit within a tenant. The configuration policies set on a namespace apply to all the topics created in that namespace. You can create multiple namespaces for a tenant using the StreamNative Cloud Console, REST API or the pulsar-admin CLI tool.
### Permissions
In Pulsar, permissions are managed at the namespace level (within tenants and clusters). You can grant permissions to specific users for lists of operations such as `produce` and `consume`. In addition, you can revoke permissions from specific users, which means that those users cannot access the specified namespace.
### Backlog quotas
Backlogs are sets of unacknowledged messages for a topic that have been stored by bookies. Pulsar stores all unacknowledged messages in backlogs until they are processed and acknowledged.
You can use the backlog quotas to control the allowable size of backlogs at the namespace level. You can set the following items for a backlog quota:
* an allowable size threshold for each topic in the namespace
* a retention policy that determines the action the broker takes if the threshold is exceeded.
The following table lists available retention policies.
| Policy | Action |
| --------------------------- | ----------------------------------------------------------------- |
| `producer_request_hold` | The broker holds but does not persist producers' request payload. |
| `producer_exception` | The broker disconnects from the client by throwing an exception. |
| `consumer_backlog_eviction` | The broker begins discarding backlog messages. |
### Bundles
For assignment, a namespace is sharded into a list of bundles, with each bundle comprising a portion of the overall hash range of the namespace. A bundle is a virtual group of topics that belong to the same namespace. A namespace bundle is defined as a range between two 32-bit hashes, such as 0x00000000 and 0xffffffff. By default, four bundles are supported for each namespace.
Since the load for topics in a bundle might change over time, one bundle can be split into two bundles by brokers. Then, the new smaller bundle is reassigned to different brokers. By default, the newly split bundles are immediately offloaded to other brokers to facilitate the traffic distribution.
### Dispatch rate
Dispatch rate refers to the number of messages dispatched per second by topics for a namespace. Dispatch rate can be restricted by the number of messages per second (`msg-dispatch-rate`) or by the number of bytes of messages per second (`byte-dispatch-rate`). Dispatch rate is in seconds and it can be configured with `dispatch-rate-period`. By default, `msg-dispatch-rate` and `byte-dispatch-rate` are both set to -1, which indicates that throttling is disabled.
## Create a namespace