Skip to content
Kong Docs are moving soon! Our docs are migrating to a new home. You'll be automatically redirected to the new site in the future. In the meantime, view this page on the new site!
Kong Logo | Kong Docs Logo
  • Docs
    • Explore the API Specs
      View all API Specs View all API Specs View all API Specs arrow image
    • Documentation
      API Specs
      Kong Gateway
      Lightweight, fast, and flexible cloud-native API gateway
      Kong Konnect
      Single platform for SaaS end-to-end connectivity
      Kong AI Gateway
      Multi-LLM AI Gateway for GenAI infrastructure
      Kong Mesh
      Enterprise service mesh based on Kuma and Envoy
      decK
      Helps manage Kong’s configuration in a declarative fashion
      Kong Ingress Controller
      Works inside a Kubernetes cluster and configures Kong to proxy traffic
      Kong Gateway Operator
      Manage your Kong deployments on Kubernetes using YAML Manifests
      Insomnia
      Collaborative API development platform
  • Plugin Hub
    • Explore the Plugin Hub
      View all plugins View all plugins View all plugins arrow image
    • Functionality View all View all arrow image
      View all plugins
      AI's icon
      AI
      Govern, secure, and control AI traffic with multi-LLM AI Gateway plugins
      Authentication's icon
      Authentication
      Protect your services with an authentication layer
      Security's icon
      Security
      Protect your services with additional security layer
      Traffic Control's icon
      Traffic Control
      Manage, throttle and restrict inbound and outbound API traffic
      Serverless's icon
      Serverless
      Invoke serverless functions in combination with other plugins
      Analytics & Monitoring's icon
      Analytics & Monitoring
      Visualize, inspect and monitor APIs and microservices traffic
      Transformations's icon
      Transformations
      Transform request and responses on the fly on Kong
      Logging's icon
      Logging
      Log request and response data using the best transport for your infrastructure
  • Support
  • Community
  • Kong Academy
Get a Demo Start Free Trial
Kong Mesh
2.10.x (latest)
  • Home icon
  • Kong Mesh
  • Guides
  • Deploy Kong Mesh using Terraform and Konnect
