Skip to content

Commit

Permalink
Managed Node Group launch template disk size fix (#1305)
Browse files Browse the repository at this point in the history
This fixes the handling of disk size changes when a custom launch
template is created for the MNG.
It is based on the Community PR #1229 by @JustASquid, I just added some
test fixes on top.

Fixes #1228

---------

Co-authored-by: Daniel West <[email protected]>
  • Loading branch information
flostadler and JustASquid authored Aug 21, 2024
1 parent f907582 commit 453da6a
Show file tree
Hide file tree
Showing 10 changed files with 167 additions and 0 deletions.
1 change: 1 addition & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -462,6 +462,7 @@ jobs:
- MigrateNodeGroups
- MNG_withAwsAuth
- MNG_withMissingRole
- MNG_DiskSize
- MultiRole
- NodeGroup
- NodegroupOptions
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/run-acceptance-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -440,6 +440,7 @@ jobs:
- MigrateNodeGroups
- MNG_withAwsAuth
- MNG_withMissingRole
- MNG_DiskSize
- MultiRole
- NodeGroup
- NodegroupOptions
Expand Down
32 changes: 32 additions & 0 deletions examples/examples_nodejs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,38 @@ func TestAccMNG_withAwsAuth(t *testing.T) {
programTestWithExtraOptions(t, &test, nil)
}

func TestAccMNG_DiskSize(t *testing.T) {
if testing.Short() {
t.Skip("skipping test in short mode.")
}
test := getJSBaseOptions(t).
With(integration.ProgramTestOptions{
Dir: path.Join(getCwd(t), "tests", "managed-ng-disk-size"),
ExtraRuntimeValidation: func(t *testing.T, info integration.RuntimeValidationStackInfo) {
utils.RunEKSSmokeTest(t,
info.Deployment.Resources,
info.Outputs["kubeconfig"],
)

assert.NoError(t, utils.ValidateNodes(t, info.Outputs["kubeconfig"], func(nodes *corev1.NodeList) {
require.NotNil(t, nodes)
assert.NotEmpty(t, nodes.Items)

for _, node := range nodes.Items {
nodeEphemeralStorage := node.Status.Capacity[corev1.ResourceEphemeralStorage]

// Defined in test managed-ng-disk-size
var desiredSizeGB int64 = 50
assert.True(t, nodeEphemeralStorage.CmpInt64(desiredSizeGB*1_000_000_000) >= 0)
}

}))
},
})

programTestWithExtraOptions(t, &test, nil)
}

func TestAccTags(t *testing.T) {
test := getJSBaseOptions(t).
With(integration.ProgramTestOptions{
Expand Down
3 changes: 3 additions & 0 deletions examples/tests/managed-ng-disk-size/Pulumi.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
name: managed-ng-disk-size
description: Tests that disk size can be specified correctly when a custom launch template is automatically created.
runtime: nodejs
3 changes: 3 additions & 0 deletions examples/tests/managed-ng-disk-size/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# tests/managed-ng-disk-size

Tests that disk size can be specified correctly when a custom launch template is automatically created.
39 changes: 39 additions & 0 deletions examples/tests/managed-ng-disk-size/iam.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import * as aws from "@pulumi/aws";
import * as pulumi from "@pulumi/pulumi";
import * as iam from "./iam";

const managedPolicyArns: string[] = [
"arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy",
"arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy",
"arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly",
];

// Creates a role and attaches the EKS worker node IAM managed policies
export function createRole(name: string): aws.iam.Role {
const role = new aws.iam.Role(name, {
assumeRolePolicy: aws.iam.assumeRolePolicyForPrincipal({
Service: "ec2.amazonaws.com",
}),
});

let counter = 0;
for (const policy of managedPolicyArns) {
// Create RolePolicyAttachment without returning it.
const rpa = new aws.iam.RolePolicyAttachment(`${name}-policy-${counter++}`,
{ policyArn: policy, role: role },
);
}

return role;
}

// Creates a collection of IAM roles.
export function createRoles(name: string, quantity: number): aws.iam.Role[] {
const roles: aws.iam.Role[] = [];

for (let i = 0; i < quantity; i++) {
roles.push(iam.createRole(`${name}-role-${i}`));
}

return roles;
}
37 changes: 37 additions & 0 deletions examples/tests/managed-ng-disk-size/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import * as awsx from '@pulumi/awsx';
import * as eks from "@pulumi/eks";
import * as pulumi from "@pulumi/pulumi";
import * as iam from "./iam";

const eksVpc = new awsx.ec2.Vpc("eks-vpc", {
enableDnsHostnames: true,
cidrBlock: "10.0.0.0/16",
});

// IAM roles for the node groups.
const role = iam.createRole("example-role");

const projectName = pulumi.getProject();

const cluster = new eks.Cluster(`${projectName}`, {
skipDefaultNodeGroup: true,
deployDashboard: false,
vpcId: eksVpc.vpcId,
// Public subnets will be used for load balancers
publicSubnetIds: eksVpc.publicSubnetIds,
// Private subnets will be used for cluster nodes
privateSubnetIds: eksVpc.privateSubnetIds,
instanceRoles: [role],
});

// Export the cluster's kubeconfig.
export const kubeconfig = cluster.kubeconfig;

// Create a managed node group using a cluster as input.
eks.createManagedNodeGroup(`${projectName}-managed-ng`, {
cluster: cluster,
nodeRole: role,
// Force creating a custom launch template
bootstrapExtraArgs: "--max-pods=500",
diskSize: 50,
});
13 changes: 13 additions & 0 deletions examples/tests/managed-ng-disk-size/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"name": "managed-ng-disk-size",
"devDependencies": {
"typescript": "^4.0.0",
"@types/node": "latest"
},
"dependencies": {
"@pulumi/pulumi": "^3.0.0",
"@pulumi/aws": "^6.0.0",
"@pulumi/eks": "latest",
"@pulumi/awsx": "^2.0.0"
}
}
24 changes: 24 additions & 0 deletions examples/tests/managed-ng-disk-size/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"compilerOptions": {
"outDir": "bin",
"target": "es6",
"lib": [
"es6"
],
"module": "commonjs",
"moduleResolution": "node",
"declaration": true,
"sourceMap": true,
"stripInternal": true,
"experimentalDecorators": true,
"pretty": true,
"noFallthroughCasesInSwitch": true,
"noImplicitAny": true,
"noImplicitReturns": true,
"forceConsistentCasingInFileNames": true,
"strictNullChecks": true
},
"files": [
"index.ts"
]
}
14 changes: 14 additions & 0 deletions nodejs/eks/nodegroup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1742,6 +1742,9 @@ function createManagedNodeGroupInternal(
let launchTemplate: aws.ec2.LaunchTemplate | undefined;
if (args.kubeletExtraArgs || args.bootstrapExtraArgs || args.enableIMDSv2) {
launchTemplate = createMNGCustomLaunchTemplate(name, args, core, parent, provider);

// Disk size is specified in the launch template.
delete nodeGroupArgs.diskSize;
}

if (launchTemplate?.imageId) {
Expand Down Expand Up @@ -1841,9 +1844,20 @@ Content-Type: text/x-shellscript; charset="us-ascii"
? { httpTokens: "required", httpPutResponseHopLimit: 2, httpEndpoint: "enabled" }
: undefined;

const blockDeviceMappings = args.diskSize ? [
{
// /dev/xvda is the default device name for the root volume on an Amazon Linux 2 & AL2023 instance.
deviceName: "/dev/xvda",
ebs: {
volumeSize: args.diskSize
},
},
] : undefined;

return new aws.ec2.LaunchTemplate(
`${name}-launchTemplate`,
{
blockDeviceMappings,
userData,
metadataOptions,
// We need to supply an imageId if userData is set, otherwise AWS will attempt to merge the user data which will result in
Expand Down

0 comments on commit 453da6a

Please sign in to comment.