Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Designing Scalable and Cost-Effective Cloud-Native Applications with AWS Core Services

Tech 1

Modern cloud architecture moves beyond basic infrastructure provisioning to leverage specialized services for performance, scalability, and operational efficiency. This article provides practical implementations across three key architectural patterns, detailing the configuration of core AWS services.

Pattern 1: Resilient Monolith with Compute-Storage Separation This pattern applies to monolithic applications where the compute layer can be made stateless by offloading persistent data to a managed service.

Architecture Overview The model involves an Amazon EC2 instance hosting the application logic, which is configured to store all user-generated data in an Amazon S3 bucket. This separation resolves key challenges in traditional monolithic deployments:

  • Data Persistence: Application servers are ephemeral; data stored locally on an EBS volume is lost if the instance terminates. S3 provides 99.999999999% (11 nines) durability and effectively infinite scalability.
  • Compute Flexibility: Decoupling data from logic allows the EC2 instance to be treated as a replaceable component. Instances can be upgraded, restarted, or replaced without risk to user data.

Implementation Steps

  1. Provision the EC2 Instance:

    • Launch an instance using an Ubuntu LTS AMI (e.g., t3.micro).
    • Configure the security group to allow HTTP (port 80) from 0.0.0.0/0 and SSH (port 22) only from a trusted IP range.
    • Allocate and associate an Elastic IP to provide a stable public IP address for the service.
  2. Configure the S3 Backend:

    • Create an S3 bucket with a globally unique name.
    • Ensure Block all public access is enabled. This is a critical security setting.
    • Enable default server-side encryption (SSE-S3) for data at rest.
  3. Establish Secure Access with IAM:

    • Create an IAM user (e.g., app-s3-access) with Programmatic access.
    • Attach the AmazonS3FullAccess managed policy. (Note: For production, follow the principle of least privilege by creating a custom policy scoped to specific bucket operations.)
    • Securely store the generated Access Key ID and Secret Access Key.
  4. Deploy and Connect the Application (NextCloud Example):

    • Connect via SSH to the EC2 instance using its Elastic IP.
    • Install a LAMP/LEMP stack and deploy the NextCloud application.
    • Complete the initial web-based setup for NextCloud.
    • Enable the External storage support app from the NextCloud application marketplace.
    • Navigate to Settings > Administration > External storage. Add a new storage of type Amazon S3.
    • Configure the connection with the bucket name, region, and the IAM user's credentials.
    • Verify the connection. Files uploaded to the linked folder in NextCloud will now be stored as objects in the S3 bucket.

Pattern 2: Serverless Dynamic API with Lambda and API Gateway This pattern abstracts server management, allowing developers to focus solely on business logic executed in response to events.

Request Flow

  1. Client sends an HTTP request to an API Gateway endpoint.
  2. API Gateway authenticates, validates, and transforms the request.
  3. API Gateway invokes a specific Lambda function, passing request details in the event object.
  4. Lambda executes the function code in a managed runtime.
  5. The function's response is returned to API Gateway, which formats and sends the HTTP response back to the client.

Implementation Steps

  1. Create the Lambda Function:

    • Navigate to AWS Lambda and Create function from scratch.
    • Name it (e.g., DynamicResponder) and select a runtime (e.g., Python 3.12).
    • Use the default execution role.
    • Replace the default code with a handler that returns a basic JSON response.
    import json
    
    def lambda_handler(event, context):
        return {
            'statusCode': 200,
            'headers': {'Content-Type': 'application/json'},
            'body': json.dumps({'message': 'API is active'})
        }
    
    • Click Deploy.
  2. Create the API Gateway HTTP API:

    • Navigate to Amazon API Gateway and Create API > HTTP API > Build.
    • Add an integration: Type Lambda, select the DynamicResponder function.
    • Name the API (e.g., DemoAPI).
    • Configure a route: Method GET, Path /greet, Target set to the Lambda integration.
    • Review and create the API. Note the provided Invoke URL.
  3. Add Dynamic Parameter Handling:

    • Update the Lambda function code to read a query string parameter.
    import json
    
    def lambda_handler(event, context):
        # Extract the 'user' query parameter
        username = 'Guest'
        query_params = event.get('queryStringParameters', {})
        if query_params and 'user' in query_params:
            username = query_params['user']
    
        response_message = f"Hello, {username}!"
    
        return {
            'statusCode': 200,
            'headers': {'Content-Type': 'application/json'},
            'body': json.dumps({'greeting': response_message})
        }
    
    • Deploy the updated function.
    • Test the API by accessing the Invoke URL with the path /greet?user=Developer.

Pattern 3: High-Performance Static Site Delivery via Global CDN This architecture delivers static content (HTML, CSS, JS, media) with low latency and high security using S3 and CloudFront.

Architecture Overview User requests are routed to the nearest CloudFront Edge Location. If the content is cached, it's served immediately. On a cache miss, CloudFront fetches the content from the S3 origin, serves it, and caches it for future requests.

Implementation Steps

  1. Prepare the S3 Origin:

    • Create an S3 bucket and upload your static website files (e.g., index.html).
    • In the bucket Properties, enable Static website hosting. Set index.html as the index document.
    • Temporarily apply a bucket policy allowing public read access to objects. This will be locked down in the next step.
    {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Sid": "PublicReadGetObject",
                "Effect": "Allow",
                "Principal": "*",
                "Action": "s3:GetObject",
                "Resource": "arn:aws:s3:::YOUR-BUCKET-NAME/*"
            }
        ]
    }
    
  2. Create and Secure the CloudFront Distribution:

    • Navigate to Amazon CloudFront and Create Distribution.
    • For the origin domain, select your S3 bucket from the list.
    • Under Origin access, select Origin access control settings (recommended). Click Create control setting.
    • A policy will be generated. Copy this policy, go to your S3 bucket's Permissions, and replace the existing public bucket policy with the new OAC policy. This restricts bucket access to CloudFront only.
    • Under Viewer protocol policy, select Redirect HTTP to HTTPS.
    • Click Create distribution. Note the distribution domain name (e.g., d123abc.cloudfront.net).
  3. Configure Custom Domain and HTTPS (Optional):

    • In AWS Certificate Manager (us-east-1 region), Request a public certificate for your custom domain (e.g., www.example.com). Use DNS validation.
    • Add the provided CNAME record to your domain's DNS configuration.
    • Once the certificate is issued, edit your CloudFront distribution.
    • In Settings, set the Custom SSL certificate to the ACM certificate you created.
    • Add your domain (e.g., www.example.com) to the Alternate domain name (CNAME) field.
  4. Update DNS and Validate:

    • In your DNS provider, create a CNAME record pointing your custom domain (e.g., www) to the CloudFront distribution domain name.
    • After propagation, access your site via https://www.example.com. Use browser developer tools to check response headers for X-Cache: Hit from CloudFront to confirm CDN delivery.

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.