github-edit-pageEdit this page
report-issueReport an issue
  • Kong Gateway
  • Kong Konnect
  • Kong Mesh
  • Kong AI Gateway
  • Plugin Hub
  • decK
  • Kong Ingress Controller
  • Kong Gateway Operator
  • Insomnia
  • Kuma

  • Docs contribution guidelines
  • dev
  • 2.10.x (latest)
  • 2.9.x
  • 2.8.x
  • 2.7.x (LTS)
  • 2.6.x
  • 2.5.x
  • 2.4.x
  • 2.3.x
  • 2.2.x
  • Introduction
    • About service meshes
    • Overview of Kong Mesh
    • How Kong Mesh works
    • Architecture
    • Install
    • Concepts
    • Stages of software availability
    • Version support policy
    • Software Bill of Materials
    • Vulnerability patching process
    • Mesh requirements
    • Release notes
  • Quickstart
    • Deploy Kong Mesh on Kubernetes
    • Deploy Kong Mesh on Universal
  • Kong Mesh in Production
    • Overview
    • Deployment topologies
      • Overview
      • Single-zone deployment
      • Multi-zone deployment
    • Use Kong Mesh
    • Control plane deployment
      • Kong Mesh license
      • Deploy a single-zone control plane
      • Deploy a multi-zone global control plane
      • Zone Ingress
      • Zone Egress
      • Configure zone proxy authentication
      • Control plane configuration reference
      • Systemd
      • Kubernetes
      • kumactl
      • Deploy Kong Mesh in Production with Helm
    • Configuring your Mesh and multi-tenancy
    • Data plane configuration
      • Data plane proxy
      • Configure the data plane on Kubernetes
      • Configure the data plane on Universal
      • Configure the Kong Mesh CNI
      • Configure transparent proxying
      • IPv6 support
    • Secure your deployment
      • Manage secrets
      • Authentication with the API server
      • Authentication with the data plane proxy
      • Configure data plane proxy membership
      • Secure access across services
      • Kong Mesh RBAC
      • FIPS support
    • Kong Mesh user interface
    • Inspect API
      • Matched policies
      • Affected data plane proxies
      • Envoy proxy configuration
    • Upgrades and tuning
      • Upgrade Kong Mesh
      • Performance fine-tuning
      • Version specific upgrade notes
    • Control Plane Configuration
      • Modifying the configuration
      • Inspecting the configuration
      • Store
  • Using Kong Mesh
    • Zero Trust & Application Security
      • Mutual TLS
      • External Service
    • Resiliency & Failover
      • Dataplane Health
      • Service Health Probes
    • Managing incoming traffic with gateways
      • How ingress works in Kuma
      • Delegated gateways
      • Built-in gateways
      • Running built-in gateway pods on Kubernetes
      • Configuring built-in listeners
      • Configuring built-in routes
      • Using the Kubernetes Gateway API
    • Observability
      • Demo setup
      • Control plane metrics
      • Configuring Prometheus
      • Configuring Grafana
      • Configuring Datadog
      • Observability in multi-zone
    • Route & Traffic shaping
      • Protocol support in Kong Mesh
    • Service Discovery & Networking
      • Service Discovery
      • MeshService
      • MeshMultiZoneService
      • HostnameGenerator
      • DNS
      • Non-mesh traffic
      • MeshExternalService
      • Transparent Proxying
  • Policies
    • Introduction
      • What is a policy?
      • What do policies look like?
      • Writing a targetRef
      • Merging configuration
      • Using policies with MeshService
      • Examples
      • Applying policies in shadow mode
    • MeshAccessLog
      • TargetRef support matrix
      • Configuration
      • Examples
    • MeshCircuitBreaker
      • TargetRef support matrix
      • Configuration
      • Examples
    • MeshFaultInjection
      • TargetRef support matrix
      • Configuration
      • Examples
    • MeshHealthCheck
      • TargetRef support matrix
      • Configuration
      • Examples
    • MeshHTTPRoute
      • TargetRef support matrix
      • Configuration
      • Examples
      • Merging
    • MeshLoadBalancingStrategy
      • TargetRef support matrix
      • Configuration
      • Examples
    • MeshMetric
      • TargetRef support matrix
      • Configuration
      • Prometheus
      • OpenTelemetry
      • Examples
    • MeshPassthrough
      • TargetRef support matrix
      • Configuration
      • Examples
    • MeshProxyPatch
      • TargetRef support matrix
      • Configuration
      • Examples
      • Merging
    • MeshRateLimit
      • TargetRef support matrix
      • Configuration
      • Examples
    • MeshRetry
      • TargetRef support matrix
      • Configuration
      • Examples
    • MeshTCPRoute
      • TargetRef support matrix
      • Configuration
      • Examples
      • Route policies with different types targeting the same destination
    • MeshTimeout
      • TargetRef support matrix
      • Configuration
      • Examples
    • MeshTLS
      • TargetRef support matrix
      • Configuration
      • Examples
    • MeshTrace
      • TargetRef support matrix
      • Configuration
      • Examples
    • MeshTrafficPermission
      • TargetRef support matrix
      • Configuration
      • Examples
    • MeshOPA
    • MeshGlobalRateLimit (beta)
    • Previous Policies
      • General notes about Kong Mesh policies
      • How Kong Mesh chooses the right policy to apply
      • Traffic Permissions
      • Traffic Route
      • Traffic Metrics
      • Traffic Trace
      • Traffic Log
      • Locality-aware Load Balancing
      • Fault Injection
      • Health Check
      • Circuit Breaker
      • Retry
      • Timeout
      • Rate Limit
      • Virtual Outbound
      • MeshGatewayRoute
      • OPA policy
  • Guides
    • Federate zone control plane
    • Add a builtin Gateway
    • Add Kong as a delegated Gateway
    • Kubernetes Gateway API
    • Collect Metrics with OpenTelemetry
    • Migration to the new policies
    • Progressively rolling in strict mTLS
    • Producer and consumer policies
    • Configuring inbound traffic with Rules API
    • Upgrading Transparent Proxy
    • Deploy Kong Mesh using Terraform and Konnect
    • Import existing Konnect Kong Mesh deployment to Terraform
  • Enterprise Features
    • Overview
    • HashiCorp Vault CA
    • Amazon ACM Private CA
    • cert-manager Private CA
    • OPA policy support
    • MeshOPA
    • Multi-zone authentication
    • FIPS support
    • Certificate Authority rotation
    • Role-Based Access Control
    • Red Hat
      • UBI Images
      • Red Hat OpenShift Quickstart
    • Windows Support
    • ECS Support
    • Auditing
    • MeshGlobalRateLimit (beta)
    • Verify signatures for signed Kong Mesh images
    • Build provenance
      • Verify build provenance for signed Kong Mesh images
      • Verify build provenance for signed Kong Mesh binaries
  • Reference
    • HTTP API
    • Kubernetes annotations and labels
    • Kuma data collection
    • Control plane configuration reference
    • Envoy proxy template
  • Community
    • Contribute to Kuma
enterprise-switcher-icon Switch to OSS
On this pageOn this page
  • Introduction
  • Prerequisites
    • Requirements
    • Terraform variables
    • Provider Configuration
  • Mesh Resources
    • Mesh Control Plane
    • Creating a Mesh
    • Adding an example policy
    • Impact of Renaming Resources
  • Deploying a Kubernetes Zone
    • Create a cluster
    • Configure the Kubernetes and Helm providers
    • Create a system account
    • Create a Zone deployment
  • Cleaning up

Deploy Kong Mesh using Terraform and Konnect

Introduction

This guide explains how to create and manage Kong Mesh using Terraform and Konnect. It covers:

  • setting up the Terraform environment,
  • configuring providers,
  • deploying a Global Control Plane with a Mesh in Konnect,
  • and deploying a zone.

Prerequisites

Requirements

  • Konnect Personal Access Token
  • terraform (tested on 1.11.2)
  • k3d (tested on k3d v5.8.1, k3s v1.31.4-k3s1)

Terraform variables

This guide allows you to customise the access token and region used by your manifests.

Create a variables.tf file with the following contents:

variable "konnect_personal_access_token" {
    type    = string
}

variable "region" {
    type    = string
}

These variables can be provided at runtime, or set using environment variables. Set the following environment variables, replacing kpat_... with your Konnect access token:

export TF_VAR_konnect_personal_access_token="kpat_..." # or "spat_..."
export TF_VAR_region="us"

Provider Configuration

This guide uses the konnect and konnect-beta Terraform providers.

The konnect provider is the General Availability version. Features initially available in the beta version (konnect-beta) will move to the GA version (konnect) once they are stable and fully tested.

There is a beta version of the provider called konnect-beta that has the latest features.

Mesh resources are available only in the beta provider, but they will be available in the konnect provider shortly.

Create a providers.tf file with the following contents:

terraform {
  required_providers {
    konnect = {
      source = "kong/konnect"
      version = "2.4.1"
    }
    konnect-beta = {
      source  = "kong/konnect-beta"
      version = "0.1.1"
    }
  }
}

provider "konnect" {
    personal_access_token = var.konnect_personal_access_token
    server_url            = "https://${var.region}.api.konghq.com"
}

provider "konnect-beta" {
    personal_access_token = var.konnect_personal_access_token
    server_url            = "https://${var.region}.api.konghq.com"
}

Download the providers using terraform init:

terraform init

You will see the following message in green text:

Terraform has been successfully initialized!

Mesh Resources

At this point you have installed and configured the providers successfully. It’s time to create some resources using the Konnect API.

Mesh Control Plane

Create a file named main.tf and add the following to create a Global Control Plane in Konnect:

resource "konnect_mesh_control_plane" "my_meshcontrolplane" {
  provider    = konnect-beta
  name        = "tf-cp"
  description = "A control plane created using terraform"
  labels = {
    "terraform" = "true"
  }
}

After saving the file, run terraform apply -auto-approve to create the resource.

You should see:

  # konnect_mesh_control_plane.my_meshcontrolplane will be created
  + resource "konnect_mesh_control_plane" "my_meshcontrolplane" {
      + created_at  = (known after apply)
      + description = "A control plane created using terraform"
      + features    = (known after apply)
      + id          = (known after apply)
      + labels      = {
          + "terraform" = "true"
        }
      + name        = "tf-cp"
      + updated_at  = (known after apply)
    }

Creating a Mesh

Now that there is a Control Plane, we can create a new Mesh.

Notice that the cp_id property is set to the ID of the control plane created in the previous step.

The skip_creating_initial_policies property is set to ["*"] to skip creating the default policies so that all resources in the Mesh are tracked by Terraform.

Add the following to main.tf:

resource "konnect_mesh" "my_mesh" {
  provider = konnect-beta

  name     = "my-mesh"
  type     = "Mesh"
  skip_creating_initial_policies = [ "*" ]

  cp_id    = konnect_mesh_control_plane.my_meshcontrolplane.id
}

Run terraform apply -auto-approve and watch as Terraform creates a new Mesh in your Control Plane.

Let’s add mTLS to the mesh. Replace the konnect_mesh resource you added in main.tf with the following definition:

