From 2beea0539789dc265b883cb72039e7b1c6573157 Mon Sep 17 00:00:00 2001 From: Rishabh Singh Date: Mon, 10 Jun 2024 14:31:26 -0700 Subject: [PATCH 1/2] Add support for c5.2xlarge and c6g.2xlarge instance types Signed-off-by: Rishabh Singh --- lib/opensearch-config/node-config.ts | 6 ++++++ test/opensearch-cluster-cdk.test.ts | 4 ++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/lib/opensearch-config/node-config.ts b/lib/opensearch-config/node-config.ts index d192945eb74..4281953a69c 100644 --- a/lib/opensearch-config/node-config.ts +++ b/lib/opensearch-config/node-config.ts @@ -43,6 +43,7 @@ export enum x64Ec2InstanceType { M5_2XLARGE = 'm5.2xlarge', C5_LARGE = 'c5.large', C5_XLARGE = 'c5.xlarge', + C5_2XLARGE = 'c5.2xlarge', R5_LARGE = 'r5.large', R5_XLARGE = 'r5.xlarge', R5_2XLARGE = 'r5.2xlarge', @@ -64,6 +65,7 @@ export enum arm64Ec2InstanceType { M6G_2XLARGE = 'm6g.2xlarge', C6G_LARGE = 'c6g.large', C6G_XLARGE = 'c6g.xlarge', + C6G_2XLARGE = 'c6g.2xlarge', R6G_LARGE = 'r6g.large', R6G_XLARGE = 'r6g.xlarge', R6G_2XLARGE = 'r6g.2xlarge', @@ -83,6 +85,8 @@ export const getX64InstanceTypes = (instanceType: string) => { return InstanceType.of(InstanceClass.C5, InstanceSize.LARGE); case x64Ec2InstanceType.C5_XLARGE: return InstanceType.of(InstanceClass.C5, InstanceSize.XLARGE); + case x64Ec2InstanceType.C5_2XLARGE: + return InstanceType.of(InstanceClass.C5, InstanceSize.XLARGE2); case x64Ec2InstanceType.R5_LARGE: return InstanceType.of(InstanceClass.R5, InstanceSize.LARGE); case x64Ec2InstanceType.R5_XLARGE: @@ -126,6 +130,8 @@ export const getArm64InstanceTypes = (instanceType: string) => { return InstanceType.of(InstanceClass.C6G, InstanceSize.LARGE); case arm64Ec2InstanceType.C6G_XLARGE: return InstanceType.of(InstanceClass.C6G, InstanceSize.XLARGE); + case arm64Ec2InstanceType.C6G_2XLARGE: + return InstanceType.of(InstanceClass.C6G, InstanceSize.XLARGE2); case arm64Ec2InstanceType.R6G_LARGE: return InstanceType.of(InstanceClass.R6G, InstanceSize.LARGE); case arm64Ec2InstanceType.R6G_XLARGE: diff --git a/test/opensearch-cluster-cdk.test.ts b/test/opensearch-cluster-cdk.test.ts index e7fce530890..eb5e2e1b8e2 100644 --- a/test/opensearch-cluster-cdk.test.ts +++ b/test/opensearch-cluster-cdk.test.ts @@ -380,7 +380,7 @@ test('Throw error on wrong cpu arch to instance mapping', () => { expect(error).toBeInstanceOf(Error); // @ts-ignore expect(error.message).toEqual('Invalid instance type provided, please provide any one the following: ' - + 'm6g.xlarge,m6g.2xlarge,c6g.large,c6g.xlarge,r6g.large,r6g.xlarge,r6g.2xlarge,r6g.4xlarge,r6g.8xlarge,' + + 'm6g.xlarge,m6g.2xlarge,c6g.large,c6g.xlarge,c6g.2xlarge,r6g.large,r6g.xlarge,r6g.2xlarge,r6g.4xlarge,r6g.8xlarge,' + 'g5g.large,g5g.xlarge'); } }); @@ -422,7 +422,7 @@ test('Throw error on ec2 instance outside of enum list', () => { expect(error).toBeInstanceOf(Error); // @ts-ignore expect(error.message).toEqual('Invalid instance type provided, please provide any one the following: ' - + 'm5.xlarge,m5.2xlarge,c5.large,c5.xlarge,r5.large,r5.xlarge,r5.2xlarge,r5.4xlarge,r5.8xlarge,g5.large,' + + 'm5.xlarge,m5.2xlarge,c5.large,c5.xlarge,c5.2xlarge,r5.large,r5.xlarge,r5.2xlarge,r5.4xlarge,r5.8xlarge,g5.large,' + 'g5.xlarge,i3.large,i3.xlarge,i3.2xlarge,i3.4xlarge,i3.8xlarge,inf1.xlarge,inf1.2xlarge'); } }); From 0e36d5b858f33967c6c1677cf1bb6deabb91ac9e Mon Sep 17 00:00:00 2001 From: Rishabh Singh Date: Mon, 23 Sep 2024 09:43:59 -0700 Subject: [PATCH 2/2] use gp3 volume type by default Signed-off-by: Rishabh Singh --- lib/infra/infra-stack.ts | 146 ++++++++++++++-------------- test/opensearch-cluster-cdk.test.ts | 25 +++-- 2 files changed, 92 insertions(+), 79 deletions(-) diff --git a/lib/infra/infra-stack.ts b/lib/infra/infra-stack.ts index 1e89de63f85..8ff005c81c7 100644 --- a/lib/infra/infra-stack.ts +++ b/lib/infra/infra-stack.ts @@ -151,6 +151,7 @@ export interface InfraProps extends StackProps { export class InfraStack extends Stack { public readonly elb: NetworkLoadBalancer | ApplicationLoadBalancer; + public readonly elbType: LoadBalancerType; private instanceRole: Role; @@ -320,8 +321,7 @@ export class InfraStack extends Stack { const storageVolType = `${props?.storageVolumeType ?? scope.node.tryGetContext('storageVolumeType')}`; if (storageVolType === 'undefined') { - // use gp2 volume by default - this.storageVolumeType = getVolumeType('gp2'); + this.storageVolumeType = getVolumeType('gp3'); } else { this.storageVolumeType = getVolumeType(storageVolType); } @@ -412,26 +412,26 @@ export class InfraStack extends Stack { const certificateArn = `${props?.certificateArn ?? scope.node.tryGetContext('certificateArn')}`; // Set the load balancer type, defaulting to NLB if not specified - const loadBalancerTypeStr = scope.node.tryGetContext('loadBalancerType') ?? 'nlb' + const loadBalancerTypeStr = scope.node.tryGetContext('loadBalancerType') ?? 'nlb'; this.elbType = props?.loadBalancerType ?? LoadBalancerType[(loadBalancerTypeStr).toUpperCase() as keyof typeof LoadBalancerType]; switch (this.elbType) { - case LoadBalancerType.NLB: - this.elb = new NetworkLoadBalancer(this, 'clusterNlb', { - vpc: props.vpc, - internetFacing: (!this.isInternal), - crossZoneEnabled: true, - }); - break; - case LoadBalancerType.ALB: - this.elb = new ApplicationLoadBalancer(this, 'clusterAlb', { - vpc: props.vpc, - internetFacing: (!this.isInternal), - crossZoneEnabled: true, - securityGroup: props.securityGroup, - }); - break; - default: - throw new Error('Invalid load balancer type provided. Valid values are ' + Object.values(LoadBalancerType).join(', ')); + case LoadBalancerType.NLB: + this.elb = new NetworkLoadBalancer(this, 'clusterNlb', { + vpc: props.vpc, + internetFacing: (!this.isInternal), + crossZoneEnabled: true, + }); + break; + case LoadBalancerType.ALB: + this.elb = new ApplicationLoadBalancer(this, 'clusterAlb', { + vpc: props.vpc, + internetFacing: (!this.isInternal), + crossZoneEnabled: true, + securityGroup: props.securityGroup, + }); + break; + default: + throw new Error(`Invalid load balancer type provided. Valid values are ${Object.values(LoadBalancerType).join(', ')}`); } const opensearchPortMap = `${props?.mapOpensearchPortTo ?? scope.node.tryGetContext('mapOpensearchPortTo')}`; @@ -464,7 +464,7 @@ export class InfraStack extends Stack { this.elbType, 'opensearch', this.opensearchPortMapping, - (useSSLOpensearchListener) ? certificateArn : undefined + (useSSLOpensearchListener) ? certificateArn : undefined, ); let dashboardsListener: NetworkListener | ApplicationListener; @@ -476,7 +476,7 @@ export class InfraStack extends Stack { this.elbType, 'dashboards', this.opensearchDashboardsPortMapping, - (useSSLDashboardsListener) ? certificateArn : undefined + (useSSLDashboardsListener) ? certificateArn : undefined, ); } if (this.singleNodeCluster) { @@ -513,7 +513,8 @@ export class InfraStack extends Stack { 'single-node-target', 9200, new InstanceTarget(singleNodeInstance), - false); + false, + ); if (this.dashboardsUrl !== 'undefined') { InfraStack.addTargetsToListener( @@ -522,7 +523,8 @@ export class InfraStack extends Stack { 'single-node-osd-target', 5601, new InstanceTarget(singleNodeInstance), - false); + false, + ); } new CfnOutput(this, 'private-ip', { value: singleNodeInstance.instancePrivateIp, @@ -694,7 +696,8 @@ export class InfraStack extends Stack { 'opensearchTarget', 9200, clientNodeAsg, - false); + false, + ); if (this.dashboardsUrl !== 'undefined') { InfraStack.addTargetsToListener( @@ -703,7 +706,8 @@ export class InfraStack extends Stack { 'dashboardsTarget', 5601, clientNodeAsg, - false); + false, + ); } } new CfnOutput(this, 'loadbalancer-url', { @@ -1051,38 +1055,38 @@ export class InfraStack extends Stack { * Otherwise, the protocol will be set to TCP/HTTP. */ private static createListener(elb: BaseLoadBalancer, elbType: LoadBalancerType, id: string, port: number, - certificateArn?: string): ApplicationListener | NetworkListener { + certificateArn?: string): ApplicationListener | NetworkListener { const useSSL = !!certificateArn; let protocol: ApplicationProtocol | Protocol; - switch(elbType) { - case LoadBalancerType.ALB: - protocol = useSSL ? ApplicationProtocol.HTTPS : ApplicationProtocol.HTTP; - break; - case LoadBalancerType.NLB: - protocol = useSSL ? Protocol.TLS : Protocol.TCP; - break; - default: - throw new Error('Unsupported load balancer type.'); + switch (elbType) { + case LoadBalancerType.ALB: + protocol = useSSL ? ApplicationProtocol.HTTPS : ApplicationProtocol.HTTP; + break; + case LoadBalancerType.NLB: + protocol = useSSL ? Protocol.TLS : Protocol.TCP; + break; + default: + throw new Error('Unsupported load balancer type.'); } const listenerProps: BaseApplicationListenerProps | BaseNetworkListenerProps = { - port: port, - protocol: protocol, + port, + protocol, certificates: useSSL ? [ListenerCertificate.fromArn(certificateArn)] : undefined, }; - switch(elbType) { - case LoadBalancerType.ALB: { - const alb = elb as ApplicationLoadBalancer; - return alb.addListener(id, listenerProps as BaseApplicationListenerProps); - } - case LoadBalancerType.NLB: { - const nlb = elb as NetworkLoadBalancer; - return nlb.addListener(id, listenerProps as BaseNetworkListenerProps); - } - default: - throw new Error('Unsupported load balancer type.'); + switch (elbType) { + case LoadBalancerType.ALB: { + const alb = elb as ApplicationLoadBalancer; + return alb.addListener(id, listenerProps as BaseApplicationListenerProps); + } + case LoadBalancerType.NLB: { + const nlb = elb as NetworkLoadBalancer; + return nlb.addListener(id, listenerProps as BaseNetworkListenerProps); + } + default: + throw new Error('Unsupported load balancer type.'); } } @@ -1091,28 +1095,28 @@ export class InfraStack extends Stack { * Works for both Application Load Balancers and Network Load Balancers. */ private static addTargetsToListener(listener: BaseListener, elbType: LoadBalancerType, id: string, port: number, target: AutoScalingGroup | InstanceTarget, - securityEnabled: boolean) { - switch(elbType) { - case LoadBalancerType.ALB: { - const albListener = listener as ApplicationListener; - albListener.addTargets(id, { - port: port, - protocol: securityEnabled ? ApplicationProtocol.HTTPS : ApplicationProtocol.HTTP, - targets: [target], - }); - break; - } - case LoadBalancerType.NLB: { - const nlbListener = listener as NetworkListener; - nlbListener.addTargets(id, { - port: port, - protocol: securityEnabled ? Protocol.TLS : Protocol.TCP, - targets: [target], - }); - break; - } - default: - throw new Error('Unsupported load balancer type.'); + securityEnabled: boolean) { + switch (elbType) { + case LoadBalancerType.ALB: { + const albListener = listener as ApplicationListener; + albListener.addTargets(id, { + port, + protocol: securityEnabled ? ApplicationProtocol.HTTPS : ApplicationProtocol.HTTP, + targets: [target], + }); + break; + } + case LoadBalancerType.NLB: { + const nlbListener = listener as NetworkListener; + nlbListener.addTargets(id, { + port, + protocol: securityEnabled ? Protocol.TLS : Protocol.TCP, + targets: [target], + }); + break; + } + default: + throw new Error('Unsupported load balancer type.'); } } } diff --git a/test/opensearch-cluster-cdk.test.ts b/test/opensearch-cluster-cdk.test.ts index 0f6be488d84..8903e3b77b8 100644 --- a/test/opensearch-cluster-cdk.test.ts +++ b/test/opensearch-cluster-cdk.test.ts @@ -469,7 +469,7 @@ test('Test multi-node cluster with only data-nodes', () => { { Ebs: { VolumeSize: 200, - VolumeType: 'gp2', + VolumeType: 'gp3', }, }, ], @@ -1071,13 +1071,22 @@ test('Ensure target group protocol is always TCP', () => { }); }); - describe.each([ - { loadBalancerType: 'alb', securityDisabled: false, expectedType: 'application', expectedProtocol: 'HTTPS' }, - { loadBalancerType: 'alb', securityDisabled: true, expectedType: 'application', expectedProtocol: 'HTTP' }, - { loadBalancerType: 'nlb', securityDisabled: false, expectedType: 'network', expectedProtocol: 'TLS' }, - { loadBalancerType: 'nlb', securityDisabled: true, expectedType: 'network', expectedProtocol: 'TCP' }, -])('Test $loadBalancerType creation with securityDisabled=$securityDisabled', ({ loadBalancerType, securityDisabled, expectedType, expectedProtocol }) => { + { + loadBalancerType: 'alb', securityDisabled: false, expectedType: 'application', expectedProtocol: 'HTTPS', + }, + { + loadBalancerType: 'alb', securityDisabled: true, expectedType: 'application', expectedProtocol: 'HTTP', + }, + { + loadBalancerType: 'nlb', securityDisabled: false, expectedType: 'network', expectedProtocol: 'TLS', + }, + { + loadBalancerType: 'nlb', securityDisabled: true, expectedType: 'network', expectedProtocol: 'TCP', + }, +])('Test $loadBalancerType creation with securityDisabled=$securityDisabled', ({ + loadBalancerType, securityDisabled, expectedType, expectedProtocol, +}) => { test(`should create ${loadBalancerType} with securityDisabled=${securityDisabled}`, () => { const app = new App({ context: { @@ -1095,7 +1104,7 @@ describe.each([ }, }); - // WHEN + // WHEN const networkStack = new NetworkStack(app, 'opensearch-network-stack', { env: { account: 'test-account', region: 'us-east-1' }, });