Skip to content

Commit

Permalink
Merge pull request #822 from aws-quickstart/feature/windowsBuilder
Browse files Browse the repository at this point in the history
Windows Builder for Windows Blueprints
  • Loading branch information
shapirov103 authored Aug 16, 2023
2 parents 9ecd9dc + 1946d4c commit 84d9173
Show file tree
Hide file tree
Showing 3 changed files with 322 additions and 0 deletions.
78 changes: 78 additions & 0 deletions docs/builders/windows-builder.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# Windows Builder

The `WindowsBuilder` allows you to get started with a builder class to configure with required setup as you prepare a blueprint for setting up EKS cluster with windows to run your windows workloads.

The `WindowsBuilder` creates the following:
- An EKS Cluster` with passed k8s version and cluster tags.
- A non-windows nodegroup for standard software with parameters passed.
- A windows nodegroup to schedule windows workloads with parameters passed.

## Input Parameters

`WindowsOptions` which takes inputs to `WindowsBuilder` supports following parameters:

- `kubernetesVersion` : Required field, Kubernetes version to use for the cluster
- `instanceClass`: Required field, Instance class to use for the cluster
- `instanceSize`: Required field, Instance size to use for the cluster
- `nodeRole`: optional, Node IAM Role to be attached to Windows and Non-windows nodes.
- `windowsAmiType`: Required field, AMI Type for Windows Nodes. For example `WINDOWS_FULL_2022_X86_64`.
- `desiredNodeSize`: Optional field, Desired number of nodes to use for the cluster
- `minNodeSize`: Optional field, Minimum number of nodes to use for the cluster
- `maxNodeSize`: Optional field, Maximum number of nodes to use for the cluster
- `blockDeviceSize`: Optional field, Block device size
- `noScheduleForWindowsNodes`: Optional field, No Schedule for Windows Nodes, this allows Windows nodes to be marked as no-schedule by default to prevent any linux workloads from scheduling.
- `clusterProviderTags`: Optional field, Cluster Provider Tags
- `genericNodeGroupTags`: Optional field, Generic Node Group Tags for non-windows nodes which run standard cluster software.
- `windowsNodeGroupTags`: Optional field, Windows Node Group Tags.

### Demonstration - Building Windows on EKS Cluster

The below usage helps you with a demonstration to use `WindowsBuilder` to configure a required setup as you prepare a blueprint for setting up windows nodes on a new EKS cluster.

```typescript
import * as blueprints from "@aws-quickstart/eks-blueprints";
import * as ec2 from "aws-cdk-lib/aws-ec2";
import * as eks from "aws-cdk-lib/aws-eks";
import * as iam from "aws-cdk-lib/aws-iam";
import { Construct } from "constructs";
import { WindowsBuilder, WindowsOptions } from '../common/windows-builder';
import { WindowsVpcCni } from "./vpc-cni";

export default class WindowsConstruct {
build(scope: Construct, id: string) {
const account = process.env.CDK_DEFAULT_ACCOUNT!;
const region = process.env.CDK_DEFAULT_REGION!;
const stackID = `${id}-eks-blueprint`;

const nodeRole = new blueprints.CreateRoleProvider("blueprint-node-role", new iam.ServicePrincipal("ec2.amazonaws.com"),
[
iam.ManagedPolicy.fromAwsManagedPolicyName("AmazonEKSWorkerNodePolicy"),
iam.ManagedPolicy.fromAwsManagedPolicyName("AmazonEC2ContainerRegistryReadOnly"),
iam.ManagedPolicy.fromAwsManagedPolicyName("AmazonSSMManagedInstanceCore"),
iam.ManagedPolicy.fromAwsManagedPolicyName("AmazonEKS_CNI_Policy")
]);

const options: WindowsOptions = {
kubernetesVersion: eks.KubernetesVersion.of("1.27"),
instanceClass: ec2.InstanceClass.M5,
instanceSize: ec2.InstanceSize.XLARGE4
};

const addOns: Array<blueprints.ClusterAddOn> = [
new WindowsVpcCni()
];

WindowsBuilder.builder(options)
.addOns(...addOns)
.account(account)
.region(region)
.resourceProvider("node-role", nodeRole)
.resourceProvider(
blueprints.GlobalResources.Vpc,
new blueprints.VpcProvider()
)
.build(scope, stackID);
}
}

```
243 changes: 243 additions & 0 deletions lib/builders/windows-builder.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,243 @@
import * as blueprints from '../../lib';
import * as utils from "../utils";
import { NestedStack, NestedStackProps } from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as eks from "aws-cdk-lib/aws-eks";
import * as ec2 from "aws-cdk-lib/aws-ec2";
import * as iam from 'aws-cdk-lib/aws-iam';
import { NodegroupAmiType } from 'aws-cdk-lib/aws-eks';
import merge from 'ts-deepmerge';

/**
* Configuration options for Windows Builder.
*/
export interface WindowsOptions {
/**
* Required, Kubernetes version to use for the cluster.
*/
kubernetesVersion: eks.KubernetesVersion,

/**
* Required, Instance class to use for the cluster.
*/
instanceClass: ec2.InstanceClass,

/**
* Required, Instance size to use for the cluster.
*/
instanceSize: ec2.InstanceSize,

/**
* optional, Node IAM Role to be attached to Windows
* and Non-windows nodes.
*/
nodeRole?: iam.Role,

/**
* Optional, AMI Type for Windows Nodes
*/
windowsAmiType?: NodegroupAmiType,

/**
* Optional, Desired number of nodes to use for the cluster.
*/
desiredNodeSize?: number,

/**
* Optional, Minimum number of nodes to use for the cluster.
*/
minNodeSize?: number,

/**
* Optional, Maximum number of nodes to use for the cluster.
*/
maxNodeSize?: number,

/**
* Optional, Block device size.
*/
blockDeviceSize?: number,

/**
* Optional, No Schedule for Windows Nodes, this allows Windows
* nodes to be marked as no-schedule by default to prevent any
* linux workloads from scheduling.
*/
noScheduleForWindowsNodes?: boolean,

/**
* Optional, Cluster Provider Tags.
*/
clusterProviderTags?: {
[key: string]: string;
},

/**
* Optional, Generic Node Group Tags for non-windows nodes
* which run standard cluster software.
*/
genericNodeGroupTags?: {
[key: string]: string;
}

/**
* Optional, Windows Node Group Tags.
*/
windowsNodeGroupTags?: {
[key: string]: string;
}
}

/**
* Default props to be used when creating the non-windows and windows nodes
* for Windows EKS cluster
*/
const defaultOptions: WindowsOptions = {
kubernetesVersion: eks.KubernetesVersion.of("1.27"),
instanceClass: ec2.InstanceClass.M5,
instanceSize: ec2.InstanceSize.XLARGE4,
nodeRole: blueprints.getNamedResource("node-role") as iam.Role,
windowsAmiType: NodegroupAmiType.WINDOWS_FULL_2022_X86_64,
desiredNodeSize: 2,
minNodeSize: 2,
maxNodeSize: 3,
blockDeviceSize: 50,
noScheduleForWindowsNodes: true,
clusterProviderTags: {
"Name": "blueprints-windows-eks-cluster",
"Type": "generic-windows-cluster"
},
genericNodeGroupTags: {
"Name": "Mng-linux",
"Type": "Managed-linux-Node-Group",
"LaunchTemplate": "Linux-Launch-Template",
},
windowsNodeGroupTags: {
"Name": "Managed-Node-Group",
"Type": "Windows-Node-Group",
"LaunchTemplate": "WindowsLT",
"kubernetes.io/cluster/windows-eks-blueprint": "owned"
}
};

/**
* This builder class helps you prepare a blueprint for setting up
* windows nodes with EKS cluster. The `WindowsBuilder` creates the following:
* 1. An EKS Cluster` with passed k8s version and cluster tags.
* 2. A non-windows nodegroup for standard software.
* 3. A windows nodegroup to schedule windows workloads
*/
export class WindowsBuilder extends blueprints.BlueprintBuilder {

/**
* This method helps you prepare a blueprint for setting up windows nodes with
* usage tracking addon
*/
public static builder(options: WindowsOptions): WindowsBuilder {
const builder = new WindowsBuilder();
const mergedOptions = merge(defaultOptions, options);

builder
.clusterProvider(
new blueprints.GenericClusterProvider({
version: mergedOptions.kubernetesVersion,
tags: mergedOptions.clusterProviderTags,
role: blueprints.getResource(context => {
return new iam.Role(context.scope, 'ClusterRole', {
assumedBy: new iam.ServicePrincipal("eks.amazonaws.com"),
managedPolicies: [
iam.ManagedPolicy.fromAwsManagedPolicyName("AmazonEKSClusterPolicy"),
iam.ManagedPolicy.fromAwsManagedPolicyName("AmazonEKSVPCResourceController")
]
});
}),
managedNodeGroups: [
addGenericNodeGroup(mergedOptions),
addWindowsNodeGroup(mergedOptions)
]
})
)
.addOns(
new blueprints.NestedStackAddOn({
id: "usage-tracking-addon",
builder: UsageTrackingAddOn.builder(),
})
);
return builder;
}
}

