Sai Umesh

Building a well-architected EKS cluster and its components using EKS Blueprints.

6 min read

Building an EKS cluster and its components can be overwhelming, especially when dealing with various elements like VPCs, ALB Controllers, Karpenter Autoscalers, ArgoCD, and other commonly used add-ons. Wouldn’t it be nice to have a package that simplifies this process, helping you create a well-architected, guided, and consistent setup across AWS accounts? Enter, EKS Blueprint using CDK and EKS Blueprint using Terraform. I haven’t worked with the Terraform version, so we’ll be focusing solely on the CDK Blueprint.

What is EKS Blueprints?

What is actually a What is EKS Blueprints? In their own words, EKS Blueprints helps you compose complete EKS clusters that are fully bootstrapped with the operational software that is needed to deploy and operate workloads. With EKS Blueprints, you describe the configuration for the desired state of your EKS environment, such as the control plane, worker nodes, and Kubernetes add-ons, as an IaC blueprint. You can read more about it here

I’ve been working with EKS and its components for over four years. While I’m comfortable with it now, getting started was really challenging, especially since there wasn’t a solid package to help build EKS. I do like Eksctl, but I prefer using IAC for more control.

Even though I highly recommend using Blueprints, I’d still suggest building all the EKS components from scratch starting from the VPC, to the control plane, and down to the worker nodes.

Now, let’s dive into some sample code and explore a few of the features that I really love.

Deploying EKS Cluster

import * as cdk from 'aws-cdk-lib';
import * as blueprints from '@aws-quickstart/eks-blueprints';

const app = new cdk.App();
const account = 'XXXXXXXXXXXXX';
const region = 'us-east-2';
const version = 'auto';

blueprints.HelmAddOn.validateHelmVersions = true; // optional if you would like to check for newer versions

const addOns: Array<blueprints.ClusterAddOn> = [
    new blueprints.addons.ArgoCDAddOn(),
    new blueprints.addons.MetricsServerAddOn(),
    new blueprints.addons.ClusterAutoScalerAddOn(),
    new blueprints.addons.AwsLoadBalancerControllerAddOn(),
    new blueprints.addons.VpcCniAddOn(), // support network policies ootb
    new blueprints.addons.CoreDnsAddOn(),
    new blueprints.addons.KubeProxyAddOn()
];

const stack = blueprints.EksBlueprint.builder()
    .account(account)
    .region(region)
    .version(version)
    .addOns(...addOns)
    .useDefaultSecretEncryption(true) // set to false to turn secret encryption off (non-production/demo cases)
    .build(app, 'eks-blueprint');

Teams

The EKS Blueprints framework simplifies onboarding teams and managing cluster access. It supports two team types: ApplicationTeam, for workload management in namespaces, and PlatformTeam, for platform admins with cluster-wide access.

ApplicationTeam

export class TeamAwesome extends ApplicationTeam {
    constructor(app: App) {
        super({
            name: "team-awesome",
            users: [
                new ArnPrincipal(`arn:aws:iam::${YOUR_IAM_ACCOUNT}:user/user1`),  
                new ArnPrincipal(`arn:aws:iam::${YOUR_IAM_ACCOUNT}:user/user2`)
            ],
            teamManifestDir: './examples/teams/team-awesome/'
        });
    }
}

PlatformTeam

export class TeamAwesome extends PlatformTeam {
    constructor(app: App) {
        super({
            name: "team-awesome",
            users: [
                new ArnPrincipal(`arn:aws:iam::${YOUR_IAM_ACCOUNT}:user/user1`),  
                new ArnPrincipal(`arn:aws:iam::${YOUR_IAM_ACCOUNT}:user/user2`)
            ]

        });
    }
}

AddOns

One thing I really like about EKS Blueprints is how it handles AddOns. You get to pick exactly what runs in your clusters. With the ClusterAddOn interface, you can apply manifests or call AWS APIs whatever works. This flexibility makes managing clusters a lot easier.

Resource Provider

Resource Provider, a resource is just a construct that implements the IResource interface from aws-cdk-lib, which makes it a fit for any AWS resource. It could be a Route 53 hosted zone, an ACM certificate, a VPC, or even a DynamoDB table—super useful for both add-ons and teams.

getResource((context: ResourceContext) => new Policy(
    context.scope,
    'id',
    { ...options },
)),

Challenges

While EKS Blueprints is well-architected, I did run into a few challenges like with any product. It’s definitely opinionated in its design, which is fair, but while it’s flexible enough to work for you most of the time, it’s not always perfect.


Sai Umesh

I’m Sai Umesh, a software engineer based in India. Working as a DevOps engineer.