in source/idea/idea-administrator/src/ideaadministrator/app/cdk/stacks/cluster_manager_stack.py [0:0]
def build_auto_scaling_group(self):
key_pair_name = self.context.config().get_string('cluster.network.ssh_key_pair', required=True)
is_public = self.context.config().get_bool('cluster-manager.ec2.autoscaling.public', False) and len(self.cluster.public_subnets) > 0
base_os = self.context.config().get_string('cluster-manager.ec2.autoscaling.base_os', required=True)
instance_ami = self.context.config().get_string('cluster-manager.ec2.autoscaling.instance_ami', required=True)
instance_type = self.context.config().get_string('cluster-manager.ec2.autoscaling.instance_type', required=True)
volume_size = self.context.config().get_int('cluster-manager.ec2.autoscaling.volume_size', default=200)
enable_detailed_monitoring = self.context.config().get_bool('cluster-manager.ec2.autoscaling.enable_detailed_monitoring', default=False)
min_capacity = self.context.config().get_int('cluster-manager.ec2.autoscaling.min_capacity', default=1)
max_capacity = self.context.config().get_int('cluster-manager.ec2.autoscaling.max_capacity', default=3)
cooldown_minutes = self.context.config().get_int('cluster-manager.ec2.autoscaling.cooldown_minutes', default=5)
default_instance_warmup = self.context.config().get_int('cluster-manager.ec2.autoscaling.default_instance_warmup', default=15)
new_instances_protected_from_scale_in = self.context.config().get_bool('cluster-manager.ec2.autoscaling.new_instances_protected_from_scale_in', default=True)
elb_healthcheck_grace_time_minutes = self.context.config().get_int('cluster-manager.ec2.autoscaling.elb_healthcheck.grace_time_minutes', default=15)
scaling_policy_target_utilization_percent = self.context.config().get_int('cluster-manager.ec2.autoscaling.cpu_utilization_scaling_policy.target_utilization_percent', default=80)
scaling_policy_estimated_instance_warmup_minutes = self.context.config().get_int('cluster-manager.ec2.autoscaling.cpu_utilization_scaling_policy.estimated_instance_warmup_minutes', default=15)
rolling_update_max_batch_size = self.context.config().get_int('cluster-manager.ec2.autoscaling.rolling_update_policy.max_batch_size', default=1)
rolling_update_min_instances_in_service = self.context.config().get_int('cluster-manager.ec2.autoscaling.rolling_update_policy.min_instances_in_service', default=1)
rolling_update_pause_time_minutes = self.context.config().get_int('cluster-manager.ec2.autoscaling.rolling_update_policy.pause_time_minutes', default=15)
metadata_http_tokens = self.context.config().get_string('cluster-manager.ec2.autoscaling.metadata_http_tokens', required=True)
https_proxy = self.context.config().get_string('cluster.network.https_proxy', required=False, default='')
no_proxy = self.context.config().get_string('cluster.network.no_proxy', required=False, default='')
proxy_config = {}
if Utils.is_not_empty(https_proxy):
proxy_config = {
'http_proxy': https_proxy,
'https_proxy': https_proxy,
'no_proxy': no_proxy
}
kms_key_id = self.context.config().get_string('cluster.ebs.kms_key_id', required=False, default=None)
if kms_key_id is not None:
kms_key_arn = self.get_kms_key_arn(kms_key_id)
ebs_kms_key = kms.Key.from_key_arn(scope=self.stack, id=f'ebs-kms-key', key_arn=kms_key_arn)
else:
ebs_kms_key = kms.Alias.from_alias_name(scope=self.stack, id=f'ebs-kms-key-default', alias_name='alias/aws/ebs')
if is_public:
vpc_subnets = ec2.SubnetSelection(
subnets=self.cluster.public_subnets
)
else:
vpc_subnets = ec2.SubnetSelection(
subnets=self.cluster.private_subnets
)
block_device_name = Utils.get_ec2_block_device_name(base_os)
user_data = BootstrapUserDataBuilder(
aws_region=self.aws_region,
bootstrap_package_uri=self.bootstrap_package_uri,
install_commands=[
'/bin/bash cluster-manager/setup.sh'
],
proxy_config=proxy_config,
base_os=base_os,
bootstrap_source_dir_path=ideaadministrator.props.bootstrap_source_dir
).build()
launch_template = ec2.LaunchTemplate(
self.stack, f'{self.module_id}-lt',
instance_type=ec2.InstanceType(instance_type),
machine_image=ec2.MachineImage.generic_linux({
self.aws_region: instance_ami
}),
security_group=self.cluster_manager_security_group,
user_data=ec2.UserData.custom(cdk.Fn.sub(user_data)),
key_name=key_pair_name,
block_devices=[ec2.BlockDevice(
device_name=block_device_name,
volume=ec2.BlockDeviceVolume(ebs_device=ec2.EbsDeviceProps(
encrypted=True,
kms_key=ebs_kms_key,
volume_size=volume_size,
volume_type=ec2.EbsDeviceVolumeType.GP3
))
)],
role=self.cluster_manager_role,
require_imdsv2=True if metadata_http_tokens == "required" else False,
associate_public_ip_address=is_public
)
self.auto_scaling_group = asg.AutoScalingGroup(
self.stack, 'cluster-manager-asg',
vpc=self.cluster.vpc,
vpc_subnets=vpc_subnets,
auto_scaling_group_name=f'{self.cluster_name}-{self.module_id}-asg',
launch_template=launch_template,
instance_monitoring=asg.Monitoring.DETAILED if enable_detailed_monitoring else asg.Monitoring.BASIC,
group_metrics=[asg.GroupMetrics.all()],
min_capacity=min_capacity,
max_capacity=max_capacity,
new_instances_protected_from_scale_in=new_instances_protected_from_scale_in,
default_instance_warmup=cdk.Duration.minutes(default_instance_warmup),
cooldown=cdk.Duration.minutes(cooldown_minutes),
health_check=asg.HealthCheck.elb(
grace=cdk.Duration.minutes(elb_healthcheck_grace_time_minutes)
),
update_policy=asg.UpdatePolicy.rolling_update(
max_batch_size=rolling_update_max_batch_size,
min_instances_in_service=rolling_update_min_instances_in_service,
pause_time=cdk.Duration.minutes(rolling_update_pause_time_minutes)
),
termination_policies=[
asg.TerminationPolicy.DEFAULT
]
)
self.auto_scaling_group.scale_on_cpu_utilization(
'cpu-utilization-scaling-policy',
target_utilization_percent=scaling_policy_target_utilization_percent,
estimated_instance_warmup=cdk.Duration.minutes(scaling_policy_estimated_instance_warmup_minutes)
)
cdk.Tags.of(self.auto_scaling_group).add(constants.IDEA_TAG_NODE_TYPE, constants.NODE_TYPE_APP)
cdk.Tags.of(self.auto_scaling_group).add(constants.IDEA_TAG_NAME, f'{self.cluster_name}-{self.module_id}')
self.auto_scaling_group.node.add_dependency(self.notifications_sqs_queue)
if not enable_detailed_monitoring:
self.add_nag_suppression(
construct=self.auto_scaling_group,
suppressions=[IdeaNagSuppression(rule_id='AwsSolutions-EC28', reason='detailed monitoring is a configurable option to save costs')],
apply_to_children=True
)
self.add_nag_suppression(
construct=self.auto_scaling_group,
suppressions=[
IdeaNagSuppression(rule_id='AwsSolutions-AS3', reason='ASG notifications scaling notifications can be managed via AWS Console')
]
)