前言

在上一篇文章中,我們介紹了 AWS 的基礎架構與 IAM 安全概念。本篇將深入探討後端工程師最常接觸的核心服務——運算服務(Compute Services)。

AWS 提供了多種運算服務,從傳統的虛擬機器到無伺服器架構,再到容器編排平台。選擇正確的運算服務,直接影響到應用程式的效能、成本與維護複雜度。

本篇將涵蓋以下重點:

  • EC2 執行個體類型選擇與最佳化
  • Lambda 無伺服器架構的適用場景與限制
  • ECS 與 EKS 的容器化部署策略
  • Fargate 無伺服器容器的實務應用
  • 如何根據需求選擇合適的運算服務

運算服務全景圖

在深入各個服務之前,先來了解 AWS 運算服務的整體架構:

graph TB
    subgraph "AWS 運算服務"
        subgraph "虛擬機器"
            A[EC2]
        end
        
        subgraph "容器服務"
            B[ECS]
            C[EKS]
            D[Fargate]
        end
        
        subgraph "無伺服器"
            E[Lambda]
            F[App Runner]
        end
    end
    
    G[你的應用程式] --> A
    G --> B
    G --> C
    G --> E
    
    B --> D
    C --> D
服務 抽象層級 管理複雜度 適用場景
EC2 最低(虛擬機器) 高 完全控制、特殊需求
ECS 中(容器編排) 中 Docker 容器部署
EKS 中(Kubernetes) 中高 K8s 生態系統
Fargate 高(無伺服器容器) 低 無需管理底層
Lambda 最高(函數) 最低 事件驅動、短時任務

EC2:彈性運算雲端

EC2 基本概念

EC2(Elastic Compute Cloud)是 AWS 最基礎的運算服務,提供可調整大小的虛擬機器。作為後端工程師,理解 EC2 是掌握其他服務的基礎。

EC2 核心組件:

graph LR
    subgraph "EC2 執行個體"
        A[AMI 映像檔] --> B[Instance 執行個體]
        C[Instance Type] --> B
        D[Security Group] --> B
        E[Key Pair] --> B
        B --> F[EBS Volume]
        B --> G[Network Interface]
    end
  • AMI(Amazon Machine Image):作業系統與預裝軟體的模板
  • Instance Type:決定 CPU、記憶體、網路效能
  • Security Group:虛擬防火牆,控制進出流量
  • Key Pair:SSH 登入用的金鑰對
  • EBS Volume:持久化儲存

執行個體類型深度解析

EC2 執行個體類型的命名遵循特定規則:

1
2
3
4
5
m5.2xlarge
│ │ │
│ │ └── 大小(xlarge, 2xlarge, 4xlarge...)
│ └──── 代數(越新越好,效能/價格比更高)
└────── 系列(用途類型)

主要系列與適用場景:

系列 特性 適用場景 範例
M 通用平衡型 Web 伺服器、應用程式伺服器 m6i.xlarge
C 運算優化 高 CPU 需求、批次處理 c6i.2xlarge
R 記憶體優化 資料庫、快取伺服器 r6i.4xlarge
T 可突增效能 開發環境、低流量網站 t3.medium
G/P GPU 運算 機器學習、影像處理 g4dn.xlarge
I 儲存優化 高 IOPS 資料庫 i3.large

T 系列的 CPU Credit 機制

T 系列執行個體使用 CPU Credit 機制,這是成本優化的關鍵:

graph TD
    A[基準效能] --> B{CPU 使用率}
    B -->|低於基準| C[累積 Credit]
    B -->|高於基準| D[消耗 Credit]
    D --> E{Credit 餘額}
    E -->|有餘額| F[維持高效能]
    E -->|無餘額| G[限制為基準效能]

T3 執行個體基準效能:

類型 vCPU 基準效能 每小時累積 Credit
t3.micro 2 10% 12
t3.small 2 20% 24
t3.medium 2 20% 24
t3.large 2 30% 36

實務建議:

  • 開發環境使用 t3.small 或 t3.medium
  • 生產環境如果 CPU 使用率穩定 > 30%,考慮換用 M 或 C 系列
  • 使用 CloudWatch 監控 CPUCreditBalance 指標

EC2 購買選項與成本優化

