Test Projek AWS

Tutorial lengkap konfigurasi infrastruktur cloud AWS untuk membership application dengan VPC, Lambda, S3, DynamoDB, SQS, SNS, dan monitoring EC2

Pengantar

Project ini adalah implementasi infrastruktur cloud AWS yang menggabungkan beberapa layanan AWS untuk membuat sistem order processing yang scalable dan robust. Sistem ini dirancang untuk menangani order dari dua sumber berbeda (S3 upload dan ALB HTTP request) dan memproses data melalui pipeline yang melibatkan Lambda, DynamoDB, dan SNS.

Teknologi yang digunakan:

  • AWS VPC untuk isolated network
  • AWS Lambda untuk serverless processing
  • AWS S3 untuk object storage
  • AWS DynamoDB untuk NoSQL database
  • AWS SQS untuk message queue
  • AWS SNS untuk notification service
  • AWS Application Load Balancer (ALB) untuk routing
  • EC2 untuk monitoring dashboard

AWS Infrastructure Architecture


Arsitektur Sistem

Alur sistem secara umum:

  1. Input: Order masuk dari S3 upload atau HTTP request melalui ALB
  2. Queue: Pesan ditampung di SQS
  3. Processing: Lambda proses membaca dari SQS dan memproses order
  4. Storage: Data disimpan ke DynamoDB dan S3 Archive
  5. Notification: Notifikasi dikirim melalui SNS
  6. Monitoring: Dashboard EC2 menampilkan real-time status order

Konfigurasi VPC

VPC adalah virtual network yang akan menampung semua resource AWS kita.

Langkah-Langkah Membuat VPC:

  1. Buka AWS Console → VPC Dashboard
  2. Pilih VPC only (jangan menggunakan VPC Wizard)
  3. Atur konfigurasi berikut:
    • Name tag: lks-26
    • IPv4 CIDR block: 10.0.0.0/16
    • Klik Create VPC

Mengaktifkan DNS:

  1. Pilih VPC lks-26 yang baru dibuat
  2. Klik ActionsEdit VPC Settings
  3. Aktifkan:
    • Enable DNS Resolution: Yes
    • Enable DNS hostname: Yes
  4. Klik Save

Konfigurasi Subnet

Subnet adalah pembagian IP address dalam VPC. Kita membuat 4 subnet dengan 2 di zona us-east-1 dan 2 di zona us-east-2 untuk high availability.

Detail Subnet:

Subnet NameAvailability ZoneIPv4 CIDR BlockTipe
lks-public-Aus-east-1a10.0.1.0/24Public
lks-private-Aus-east-1a10.0.2.0/24Private
lks-public-Bus-east-2a10.0.3.0/24Public
lks-private-Bus-east-2a10.0.4.0/24Private

Langkah Membuat Subnet:

  1. Buka VPC Dashboard → Subnets
  2. Klik Create Subnet
  3. Pilih VPC ID: lks-26
  4. Isi nama dan CIDR block sesuai tabel di atas
  5. Pilih Availability Zone yang sesuai
  6. Ulangi untuk 4 subnet

Internet Gateway & Route Table

Internet Gateway

Gateway ini memungkinkan komunikasi antara public subnet dengan internet.

  1. Buka Internet Gateways di VPC Console
  2. Klik Create Internet Gateway
  3. Atur:
    • Name tag: LKS-IGW
  4. Klik Create
  5. Pilih IGW yang baru dibuat → Attach to VPC → Pilih lks-26

Route Table - Public

Route table untuk public subnet yang terhubung ke internet.

  1. Buka Route Tables
  2. Klik Create Route Table
  3. Atur:
    • Name: LKS-RT-PUBLIC
    • VPC: lks-26
  4. Tambahkan route:
    • Destination: 0.0.0.0/0
    • Target: LKS-IGW
  5. Associate Subnet: Pilih lks-public-A dan lks-public-B

Route Table - Private

Route table untuk private subnet (tidak terhubung langsung ke internet).

  1. Ulangi membuat route table baru
  2. Atur:
    • Name: LKS-RT-PRIVATE
    • VPC: lks-26
  3. Jangan tambahkan route ke internet (traffic lokal saja)
  4. Associate Subnet: Pilih lks-private-A dan lks-private-B

Security Group

Security Group berperan sebagai firewall untuk mengontrol traffic inbound dan outbound.

1. ALB-SG (Security Group untuk Load Balancer)

Menerima traffic HTTP publik dan meneruskan ke Lambda.

Inbound Rules:

  • Type: HTTP | Port: 80 | Source: 0.0.0.0/0 (allow all)

Outbound Rules:

  • Type: All Traffic | Destination: Lambda-SG

2. Lambda-SG (Security Group untuk Lambda Functions)

Menerima traffic dari ALB dan mengirim ke endpoints.

Inbound Rules:

  • Type: HTTP | Port: 80 | Source: ALB-SG

Outbound Rules:

  • Type: HTTPS | Port: 443 | Destination: Endpoint-SG (untuk SQS)
  • Type: HTTPS | Port: 443 | Destination: 0.0.0.0/0 (untuk S3/DynamoDB)

3. Endpoint-SG (Security Group untuk VPC Endpoints)

Melindungi akses ke SQS endpoint dari Lambda.

Inbound Rules:

  • Type: HTTPS | Port: 443 | Source: Lambda-SG

Outbound Rules:

  • Allow all (default)

4. EC2-SG (Security Group untuk Monitoring & Grader)

Menerima traffic untuk dashboard monitoring dan API grader.

Inbound Rules:

  • Type: HTTP | Port: 80 | Source: 0.0.0.0/0 (dashboard)
  • Type: Custom TCP | Port: 5000 | Source: 0.0.0.0/0 (API grader)
  • Type: SSH | Port: 22 | Source: Your IP (opsional, untuk remote)

Outbound Rules:

  • Allow all (default)

VPC Endpoints

Endpoints memungkinkan akses ke AWS services dari private subnet tanpa melalui internet.

1. Gateway Endpoints (S3 & DynamoDB)

Langkah-langkah membuat Gateway Endpoint:

  1. Buka VPC DashboardEndpoints
  2. Klik Create Endpoint
  3. Cari service: com.amazonaws.us-east-1.s3 (type: Gateway)
  4. Pilih:
    • VPC: lks-26
    • Route Tables: Pilih LKS-RT-PRIVATE
  5. Klik Create Endpoint
  6. Ulangi untuk DynamoDB: com.amazonaws.us-east-1.dynamodb

2. Interface Endpoint (SQS)

Endpoint untuk akses SQS dari Lambda di private subnet.

  1. Buka Create Endpoint
  2. Cari service: com.amazonaws.us-east-1.sqs (type: Interface)
  3. Pilih:
    • VPC: lks-26
    • Subnets: lks-private-A dan lks-private-B
    • Security Groups: Endpoint-SG
  4. PENTING: Aktifkan Enable DNS name → Ini memungkinkan Lambda menemukan SQS via DNS
  5. Klik Create Endpoint

AWS Services Setup

S3 Bucket

Buat 2 bucket S3 untuk menangani order files:

  1. lks-orders (atau custom name) - Upload bucket

    • Gunakan untuk upload file order
    • Enable S3 Event Notification → Kirim event ke SQS
  2. lks-archive (atau custom name) - Archive bucket

    • Gunakan untuk menyimpan archive order yang sudah diproses

Cara setting S3 Event Notification:

  1. Pilih Upload Bucket → PropertiesEvent Notifications
  2. Buat notif event:
    • Event types: All object create events
    • Destination: SQS Queue
    • Queue: OrdersQueue

DynamoDB

Database NoSQL untuk menyimpan data order.

  1. Buka DynamoDBCreate Table
  2. Atur:
    • Table name: Orders
    • Partition Key: OrderId (String)
  3. Klik Create Table

SQS

Message queue untuk komunikasi antara S3/ALB dan Lambda processor.

  1. Buka SQSCreate Queue

  2. Buat queue:

    • OrdersQueue - Untuk menerima order dari S3
  3. Set Queue Policy untuk OrdersQueue (allow S3 to send message):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
{
  "Sid": "AllowS3ToSendMessage",
  "Effect": "Allow",
  "Principal": {
    "Service": "s3.amazonaws.com"
  },
  "Action": "sqs:SendMessage",
  "Resource": "arn:aws:sqs:us-east-1:829830008823:OrdersQueue",
  "Condition": {
    "ArnLike": {
      "aws:SourceArn": "arn:aws:s3:::lks-orders"
    }
  }
}

SNS

Notification service untuk mengirim email ketika order selesai diproses.

  1. Buka SNSCreate Topic
  2. Atur:
    • Topic name: OrderNotification
    • Display name: LKS Order Notification
  3. Klik Create Topic
  4. Masuk ke topic → Create Subscription
  5. Pilih Protocol: Email
  6. Isi Endpoint: Email kamu untuk menerima notifikasi
  7. Confirm subscription dari email yang dikirim SNS

Lambda Functions

Buat 2 Lambda function untuk processing:

Lambda 1: Ingest Function (menerima order dari ALB)

  1. Buka LambdaCreate Function
  2. Atur:
    • Function name: LambdaIngest
    • Runtime: Python 3.12
    • Execution role: LabRole
  3. Klik Create
  4. Copy kode di bawah dan deploy
  5. Add trigger: ALB → Target group: LKS-TG

Lambda 2: Process Function (memproses order dari SQS)

  1. Ulangi membuat Lambda
  2. Atur:
    • Function name: LambdaProses
    • Runtime: Python 3.12
    • Execution role: LabRole
  3. Klik Create
  4. Copy kode di bawah dan deploy
  5. Add trigger: SQS → Queue: OrdersQueue

Load Balancer & Target Group

Target Group

Target group menghubungkan ALB dengan Lambda Ingest.

  1. Buka EC2Target Groups
  2. Klik Create Target Group
  3. Atur:
    • Target type: Lambda Function
    • Target Group name: LKS-TG
    • Lambda function: LambdaIngest
  4. Klik Create

Application Load Balancer

  1. Buka EC2Load Balancers
  2. Klik Create Load BalancerApplication Load Balancer
  3. Atur:
    • Name: lks-alb
    • Scheme: Internet-facing
    • VPC: lks-26
    • Availability Zones: Pilih subnets public (lks-public-A, lks-public-B)
    • Security Groups: ALB-SG
  4. Konfigurasi Listener:
    • Protocol: HTTP | Port: 80
    • Forward to: Target Group LKS-TG
  5. Klik Create
  6. Tunggu hingga provisioning selesai
  7. Copy DNS Name untuk testing

Lambda Functions - Kode

Kode Lambda Ingest

Function ini menerima HTTP request dari ALB dan memasukkan pesan ke SQS OrderQueue.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import json
import boto3
import os

sqs = boto3.client('sqs')
QUEUE_URL = 'https://sqs.us-east-1.amazonaws.com/829830008823/OrderQueue'

def lambda_handler(event, context):
    try:
        # ALB mengirimkan data di dalam 'body'
        body = json.loads(event['body'])
        
        # Kirim pesan ke SQS
        sqs.send_message(
            QueueUrl=QUEUE_URL,
            MessageBody=json.dumps(body)
        )
        
        return {
            "statusCode": 201,
            "body": json.dumps({"message": "Order accepted!"})
        }
    except Exception as e:
        return {
            "statusCode": 500,
            "body": json.dumps({"error": str(e)})
        }

Penjelasan:

  • Function ini menerima HTTP request dari ALB
  • Parse body dari request sebagai JSON
  • Kirim pesan ke OrderQueue di SQS untuk diproses kemudian
  • Return response dengan status 201 (Created) jika berhasil menerima order

Kode Lambda Process

Function ini memproses order dari SQS, menyimpan ke DynamoDB, mengarsipkan ke S3, dan mengirim notifikasi SNS.

PENTING: Ganti variabel berikut dengan informasi actual Anda:

  • ARCHIVE_BUCKET: Nama S3 bucket archive Anda
  • SNS_TOPIC_ARN: ARN dari SNS topic Anda
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
import json
import boto3
import os
from botocore.config import Config

# Konfigurasi
REGION = 'us-east-1'
ARCHIVE_BUCKET = 'lks-storage-nama-kamu' # GANTI SESUAI NAMA BUCKETMU
SNS_TOPIC_ARN = 'arn:aws:sns:us-east-1:829830008823:OrderNotification' # GANTI DENGAN ARN SNS-MU

aws_config = Config(region_name=REGION, connect_timeout=5, retries={'max_attempts': 2})

