diff --git a/app/_data/series.yml b/app/_data/series.yml index f926772d6c..9e18c98eba 100644 --- a/app/_data/series.yml +++ b/app/_data/series.yml @@ -41,3 +41,6 @@ mcp-acls: mesh-get-started-universal: title: Get started with {{site.mesh_product_name}} on Universal url: /mesh/get-started/universal/install/ +operator-multi-tenancy: + title: Deploy multiple isolated gateways on the same cluster + url: /operator/dataplanes/how-to/multi-tenancy/setup/ diff --git a/app/_how-tos/operator/operator-multi-tenancy-1-setup.md b/app/_how-tos/operator/operator-multi-tenancy-1-setup.md new file mode 100644 index 0000000000..3892ef6406 --- /dev/null +++ b/app/_how-tos/operator/operator-multi-tenancy-1-setup.md @@ -0,0 +1,147 @@ +--- +title: Install {{ site.operator_product_name }} for multi-tenancy +description: "Create tenant namespaces, install {{ site.operator_product_name }} scoped to those namespaces, and apply a KongLicense." +content_type: how_to + +permalink: /operator/dataplanes/how-to/multi-tenancy/setup/ +series: + id: operator-multi-tenancy + position: 1 + +breadcrumbs: + - /operator/ + - index: operator + group: Gateway Deployment + - index: operator + group: Gateway Deployment + section: "How-To" + +products: + - operator + +works_on: + - on-prem + +min_version: + operator: '2.0' + +related_resources: + - text: "Multi-tenancy reference" + url: /operator/reference/multi-tenancy/ + - text: "Limiting namespaces watched by ControlPlane" + url: /operator/reference/control-plane-watch-namespaces/ + +tldr: + q: How do I set up {{ site.operator_product_name }} for multi-tenancy? + a: | + Install {{ site.operator_product_name }} with `env.watch_namespace` scoped to your + tenant namespaces, then apply a single `KongLicense` in `kong-system`. + +prereqs: + skip_product: true + inline: + - title: "{{site.ee_product_name}} license" + icon_url: /assets/icons/key.svg + content: | + Save your {{site.ee_product_name}} license as `license.json` in your current working directory. If you don't have a license, contact your Kong representative. +--- + +This series deploys two independent {{ site.base_gateway }} instances — one public-facing, one private — on the same cluster using a single {{ site.operator_product_name }} installation. Each gateway is scoped to its own namespace so that its in-memory {{ site.kic_product_name_short }} only processes routes from that namespace. + +The following diagram shows the end state you'll build across this series: + + +{% mermaid %} +flowchart TB + subgraph cluster["Kubernetes Cluster"] + subgraph sys["kong-system"] + KO["{{ site.operator_product_name }}\n(KongLicense)"] + end + + subgraph pub["kong-gw-public"] + ConfigPub["GatewayConfiguration\nwatchNamespaces: own"] + GWPub["Gateway: gw-public"] + DPPub["Data plane Pod"] + SvcPub["echo service\nHTTPRoute /echo"] + end + + subgraph priv["kong-gw-private"] + ConfigPriv["GatewayConfiguration\nwatchNamespaces: own"] + GWPriv["Gateway: gw-private"] + DPPriv["Data plane Pod"] + SvcPriv["echo service\nHTTPRoute /echo"] + end + + KO -->|manages| GWPub + KO -->|manages| GWPriv + ConfigPub -.->|configures| GWPub + ConfigPriv -.->|configures| GWPriv + GWPub -->|provisions| DPPub + GWPriv -->|provisions| DPPriv + DPPub -->|routes traffic to| SvcPub + DPPriv -->|routes traffic to| SvcPriv + end +{% endmermaid %} + + +## Create namespaces + +Create the system namespace and the two tenant namespaces: + +```bash +kubectl create namespace kong-system +kubectl create namespace kong-gw-public +kubectl create namespace kong-gw-private +``` + +## Install {{ site.operator_product_name }} + +1. Add the Kong Helm chart repository: + + ```bash + helm repo add kong https://charts.konghq.com + helm repo update + ``` + +1. Install {{ site.operator_product_name }} scoped to the two tenant namespaces. The `watch_namespace` value prevents the operator from reconciling resources in any other namespace. + + ```bash + helm upgrade --install kong-operator kong/kong-operator \ + -n kong-system \ + --create-namespace \ + --set image.tag={{ site.data.operator_latest.release }} \ + --values - < **Note:** Setting this field in `ControlPlane` will configure the `CONTROLLER_WATCH_NAMESPACE` environment variable in the managed {{ site.kic_product_name }}. -> If you manually set the `CONTROLLER_WATCH_NAMESPACE` environment variable through `podTemplateSpec`, it will **override** this configuration. +> The `watchNamespaces` setting configures the `CONTROLLER_WATCH_NAMESPACE` environment variable in the managed {{ site.kic_product_name_short }}. If you set this variable manually through `podTemplateSpec`, it will override the `watchNamespaces` field. The `all` and `own` types don't require any further changes or additional resources. The `list` type requires further configuration. @@ -41,17 +48,18 @@ The `all` and `own` types don't require any further changes or additional resour The `list` type requires two additional steps: -1. Specify the namespaces to watch in the `spec.watchNamespaces.list` field. +1. Specify the namespaces to watch in the `spec.watchNamespaces.list` field: + ```yaml spec: watchNamespaces: type: list - list: - - namespace-a - - namespace-b + list: + - namespace-a + - namespace-b ``` -1. Create a `WatchNamespaceGrant` resource in each of the specified namespaces. This resource grants the `ControlPlane` permission to watch resources in the specified namespace. It can be defined as: +1. Create a `WatchNamespaceGrant` resource in each of the specified namespaces. This resource grants the `ControlPlane` permission to watch resources in that namespace: ```yaml apiVersion: gateway-operator.konghq.com/v1alpha1 @@ -68,20 +76,18 @@ The `list` type requires two additional steps: For more information on the `WatchNamespaceGrant` CRD, see the [CRD reference](/operator/reference/custom-resources/#watchnamespacegrant). -## Multi-tenancy using watch namespaces {% new_in 2.0 %} +## Operator-level namespace scoping {% new_in 2.0 %} -Multi-tenancy, in the context of {{ site.operator_product_name }}, is an approach that allows multiple instances of the {{ site.operator_product_name }} to share the same underlying infrastructure while keeping their data isolated and more specifically to watch disjoint namespaces. - -This allows you to configure {{ site.operator_product_name }} itself to watch namespaces instead of always specifying them in the `ControlPlane` resources. +From v2.0, you can scope {{ site.operator_product_name }} itself to watch only specific namespaces. This is separate from the per-`ControlPlane` `watchNamespaces` configuration and is useful when running multiple {{ site.operator_product_name }} instances on the same cluster with strictly disjoint namespace assignments. {:.warning} -> **Important:** If you configure watch namespaces on both {{ site.operator_product_name }} and `ControlPlane` resources, they must be configured so that they don't conflict. For example, if the {{ site.operator_product_name }} watches namespaces A and B, the `ControlPlane` resource can only define watch namespaces A and B. If you use other watch namespaces, such as namespace C, the `ControlPlane` object will receive an appropriate status condition and won't reconcile your configuration. +> If you configure watch namespaces on both {{ site.operator_product_name }} and `ControlPlane` resources, they must not conflict. For example, if {{ site.operator_product_name }} watches namespaces A and B, the `ControlPlane` can only define watch namespaces A or B. Using namespace C would cause the `ControlPlane` to receive a failure status condition and stop reconciling. You can set watch namespaces for {{ site.operator_product_name }} using several methods: {% navtabs "multi-tenant-namespaces" %} {% navtab "Helm chart" %} -When using the `kong-operator` Helm chart, you can use the `env` top level configuration in your `values.yaml`: +When using the `kong-operator` Helm chart, use the `env` top-level configuration in your `values.yaml`: ```yaml env: @@ -94,15 +100,10 @@ KONG_OPERATOR_WATCH_NAMESPACES='namespace-a,namespace-b' ``` {% endnavtab %} {% navtab "CLI" %} -To specify the comma separated list of namespaces to watch you can use the `--watch-namespaces` flag: +Use the `--watch-namespaces` flag with a comma-separated list of namespaces: ```bash ... --watch-namespaces namespace-a,namespace-b ... ``` {% endnavtab %} {% endnavtabs %} - - - - - diff --git a/app/operator/reference/multi-tenancy.md b/app/operator/reference/multi-tenancy.md new file mode 100644 index 0000000000..8774022971 --- /dev/null +++ b/app/operator/reference/multi-tenancy.md @@ -0,0 +1,59 @@ +--- +title: "Multi-tenancy" +description: "Understand how to run multiple isolated {{ site.base_gateway }} instances on the same Kubernetes cluster using {{ site.operator_product_name }}." +content_type: reference +layout: reference + +breadcrumbs: + - /operator/ + - index: operator + group: Reference + +products: + - operator + +works_on: + - on-prem + +min_version: + operator: '1.6' + +related_resources: + - text: "Deploy multiple isolated gateways on the same cluster" + url: /operator/dataplanes/how-to/multi-tenancy/setup/ + - text: "{{site.operator_product_name}} architecture" + url: /operator/reference/architecture/ + - text: "Limiting namespaces watched by ControlPlane" + url: /operator/reference/control-plane-watch-namespaces/ + - text: "Gateway configuration" + url: /operator/dataplanes/gateway-configuration/ + - text: "Managed Gateways" + url: /operator/dataplanes/managed-gateways/ + - text: "Custom Resources" + url: /operator/reference/custom-resources/ +--- + +Multi-tenancy in {{ site.operator_product_name }} means running multiple isolated {{ site.base_gateway }} instances — each with their own routing configuration, data plane, and namespace scope — on the same Kubernetes cluster, managed by a single {{ site.operator_product_name }} installation. + +Common use cases include separating a public-facing API gateway from an internal one, or giving different teams independent gateway instances without requiring separate clusters. For a step-by-step walkthrough, see [Deploy multiple isolated gateways](/operator/dataplanes/how-to/multi-tenancy/setup/). + +## How it works + +Each tenant is represented by a `Gateway`, provisioned using three resources: + +* `GatewayConfiguration`: A Kong-specific resource that configures the control plane and data plane options for a gateway, such as the proxy image, environment variables, and namespace watch scope. +* `GatewayClass`: A cluster-scoped Gateway API resource that registers {{ site.operator_product_name }} as the controller for gateways of this class. It references the `GatewayConfiguration` via `parametersRef`. +* `Gateway`: A namespaced Gateway API resource that declares a gateway instance. It references the `GatewayClass` via `gatewayClassName`, which is how {{ site.operator_product_name }} associates it with the correct `GatewayConfiguration`. + +For each `Gateway`, {{ site.operator_product_name }} creates: + +* One in-memory {{ site.kic_product_name_short }} instance embedded inside the {{ site.operator_product_name }} Pod, which watches Gateway API resources and translates them into Kong configuration. +* One data plane deployment running {{ site.base_gateway }} in DB-less mode. + +Multiple `Gateway` resources can coexist in the same cluster. The resulting in-memory {{ site.kic_product_name_short }} instances and data plane Pods are independent of each other. A single {{ site.operator_product_name }} installation manages them all. + +## Namespace isolation + +By default, each in-memory {{ site.kic_product_name_short }} instance watches all namespaces for Gateway API resources (`HTTPRoute`, `GRPCRoute`, etc.). Without additional configuration, one tenant's {{ site.kic_product_name_short }} would also process another tenant's routes, so namespace isolation is required for multi-tenancy. + +Set `watchNamespaces` on `GatewayConfiguration.spec.controlPlaneOptions` to restrict each gateway's in-memory {{ site.kic_product_name_short }} to its own namespace. For the full field reference, type options, `WatchNamespaceGrant` configuration, and operator-level scoping, see [Limiting namespaces watched by ControlPlane](/operator/reference/control-plane-watch-namespaces/). \ No newline at end of file