pie title EC2 成本優化策略
    "On-Demand" : 30
    "Reserved Instances" : 40
    "Spot Instances" : 20
    "Savings Plans" : 10

各種購買選項比較:

選項 折扣幅度 承諾期 適用場景
On-Demand 無折扣 無 開發測試、臨時需求
Reserved 最高 72% 1-3 年 穩定的生產負載
Spot 最高 90% 無(可被中斷) 批次處理、CI/CD
Savings Plans 最高 72% 1-3 年 混合運算需求

Spot Instance 實務應用

Spot Instance 可以大幅降低成本,但需要處理中斷情況:

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
// Go 語言:處理 Spot 中斷通知
package main

import (
"context"
"log"
"net/http"
"time"
)

const spotTerminationURL = "http://169.254.169.254/latest/meta-data/spot/instance-action"

func checkSpotTermination(ctx context.Context) {
ticker := time.NewTicker(5 * time.Second)
defer ticker.Stop()

for {
select {
case <-ctx.Done():
return
case <-ticker.C:
resp, err := http.Get(spotTerminationURL)
if err != nil {
continue
}

if resp.StatusCode == 200 {
log.Println("Spot 中斷通知收到,開始優雅關閉...")
// 執行清理工作:
// 1. 停止接受新請求
// 2. 完成進行中的請求
// 3. 保存狀態到持久化儲存
gracefulShutdown()
}
resp.Body.Close()
}
}
}

Spot 最佳實踐:

  • 使用多種執行個體類型,分散中斷風險
  • 應用程式設計為無狀態(Stateless)
  • 使用 Auto Scaling Group 的混合模式
  • 適合:CI/CD workers、資料處理、測試環境

Lambda:無伺服器運算

Lambda 核心概念

AWS Lambda 是事件驅動的無伺服器運算服務。你只需要提供程式碼,AWS 負責所有基礎設施管理。

sequenceDiagram
    participant Event as 事件來源
    participant Lambda as Lambda Service
    participant Function as 你的函數
    participant Resource as AWS 資源
    
    Event->>Lambda: 觸發事件
    Lambda->>Function: 執行函數
    Function->>Resource: 存取資源(S3/DynamoDB等)
    Resource-->>Function: 回傳結果
    Function-->>Lambda: 執行完成
    Lambda-->>Event: 回傳回應

Lambda 特性:

特性 說明
執行時間限制 最長 15 分鐘
記憶體配置 128 MB - 10,240 MB
暫存空間 /tmp 目錄,最大 10 GB
並發限制 預設 1,000(可申請提高)
計費單位 毫秒級計費

Lambda 適用場景分析

✅ 適合使用 Lambda:

  • API 後端(搭配 API Gateway)
  • 事件處理(S3 上傳觸發、DynamoDB Streams)
  • 定時任務(CloudWatch Events/EventBridge)
  • 資料轉換(ETL 流程)
  • Webhook 處理

❌ 不適合使用 Lambda:

  • 長時間運行的任務(> 15 分鐘)
  • 需要持久連線的服務(WebSocket 伺服器)
  • 高頻率、低延遲要求(冷啟動影響)
  • 需要大量本地儲存的應用

Cold Start 問題與解決方案

Cold Start(冷啟動)是 Lambda 最常被討論的效能問題:

graph LR
    A[請求到達] --> B{執行環境}
    B -->|已存在| C[Warm Start<br/>~1-10ms]
    B -->|需建立| D[Cold Start<br/>~100ms-數秒]
    D --> E[下載程式碼]
    E --> F[初始化執行環境]
    F --> G[執行 Init 程式碼]
    G --> H[執行 Handler]
    C --> H

Cold Start 時間因素:

因素 影響程度 優化建議
程式語言 高 Go/Python 較快,Java/C# 較慢
程式碼大小 中 減少依賴、使用 Lambda Layer
記憶體配置 中 增加記憶體可加速初始化
VPC 配置 高 避免不必要的 VPC,使用 VPC 端點

解決方案:

  1. Provisioned Concurrency(預置並發)
1
2
3
4
5
# serverless.yml 範例
functions:
api:
handler: main.handler
provisionedConcurrency: 5 # 保持 5 個 warm 執行環境
  1. 定時 Warm Up
