-
Notifications
You must be signed in to change notification settings - Fork 206
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #822 from aws-quickstart/feature/windowsBuilder
Windows Builder for Windows Blueprints
- Loading branch information
Showing
3 changed files
with
322 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | ||
} | ||
} | ||
|
||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters