diff --git a/website/content/docs/k8s/multiport/configure.mdx b/website/content/docs/k8s/multiport/configure.mdx
new file mode 100644
index 00000000000..0cae43d471f
--- /dev/null
+++ b/website/content/docs/k8s/multiport/configure.mdx
@@ -0,0 +1,480 @@
+---
+layout: docs
+page_title: Configure multi-port services
+description: Learn how to enable the v2 catalog and configure services to support multiple ports in Consul on Kubernetes. You can configure multiple ports on a single service or multiple services and ports in a single container.
+---
+
+# Configure multi-port services
+
+
+
+Multi-port services are part of a beta release. This documentation supports testing and development scenarios. Do not use multi-port services or the v2 catalog API in secure production environments.
+
+
+
+This page describes the process for integrating a service that uses multiple ports in a single container when running Consul on Kubernetes deployments. It includes example configurations to demonstrate an end-to-end deployment test of Consul's multi-port features.
+
+## Prerequisites
+
+Registering multi-port services with Consul requires Kubernetes. Multi-port services are not supported on VM deployments.
+
+The following software versions are required:
+
+- Consul v1.17.0
+- `consul-k8s` CLI v1.3.0+ or `hashicorp/consul` Helm chart release v1.3.0+
+
+For more information about upgrading versions for `consul-k8s` and Helm charts, refer to [Update the Consul K8s CLI](/consul/docs/k8s/upgrade/upgrade-cli) and [Upgrade Helm chart version](/consul/docs/k8s/upgrade#upgrade-helm-chart-version).
+
+There are additional requirements for service mesh proxies in transparent proxy mode. This mode enables queries through Kube DNS instead of Consul DNS over permissive mTLS settings. For more information about the steps to configure global settings and enable permissive mTLS mode before registering a service, refer to the [onboard services in transparent mode workflow](/consul/docs/k8s/connect/onboarding-tproxy-mode#workflow).
+
+## Enable the v2 catalog
+
+To enable the v2 catalog and its support for multi-port services, set `global.experiments: ["resource-apis"]` and `ui.enabled: false`. The following example includes these parameter in a Helm chart with minimal required configurations for the Consul installation:
+
+
+
+```yaml
+global:
+ enabled: true
+ name: consul
+ image: hashicorp/consul:1.17.0-rc1
+ datacenter: dc1
+ tls:
+ enabled: true
+ experiments: ["resource-apis"]
+server:
+ enabled: true
+ replicas: 1
+connectInject:
+ enabled: true
+ui:
+ enabled: false
+```
+
+
+
+Then install Consul to your Kubernetes cluster using either the `consul-k8s` CLI or Helm.
+
+
+
+
+
+```shell-session
+$ consul-k8s install -config-file=values.yaml
+```
+
+
+
+
+
+```shell-session
+$ helm install consul hashicorp/consul --create-namespace --namespace consul --values values.yaml
+```
+
+
+
+
+## Define the multi-port service
+
+Consul's v2 catalog supports two methods for defining multi-port services in Kubernetes:
+
+- Method 1: Define a single Kubernetes Service that exposes multiple ports
+- Method 2: Define multiple Kubernetes Services that expose individual ports
+
+These methods affect how the Services are addressed in Kubernetes.
+
+Each tab in the following example contains a configuration that defines an `api` service using one of these methods. Both definitions schedule a Pod running two containers that each support traffic to one of the ports exposed by the Service. In `Method 1`, both services are addressed using `api` because both services are exposed by a single service. In `Method 2`, `api` and `api-admin` are defined as separate services and can be addressed using distinct names.
+
+
+
+
+
+
+
+```yaml
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ name: api
+---
+apiVersion: v1
+kind: Service
+metadata:
+ name: api
+spec:
+ selector:
+ app: api
+ ports:
+ - name: api
+ port: 80
+ targetPort: api
+ - name: admin
+ port: 90
+ targetPort: admin
+---
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: api
+spec:
+ replicas: 1
+ selector:
+ matchLabels:
+ app: api
+ template:
+ metadata:
+ name: api
+ labels:
+ app: api
+ annotations:
+ "consul.hashicorp.com/mesh-inject": "true"
+ 'consul.hashicorp.com/transparent-proxy': 'true'
+ spec:
+ containers:
+ - name: api
+ image: docker.mirror.hashicorp.services/hashicorp/http-echo:latest
+ args:
+ - -text="hello world"
+ - -listen=:8080
+ ports:
+ - containerPort: 8080
+ name: api
+ - name: api-admin
+ image: docker.mirror.hashicorp.services/hashicorp/http-echo:latest
+ args:
+ - -text="hello world from 9090 admin"
+ - -listen=:9090
+ ports:
+ - containerPort: 9090
+ name: admin
+ serviceAccountName: api
+```
+
+
+
+
+
+
+
+
+```yaml
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ name: api
+---
+apiVersion: v1
+kind: Service
+metadata:
+ name: api
+spec:
+ selector:
+ app: api
+ ports:
+ - name: api
+ port: 80
+ targetPort: api
+---
+apiVersion: v1
+kind: Service
+metadata:
+ name: api-admin
+spec:
+ selector:
+ app: api
+ ports:
+ - name: admin
+ port: 90
+ targetPort: admin
+---
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: api
+spec:
+ replicas: 1
+ selector:
+ matchLabels:
+ app: api
+ template:
+ metadata:
+ name: api
+ labels:
+ app: api
+ annotations:
+ "consul.hashicorp.com/mesh-inject": "true"
+ 'consul.hashicorp.com/transparent-proxy': 'true'
+ spec:
+ containers:
+ - name: api
+ image: docker.mirror.hashicorp.services/hashicorp/http-echo:latest
+ args:
+ - -text="hello world"
+ - -listen=:8080
+ ports:
+ - containerPort: 8080
+ name: api
+ - name: api-admin
+ image: docker.mirror.hashicorp.services/hashicorp/http-echo:latest
+ args:
+ - -text="hello world from 9090 admin"
+ - -listen=:9090
+ ports:
+ - containerPort: 9090
+ name: admin
+ serviceAccountName: api
+```
+
+
+
+
+
+For testing purposes, the following example defines a Service to function as a static client that you can use to verify that the multi-port services function correctly.
+
+
+
+```yaml
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ name: web
+---
+apiVersion: v1
+kind: Service
+metadata:
+ name: web
+spec:
+ selector:
+ app: web
+ ports:
+ - port: 80
+---
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: web
+spec:
+ replicas: 1
+ selector:
+ matchLabels:
+ app: web
+ template:
+ metadata:
+ name: web
+ labels:
+ app: web
+ annotations:
+ "consul.hashicorp.com/mesh-inject": "true"
+ 'consul.hashicorp.com/transparent-proxy': 'true'
+ spec:
+ containers:
+ - name: web
+ image: curlimages/curl:latest
+ # Just spin & wait forever, we'll use `kubectl exec` to demo
+ command: ['/bin/sh', '-c', '--']
+ args: ['while true; do sleep 30; done;']
+ serviceAccountName: web
+```
+
+
+
+To apply these services to your Kubernetes deployment and register them with Consul, run the following command:
+
+```shell-session
+$ kubectl apply -f api.yaml -f web.yaml --namespace consul
+```
+
+## Configure traffic permissions
+
+Consul uses traffic permissions to validate communication between services based on L4 identity. In the beta release of the v2 catalog API, traffic permissions allow all services by default. In order to verify that services function correctly on each port, create CRDs that deny traffic to each port.
+
+The following examples create Consul CRDs that allow traffic to only one port of the multi-port service. Each resource separately denies `web` permission when it is a source of traffic to one of the services. These traffic permissions work with either method for defining a multi-port service.
+
+
+
+
+
+```yaml
+apiVersion: auth.consul.hashicorp.com/v2beta1
+kind: TrafficPermissions
+metadata:
+ name: web-to-api-port-deny
+spec:
+ destination:
+ identityName: api
+ action: deny
+ permissions:
+ - sources:
+ - identityName: web
+ destinationRules:
+ - portNames: ["api"]
+```
+
+
+
+
+
+```yaml
+apiVersion: auth.consul.hashicorp.com/v2beta1
+kind: TrafficPermissions
+metadata:
+ name: web-to-admin-port-deny
+spec:
+ destination:
+ identityName: api
+ action: deny
+ permissions:
+ - sources:
+ - identityName: web
+ destinationRules:
+ - portNames: ["admin"]
+```
+
+
+
+
+## Validate multi-port connection
+
+To open a shell to the `web` container, you need the name of the Pod it currently runs on. Run the following command to return a list of Pods:
+
+```shell-session
+$ kubectl get pods
+NAME READY STATUS RESTARTS AGE
+api-7dc9d84f-kfnwz 2/2 Running 0 23s
+web-7bc5786747-b5pzl 1/1 Running 0 23s
+```
+
+### Validate both ports
+
+Use the `web` Pod's name to open a shell session and test the `api` service on port 80.
+
+
+
+
+
+```shell-session
+$ kubectl exec -it web-7bc5786747-b5pzl -- curl api:80
+hello world
+```
+
+Then test the `api` service on port 90.
+
+```shell-session
+$ kubectl exec -it web-7bc5786747-b5pzl -- curl api:90
+hello world from 9090 admin
+```
+
+
+
+
+
+```shell-session
+$ kubectl exec -it web-7bc5786747-b5pzl -- curl api:80
+hello world
+```
+
+Then test the `api-admin` service on port 90.
+
+```shell-session
+$ kubectl exec -it web-7bc5786747-b5pzl -- curl api-admin:90
+hello world from 9090 admin
+```
+
+
+
+
+### Validate port 80
+
+Apply the CRD to allow traffic to port 80 only:
+
+```shell-session
+$ kubectl apply -f deny-90.yaml --namespace consul
+```
+
+
+
+
+
+Then, open a shell session in the `web` container and test the `api` service on port 80.
+
+```shell-session
+$ kubectl exec -it web-7bc5786747-b5pzl -- curl api:80
+hello world
+```
+
+Test the `api` service on port 90. This command should fail, indicating that the traffic permission is in effect.
+
+```shell-session
+$ kubectl exec -it web-7bc5786747-b5pzl -- curl api:90
+```
+
+
+
+
+
+Then, open a shell session in the `web` container and test the `api` service on port 80.
+
+```shell-session
+$ kubectl exec -it web-7bc5786747-b5pzl -- curl api:80
+hello world
+```
+
+Test the `admin` service on port 90. This command should fail, indicating that the traffic permission is in effect.
+
+```shell-session
+$ kubectl exec -it web-7bc5786747-b5pzl -- curl api-admin:90
+```
+
+
+
+
+Before testing the other port, remove the `TrafficPermissions` CRD.
+
+```shell-session
+$ kubectl delete -f deny-90.yaml --namespace consul
+```
+
+### Validate port 90
+
+Apply the CRD to allow traffic to port 90 only:
+
+```shell-session
+$ kubectl apply -f deny-80.yaml --namespace consul
+```
+
+
+
+
+
+Then, open a shell session in the `web` container and test the `api` service on port 90.
+
+```shell-session
+$ kubectl exec -it web-7bc5786747-b5pzl -- curl api:90
+hello world from 9090 admin
+```
+
+Test the `api` service on port 80. This command should fail, indicating that the traffic permission is in effect.
+
+```shell-session
+$ kubectl exec -it web-7bc5786747-b5pzl -- curl api:80
+```
+
+
+
+
+
+Then, open a shell session in the `web` container and test the `api-admin` service on port 90.
+
+```shell-session
+$ kubectl exec -it web-7bc5786747-b5pzl -- curl api-admin:90
+hello world from 9090 admin
+```
+
+Test the `api` service on port 80. This command should fail, indicating that the traffic permission is in effect.
+
+```shell-session
+$ kubectl exec -it web-7bc5786747-b5pzl -- curl api:80
+```
+
+
+
\ No newline at end of file
diff --git a/website/content/docs/k8s/multiport/index.mdx b/website/content/docs/k8s/multiport/index.mdx
new file mode 100644
index 00000000000..9b8ef4dac9c
--- /dev/null
+++ b/website/content/docs/k8s/multiport/index.mdx
@@ -0,0 +1,69 @@
+---
+layout: docs
+page_title: Multi-port services for service mesh
+description: Consul on Kubernetes supports multi-port services for both service discovery and service mesh scenarios. Learn about Consul’s v2 catalog changes to support multiple ports for a service running in a single container.
+---
+
+# Multi-port services for service mesh
+
+
+
+Multi-port services are part of a beta release. This documentation supports testing and development scenarios. Do not use multi-port services or the v2 catalog API in secure production environments.
+
+
+
+This topic describes changes to Consul's catalog that allow you to register a service with multiple ports on Kubernetes deployments.
+
+## Background
+
+When Consul registers services, v1 of its catalog API tracks the following information:
+
+- IDs of the specific _service instances_ that are registered
+- Locations of the _nodes_ the instances run on
+- Names of the _services_ the instances are associated with
+
+This catalog API was designed prior to the introduction of Consul’s service mesh features. Services and service instances are coupled in the catalog such that Consul's ACL system requires a Kubernetes ServiceAccount resource to match the Service name. As a result, only one service can represent a Kubernetes Workload in the Consul catalog.
+
+Since then, the cloud networking needs for applications have evolved and the Consul catalog adapted to support workarounds for these needs. For example, [Kubernetes Pods with multiple ports](/consul/docs/k8s/connect#kubernetes-pods-with-multiple-ports) demonstrates how you can schedule a service with multiple ports so that Consul registers it in the catalog as distinct services with their own service instances. However, this workaround results in additional resource consumption because Consul requires that each service and port use their own proxy and Consul dataplane so that it can recognize them as distinct services.
+
+### Catalog API v2 beta
+
+Consul v1.17 introduces a new version of the catalog API designed to bridge differences between the Consul and Kubernetes data models. The v2 catalog API still tracks services and nodes for Consul, but replaces service instances with _workloads_ and _workload identites_.
+
+- `Workload` is an application instance running in a set of one or more Pods scheduled according to a Kubernetes Workload resource such as a Deployment or StatefulSet. It is similar to [Kubernetes Workloads](https://kubernetes.io/docs/concepts/workloads/).
+- `WorkloadIdentities` provide a distinct identity for a Workload to assume in a Kubernetes cluster. THey are similar to [Kubernetes Service Accounts](https://kubernetes.io/docs/concepts/security/service-accounts/).
+
+This catalog structure enables Consul to associate a single Kubernetes Workload with multiple services in its catalog.
+
+The v2 catalog API also tracks the following information about services when they are registered with Consul:
+
+- `ServiceEndpoints` maps services to workload addresses and endpoints. This resource is computed by Consul.
+- `HealthStatus` is a resource for reporting the health status of a workload.
+- `HealthCheck` is a resource for defining the health checks for a workload.
+- `ProxyConfiguration` represents a configuration for a sidecar or gateway proxy, similar to the `Proxy` field in the current service definition.
+- `Destinations` represents explicit service upstreams.
+- `TrafficPermissions` is a replacement for the `ServiceIntentions` custom resource definition (CRD). Traffic permissions replace service intentions for all services in the v2 catalog, which enables L4 traffic authorization according to workload identity instead of service identity.
+
+The v2 catalog API is available alongside the existing v1 catalog API, but the catalogs cannot be used simultaneously. The v2 catalog is disabled by default. This beta release is for testing and development purposes only. We do not recommend implementing v2 in production environments or migrating to v2 until the API is generally available.
+
+## Workflow
+
+To use a multi-port service in Consul on Kubernetes deployments, complete the following steps:
+
+1. Enable the v2 catalog. Add `global.experiments: ["resource-apis"]` and `ui.enabled: false` to a cluster's Helm chart before deploying Consul.
+1. Use the `"consul.hashicorp.com/mesh-inject": "true"` annotation so that Consul registers the service automatically when Kubernetes deploys containers.
+1. Configure traffic permissions. In the beta release, services registered to the v2 catalog allow all traffic by default. You can use the `TrafficPermissions` CRD to deny traffic to individual services for testing purposes.
+1. Validate multi-port functionality. Send test traffic to each port to confirm that traffic is authorized and routed correctly.
+
+For an example configuration and instructions for each of the steps in this workflow, refer to [configure multi-port services](/consul/docs/k8s/multiport/configure).
+
+## Constraints and limitations
+
+Be aware of the following constraints and technical limitations on using multi-port services and the v2 catalog API:
+
+- The v2 catalog API beta does not support connections with client agents. It is only available for Kubernetes deployments, which use [Consul dataplanes](consul/docs/connect/dataplane) instead of client agents.
+- The v1 and v2 catalog APIs cannot run concurrently.
+- The Consul UI does not support multi-port services or the v2 catalog API in this release. You must disable the UI in the Helm chart in order to use the v2 catalog API.
+- HCP Consul does not support multi-port services or the v2 catalog API in this release.
+- The v2 catalog API does not support ACLs in the beta release.
+- We do not recommend updating existing clusters to enable the v2 catalog in this release. To use the v2 catalog, deploy a new Consul cluster.
\ No newline at end of file
diff --git a/website/data/docs-nav-data.json b/website/data/docs-nav-data.json
index 419a706db59..ab452439a47 100644
--- a/website/data/docs-nav-data.json
+++ b/website/data/docs-nav-data.json
@@ -1510,6 +1510,19 @@
}
]
},
+ {
+ "title": "Multi-port services",
+ "routes": [
+ {
+ "title": "Overview",
+ "path": "k8s/multiport"
+ },
+ {
+ "title": "Configure multi-port services",
+ "path": "k8s/multiport/configure"
+ }
+ ]
+ },
{
"title": "L7 traffic management",
"routes": [