Modernize Apps With Hybrid Deployment
Claudio Acquaviva

By on January 28, 2022

Kong Data Plane Life Cycle With AWS Cloud Development Kit

From the modern application platform perspective, products should allow architects and DevOps teams to support dynamic topologies. That means a multi-platform capability is required but not sufficient. In fact, for several reasons, companies are looking for hybrid deployments to run their applications on several platforms simultaneously. Moreover, the topology should support and adjust for new and continuous architecture changes.

Supporting Modern Application Architectures

Currently, companies are modernizing application development, refactoring existing applications from monoliths to microservices. At the same time, companies should transfer workloads running on-premises to other environments, including cloud or multi-cloud-based platforms.

In summary, product vendors and their products should follow and support any technical decisions the customers will make along the way.

To address these fundamental and critical requirements, Kong designed Kong Konnect. Its Hybrid Mode provides a flexible and scalable deployment capability to support the microservices-based application architecture life cycle.

In such a deployment, the API gateway splits into two main sublayers: 

  • Control Plane (CP): The CP is responsible for administrative tasks, including API and policy definition and life cycle.
  • Data Plane (DP): The DP receives and exposes the APIs created by the CP so consumers can send requests to it. Moreover, it controls the API exposure with the policies previously made by the CP.

The diagram below illustrates a typical Kong Konnect Hybrid Mode deployment:

Control Plane vs Data Plane Konnect

You can think about this deployment from another perspective:

  • The CP is implemented in a very stable environment, used only by admins to deal with the APIs and policies life cycle.
  • The DP is implemented in a very dynamic environment, with instances being deployed and destroyed all the time to support new technical requirements, throughput, topology adjustments, etc.

The flexible capabilities provided by the DPs fit perfectly with the workload transfer process behind them, transforming and refactoring current monolith-based applications into distributed microservices running on multiple platforms.

From the API life cycle and CPs perspective, this intense transformation process should produce a minimum impact across existing and new applications.

Learn more about Control Plane vs Data Plane

Data Plane Life Cycle

During a new DP incarnation process, four topics need to be solved.

Data Plane Runtime

The DP deploys on different runtimes in a hybrid environment, including VMs, Docker, Kubernetes, etc. Again, regardless of those runtimes, logically speaking, we’re still managing a single Kong Konnect gateway cluster.

Control Plane/Data Plane Communication

The DP/CP communication is based on secure mTLS encrypted tunnels. Before getting a new DP instance up and running, we should handle the digital certificate/key pair distribution. Kong provides two main modes for it:

  • Default Shared mode: Kong CLI generates the pair and distributes it across the CP and DPs.
  • PKI mode: The CP and DPs rely on a central certificate authority (CA). Kong validates both sides by checking if they are from the same CA.

Kong Enterprise License

The CP and all DPs should have the Kong Enterprise license injected; otherwise, they won’t be able to take advantage of several capabilities including, for instance:

  • Enterprise plugins, like OIDC, mTLS, Kafka, GraphQL integration, etc.
  • Vitals to monitor Gateway health and performance
  • DevPortal for Swagger/OpenAPI-based API documentation

Life Cycle Automation

Considering the dynamic characteristics of the DP, the CP/DP communication and license topics, it’s important to have specific technologies and infrastructure to automate the DP life cycle and therefore implement a more robust and agile DP infrastructure to support the existing workloads.

Kong Konnect and AWS

The following diagram depicts an example of a Kong Konnect deployment in AWS Cloud:

  • The CP is running, for instance, in an Amazon Linux EC2 with ASG (Auto Scaling Group).
  • The CP repository is implemented with Amazon RDS for PostgreSQL.
  • DP 1 is running on Amazon ECS (Elastic Container Service).
  • DP 2 is running on Amazon EKS (Elastic Kubernetes Service).
  • Both DPs share a collection of AWS Services like Cognito for OIDC-based authentication processes, ElastiCache for Redis for rate limiting and caching, and OpenSearch for Log processing.
  • Both ECS and EKS provide high availability and elasticity for the DPs.
  • DPs protect service- and microservices-based workloads running in their environments.

Other AWS runtimes could be included or removed in and from our topology to satisfy and support the service and microservice workload migration and evolution, such as another EKS Cluster running in the same or new AWS region, EKS Anywhere running on premises, etc.

