Exemplo n.º 1
0
 def _setup_mysql_serverless(self) -> None:
     port = 3306
     database = "test"
     schema = "test"
     aurora_mysql = rds.ServerlessCluster(
         self,
         "aws-data-wrangler-aurora-cluster-mysql-serverless",
         removal_policy=RemovalPolicy.DESTROY,
         engine=rds.DatabaseClusterEngine.aurora_mysql(
             version=rds.AuroraMysqlEngineVersion.VER_5_7_12,
         ),
         cluster_identifier="mysql-serverless-cluster-wrangler",
         default_database_name=database,
         credentials=rds.Credentials.from_password(
             username=self.db_username,
             password=self.db_password_secret,
         ),
         scaling=rds.ServerlessScalingOptions(
             auto_pause=Duration.minutes(5),
             min_capacity=rds.AuroraCapacityUnit.ACU_1,
             max_capacity=rds.AuroraCapacityUnit.ACU_1,
         ),
         backup_retention=Duration.days(1),
         vpc=self.vpc,
         vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PRIVATE_WITH_NAT),
         subnet_group=self.rds_subnet_group,
         security_groups=[self.db_security_group],
         enable_data_api=True,
     )
     secret = secrets.Secret(
         self,
         "aws-data-wrangler-mysql-serverless-secret",
         secret_name="aws-data-wrangler/mysql-serverless",
         description="MySQL serverless credentials",
         generate_secret_string=secrets.SecretStringGenerator(
             generate_string_key="dummy",
             secret_string_template=json.dumps(
                 {
                     "username": self.db_username,
                     "password": self.db_password,
                     "engine": "mysql",
                     "host": aurora_mysql.cluster_endpoint.hostname,
                     "port": port,
                     "dbClusterIdentifier": aurora_mysql.cluster_identifier,
                     "dbname": database,
                 }
             ),
         ),
     )
     CfnOutput(self, "MysqlServerlessSecretArn", value=secret.secret_arn)
     CfnOutput(self, "MysqlServerlessClusterArn", value=aurora_mysql.cluster_arn)
     CfnOutput(self, "MysqlServerlessAddress", value=aurora_mysql.cluster_endpoint.hostname)
     CfnOutput(self, "MysqlServerlessPort", value=str(port))
     CfnOutput(self, "MysqlServerlessDatabase", value=database)
     CfnOutput(self, "MysqlServerlessSchema", value=schema)
    def __init__(self, scope: core.Construct, id: str, **kwargs) -> None:
        super().__init__(scope, id, **kwargs)

        # IAM Roles
        # TBD

        # First, we want to create a VPC for the Aurora DB
        self.vpc = ec2.Vpc(
            self,
            "VPC",
            max_azs=2,
            cidr="10.0.0.0/24",
            nat_gateways=1,
        )
        core.CfnOutput(self, "Output", value=self.vpc.vpc_id)

        # Create Aurora Serverless instance to maintain current snapshot of data
        cluster = rds.ServerlessCluster(
            self,
            'nrawling-testcluster',
            engine=rds.DatabaseClusterEngine.aurora_postgres(
                version=rds.AuroraPostgresEngineVersion.VER_10_7),
            vpc=self.vpc,
            scaling=rds.ServerlessScalingOptions(
                auto_pause=core.Duration.minutes(10),
                min_capacity=rds.AuroraCapacityUnit.ACU_8,
                max_capacity=rds.AuroraCapacityUnit.ACU_16,
            ))

        # Create Dynamo Source table
        dynamo = dynamodb.Table(self,
                                "ss-nrawling-testtable-780856337633",
                                partition_key=dynamodb.Attribute(
                                    name='PK',
                                    type=dynamodb.AttributeType.STRING))

        # S3 bucket will store stream output
        bucket = s3.Bucket(self,
                           "ss-nrawling-testbucket-780856337633",
                           versioned=False,
                           removal_policy=core.RemovalPolicy.DESTROY,
                           bucket_name="ss-nrawling-testbucket-780856337633")