resource "konnect_mesh" "my_mesh" {
  provider = konnect-beta

  name     = "my-mesh"
  type     = "Mesh"
  skip_creating_initial_policies = [ "*" ]

  mtls = {
    "backends" = [
      {
        "name" = "ca-1"
        "type" = "builtin"
      }
    ]
    "mode"           = "permissive"
    "enabledBackend" = "ca-1"
  }

  cp_id    = konnect_mesh_control_plane.my_meshcontrolplane.id
}

Run terraform apply -auto-approve and you will see the Mesh being updated in place:

  # konnect_mesh.my_mesh will be updated in-place
  ~ resource "konnect_mesh" "my_mesh" {
      + mtls                           = {
          + backends = [
              + {
                  + name = "ca-1"
                  + type = "builtin"
                },
            ]
        }
        name                           = "my-mesh"
        # (3 unchanged attributes hidden)
    }

For full schema of the Mesh resource, see the konnect-beta provider documentation.

Adding an example policy

The Kong Mesh documentation policy examples now contain an additional “Terraform” tab showing a Terraform representation of a policy.

Let’s take an example from MeshTrafficPermission page

Autogenerated labels like “kuma.io/mesh”, “kuma.io/origin” etc. have to be manually added to the resources. This limitation will be removed in the GA release.

Add the following policy to main.tf:

resource "konnect_mesh_traffic_permission" "allow_all" {
 provider = konnect-beta

 type = "MeshTrafficPermission"
 name = "allow-all"
 spec = {
   from = [
     {
       target_ref = {
         kind = "Mesh"
       }
       default = {
         action = "Allow"
       }
     }
   ]
 }
 labels   = {
   "kuma.io/mesh" = konnect_mesh.my_mesh.name
 }

 cp_id    = konnect_mesh_control_plane.my_meshcontrolplane.id
 mesh     = konnect_mesh.my_mesh.name
}


Run terraform apply -auto-approve to create the policy.

Impact of Renaming Resources

Certain properties (like Mesh name, policy name, etc.) are used as identifiers and changing them will result in a new resource being created and all dependant resources being recreated.

So changing mesh name to another-name

resource "konnect_mesh" "my_mesh" {
  # ...
  name = "another-name"
  # ...
}

Will result in forced replacement of both mesh and konnect_mesh_traffic_permission resources:

    # konnect_mesh.my_mesh must be replaced
-/+ resource "konnect_mesh" "my_mesh" {
      ~ name                           = "mesh1" -> "another-name" # forces replacement
        # (4 unchanged attributes hidden)
    }

  # konnect_mesh_access_log.konnect_mesh_traffic_permission must be replaced