Moreover, we should include new AWS Services to help us with the digital certificate/key pair process for mTLS tunnels and a safe place to store the Kong Enterprise license. The following diagram includes AWS Secrets Manager and ACM (AWS Certificate Manager) to implement those processes:

AWS Secrets Manager and AWS Certificate Manager for Kong Konnect

AWS Certificate Manager Private Certificate Authority provides a secure way to create a private CA and use it to create and manage private certificates and keys for the Kong Konnect Cluster. AWS Secrets Manager helps us to protect secrets like the Kong Konnect license.

However, we are still not addressing the DP life cycle automation. The first option to do it would be AWS CloudFormation.

Data Plane Automation Option #1: AWS CloudFormation

AWS CloudFormation is an infrastructure as code (IaC) service that allows us to:

  • Provision AWS infrastructure deployments based on templates and declarations.
  • Leverage AWS products and third-party resources like Kong. This is particularly important for a Kong deployment since it usually runs on top of AWS run times and integrates AWS Services like Amazon ElastiCache, Cognito, OpenSearch, AMP/AMG, etc.
  • Build scalable infrastructures in AWS Cloud without worrying about creating and configuring the underlying AWS infrastructure.

For example, below are CloudFormation template samples injecting the Kong Konnect Helm Charts to deploy both the Control Plane and Data Plane. Note that the template follows the same specific settings for both planes we normally use in regular Helm Chart-based deployments.

We can deploy the CP and DP with commands like these:

aws cloudformation create-stack --stack-name k4k8s-controlplane-eks --template-body \
file://k4k8s-controlplane.yaml \
--parameters \
ParameterKey=EKSClusterName,ParameterValue=CF-k4k8s \
ParameterKey=Namespace,ParameterValue=kong \

aws cloudformation create-stack --stack-name k4k8s-dataplane-eks --template-body \
file://k4k8s-dataplane.yaml \
--parameters \
ParameterKey=EKSClusterName,ParameterValue=CF-k4k8s \
ParameterKey=Namespace,ParameterValue=kong-dp \

Data Plane Automation Option #2: AWS Cloud Development Kit

While managing AWS CloudFormation YAML and JSON-based templates sounds like a straightforward process, they are not programming languages. Moreover, adding more functionalities to our deployments becomes a hard maintenance process with increasing and multiple versions of templates.

