Bỏ qua để đến nội dung

Classic Solutions Architecture – các case study kinh điển

Đây là chương ghép mọi thứ lại với nhau. Ở các chương trước bạn học từng dịch vụ riêng lẻ: EC2, EBS, EFS, ELB, ASG, RDS, ElastiCache, Route 53. Chương này cho thấy chúng phối hợp với nhau như thế nào trong một hệ thống thật, và quan trọng hơn là cho thấy quá trình suy nghĩ của một Solutions Architect: bắt đầu từ kiến trúc đơn giản nhất, gặp vấn đề, rồi từng bước sửa.

Đây là chương bạn cần thật sự thoải mái với nó, vì đề thi SAA-C03 chủ yếu là các câu hỏi tình huống dạng “kiến trúc này có vấn đề gì, sửa thế nào”.

Ba case study sẽ đi qua:

  • WhatIsTheTime.com — web app stateless.
  • MyClothes.com — web app stateful (có giỏ hàng).
  • MyWordPress.com — web app stateful có upload file.

Sau đó là hai mục khép lại chương: khởi tạo ứng dụng thật nhanhElastic Beanstalk.

WhatIsTheTime.com là website cho người ta biết bây giờ là mấy giờ. Yêu cầu:

  • Không cần database.
  • Muốn bắt đầu nhỏchấp nhận được downtime ở giai đoạn đầu.
  • Về sau muốn scale được cả dọc và ngang, không downtime.

Hãy xem hành trình của một Solutions Architect với ứng dụng này.

Một Public EC2 duy nhất, gắn Elastic IP Address. User hỏi “What time is it?”, máy trả “5:30 pm!”. Đơn giản, chạy được, nhưng chỉ một máy.

Tải tăng, ta nâng instance lên loại lớn hơn (ví dụ lên M5). Vẫn là một Public EC2 với Elastic IP. Vấn đề rõ ràng: có downtime trong lúc nâng cấp lên M5 — vì phải stop máy để đổi instance type.

Thay vì một máy to, ta dùng nhiều EC2 instance. Ở bước này các instance là public EC2 instance, không có Elastic IP, và người dùng tìm thấy chúng qua một DNS Query cho api.whatisthetime.com trả về các A Record với TTL 1 giờ.

Vấn đề xuất hiện ngay: khi một instance biến mất (INSTANCE IS GONE!) — bị terminate hoặc chết — thì A record vẫn còn trong cache của client suốt 1 giờ TTL, và người dùng vẫn cố kết nối tới một máy đã không còn. Việc thêm/bớt instance bằng cách sửa DNS record thủ công là một kiến trúc tồi.

Ta chuyển các EC2 vào private và đặt một ELB kèm Health Checks ở phía trước. DNS Query cho api.whatisthetime.com giờ trỏ tới một Alias Record của load balancer.

  • Health check giúp ELB tự loại instance chết ra khỏi vòng phục vụ — client không còn bị dính IP của máy đã chết.
  • Security group rules được thắt lại (Restricted): EC2 chỉ nhận traffic từ load balancer.

Ta bọc các EC2 private vào một Auto Scaling group phía sau ELB + Health Checks. Giờ việc thêm/bớt máy theo tải là tự động, và instance mới tự đăng ký vào load balancer.

Cuối cùng, ta mở rộng ra nhiều Availability Zone: ASG trải trên Availability zone 1 đến 3, và ELB + Health Checks + Multi AZ. Đến đây hệ thống sống sót được khi mất một AZ.

Bước 7 – Reserve capacity để tiết kiệm

Phần tiêu đề “Bước 7 – Reserve capacity để tiết kiệm”

Vì ta luôn cần tối thiểu 2 AZ, nghĩa là luôn có một lượng instance chạy 24/7. Phần minimum capacity đó nên được mua dưới dạng reserved instancestiết kiệm chi phí, trong khi phần scale thêm vẫn dùng On-Demand.

  • Public vs Private IP và EC2 instance.
  • Elastic IP vs Route 53 vs Load Balancers.
  • Route 53 TTL, A record và Alias Record.
  • Bảo trì EC2 instance thủ công vs Auto Scaling Group.
  • Multi AZ để sống sót qua thảm họa.
  • ELB Health Checks.
  • Security Group Rules.
  • Reservation of capacity để tiết kiệm chi phí khi có thể.

