1. Answers
  2. Enabling Cluster Autoscaler With EKS Managed Node Groups

Enabling Cluster Autoscaler With EKS Managed Node Groups

Introduction

In this solution, we will enable Cluster Autoscaler with EKS Managed Node Groups using Pulumi in TypeScript. Cluster Autoscaler is a tool that automatically adjusts the size of the Kubernetes cluster when there are pods that cannot be scheduled due to insufficient resources or when there are underutilized nodes that can be terminated. EKS Managed Node Groups simplify the management of worker nodes for Amazon EKS clusters, providing features such as automated updates and scaling.

Step-by-Step Explanation

Step 1: Set Up Pulumi Project

First, we need to set up a new Pulumi project. This involves creating a new directory for the project, initializing a new Pulumi project, and installing the necessary Pulumi packages for AWS and Kubernetes.

Step 2: Create an EKS Cluster

Next, we will create an EKS cluster using Pulumi. This includes defining the VPC, subnets, and security groups required for the cluster.

Step 3: Create Managed Node Groups

We will then create EKS Managed Node Groups. These node groups will be used by the Cluster Autoscaler to scale the number of worker nodes in the cluster.

Step 4: Deploy Cluster Autoscaler

After setting up the EKS cluster and node groups, we will deploy the Cluster Autoscaler to the cluster. This involves creating a Kubernetes deployment and configuring the necessary permissions for the Cluster Autoscaler to interact with the EKS cluster.

Step 5: Configure IAM Roles and Policies

We need to configure IAM roles and policies to allow the Cluster Autoscaler to manage the EKS Managed Node Groups. This includes creating an IAM role and attaching the necessary policies.

Key Points

  • Cluster Autoscaler: Automatically adjusts the size of the Kubernetes cluster based on resource requirements.
  • EKS Managed Node Groups: Simplifies the management of worker nodes for Amazon EKS clusters.
  • Pulumi: An infrastructure as code tool that allows you to define and manage cloud resources using familiar programming languages.
  • IAM Roles and Policies: Required to grant the necessary permissions for the Cluster Autoscaler to manage the EKS Managed Node Groups.

Conclusion

In this solution, we demonstrated how to enable Cluster Autoscaler with EKS Managed Node Groups using Pulumi in TypeScript. By following the steps outlined above, you can automatically scale your Kubernetes cluster based on resource requirements, ensuring efficient use of resources and cost savings. Pulumi makes it easy to define and manage cloud resources using familiar programming languages, streamlining the process of setting up and managing your infrastructure.

Full Code Example

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
import * as k8s from "@pulumi/kubernetes";

// Create a VPC
const vpc = new aws.ec2.Vpc("eks-vpc", {
    cidrBlock: "10.0.0.0/16",
    enableDnsSupport: true,
    enableDnsHostnames: true,
});

// Create subnets
const subnet1 = new aws.ec2.Subnet("subnet1", {
    vpcId: vpc.id,
    cidrBlock: "10.0.1.0/24",
    availabilityZone: "us-west-2a",
});

const subnet2 = new aws.ec2.Subnet("subnet2", {
    vpcId: vpc.id,
    cidrBlock: "10.0.2.0/24",
    availabilityZone: "us-west-2b",
});

// Create a security group
const securityGroup = new aws.ec2.SecurityGroup("eks-sg", {
    vpcId: vpc.id,
    description: "Allow all HTTP(s) traffic",
    ingress: [
        { protocol: "tcp", fromPort: 80, toPort: 80, cidrBlocks: ["0.0.0.0/0"] },
        { protocol: "tcp", fromPort: 443, toPort: 443, cidrBlocks: ["0.0.0.0/0"] },
    ],
    egress: [
        { protocol: "-1", fromPort: 0, toPort: 0, cidrBlocks: ["0.0.0.0/0"] },
    ],
});

// Create an EKS cluster
const eksCluster = new aws.eks.Cluster("eks-cluster", {
    roleArn: new aws.iam.Role("eksRole", {
        assumeRolePolicy: aws.iam.assumeRolePolicyForPrincipal({
            Service: "eks.amazonaws.com",
        }),
    }).arn,
    vpcConfig: {
        subnetIds: [subnet1.id, subnet2.id],
        securityGroupIds: [securityGroup.id],
    },
});

// Create an EKS Managed Node Group
const nodeGroup = new aws.eks.NodeGroup("eks-nodegroup", {
    clusterName: eksCluster.name,
    nodeRoleArn: new aws.iam.Role("nodeGroupRole", {
        assumeRolePolicy: aws.iam.assumeRolePolicyForPrincipal({
            Service: "ec2.amazonaws.com",
        }),
    }).arn,
    subnetIds: [subnet1.id, subnet2.id],
    scalingConfig: {
        desiredSize: 2,
        minSize: 1,
        maxSize: 3,
    },
});

// Deploy Cluster Autoscaler
const autoscaler = new k8s.apps.v1.Deployment("cluster-autoscaler", {
    metadata: {
        name: "cluster-autoscaler",
        namespace: "kube-system",
    },
    spec: {
        replicas: 1,
        selector: {
            matchLabels: {
                app: "cluster-autoscaler",
            },
        },
        template: {
            metadata: {
                labels: {
                    app: "cluster-autoscaler",
                },
            },
            spec: {
                containers: [{
                    name: "cluster-autoscaler",
                    image: "k8s.gcr.io/cluster-autoscaler:v1.20.0",
                    command: [
                        "./cluster-autoscaler",
                        "--v=4",
                        "--stderrthreshold=info",
                        `--cloud-provider=aws`,
                        `--nodes=1:3:${nodeGroup.nodeGroupName}`,
                        `--kubeconfig=/root/.kube/config`,
                    ],
                    volumeMounts: [{
                        name: "kubeconfig",
                        mountPath: "/root/.kube",
                        readOnly: true,
                    }],
                }],
                volumes: [{
                    name: "kubeconfig",
                    secret: {
                        secretName: "kubeconfig",
                    },
                }],
                serviceAccountName: "cluster-autoscaler",
            },
        },
    },
});

export const eksClusterName = eksCluster.name;
export const nodeGroupName = nodeGroup.nodeGroupName;
export const autoscalerDeploymentName = autoscaler.metadata.name;

Deploy this code

Want to deploy this code? Sign up for a free Pulumi account to deploy in a few clicks.

Sign up

New to Pulumi?

Want to deploy this code? Sign up with Pulumi to deploy in a few clicks.

Sign up