<a id="multi-tenancy-onboard-a-tenant"></a>

# Onboard an LKC to a Multi-Tenant Physical Kafka Cluster

Provision a Logical Kafka Cluster (LKC) on an existing multi-tenant
Physical Kafka Cluster (PKC) in Confluent Private Cloud. Platform operators perform this
procedure once per LKC.

## Prerequisites

Before you begin, ensure you have the following:

- A multi-tenant PKC. For more information, see the Deploy a
  Multi-Tenant Physical Kafka Cluster page.
  
- A user principal or service account configured in your shared
  identity provider (IdP). To secure your IdP integration, see
  [Plan Security for Confluent for Kubernetes](https://docs.confluent.io/operator/current/co-plan-security.html).
- A `KafkaRestClass` in the same namespace as the LKC, whose principal holds
  the `OrganizationAdmin` role on the PKC. A `TenantAdmin` can’t create
  an LKC. Name the `KafkaRestClass` `default`, or reference it with
  `spec.kafkaRestClassRef` in both the `LogicalKafkaCluster` manifest and
  the role binding manifest in [Step 7](#multi-tenancy-onboard-step-7).
  Alternatively, set `spec.kafkaRest` on the `LogicalKafkaCluster` to
  provide the connection details inline. You can’t set both
  `spec.kafkaRestClassRef` and `spec.kafkaRest`.

<a id="multi-tenancy-onboard-step-1"></a>

## Step 1: Assess PKC capacity

Before provisioning an LKC, estimate the LKC’s workload requirements:

- Producer and consumer byte rates
- Total client connection count
- Total topic partition count

Compare these requirements against the PKC capacity baseline
established during initial cluster deployment. For more information,
see the Deploy a Multi-Tenant Physical Kafka Cluster page. If host
capacity is insufficient, scale the underlying PKC before proceeding.

#### IMPORTANT
A multi-tenant cluster stores tenant metadata in the cluster registry and supports up to
25 LKCs by default. To support more than 25 LKCs, enable compression by
setting
`confluent.metadata.server.cluster.registry.compression.enable=true` in the
Metadata Service (MDS) configuration before reaching the limit. You cannot disable
compression after you enable it.



<a id="multi-tenancy-onboard-step-2"></a>

## Step 2: Configure resource quotas and limits

Set the following quotas and limits on the `LogicalKafkaCluster`
custom resource (CR). Size each value as a share of the PKC’s
capacity-planning baseline from [Step 1](#multi-tenancy-onboard-step-1), so that the combined values of all
LKCs stay within what the PKC can deliver.

- `spec.quotas.ingressByteRate` and `spec.quotas.egressByteRate`:
  The LKC’s producer and consumer throughput limits, in bytes per
  second. The minimum value is `1`. If you omit a value, the LKC has no
  limit of its own in that direction. Only the PKC’s broker-wide limits
  apply, and all LKCs on the PKC share them.
- `spec.quotas.brokerRequestThreads`: The request-processing thread
  time that the LKC can use on each broker. Specify the value as a
  thread count, not a percentage. For example, `1.0` is one thread
  fully busy, and `2.5` allows 2.5 threads fully busy. The value must
  be greater than `0`. If you omit the value, it defaults to `2.5`
  threads.
- `spec.limits.maxPartitions`: The maximum partition count across
  the LKC’s topics. If you omit the value, the broker’s default limit,
  `4096` partitions, applies.
- `spec.limits.maxMessageSizeBytes`: The maximum
  `max.message.bytes` value a client can set on a topic in the
  LKC. If you omit the value, the broker’s default maximum applies.
  A topic that a client creates without `max.message.bytes` uses the
  broker’s `message.max.bytes` value, whatever this limit is. To keep every
  topic in the LKC within the limit, set the limit at or above
  `message.max.bytes`.

The LKC also has a limit on the number of client connections. Each broker
limits an LKC to `heapGiB × 1024` connections, where `heapGiB` is the
broker’s JVM heap size in GiB. You can’t change this limit for an individual
LKC. For the broker-level capacity values, see the Deploy a Multi-Tenant
Physical Kafka Cluster page.

<a id="multi-tenancy-onboard-step-3"></a>

## Step 3: Define a unique LKC name

Choose a unique name for the LKC. If you leave `spec.name` unset,
CFK uses the LKC CR’s object name.

The name must be unique on the PKC and one to 64 characters long. It can
contain letters, numbers, periods, underscores, and hyphens, and it
must start with a letter or number. Names of the form `lkc-*-external`
are reserved.

<a id="multi-tenancy-onboard-step-4"></a>

## Step 4: Create the `LogicalKafkaCluster` manifest

1. Create a manifest file named `lkc.yaml` with the following
   configuration:
   ```yaml
   apiVersion: platform.confluent.io/v1beta1
   kind: LogicalKafkaCluster
   metadata:
     name: <lkc-name>
     namespace: <lkc-namespace>
   spec:
     name: <lkc-display-name>
     kafkaClusterRef:
       kind: Kafka
       name: <pkc-name>
       namespace: <pkc-namespace>
     quotas:
       ingressByteRate: <ingress-byte-rate>
       egressByteRate: <egress-byte-rate>
       brokerRequestThreads: <broker-request-threads>
     limits:
       maxPartitions: <max-partitions>
       maxMessageSizeBytes: <max-message-size-bytes>
   ```

   Replace the placeholders with your values:
   - `<lkc-name>`: A Kubernetes object name for the LKC CR. This
     name is separate from the LKC name you chose in [Step 3](#multi-tenancy-onboard-step-3), although you can use the same
     value.
   - `<lkc-namespace>`: The Kubernetes namespace for the LKC CR. The
     `KafkaRestClass` that CFK uses to create the LKC must be in this
     namespace.
   - `<lkc-display-name>`: The LKC name you chose in [Step 3](#multi-tenancy-onboard-step-3).
   - `<pkc-name>`: The name of the PKC’s `Kafka` CR you configured
     by following the Deploy a Multi-Tenant Physical Kafka Cluster
     page.
   - `<pkc-namespace>`: The namespace of the PKC’s `Kafka` CR. This can
     differ from the LKC’s namespace.
   - `<ingress-byte-rate>`, `<egress-byte-rate>`,
     `<broker-request-threads>`, `<max-partitions>`,
     `<max-message-size-bytes>`: The values you sized in [Step 2](#multi-tenancy-onboard-step-2).

   
2. Apply the configuration:
   ```bash
   kubectl apply -f lkc.yaml
   ```

<a id="multi-tenancy-onboard-step-5"></a>

## Step 5: Verify LKC provisioning and operational isolation

1. Confirm that the `STATE` column reports `CREATED` and the
   `PHASE` column reports `Running`. Note the `LKC-ID` value:
   ```bash
   kubectl get logicalkafkacluster <lkc-name> -n <your-namespace>
   ```
2. Retrieve the LKC’s dedicated bootstrap URL from its
   `status.bootstrapEndpoint` field:
   ```bash
   kubectl get logicalkafkacluster <lkc-name> -n <your-namespace> \
     -o jsonpath='{.status.bootstrapEndpoint}'
   ```

   Make sure that your DNS resolves this URL and that the broker certificate
   includes the LKC hostnames. For the DNS records and certificate names, see
   [Configure TLS Certificates and DNS for Multi-Tenant PKCs](tls-options.md#multi-tenancy-tls-options).
3. Create a client configuration file named `client.properties` for a
   principal that holds the `OrganizationAdmin` role on the PKC, such as
   the identity you used to deploy the PKC:
   ```properties
   security.protocol=SASL_SSL
   sasl.mechanism=PLAIN
   sasl.jaas.config=org.apache.kafka.common.security.plain.PlainLoginModule required username="<username>" password="<password>";
   ssl.truststore.type=PEM
   ssl.truststore.location=<ca-certificate-path>
   ```

   Replace the placeholders with your values:
   - `<username>` and `<password>`: The principal’s credentials for the
     PKC’s external listener.
   - `<ca-certificate-path>`: The path to the CA certificate that signed
     the PKC’s broker certificate.

   This example uses SASL/PLAIN. If your PKC’s external listener uses a
   different mechanism, configure the client for that mechanism. For more
   information, see [Authentication in Confluent Platform](../../security/authentication/overview.md#authentication-overview).
4. Connect to the bootstrap URL, create a test topic, and confirm that it
   appears in the LKC’s own topic list. For the `kafka-topics` command
   syntax, see [Use the command-line tools](../../get-started/tutorial-multi-broker.md#ak-commands-cheat-sheet):
   ```bash
   kafka-topics --bootstrap-server <lkc-bootstrap-url> \
     --command-config client.properties \
     --create --topic test-topic --partitions 3 --replication-factor 3

   kafka-topics --bootstrap-server <lkc-bootstrap-url> \
     --command-config client.properties --list
   ```

   Replace `<lkc-bootstrap-url>` with the `status.bootstrapEndpoint`
   value from the previous step.
5. Using the same client, produce and consume test messages on that
   topic. For `kafka-console-producer` and `kafka-console-consumer`
   usage, see the same [command-line tools](../../get-started/tutorial-multi-broker.md#ak-commands-cheat-sheet)
   page.
6. If this isn’t the first LKC on the PKC, connect to another
   LKC’s bootstrap URL. Confirm that the client can’t list or
   access the test topic you created in this LKC.

<a id="multi-tenancy-onboard-step-6"></a>

## Step 6: Identify the `TenantAdmin` principal

Choose an existing principal in your shared IdP to receive the
`TenantAdmin` role for this LKC.

<a id="multi-tenancy-onboard-step-7"></a>

## Step 7: Assign the `TenantAdmin` role

1. Create a manifest file named `rolebinding.yaml` to grant the
   `TenantAdmin` role, scoped to this LKC:
   ```yaml
   apiVersion: platform.confluent.io/v1beta1
   kind: ConfluentRolebinding
   metadata:
     name: <tenant-admin-binding-name>
     namespace: <your-namespace>
   spec:
     principal:
       type: user
       name: <tenant-admin-identity>
     role: TenantAdmin
     kafkaClusterRef:
       kind: LogicalKafkaCluster
       name: <lkc-name>
   ```

   Replace the placeholders with your values:
   - `<tenant-admin-binding-name>`: A name for the
     `ConfluentRolebinding` CR.
   - `<tenant-admin-identity>`: The `TenantAdmin`’s identity from
     [Step 6](#multi-tenancy-onboard-step-6).
   - `<lkc-name>`: The name of the LKC you created in [Step 4](#multi-tenancy-onboard-step-4). The `LogicalKafkaCluster` CR must be
     in the same namespace as the role binding.
2. Apply the configuration:
   ```bash
   kubectl apply -f rolebinding.yaml
   ```

For more information about managing role-based access control (RBAC) with CRs, see [Manage
RBAC for Confluent Platform Using Confluent for Kubernetes](https://docs.confluent.io/operator/current/co-manage-rbac.html).

<a id="multi-tenancy-onboard-step-8"></a>

## Step 8: Provide connection details to the `TenantAdmin`

Provide the following to the `TenantAdmin` so that they can
start onboarding their own developers:

- The LKC’s dedicated bootstrap URL, from [Step 5](#multi-tenancy-onboard-step-5).
- The authentication mechanisms configured on the PKC’s shared IdP.
- The Confluent Control Center URL, so that the `TenantAdmin` can monitor their
  own LKC’s resources and usage statistics.
- The quota and limit boundaries you set in [Step 2](#multi-tenancy-onboard-step-2).
- An escalation path for requesting a quota increase or reporting an
  issue.

## Related content

- Deploy a Multi-Tenant Physical Kafka Cluster
- [Multi-Tenancy Overview](overview.md#multi-tenancy-overview)
- [Decommission an LKC](decommission-a-tenant.md#multi-tenancy-decommission-a-tenant)