1
2
3
4
5
6
7
8
9
10
11
12
13
// 使用 CloudWatch Events 定時觸發,保持執行環境溫熱
func handler(ctx context.Context, event json.RawMessage) error {
// 檢查是否為 warm-up 請求
var warmUp struct {
WarmUp bool `json:"warmUp"`
}
if json.Unmarshal(event, &warmUp) == nil && warmUp.WarmUp {
return nil // 直接返回,不執行業務邏輯
}

// 正常業務邏輯
return processRequest(event)
}

Lambda 與 Go 語言實務

Go 是 Lambda 的理想選擇:編譯為單一二進位檔、冷啟動快速、記憶體效率高。

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
package main

import (
"context"
"encoding/json"
"log"

"github.com/aws/aws-lambda-go/events"
"github.com/aws/aws-lambda-go/lambda"
"github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/service/dynamodb"
)

// 全域變數:在 Init 階段初始化,跨請求復用
var dbClient *dynamodb.Client

func init() {
// Init 階段:只在冷啟動時執行一次
cfg, err := config.LoadDefaultConfig(context.Background())
if err != nil {
log.Fatal(err)
}
dbClient = dynamodb.NewFromConfig(cfg)
}

type Request struct {
UserID string `json:"userId"`
}

type Response struct {
Message string `json:"message"`
Status int `json:"status"`
}

func handler(ctx context.Context, request events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {
var req Request
if err := json.Unmarshal([]byte(request.Body), &req); err != nil {
return events.APIGatewayProxyResponse{
StatusCode: 400,
Body: `{"error": "Invalid request body"}`,
}, nil
}

// 使用復用的 DB Client
// ... 業務邏輯

return events.APIGatewayProxyResponse{
StatusCode: 200,
Body: `{"message": "Success"}`,
Headers: map[string]string{
"Content-Type": "application/json",
},
}, nil
}

func main() {
lambda.Start(handler)
}

效能優化重點:

  • init() 函數用於初始化共享資源(DB 連線、HTTP Client)
  • 全域變數在 warm 執行環境中會被復用
  • 避免在 handler 中重複建立連線

ECS:彈性容器服務

ECS 架構概覽

ECS(Elastic Container Service)是 AWS 原生的容器編排服務。相較於 Kubernetes,ECS 更簡單易用,與 AWS 服務整合度更高。

graph TB
    subgraph "ECS 架構"
        A[ECS Cluster] --> B[Service]
        B --> C[Task Definition]
        C --> D[Container Definition]
        
        B --> E[Task 1]
        B --> F[Task 2]
        B --> G[Task N]
        
        subgraph "運行環境"
            H[EC2 Instances]
            I[Fargate]
        end
        
        E --> H
        F --> I
        G --> H
    end

核心概念:

概念 說明 類比
Cluster 容器執行的邏輯群組 Kubernetes Cluster
Service 管理 Task 的長期運行服務 Kubernetes Deployment
Task Definition 容器配置的模板 Kubernetes Pod Spec
Task 運行中的容器實例 Kubernetes Pod
Container Definition 單一容器的配置 Kubernetes Container

Task Definition 詳解

Task Definition 是 ECS 的核心配置,定義了容器如何運行:

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
{
"family": "my-api-service",
"networkMode": "awsvpc",
"requiresCompatibilities": ["FARGATE"],
"cpu": "512",
"memory": "1024",
"executionRoleArn": "arn:aws:iam::123456789012:role/ecsTaskExecutionRole",
"taskRoleArn": "arn:aws:iam::123456789012:role/ecsTaskRole",
"containerDefinitions": [
{
"name": "api",
"image": "123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/my-api:latest",
"essential": true,
"portMappings": [
{
"containerPort": 8080,
"protocol": "tcp"
}
],
"environment": [
{
"name": "ENV",
"value": "production"
}
],
"secrets": [
{
"name": "DB_PASSWORD",
"valueFrom": "arn:aws:secretsmanager:ap-northeast-1:123456789012:secret:db-password"
}
],
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-group": "/ecs/my-api-service",
"awslogs-region": "ap-northeast-1",
"awslogs-stream-prefix": "ecs"
}
},
"healthCheck": {
"command": ["CMD-SHELL", "curl -f http://localhost:8080/health || exit 1"],
"interval": 30,
"timeout": 5,
"retries": 3,
"startPeriod": 60
}
}
]
}