MyClothes.com cho người ta mua quần áo online. Điểm khác biệt so với case study trước:

  • Có một giỏ hàng (shopping cart).
  • Website có hàng trăm người dùng cùng lúc.
  • Cần scale, giữ được horizontal scalability và giữ ứng dụng web stateless càng nhiều càng tốt.
  • Người dùng không được mất giỏ hàng.
  • Người dùng cần có thông tin cá nhân (địa chỉ…) lưu trong database.

Điểm khó ở đây chính là chữ stateful: giỏ hàng là một trạng thái, mà nếu request tiếp theo của người dùng rơi vào một EC2 khác thì máy đó không biết gì về giỏ hàng.

Bắt đầu từ kiến trúc đã học: một Auto Scaling group trải trên Availability zone 1 đến 3 phía sau load balancer.

Cách đơn giản nhất: bật ELB Stickiness, để cùng một người dùng luôn được đưa về đúng một EC2 instance — máy đó giữ giỏ hàng trong bộ nhớ của nó. Hoạt động được, nhưng nếu instance đó chết thì giỏ hàng mất, và tải bị lệch.

Cách thứ hai: gửi nội dung giỏ hàng trong Web Cookies. Ứng dụng trở thành stateless thật — bất kỳ EC2 nào cũng phục vụ được. Nhưng phải trả giá:

  • HTTP request nặng hơn (vì cookie đi kèm mọi request).
  • Rủi ro bảo mậtcookie có thể bị sửa đổi.
  • Cookie phải được validate ở phía server.
  • Cookie phải nhỏ hơn 4 KB.

Cách thứ ba, và là cách tốt nhất: chỉ gửi session_id trong Web Cookies, còn dữ liệu session được lưu / lấy từ ElastiCache. Amazon DynamoDB là một lựa chọn thay thế cho ElastiCache ở vai trò này.

Ứng dụng vẫn stateless, cookie vẫn nhỏ, và dữ liệu giỏ hàng nằm ở một chỗ mà mọi EC2 đều đọc được.

Bước 5 – Lưu dữ liệu người dùng vào database

Phần tiêu đề “Bước 5 – Lưu dữ liệu người dùng vào database”

Session là dữ liệu tạm; thông tin người dùng (địa chỉ, tên…) là dữ liệu lâu dài, nên nó được lưu / lấy từ Amazon RDS.

Có hai cách để scale reads, và cả hai đều nằm trong slide:

  • RDS Read Replicas: một RDS Master nhận writes, replication sang các RDS Read Replicas phục vụ reads.
  • Lazy Loading qua ElastiCache (phương án thay thế): ứng dụng đọc từ cache; nếu hit thì xong, nếu miss thì đọc/ghi (read/write) vào RDS rồi nạp lại vào cache.

Bước 7 – Multi AZ để sống sót qua thảm họa

Phần tiêu đề “Bước 7 – Multi AZ để sống sót qua thảm họa”

Không chỉ tầng EC2 cần Multi AZ — ElastiCache Multi AZRDS Multi AZ cũng vậy. Đến đây cả ba tầng đều chịu được việc mất một AZ.

Kiến trúc bảo mật kinh điển là các security group tham chiếu lẫn nhau, mỗi tầng chỉ mở cho tầng ngay trước nó:

Tầng Rule
Load Balancer Mở HTTP / HTTPS tới 0.0.0.0/0 (toàn Internet)
EC2 Chỉ nhận traffic từ security group của Load Balancer
RDS Chỉ nhận traffic từ security group của EC2
ElastiCache Chỉ nhận traffic từ security group của EC2

Đây chính là kiến trúc 3-tier cho web application:

  • ELB sticky sessions.
  • Web client lưu cookie để làm ứng dụng stateless.
  • ElastiCache: để lưu session (phương án thay thế: DynamoDB), và để cache dữ liệu từ RDS; có Multi AZ.
  • RDS: để lưu dữ liệu người dùng, read replica để scale reads, Multi AZ cho disaster recovery.
  • Bảo mật chặt với các security group tham chiếu lẫn nhau.