The AWS Cloud Development Kit (CDK) introduces a new level of abstraction to CloudFormation-based deployments. Developers can write infrastructure as code using an object model to define reusable AWS and third-party components using several programming languages (TypeScript, JavaScript, Python, Go, Java and C#). Then, synthesize it into CloudFormation templates to provision resources.

Check the AWS CDK Developer Guide to learn more about it.

AWS CDK Construct Library

The Construct Library within the AWS CDK includes a range of constructs to provision AWS resources. AWS provides the Construct Library Hub with all official Construct Libraries to manage AWS resources and new ones for third-party resources.

For example, here’s a TypeScript snippet showing how to use the Amazon EKS Construct Library:

// include the EKS Construct Library
const eks = require("@aws-cdk/aws-eks");

// provisioning a cluster
const cluster = new eks.Cluster(this, 'hello-eks', {
  version: eks.KubernetesVersion.V1_21,

// apply a kubernetes manifest to the cluster
cluster.addManifest('kongpod', {
  apiVersion: 'v1',
  kind: 'Pod',
  metadata: { name: 'kongpod' },
  spec: {
    containers: [
        name: 'kong',
        image: 'claudioacquaviva/sampleapp',
        ports: [ { containerPort: 5000 } ]

Check the AWS CDK Construct Library API Reference to learn more about the existing CDK libraries.

Kong Konnect Hybrid Mode CDK Deployment

The AWS CDK enables developers to define end-to-end AWS infrastructures, including several Construct Libraries in the same CDK program.

The following diagram depicts the deployment of Kong Konnect Hybrid Mode with AWS CDK. Developers define reusable cloud components known as Constructs. They are composed together into Stacks and Applications.

Kong Konnect Hybrid Mode AWS CDK Deployment

A TypeScript CDK Application to do the task would look like this:

import { UpdatePolicy } from '@aws-cdk/aws-autoscaling';
import { InstanceClass, InstanceSize, InstanceType, IVpc } from '@aws-cdk/aws-ec2';
import { EndpointAccess, KubernetesVersion, MachineImageType } from '@aws-cdk/aws-eks';
import * as eks from '@aws-cdk/aws-eks';
import { PostgresEngineVersion } from '@aws-cdk/aws-rds';
import { App, Construct, Stack, StackProps } from '@aws-cdk/core';
import * as KongCP from 'kong-control-plane';
import * as KongDP from 'kong-data-plane';

const telemetry_dns = 'telemetry.kong-cp.internal';
const cluster_dns = 'cluster.kong-cp.internal';

export class KongCpEks extends Stack {

  public readonly control_plane: eks.Cluster;
  public readonly private_ca_arn : string;

  constructor(scope: Construct, id: string, props: StackProps = {} ) {
    super(scope, id, props);

    const kong_control_plane = new KongCP.KongEks(this, 'KongEksCp', {
      telemetryDns: telemetry_dns,
      clusterDns: cluster_dns,
      namespace: 'kong',
      controlPlaneClusterProps: {
        clusterName: 'kong-cp',
        version: KubernetesVersion.V1_21,
        defaultCapacity: 0,
        endpointAccess: EndpointAccess.PUBLIC_AND_PRIVATE,
      controlPlaneNodeProps: {
        instanceType: InstanceType.of(InstanceClass.T3, InstanceSize.LARGE),
        machineImageType: MachineImageType.AMAZON_LINUX_2,
        minCapacity: 2,
      rdsProps: {
        postgresversion: PostgresEngineVersion.VER_12_7,
        databasename: 'kongdb',
        username: 'kongadmin',

    this.control_plane = kong_control_plane.controlPlane;
    this.private_ca_arn = kong_control_plane.privateCaArn;

interface KongDpEksStackProps extends StackProps {
  vpc: IVpc;
  cluster_dns: String;
  telemetry_dns: String;
  private_ca_arn: string;


export class KongDpEks extends Stack {
  constructor(scope: Construct, id: string, props: KongDpEksStackProps) {
    super(scope, id, props);

    new KongDP.KongEks(this, 'KongEksDp', {
      dataPlaneClusterProps: {
        clusterName: 'kong-dp',
        version: KubernetesVersion.V1_21,
        defaultCapacity: 0,
        endpointAccess: EndpointAccess.PUBLIC_AND_PRIVATE,
        vpc: props.vpc,
      dataPlaneNodeProps: {
        instanceType: InstanceType.of(InstanceClass.T3, InstanceSize.LARGE),
        machineImageType: MachineImageType.BOTTLEROCKET,
        minCapacity: 2,
        updatePolicy: UpdatePolicy.rollingUpdate(),
      clusterDns: props.cluster_dns,
      telemetryDns: props.telemetry_dns,
      privateCaArn: props.private_ca_arn,

const devEnv = {
  account: process.env.CDK_DEFAULT_ACCOUNT,
  region: 'us-east-1',

const app = new App();

const kong_control_plane = new KongCpEks(app, 'kong-cp', { env: devEnv });

new KongDpEks(app, 'kong-dp', {
  env: devEnv,
  cluster_dns: cluster_dns,
  vpc: kong_control_plane.control_plane.vpc,
  telemetry_dns: telemetry_dns,
  private_ca_arn: kong_control_plane.private_ca_arn,


Note that the program defines two CDK Stacks: KongCpEks and KongDpEks.

Each stack defines its own Construct, including a Kong instance (playing the CP or DP role) and the related AWS Services each one of them requires.

For example, the KongCpEKS Stack’s Construct instantiates an EKS Cluster and an RDS for the PostgreSQL database. Similarly, KongDpEKS Stack’s Construct needs a single EKS Cluster. Of course, since it’s a DP, it could also include instances of ElastiCache for Redis or Cognito to implement specific API gateway policies.

The two constants defined at the very beginning of our code are DNS references to the CP endpoints, which must be accessible by all DPs. Check the Hybrid Mode Kong Enterprise documentation to learn more about those endpoints.

const telemetry_dns = 'telemetry.kong-cp.internal';
const cluster_dns = 'cluster.kong-cp.internal';
  • cluster_dns:  the address for the CP/DP connection.
  • telemetry_dns:  for Vitals telemetry data

Also, the CP creates an ACM Private CA so both lanes can store their respective Digital Certificate/Private Key pair.

CP stores the Private CA reference here:

this.private_ca_arn = kong_control_plane.privateCaArn;

As the DP uses it later:

private_ca_arn: kong_control_plane.private_ca_arn,

Kong Konnect Construct Libraries

We can see that the code above imports several official standard CDK Construct Libraries. For example:

  • @aws-cdk/aws-eks to manage EKS Clusters for both the CP and DP
  • @aws-cdk/aws-rds to instantiate an RDS for PostgreSQL database for the CP

Besides these Libraries, the code refers to new ones:

import * as KongCP from 'kong-control-plane';
import * as KongDP from 'kong-data-plane';

These are custom Kong Konnect CDK Libraries to abstract all CP and DP dependencies. 

Take a look at the following Kong DP CDK Library snippet:

const eks = require("@aws-cdk/aws-eks");
const kms = require("@aws-cdk/aws-kms");
const core_1 = require("@aws-cdk/core");
const kong_core_1 = require("kong-core");
const index_1 = require("./resources/helm-charts/kong/index");

class KongEks extends core_1.Construct {
    constructor(scope, id, props) {
        super(scope, id);
        const kong_namespace = 'kong-dp';
        const data_plane_secretskey = new kms.Key(this, 'DPSecretsKey');
        const data_plane = new eks.Cluster(this, 'DP', {
            secretsEncryptionKey: data_plane_secretskey,
            defaultCapacity: 0,
        new kong_core_1.ElastiCacheStack(this, 'KongCache', {
            numberofnodegroups: 3,
            vpc: data_plane.vpc,
        new kong_core_1.SecretsManager(this, 'KongSMProvider', {
            cluster: data_plane,
            nodegroup: dp_nodegroup,
            namespace: kong_namespace,
        new kong_core_1.CertManager(this, 'KongPCA', {
            cluster: data_plane,
            nodegroup: dp_nodegroup,
            namespace: kong_namespace,
            privateCaArn: props.privateCaArn,
            cacertname: 'kong-dp-ca-cert',
            clusterIssuerName: 'kong-dp-cluster-issuer',
            hostedZoneName: 'kong-dp.internal',
            dnsNames: [
        new index_1.KongDataPlane(this, 'KongCPHelmInstall', {
            cluster: data_plane,
            namespace: kong_namespace,
            cluster_dns: props.clusterDns,
            telemetry_dns: props.telemetryDns,

The line below creates the EKS Cluster.

const data_plane = new eks.Cluster(this, 'DP', {
            secretsEncryptionKey: data_plane_secretskey,
            defaultCapacity: 0,

This other one deals with the ElastiCache for Redis for the DP to use. As you can see, the kong_code_1  constant refers to another Kong Konnect Construct Library responsible for creating the fundamental AWS services.

 new kong_core_1.ElastiCacheStack(this, 'KongCache', {
            numberofnodegroups: 3,
            vpc: data_plane.vpc,

Check the following Kong GitHub repos to learn more about the Kong Konnect CDK Construct Libraries:

Besides the Construct Libraries, check the CDK sample application we explored in this post. For product-ready environments, the CDK Application will be managing other aspects of the deployment, including AWS regions, the number of DPs to be instantiated, etc.


The AWS Cloud Development Kit first brings a higher level of abstraction for the concept of IaC. The possibility to define deployment logic using best-of-breed programming languages available today is its main benefit.

For applications like Kong Konnect, which provides a highly dynamic and diverse environment for API consumption, the AWS CDK becomes a powerful tool to manage ​DPs and all usual AWS services integrated to implement typical policies for this layer.

Join us in an upcoming webinar to discuss and demo a Kong Enterprise deployment and AWS Services with the CDK.

This is the first post in a series of three exploring AWS CDK technology with Kong Konnect. The next posts will focus on implementing mTLS encrypted tunnels required in a Kong deployment with AWS CA and how to use AWS Secrets Manager to store Kong licenses.

Share Post