關鍵配置說明:

配置 說明
executionRoleArn ECS Agent 使用,用於拉取映像檔、寫入 Log
taskRoleArn 容器內應用程式使用,存取 AWS 資源
networkMode: awsvpc 每個 Task 有獨立 ENI(建議用於 Fargate)
secrets 從 Secrets Manager 或 Parameter Store 注入
healthCheck 容器健康檢查配置

ECS Service 與負載平衡

graph LR
    A[ALB] --> B[Target Group]
    B --> C[Task 1 - AZ-a]
    B --> D[Task 2 - AZ-b]
    B --> E[Task 3 - AZ-c]
    
    F[ECS Service] -->|管理| C
    F -->|管理| D
    F -->|管理| E
    
    G[Auto Scaling] -->|調整| F

Service 配置重點:

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
{
"serviceName": "my-api-service",
"cluster": "production-cluster",
"taskDefinition": "my-api-service:5",
"desiredCount": 3,
"launchType": "FARGATE",
"networkConfiguration": {
"awsvpcConfiguration": {
"subnets": ["subnet-xxx", "subnet-yyy"],
"securityGroups": ["sg-xxx"],
"assignPublicIp": "DISABLED"
}
},
"loadBalancers": [
{
"targetGroupArn": "arn:aws:elasticloadbalancing:...",
"containerName": "api",
"containerPort": 8080
}
],
"deploymentConfiguration": {
"maximumPercent": 200,
"minimumHealthyPercent": 100
}
}

ECS 部署策略

graph TD
    subgraph "Rolling Update"
        A1[v1] --> A2[v1 + v2]
        A2 --> A3[v2]
    end
    
    subgraph "Blue/Green"
        B1[Blue v1] --> B2[Green v2]
        B2 --> B3[切換流量]
    end

Rolling Update(預設):

  • 逐步替換舊版本 Task
  • minimumHealthyPercent: 100 表示先啟動新版本,再停止舊版本
  • 零停機時間,但需要雙倍資源

Blue/Green Deployment(搭配 CodeDeploy):

  • 完全獨立的兩個環境
  • 可快速回滾
  • 適合需要快速切換的場景

Fargate:無伺服器容器

Fargate 概念

Fargate 是 ECS 和 EKS 的無伺服器運算引擎。使用 Fargate,你不需要管理 EC2 執行個體,專注於容器本身。

graph TB
    subgraph "ECS on EC2"
        A[你管理 EC2]
        B[你管理容量規劃]
        C[你管理 OS 更新]
        D[AWS 管理容器編排]
    end
    
    subgraph "ECS on Fargate"
        E[AWS 管理一切基礎設施]
        F[你只關心容器配置]
    end

EC2 vs Fargate 選擇

考量因素 EC2 Launch Type Fargate
管理複雜度 高(需管理 EC2) 低(完全託管)
成本(持續運行) 較低 較高(約 20-30%)
成本(間歇運行) 較高 較低(按秒計費)
啟動速度 快(EC2 已運行) 較慢(需啟動基礎設施)
GPU 支援 支援 不支援
大型執行個體 支援 限制較多
Windows 容器 支援 支援(部分功能)

選擇建議:

flowchart TD
    A[需要 GPU?] -->|是| B[使用 EC2]
    A -->|否| C[需要超大規格?]
    C -->|是| B
    C -->|否| D[流量模式?]
    D -->|穩定| E[成本敏感?]
    D -->|間歇| F[使用 Fargate]
    E -->|是| B
    E -->|否| F

Fargate 成本優化

Fargate Spot 可以節省高達 70% 的成本:

1
2
3
4
5
6
7
8
9
10
11
12
13
{
"capacityProviderStrategy": [
{
"capacityProvider": "FARGATE",
"weight": 1,
"base": 2
},
{
"capacityProvider": "FARGATE_SPOT",
"weight": 4
}
]
}

這個配置表示:

  • 至少 2 個 Task 使用 FARGATE(確保穩定性)
  • 其餘按 1:4 比例分配,優先使用 FARGATE_SPOT

EKS:Kubernetes 服務

何時選擇 EKS