/**
* Nested stack that is used as tracker for Windows Accelerator
*/
export class UsageTrackingAddOn extends NestedStack {

static readonly USAGE_ID = "qs-1ubotj5kl";

public static builder(): blueprints.NestedStackBuilder {
return {
build(scope: Construct, id: string, props: NestedStackProps) {
return new UsageTrackingAddOn(scope, id, props);
}
};
}

constructor(scope: Construct, id: string, props: NestedStackProps) {
super(scope, id, utils.withUsageTracking(UsageTrackingAddOn.USAGE_ID, props));
}
}

/**
* This function adds a generic node group to the windows cluster.
* @param: options: WindowsOptions
* @returns: blueprints.ManagedNodeGroup
*/
function addGenericNodeGroup(options: WindowsOptions): blueprints.ManagedNodeGroup {

return {
id: "mng-linux",
amiType: NodegroupAmiType.AL2_X86_64,
instanceTypes: [new ec2.InstanceType('m5.4xlarge')],
desiredSize: options.desiredNodeSize,
minSize: options.minNodeSize,
maxSize: options.maxNodeSize,
nodeRole: options.nodeRole,
nodeGroupSubnets: { subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS },
launchTemplate: {
tags: options.genericNodeGroupTags,
requireImdsv2: false
}
};
}

/**
* This function adds a windows node group to the windows cluster.
* @param options: WindowsOptions
* @returns: blueprints.ManagedNodeGroup
*/
function addWindowsNodeGroup(options: WindowsOptions): blueprints.ManagedNodeGroup {
const result : blueprints.ManagedNodeGroup = {
id: "mng-windows",
amiType: options.windowsAmiType,
instanceTypes: [new ec2.InstanceType(`${options.instanceClass}.${options.instanceSize}`)],
desiredSize: options.desiredNodeSize,
minSize: options.minNodeSize,
maxSize: options.maxNodeSize,
nodeRole: options.nodeRole,
nodeGroupSubnets: { subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS },
diskSize: options.blockDeviceSize,
tags: options.windowsNodeGroupTags
};

if(options.noScheduleForWindowsNodes) {
blueprints.utils.setPath(result, "taints", [
{
key: "os",
value: "windows",
effect: eks.TaintEffect.NO_SCHEDULE
}
]);
}

return result;
}
1 change: 1 addition & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ nav:
- Builders:
- Overview: 'builders/index.md'
- Observability Builder: 'builders/observability-builder.md'
- Windows Builder: 'builders/windows-builder.ts'
- Extensibility: 'extensibility.md'
- API Reference: 'api'
markdown_extensions:
Expand Down

0 comments on commit 84d9173

Please sign in to comment.