# Resource Clients
dynamodb = boto3.resource('dynamodb', config=aws_config)
s3 = boto3.client('s3', config=aws_config)
sns = boto3.client('sns', config=aws_config)

table = dynamodb.Table('Orders')

def lambda_handler(event, context):
    try:
        for record in event['Records']:
            if 'body' not in record:
                continue
                
            body = json.loads(record['body'])
            
            # --- LOGIKA HYBRID (S3 & ALB) ---
            # 1. Cek apakah ini pesan dari S3 Event
            if 'Records' in body and 's3' in body['Records'][0]:
                # Ambil nama file sebagai Order ID
                file_name = body['Records'][0]['s3']['object']['key']
                order_id = file_name
                item_name = f"File: {file_name}"
                source_type = "S3_BUCKET"
                print(f"📦 Processing S3 Event: {file_name}")
            else:
                # 2. Jika bukan S3, anggap dari ALB/Ingest
                order_id = body.get('orderId', f"AUTO-{record['messageId'][:8]}")
                item_name = body.get('item', 'N/A')
                source_type = 'ALB_INGEST'
                print(f"🌐 Processing ALB Request: {order_id}")

            # 2. Simpan ke DynamoDB (Task 4)
            table.put_item(Item={
                'orderId': order_id,
                'item': item_name,
                'status': 'PROCESSED',
                'source': source_type
            })
            
            # 3. Arsipkan ke S3 sebagai .json (Task 4/Diagram)
            # Menggunakan ARCHIVE_BUCKET yang sudah kamu definisikan di atas
            file_key = f"archive/{order_id}.json"
            s3.put_object(
                Bucket=ARCHIVE_BUCKET,
                Key=file_key,
                Body=json.dumps(body),
                ContentType='application/json'
            )
            
            # 4. Kirim Notifikasi ke SNS (Task 5)
            message = f"Order {order_id} from {source_type} has been processed."
            sns.publish(
                TopicArn=SNS_TOPIC_ARN,
                Message=message,
                Subject="Order Notification"
            )
            
            print(f"✅ Success: {order_id} (DDB, S3, & SNS Done)")
            
        return {'status': 'success'}
    except Exception as e:
        print(f"❌ Error: {str(e)}")
        raise e

Penjelasan:

  • Membaca batch message dari SQS OrdersQueue
  • Mengidentifikasi apakah order berasal dari S3 atau ALB berdasarkan struktur message
  • Mengekstrak Order ID dan Item name
  • Menyimpan order ke tabel DynamoDB Orders dengan status PROCESSED
  • Mengarsipkan original message ke S3 Archive bucket dalam folder archive/
  • Mengirim notifikasi ke SNS Topic untuk subscriber (email)
  • Handle error dengan logging detail

EC2 Monitoring

Buat instansi EC2 untuk menampilkan real-time monitoring dashboard dan API grader.

Persiapan EC2

  1. Buka AWS ConsoleEC2
  2. Klik InstancesLaunch Instance
  3. Pilih konfigurasi:
    • AMI: Amazon Linux 2 atau Fedora (yang support dnf package manager)
    • Instance Type: t3.micro atau t2.micro
    • VPC: lks-26
    • Subnet: Public subnet (lks-public-A atau lks-public-B)
    • Security Group: EC2-SG
    • Storage: Default (8GB)
  4. Klik Launch
  5. Download private key (.pem file) untuk SSH access

Instalasi Dependencies di EC2

Setelah EC2 running, SSH ke instance dan jalankan commands berikut:

1
2
3
4
5
6
7
8
# Update sistem packages
sudo dnf update -y

# Install Python pip
sudo dnf install pip -y

# Install Flask dan boto3
sudo pip install flask boto3

Deploy Flask Monitoring App

  1. Buat file app.py pada EC2 instance
  2. Copy kode di bawah ke file tersebut
  3. Jalankan dengan sudo (karena port 80 memerlukan elevated privileges):
1
2
3
4
5
# Memberikan permission executable
sudo chmod +x app.py

# Jalankan aplikasi
sudo python3 app.py

Catatan Penting:

  • Dashboard monitoring akan berjalan pada port 80 (HTTP)
  • API Grader akan berjalan pada port 5000
  • Dashboard auto-refresh setiap 5 detik
  • Gunakan sudo karena port 80 memerlukan root privileges