EKS(Elastic Kubernetes Service)是 AWS 託管的 Kubernetes 服務。選擇 EKS 的理由:

✅ 選擇 EKS:

  • 團隊已有 Kubernetes 經驗
  • 需要跨雲端或混合雲部署
  • 需要 Kubernetes 生態系統工具(Helm、Istio 等)
  • 複雜的微服務架構

✅ 選擇 ECS:

  • 團隊是 Kubernetes 新手
  • 純 AWS 環境
  • 追求簡單易用
  • 小到中型應用

EKS 架構概覽

graph TB
    subgraph "EKS Cluster"
        subgraph "Control Plane (AWS 管理)"
            A[API Server]
            B[etcd]
            C[Controller Manager]
        end
        
        subgraph "Data Plane (你管理或使用 Fargate)"
            D[Node Group - EC2]
            E[Fargate Profile]
        end
        
        A --> D
        A --> E
    end
    
    F[kubectl] --> A
    G[Helm] --> A

EKS 節點選項

選項 說明 適用場景
Managed Node Groups AWS 管理 EC2 節點 大多數生產環境
Self-Managed Nodes 完全自行管理 特殊客製需求
Fargate 無伺服器節點 間歇性工作負載

運算服務選擇決策樹

flowchart TD
    A[開始選擇運算服務] --> B{應用類型?}
    
    B -->|事件驅動/短時任務| C{執行時間 < 15分鐘?}
    C -->|是| D[Lambda]
    C -->|否| E{需要容器?}
    
    B -->|長期運行服務| E
    
    E -->|否| F[EC2]
    E -->|是| G{團隊有 K8s 經驗?}
    
    G -->|是| H{需要 K8s 生態?}
    H -->|是| I[EKS]
    H -->|否| J[ECS]
    
    G -->|否| J
    
    J --> K{需要管理 EC2?}
    K -->|否| L[Fargate]
    K -->|是/成本考量| M[EC2 Launch Type]
    
    I --> N{節點管理?}
    N -->|簡單| O[Managed Node Groups]
    N -->|無伺服器| P[Fargate for EKS]

實務選擇案例

案例一:API 後端服務

  • 穩定流量、需要持久連線
  • 推薦:ECS + Fargate 或 EKS + Managed Nodes

案例二:圖片處理服務

  • S3 上傳觸發、處理時間短
  • 推薦:Lambda(搭配 S3 Trigger)

案例三:批次資料處理

  • 每天定時執行、可中斷
  • 推薦:ECS + Fargate Spot 或 EC2 Spot

案例四:機器學習推論

  • 需要 GPU、低延遲
  • 推薦:EC2(G 或 P 系列)或 EKS + GPU Nodes

本章重點回顧

關鍵要點

  1. EC2

    • 最大彈性,完全控制
    • 注意執行個體類型選擇與成本優化
    • Spot Instance 可大幅降低成本
  2. Lambda

    • 事件驅動、按執行時間計費
    • 注意 Cold Start 與執行時間限制
    • 適合短時任務與事件處理
  3. ECS/Fargate

    • 容器編排的最佳選擇(對於 AWS 原生應用)
    • Fargate 降低管理負擔
    • 與 AWS 服務整合度高
  4. EKS

    • Kubernetes 標準、跨雲端可攜
    • 學習曲線較陡
    • 適合有 K8s 經驗的團隊

下一篇預告

在系列的第三篇文章中,我們將深入探討 AWS 儲存與資料庫服務:

  • S3 物件儲存與最佳實踐
  • RDS 關聯式資料庫選型與優化
  • DynamoDB NoSQL 設計模式
  • ElastiCache 快取策略

系列文章導覽

  • Part 1:入門與核心概念
  • Part 2:運算服務深度解析(本篇)
  • Part 3:儲存與資料庫服務(S3、RDS、DynamoDB)
  • Part 4:網路架構與安全(VPC、ALB、Security Groups)
  • Part 5:訊息佇列與事件驅動(SQS、SNS、EventBridge)
  • Part 6:DevOps 與 CI/CD(CodePipeline、CDK)
  • Part 7:監控與可觀測性(CloudWatch、X-Ray)
  • Part 8:進階架構設計(高可用、災難復原、成本優化)

參考資源