Lần này ta muốn dựng một website WordPress có khả năng scale hoàn toàn. Yêu cầu:

  • Website phải truy cập và hiển thị đúng các ảnh được upload.
  • Dữ liệu người dùng và nội dung blog được lưu trong một database MySQL.
  • Bắt đầu với RDS Multi AZ phía sau một Auto Scaling group trải trên 3 AZ.
  • Sau đó scale bằng Aurora: Aurora MySQL với Multi AZ và Read Replicas — vì Aurora cho bạn Multi-AZ và read replica một cách dễ dàng.

Nếu lưu ảnh upload vào một Amazon EBS Volume, mọi thứ ổn khi bạn chỉ có một instance trong một Availability zone: user gửi ảnh, ảnh nằm trên EBS volume của máy đó.

Nhưng khi mở rộng sang Availability zone 2 với một EBS Volume thứ hai, vấn đề lộ ra: ảnh gửi vào máy ở AZ 1 chỉ nằm trên EBS volume của AZ 1. Người dùng sau đó rơi vào máy ở AZ 2 sẽ không thấy ảnh đó — vì EBS volume không chia sẻ được giữa các instance.

Giải pháp là EFS: một hệ thống file chia sẻ qua mạng. Mỗi AZ có một ENI (Elastic Network Interface) trỏ tới EFS, và mọi instance ở Availability zone 1 và 2 đều đọc/ghi cùng một nơi. Ảnh gửi lên từ bất kỳ máy nào cũng hiển thị được từ mọi máy.

  • Aurora Database để có Multi-AZ và Read Replica dễ dàng.
  • Lưu dữ liệu trong EBS (ứng dụng một instance) so với lưu dữ liệu trong EFS (ứng dụng phân tán).

Khi launch một stack đầy đủ (EC2, EBS, RDS), có rất nhiều việc mất thời gian:

  • Cài đặt ứng dụng.
  • Nạp dữ liệu ban đầu (hoặc dữ liệu phục hồi).
  • Cấu hình mọi thứ.
  • Khởi động ứng dụng.

Ta có thể tận dụng cloud để tăng tốc việc này:

Thành phần Cách làm nhanh
EC2 Instances Dùng Golden AMI: cài sẵn ứng dụng, dependency của OS… trước, rồi launch EC2 từ Golden AMI đó
EC2 Instances Bootstrap bằng User Data: dành cho cấu hình động, dùng script User Data
EC2 Instances Hybrid: trộn Golden AMI và User Data — đây chính là cách Elastic Beanstalk làm
RDS Databases Restore từ một snapshot: database sẽ có sẵn schema và dữ liệu
EBS Volumes Restore từ một snapshot: đĩa đã được format sẵn và có dữ liệu

Đây là hình mẫu bạn sẽ gặp lại rất nhiều lần, gồm ba subnet xếp theo tầng:

Tầng Nằm ở Thành phần
Tầng 1 PUBLIC SUBNET Route 53ELB — điểm vào từ Internet
Tầng 2 PRIVATE SUBNET Auto Scaling group với EC2 trải trên Availability zone 1 đến 3
Tầng 3 DATA SUBNET ElastiCache (lưu / lấy dữ liệu session + dữ liệu đã cache) và Amazon RDS (đọc / ghi dữ liệu), cả hai Multi AZ

Đây chính là kiến trúc mà hai case study MyClothes.com và MyWordPress.com đã dần dần dẫn tới.

Trước khi nói Beanstalk là gì, hãy nhìn vào những thứ khiến developer mệt mỏi:

  • Quản lý hạ tầng.
  • Deploy code.
  • Cấu hình toàn bộ database, load balancer…
  • Lo chuyện scaling.
  • Trong khi phần lớn web app đều có cùng một kiến trúc (ALB + ASG).
  • Cái mà developer muốn chỉ là code của họ được chạy! Và tốt nhất là chạy nhất quán trên nhiều ứng dụng và nhiều môi trường khác nhau.

Elastic Beanstalkgóc nhìn hướng developer về việc deploy ứng dụng trên AWS.

  • dùng chính các thành phần mà ta đã học: EC2, ASG, ELB, RDS…
  • Là một managed service:
    • Tự động xử lý việc cấp phát capacity, load balancing, scaling, giám sát health ứng dụng, cấu hình instance…
    • Chỉ code ứng dụng là trách nhiệm của developer.
  • Bạn vẫn có toàn quyền kiểm soát cấu hình.
  • Beanstalk miễn phí, bạn chỉ trả tiền cho các instance bên dưới.
  • Application: một tập hợp các thành phần Elastic Beanstalk (environment, version, configuration…).
  • Application Version: một phiên bản (iteration) của code ứng dụng.
  • Environment:
    • Là tập hợp các AWS resource đang chạy một application version (chỉ một version tại một thời điểm).
    • Có hai Tier: Web Server Environment TierWorker Environment Tier.
    • Bạn có thể tạo nhiều environment (dev, test, prod…).

Vòng đời sử dụng là: Create ApplicationUpload VersionLaunch EnvironmentManage Environment, và từ bước quản lý bạn có thể update version hoặc deploy new version.

  • Go
  • Java SE
  • Java with Tomcat
  • .NET Core on Linux
  • .NET on Windows Server
  • Node.js
  • PHP
  • Python
  • Ruby
  • Packer Builder
  • Single Container Docker
  • Multi-container Docker
  • Preconfigured Docker
Web Environment Worker Environment
Hình dạng ELB + Auto Scaling group với các EC2 Instance (Web Server), có Security Group, trải trên Availability Zone 1 và 2 Auto Scaling group với các EC2 Instance (Worker) trên Availability Zone 1 và 2, kéo (pull) message từ một SQS Queue
URL myapp.us-east-1.elasticbeanstalk.com
Cách scale Theo traffic web Scale theo số lượng SQS message

Một chi tiết đáng nhớ: bạn có thể đẩy message vào SQS queue từ một Web Server Tier khác — đó chính là cách ghép hai tier lại thành một hệ thống xử lý bất đồng bộ.

Mode Hình dạng Dùng cho
Single Instance Một EC2 Instance với Elastic IP và một RDS Master, trong Availability Zone 1 Rất tốt cho dev
High Availability with Load Balancer ALB + Auto Scaling Group với EC2 ở Availability Zone 1 và 2, cùng RDS Master + RDS Standby Rất tốt cho prod
Chủ đề Cần nhớ
Hành trình stateless app 1 EC2 + Elastic IP → scale dọc (có downtime) → nhiều EC2 + A record (TTL làm client dính máy đã chết) → ELB + Health Check + Alias recordASGMulti AZreserve minimum capacity
Elastic IP vs ELB Quản lý IP bằng DNS record thủ công là kiến trúc tồi; dùng ELB với Alias Record
Giữ session ELB Stickiness (đơn giản, dễ lệch tải) · Cookie (stateless nhưng request nặng, rủi ro bảo mật, < 4 KB, phải validate) · session_id + ElastiCache (tốt nhất; thay thế: DynamoDB)
Scale reads RDS Read Replicas hoặc ElastiCache Lazy Loading
Multi AZ Cần ở cả ba tầng: ASG, ElastiCache, RDS
Security Group 3-tier LB mở 0.0.0.0/0 → EC2 chỉ nhận từ SG của LB → RDS và ElastiCache chỉ nhận từ SG của EC2
EBS vs EFS EBS = ứng dụng một instance, volume không chia sẻ giữa AZ · EFS = ứng dụng phân tán, nhiều AZ dùng chung file system qua ENI
Aurora trong WordPress Cho Multi-AZ và Read Replica một cách dễ dàng
Khởi tạo nhanh Golden AMI · User Data bootstrap · Hybrid (Beanstalk) · RDS restore từ snapshot · EBS restore từ snapshot
Web App 3-tier PUBLIC SUBNET (Route 53 + ELB) → PRIVATE SUBNET (ASG, 3 AZ) → DATA SUBNET (ElastiCache + RDS)
Elastic Beanstalk Managed, dùng EC2/ASG/ELB/RDS bên dưới; chỉ code là việc của developer; miễn phí, chỉ trả tiền instance
Thành phần Beanstalk ApplicationApplication VersionEnvironment (một version tại một thời điểm, nhiều env: dev/test/prod)
Beanstalk tier Web Server Tier (ELB + ASG) · Worker Tier (ASG pull từ SQS, scale theo số message)
Deployment mode Single Instance cho dev · High Availability with Load Balancer cho prod