-/+ resource "konnect_mesh_traffic_permission" "allow_all" {
      ~ creation_time     = "2025-03-13T09:53:00.606442Z" -> (known after apply)
      ~ labels            = {
          ~ "kuma.io/mesh" = "mesh1" -> "another-name"
        }
      ~ mesh              = "mesh1" -> "another-name" # forces replacement

Deploying a Kubernetes Zone

To deploy a Kubernetes zone you can use any Kubernetes services, in this guide we will use k3d to create a local Kubernetes cluster.

Create a cluster

Create a new k3d cluster:

k3d cluster create tfmink

Store the tfmink cluster configuration in $KUBECONFIG:

export KUBECONFIG=$(k3d kubeconfig write tfmink)

In variables.tf add a variable pointing to the Kubeconfig file and configure Helm and Kubernetes providers, and a variable for the zone name:

variable "k8s_cluster_config_path" {
  type        = string
  description = "The location where this cluster's kubeconfig will be saved to."
}

variable "zone_name" {
    type    = string
    default = "tfzone1"
}

Then set TF_VAR_k8s_cluster_config_path to your kubeconfig value:

export TF_VAR_k8s_cluster_config_path=$KUBECONFIG

Configure the Kubernetes and Helm providers

Update the providers.tf with the following contents to include the time, kubernetes and helm providers:

terraform {
  required_providers {
    konnect = {
      source = "kong/konnect"
    }
    konnect-beta = {
      source  = "kong/konnect-beta"
      version = "0.1.1"
    }
    time = {
      source  = "hashicorp/time"
      version = "0.13.0"
    }
    kubernetes = {
      source  = "hashicorp/kubernetes"
      version = "2.35.1"
    }
    helm = {
      source  = "hashicorp/helm"
      version = "2.17.0"
    }
  }
}

Then add some provider configuration blocks to the bottom of providers.tf:

provider "helm" {
    kubernetes {
        config_path = pathexpand(var.k8s_cluster_config_path)
    }
}

provider "kubernetes" {
    config_path = pathexpand(var.k8s_cluster_config_path)
}

Run init -upgrade to download the new providers:

terraform init -upgrade

Create a system account

Create a new file named system-account.tf with the following contents to create a system account and a token to authenticate the zone:

resource "konnect_system_account" "zone_system_account" {
  name            = "mesh_${konnect_mesh_control_plane.my_meshcontrolplane.id}_${var.zone_name}"
  description     = "Terraform generated system account for authentication zone ${var.zone_name} in ${konnect_mesh_control_plane.my_meshcontrolplane.id} control plane."
  konnect_managed = false
}

resource "konnect_system_account_role" "zone_system_account_role" {
  account_id       = konnect_system_account.zone_system_account.id
  entity_id        = konnect_mesh_control_plane.my_meshcontrolplane.id
  entity_region    = var.region
  entity_type_name = "Mesh Control Planes"
  role_name        = "Connector"
}

resource "time_offset" "one_year_from_now" {
  offset_years = 1
}

resource "konnect_system_account_access_token" "zone_system_account_token" {
  account_id = konnect_system_account.zone_system_account.id
  expires_at = time_offset.one_year_from_now.rfc3339
  name       = konnect_system_account.zone_system_account.name
}

Store this token in Kubernetes by creating k8s.tf with the following contents:

resource "kubernetes_namespace" "kong_mesh_system" {
  metadata {
    name = "kong-mesh-system"
    labels = {
      "kuma.io/system-namespace" = "true"
    }
  }
}

resource "kubernetes_secret" "mesh_cp_token" {
  metadata {
    name = "cp-token"
    namespace = kubernetes_namespace.kong_mesh_system.metadata.0.name
  }

  data = {
    token = konnect_system_account_access_token.zone_system_account_token.token
  }

  type = "opaque"
}

Create a Zone deployment

Create a values file called values.tftpl with templated values for zone, address and control plane id:

kuma:
  controlPlane:
    mode: zone
    zone: ${zone_name}
    kdsGlobalAddress: grpcs://${region}.mesh.sync.konghq.com:443
    konnect:
      cpId: ${cp_id}
    secrets:
      - Env: KMESH_MULTIZONE_ZONE_KDS_AUTH_CP_TOKEN_INLINE
        Secret: cp-token
        Key: token
  ingress:
    enabled: true
  egress:
    enabled: true

Create a zone.tf file containing the following to create a zone:

resource "helm_release" "kong_mesh" {
  name       = "kong-mesh"
  repository = "https://kong.github.io/kong-mesh-charts"
  chart      = "kong-mesh"
  version    = "2.9.3"

  namespace = kubernetes_namespace.kong_mesh_system.metadata.0.name
  upgrade_install = true

  values = [templatefile("values.tftpl", {
    zone_name = var.zone_name,
    region    = var.region,
    cp_id     = konnect_mesh_control_plane.my_meshcontrolplane.id
  })]
}

And finally apply the changes:

terraform apply -auto-approve

You should see 7 resources created and helm_release can take some time to create. In my case it took 53 seconds:

helm_release.kong_mesh: Creation complete after 53s [id=kong-mesh]

You can check that the MeshTrafficPermission we created earlier is now available in the zone:

kubectl get meshtrafficpermissions.kuma.io -A

should print:

NAMESPACE          NAME
kong-mesh-system   allow-all-wd5xx76vc44b498c

Cleaning up

Congratulations! You just deployed a Mesh Control Plane, Mesh, policies and a Zone to Kubernetes.

To clean up all resources created by this guide, run the following command:

terraform destroy
Thank you for your feedback.
Was this page useful?
Too much on your plate? close cta icon
More features, less infrastructure with Kong Konnect. 1M requests per month for free.
Try it for Free
  • Kong
    Powering the API world

    Increase developer productivity, security, and performance at scale with the unified platform for API management, service mesh, and ingress controller.

    • Products
      • Kong Konnect
      • Kong Gateway Enterprise
      • Kong Gateway
      • Kong Mesh
      • Kong Ingress Controller
      • Kong Insomnia
      • Product Updates
      • Get Started
    • Documentation
      • Kong Konnect Docs
      • Kong Gateway Docs
      • Kong Mesh Docs
      • Kong Insomnia Docs
      • Kong Konnect Plugin Hub
    • Open Source
      • Kong Gateway
      • Kuma
      • Insomnia
      • Kong Community
    • Company
      • About Kong
      • Customers
      • Careers
      • Press
      • Events
      • Contact
  • Terms• Privacy• Trust and Compliance
© Kong Inc. 2025