in installer/resources/src/cdk_construct.py [0:0]
def storage(self):
"""
Create two EFS or FSx for Lustre file systems that will be mounted as /apps and /data
aws_efs.FileSystem is experimental and we cannot add multiple SG (as of April 2021).
Because of that we have to use CfnFilesystem
"""
if install_props.Config.storage.apps.provider == "efs" and not user_specified_variables.fs_apps:
self.soca_resources["fs_apps"] = efs.CfnFileSystem(self, "EFSApps", encrypted=install_props.Config.storage.apps.efs.encrypted, kms_key_id=None if install_props.Config.storage.apps.kms_key_id is False else install_props.Config.storage.apps.kms_key_id,
throughput_mode=install_props.Config.storage.apps.efs.throughput_mode,
file_system_tags=[
efs.CfnFileSystem.ElasticFileSystemTagProperty(key="soca:BackupPlan", value=user_specified_variables.cluster_id),
efs.CfnFileSystem.ElasticFileSystemTagProperty(key="Name", value=f"{user_specified_variables.cluster_id}-Apps")],
performance_mode=install_props.Config.storage.apps.efs.performance_mode)
if install_props.Config.storage.apps.efs.deletion_policy.upper() == "RETAIN":
self.soca_resources["fs_apps"].cfn_options.deletion_policy = cdk.CfnDeletionPolicy.RETAIN
if install_props.Config.storage.data.provider == "efs" and not user_specified_variables.fs_data:
self.soca_resources["fs_data"] = efs.CfnFileSystem(self, "EFSData", encrypted=install_props.Config.storage.data.efs.encrypted, kms_key_id=None if install_props.Config.storage.data.kms_key_id is False else install_props.Config.storage.data.kms_key_id,
throughput_mode=install_props.Config.storage.data.efs.throughput_mode,
file_system_tags=[
efs.CfnFileSystem.ElasticFileSystemTagProperty(key="soca:BackupPlan", value=user_specified_variables.cluster_id),
efs.CfnFileSystem.ElasticFileSystemTagProperty(key="Name", value=f"{user_specified_variables.cluster_id}-Data")],
lifecycle_policies=[efs.CfnFileSystem.LifecyclePolicyProperty(transition_to_ia=install_props.Config.storage.data.efs.transition_to_ia)],
performance_mode=install_props.Config.storage.data.efs.performance_mode)
if install_props.Config.storage.data.efs.deletion_policy.upper() == "RETAIN":
self.soca_resources["fs_data"].cfn_options.deletion_policy = cdk.CfnDeletionPolicy.RETAIN
# Create the mount targets for /data
if install_props.Config.storage.data.provider == "efs" and not user_specified_variables.fs_data:
for i in range(len(self.soca_resources["vpc"].select_subnets(subnet_type=ec2.SubnetType.PRIVATE).subnet_ids)):
efs.CfnMountTarget(self, f"EFSDataMountTarget{i+1}", file_system_id=self.soca_resources["fs_data"].ref,
security_groups=[self.soca_resources["compute_node_sg"].security_group_id, self.soca_resources["scheduler_sg"].security_group_id],
subnet_id=self.soca_resources["vpc"].select_subnets(subnet_type=ec2.SubnetType.PRIVATE).subnets[i].subnet_id)
# Create the mount targets for /apps
if install_props.Config.storage.apps.provider == "efs" and not user_specified_variables.fs_apps:
for i in range(len(self.soca_resources["vpc"].select_subnets(subnet_type=ec2.SubnetType.PRIVATE).subnet_ids)):
efs.CfnMountTarget(self, f"EFSAppsMountTarget{i+1}", file_system_id=self.soca_resources["fs_apps"].ref,
security_groups=[self.soca_resources["compute_node_sg"].security_group_id, self.soca_resources["scheduler_sg"].security_group_id],
subnet_id=self.soca_resources["vpc"].select_subnets(subnet_type=ec2.SubnetType.PRIVATE).subnets[i].subnet_id)
# Create CloudWatch/SNS alarm for SNS EFS. This will check BurstCreditBalance and increase allocated throughput to support temporary burst activity if needed
sns_efs_topic = sns.Topic(self, "SNSEFSTopic", display_name=f"{user_specified_variables.cluster_id}-EFSAlarm-SNS", topic_name=f"{user_specified_variables.cluster_id}-EFSAlarm-SNS")
sns_efs_topic.add_to_resource_policy(iam.PolicyStatement(effect=iam.Effect.ALLOW, actions=["sns:Publish"],
resources=[sns_efs_topic.topic_arn], principals=[iam.ServicePrincipal(principals_suffix["cloudwatch"])],
conditions={"ArnLike": {"aws:SourceArn": f"arn:{core.Aws.PARTITION}:*:*:{core.Aws.ACCOUNT_ID}:*"}}))
efs_apps_cw_alarm_low = cloudwatch.Alarm(self, "EFSAppsCWAlarmLowThreshold",
metric=cloudwatch.Metric(metric_name="BurstCreditBalance",
namespace="AWS/EFS", dimensions=dict(FileSystemId=self.soca_resources["fs_apps"].ref)),
comparison_operator=cloudwatch.ComparisonOperator.LESS_THAN_OR_EQUAL_TO_THRESHOLD,
evaluation_periods=10, period=core.Duration.minutes(1), statistic="Average", threshold=10000000)
efs_apps_cw_alarm_high = cloudwatch.Alarm(self, "EFSAppsCWAlarmHighThreshold",
metric=cloudwatch.Metric(metric_name="BurstCreditBalance",
namespace="AWS/EFS", dimensions=dict(FileSystemId=self.soca_resources["fs_apps"].ref)),
comparison_operator=cloudwatch.ComparisonOperator.GREATER_THAN_OR_EQUAL_TO_THRESHOLD,
evaluation_periods=10, period=core.Duration.minutes(1), statistic="Average", threshold=2000000000000)
efs_apps_cw_alarm_low.add_alarm_action(cw_actions.SnsAction(sns_efs_topic))
efs_apps_cw_alarm_high.add_alarm_action(cw_actions.SnsAction(sns_efs_topic))
efs_apps_throughput_lambda = aws_lambda.Function(self, f"{user_specified_variables.cluster_id}-EFSAppsLambda",
function_name=f"{user_specified_variables.cluster_id}-EFSThroughput",
description="Check EFS BurstCreditBalance and update ThroughputMode when needed",
memory_size=128, role=self.soca_resources["fs_apps_lambda_role"],
timeout=core.Duration.minutes(3),
runtime=aws_lambda.Runtime.PYTHON_3_7,
log_retention=logs.RetentionDays.INFINITE,
handler="EFSThroughputLambda.lambda_handler",
code=aws_lambda.Code.asset("../functions/EFSThroughputLambda"))
efs_apps_throughput_lambda.add_environment("EFSBurstCreditLowThreshold", "10000000")
efs_apps_throughput_lambda.add_environment("EFSBurstCreditHighThreshold", "2000000000000")
efs_apps_throughput_lambda.add_permission("InvokePermission", principal=iam.ServicePrincipal(principals_suffix["sns"]), action="lambda:InvokeFunction")
sns.Subscription(self, f"{user_specified_variables.cluster_id}-SNSEFSSubscription", protocol=sns.SubscriptionProtocol.LAMBDA, endpoint=efs_apps_throughput_lambda.function_arn, topic=sns_efs_topic)
if install_props.Config.storage.data.provider == "fsx_lustre" and not user_specified_variables.fs_data:
if install_props.Config.storage.data.fsx_lustre.storage_type == "SSD":
if install_props.Config.storage.data.fsx_lustre.deployment_type == "PERSISTENT_1":
lustre_configuration = fsx.CfnFileSystem.LustreConfigurationProperty(
per_unit_storage_throughput=install_props.Config.storage.data.fsx_lustre.per_unit_storage_throughput,
deployment_type=install_props.Config.storage.data.fsx_lustre.deployment_type)
else:
lustre_configuration = fsx.CfnFileSystem.LustreConfigurationProperty(
deployment_type=install_props.Config.storage.data.fsx_lustre.deployment_type)
else:
lustre_configuration = fsx.CfnFileSystem.LustreConfigurationProperty(
deployment_type=install_props.Config.storage.data.fsx_lustre.deployment_type,
per_unit_storage_throughput=install_props.Config.storage.data.fsx_lustre.per_unit_storage_throughput,
drive_cache_type=install_props.Config.storage.data.fsx_lustre.drive_cache_type),
self.soca_resources["fs_data"] = fsx.CfnFileSystem(self, "FSxLustreData", file_system_type="LUSTRE",
subnet_ids=[self.soca_resources["vpc"].select_subnets(subnet_type=ec2.SubnetType.PRIVATE).subnets[0].subnet_id],
lustre_configuration=lustre_configuration,
security_group_ids=[self.soca_resources["compute_node_sg"].security_group_id],
storage_capacity=install_props.Config.storage.data.fsx_lustre.storage_capacity,
storage_type=install_props.Config.storage.data.fsx_lustre.storage_type,
kms_key_id=None if install_props.Config.storage.data.kms_key_id is False else install_props.Config.storage.data.kms_key_id)
core.Tags.of(self.soca_resources["fs_data"]).add("Name", f"{user_specified_variables.cluster_id}-Data")
if install_props.Config.storage.apps.provider == "fsx_lustre" and not user_specified_variables.fs_apps:
if install_props.Config.storage.apps.fsx_lustre.storage_type == "SSD":
if install_props.Config.storage.apps.fsx_lustre.deployment_type == "PERSISTENT_1":
lustre_configuration=fsx.CfnFileSystem.LustreConfigurationProperty(
per_unit_storage_throughput=install_props.Config.storage.apps.fsx_lustre.per_unit_storage_throughput,
deployment_type=install_props.Config.storage.apps.fsx_lustre.deployment_type)
else:
lustre_configuration=fsx.CfnFileSystem.LustreConfigurationProperty(
deployment_type=install_props.Config.storage.apps.fsx_lustre.deployment_type)
else:
lustre_configuration=fsx.CfnFileSystem.LustreConfigurationProperty(
deployment_type=install_props.Config.storage.apps.fsx_lustre.deployment_type,
per_unit_storage_throughput=install_props.Config.storage.apps.fsx_lustre.per_unit_storage_throughput,
drive_cache_type=install_props.Config.storage.apps.fsx_lustre.drive_cache_type),
self.soca_resources["fs_apps"] = fsx.CfnFileSystem(self, "FSxLustreApps", file_system_type="LUSTRE",
subnet_ids=[self.soca_resources["vpc"].select_subnets(subnet_type=ec2.SubnetType.PRIVATE).subnets[0].subnet_id],
lustre_configuration=lustre_configuration,
security_group_ids=[self.soca_resources["compute_node_sg"].security_group_id],
storage_capacity=install_props.Config.storage.apps.fsx_lustre.storage_capacity,
storage_type=install_props.Config.storage.apps.fsx_lustre.storage_type,
kms_key_id=None if install_props.Config.storage.apps.kms_key_id is False else install_props.Config.storage.apps.kms_key_id)
core.Tags.of(self.soca_resources["fs_apps"]).add("Name", f"{user_specified_variables.cluster_id}-Apps")