Exemplo n.º 3
0
    def __init__(self, scope: core.Construct, construct_id: str, **kwargs) -> None:
        super().__init__(scope, construct_id, **kwargs)

        vpc = ec2.Vpc(
            scope=self,
            id="aurora-VPC",
            cidr="10.10.0.0/16"
        )

        db_secret = secretsmanager.Secret(
            scope=self,
            id="templated-secret",
            generate_secret_string=secretsmanager.SecretStringGenerator(
                secret_string_template=json.dumps(
                    {"username": "******"}),
                generate_string_key="password",
                exclude_punctuation=True,
            )
        )

        cluster = rds.ServerlessCluster(
            scope=self,
            id="Cluster",
            engine=rds.DatabaseClusterEngine.AURORA_MYSQL,
            vpc=vpc,
            enable_data_api=True,
            default_database_name ="Racing",
            credentials=rds.Credentials.from_secret(db_secret),
            # removal_policy= core
            scaling=rds.ServerlessScalingOptions(
                # default is to pause after 5 minutes of idle time
                auto_pause=core.Duration.minutes(10),
                # min_capacity=rds.AuroraCapacityUnit.ACU_8,
                # max_capacity=rds.AuroraCapacityUnit.ACU_32
            )
        )
Exemplo n.º 4
0
    def __init__(self,
                 scope: core.Construct,
                 construct_id: str,
                 database_name: str = 'cloud',
                 webapp_min_capacity: int = 1,
                 **kwargs) -> None:
        super().__init__(scope, construct_id, **kwargs)

        # setup a dedicated Virtual Private Cloud (VPC) for this entire stack
        vpc = ec2.Vpc(scope=self, id='vpc')

        # setup an auto scaling serverless Aurora/PostgreSQL database cluster
        database_cluster = rds.ServerlessCluster(
            scope=self,
            id='database',
            vpc=vpc,
            engine=rds.DatabaseClusterEngine.aurora_postgres(
                # HACK: as per AWS console only PostgreSQL 10.7 and 10.12 serverless db engine versions are supported
                version=rds.AuroraPostgresEngineVersion.VER_10_12, ),
            default_database_name=
            database_name,  # auto-create the database with this name
            scaling=rds.ServerlessScalingOptions(
                auto_pause=core.Duration.minutes(
                    10),  # pause the database after 10 minutes of idle time
                min_capacity=rds.AuroraCapacityUnit.ACU_2,
                max_capacity=rds.AuroraCapacityUnit.ACU_16,
            ))

        # webapp, a serverless Fargate service running on an ECS cluster and fronted by an application load balancer
        webapp_service = ecs_patterns.ApplicationLoadBalancedFargateService(
            scope=self,
            id='webapp',
            vpc=vpc,
            cpu=256,  # 0.25 vCPU
            memory_limit_mib=512,  # 0.5 GB RAM
            desired_count=webapp_min_capacity,  # desired Fargate task capacity
            task_image_options={
                'image': ecs.ContainerImage.from_asset(
                    directory='.'
                ),  # build Docker image in-situ, directly from Dockerfile
                'container_port': 8000,
                'environment': {
                    # security
                    'DEBUG':
                    'false',

                    # database
                    'DB_NAME':
                    database_name,
                    'DB_HOST':
                    core.Token.as_string(
                        database_cluster.cluster_endpoint.hostname),
                    'DB_PORT':
                    core.Token.as_string(
                        database_cluster.cluster_endpoint.port),
                },
                'secrets': {
                    # security
                    'SECRET_KEY':
                    ecs.Secret.from_secrets_manager(
                        secretsmanager.Secret(scope=self,
                                              id='DJANGO_SECRET_KEY')),

                    # database
                    'DB_USER':
                    ecs.Secret.from_secrets_manager(database_cluster.secret,
                                                    'username'),
                    'DB_PASS':
                    ecs.Secret.from_secrets_manager(database_cluster.secret,
                                                    'password'),
                },
            },
        )

        # allow webapp service to access the database cluster
        database_cluster.connections.allow_default_port_from(
            webapp_service.service)

        # setup webapp service auto scaling
        webapp_service_auto_scaler = webapp_service.service.auto_scale_task_count(
            min_capacity=webapp_min_capacity,
            max_capacity=30,
        )
        webapp_service_auto_scaler.scale_on_cpu_utilization(
            id='cpu-scaling',
            target_utilization_percent=
            75,  # target CPU utilization across *all* tasks in this service
        )
    def __init__(self, scope: core.Construct, construct_id: str,
                 properties: WordpressStackProperties, **kwargs) -> None:
        super().__init__(scope, construct_id, **kwargs)

        database = rds.ServerlessCluster(
            self,
            "WordpressServerless",
            engine=rds.DatabaseClusterEngine.AURORA_MYSQL,
            default_database_name="WordpressDatabase",
            vpc=properties.vpc,
            scaling=rds.ServerlessScalingOptions(
                auto_pause=core.Duration.seconds(0)),
            deletion_protection=False,
            backup_retention=core.Duration.days(7),
            removal_policy=core.RemovalPolicy.DESTROY,
        )

        file_system = efs.FileSystem(
            self,
            "WebRoot",
            vpc=properties.vpc,
            performance_mode=efs.PerformanceMode.GENERAL_PURPOSE,
            throughput_mode=efs.ThroughputMode.BURSTING,
        )

        # docker context directory
        docker_context_path = os.path.dirname(__file__) + "../../src"

        # upload images to ecr
        nginx_image = ecr_assets.DockerImageAsset(
            self,
            "Nginx",
            directory=docker_context_path,
            file="Docker.nginx",
        )

        wordpress_image = ecr_assets.DockerImageAsset(
            self,
            "Php",
            directory=docker_context_path,
            file="Docker.wordpress",
        )

        cluster = ecs.Cluster(self,
                              'ComputeResourceProvider',
                              vpc=properties.vpc)

        wordpress_volume = ecs.Volume(
            name="WebRoot",
            efs_volume_configuration=ecs.EfsVolumeConfiguration(
                file_system_id=file_system.file_system_id))

        event_task = ecs.FargateTaskDefinition(self,
                                               "WordpressTask",
                                               volumes=[wordpress_volume])

        #
        # webserver
        #
        nginx_container = event_task.add_container(
            "Nginx",
            image=ecs.ContainerImage.from_docker_image_asset(nginx_image))

        nginx_container.add_port_mappings(ecs.PortMapping(container_port=80))

        nginx_container_volume_mount_point = ecs.MountPoint(
            read_only=True,
            container_path="/var/www/html",
            source_volume=wordpress_volume.name)
        nginx_container.add_mount_points(nginx_container_volume_mount_point)

        #
        # application server
        #
        app_container = event_task.add_container(
            "Php",
            environment={
                'WORDPRESS_DB_HOST': database.cluster_endpoint.hostname,
                'WORDPRESS_TABLE_PREFIX': 'wp_'
            },
            secrets={
                'WORDPRESS_DB_USER':
                ecs.Secret.from_secrets_manager(database.secret,
                                                field="username"),
                'WORDPRESS_DB_PASSWORD':
                ecs.Secret.from_secrets_manager(database.secret,
                                                field="password"),
                'WORDPRESS_DB_NAME':
                ecs.Secret.from_secrets_manager(database.secret,
                                                field="dbname"),
            },
            image=ecs.ContainerImage.from_docker_image_asset(wordpress_image))
        app_container.add_port_mappings(ecs.PortMapping(container_port=9000))

        container_volume_mount_point = ecs.MountPoint(
            read_only=False,
            container_path="/var/www/html",
            source_volume=wordpress_volume.name)
        app_container.add_mount_points(container_volume_mount_point)

        #
        # create service
        #
        wordpress_service = ecs.FargateService(
            self,
            "InternalService",
            task_definition=event_task,
            platform_version=ecs.FargatePlatformVersion.VERSION1_4,
            cluster=cluster,
        )

        #
        # scaling
        #
        scaling = wordpress_service.auto_scale_task_count(min_capacity=2,
                                                          max_capacity=50)
        scaling.scale_on_cpu_utilization(
            "CpuScaling",
            target_utilization_percent=85,
            scale_in_cooldown=core.Duration.seconds(120),
            scale_out_cooldown=core.Duration.seconds(30),
        )

        #
        # network acl
        #
        database.connections.allow_default_port_from(wordpress_service,
                                                     "wordpress access to db")
        file_system.connections.allow_default_port_from(wordpress_service)

        #
        # external access
        #
        wordpress_service.connections.allow_from(
            other=properties.load_balancer, port_range=ec2.Port.tcp(80))

        http_listener = properties.load_balancer.add_listener(
            "HttpListener",
            port=80,
        )

        http_listener.add_targets(
            "HttpServiceTarget",
            protocol=elbv2.ApplicationProtocol.HTTP,
            targets=[wordpress_service],
            health_check=elbv2.HealthCheck(healthy_http_codes="200,301,302"))