Kode Flask Monitoring App

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
from flask import Flask, jsonify, render_template_string
import boto3
from threading import Thread

app = Flask(__name__)
dynamodb = boto3.resource('dynamodb', region_name='us-east-1')
table = dynamodb.Table('Orders')

# HTML Template untuk Dashboard
HTML_TEMPLATE = """
<!DOCTYPE html>
<html>
<head>
    <title>LKS KENDAL 2026 - MONITORING</title>
    <meta http-equiv="refresh" content="5">
    <style>
        body { font-family: Arial; margin: 40px; background: #f4f4f4; }
        table { width: 100%; border-collapse: collapse; background: white; }
        th, td { padding: 12px; border: 1px solid #ddd; text-align: left; }
        th { background: #232f3e; color: white; }
        .status { color: green; font-weight: bold; }
    </style>
</head>
<body>
    <h2>Order Monitoring Dashboard</h2>
    <table>
        <tr>
            <th>Order ID</th>
            <th>Item</th>
            <th>Source</th>
            <th>Status</th>
        </tr>
        {% for item in orders %}
        <tr>
            <td>{{ item.orderId }}</td>
            <td>{{ item.item }}</td>
            <td>{{ item.source }}</td>
            <td class="status">{{ item.status }}</td>
        </tr>
        {% endfor %}
    </table>
</body>
</html>
"""

@app.route('/')
def dashboard():
    """Menampilkan dashboard HTML dengan daftar order real-time"""
    try:
        response = table.scan()
        return render_template_string(HTML_TEMPLATE, orders=response.get('Items', []))
    except Exception as e:
        return f"Error connecting to DynamoDB: {str(e)}"

@app.route('/api/orders')
def grader_api():
    """API endpoint untuk grader - return JSON format"""
    try:
        response = table.scan()
        return jsonify(response.get('Items', []))
    except Exception as e:
        return jsonify({"error": str(e)}), 500

def run_api():
    """Menjalankan API server di port 5000 dalam thread terpisah"""
    # use_reloader=False wajib agar tidak terjadi double-run
    app.run(host='0.0.0.0', port=5000, debug=False, use_reloader=False)

if __name__ == '__main__':
    # 1. Jalankan Thread untuk API di Port 5000
    api_thread = Thread(target=run_api)
    api_thread.daemon = True  # Thread akan mati saat aplikasi utama mati
    api_thread.start()
    
    # 2. Jalankan Dashboard HTML di Port 80 (Thread Utama)
    # Gunakan: sudo python3 app.py
    app.run(host='0.0.0.0', port=80, debug=False, use_reloader=False)

Penjelasan:

  • dashboard(): Route utama yang menampilkan HTML dashboard, auto-refresh setiap 5 detik
  • grader_api(): API endpoint untuk grader/penilaian, return data dalam format JSON
  • run_api(): Menjalankan Flask server untuk API di port 5000 dalam thread terpisah
  • Dashboard port 80 berjalan di thread utama (memerlukan sudo)
  • Aplikasi membaca real-time data dari DynamoDB Orders table

Testing & Troubleshooting

Testing Flow

  1. Test Upload ke S3:

    1
    2
    
    # Upload file ke S3 lks-orders bucket
    aws s3 cp test.txt s3://lks-orders/test.txt
    
    • File akan trigger S3 event notification
    • Event dikirim ke SQS OrdersQueue
    • Lambda process akan membaca dan memproses
  2. Test via ALB HTTP:

    1
    2
    3
    
    curl -X POST http://<ALB-DNS-NAME> \
      -H "Content-Type: application/json" \
      -d '{"orderId": "ORDER-001", "item": "Sample Item"}'
    
    • Request diterima ALB → Lambda Ingest
    • Lambda Ingest memasukkan ke SQS OrderQueue
    • Lambda process membaca dan memproses
  3. Check Monitoring Dashboard:

    • Buka browser ke http://<EC2-PUBLIC-IP>
    • Lihat real-time order status
    • Atau akses API via http://<EC2-PUBLIC-IP>:5000/api/orders
Dibangun dengan Hugo
Tema Stack dirancang oleh Jimmy