前言:從本地開發到雲端生產環境
本文將深入解析一個全端專案在 AWS 上的完整基礎設施架構,展示如何透過 Kubernetes (EKS) 實現高可用性、可擴展性和成本效益的生產環境。這個平台提供線上課程、預約服務、會員管理和金流整合等功能。
本文涵蓋內容:
- 完整的 AWS EKS 叢集架構
- Strapi CMS 和 Vue.js 前端的容器化部署
- Jenkins CI/CD 自動化部署流程
- Ingress NGINX 負載均衡和 SSL 憑證管理
- 與 AWS RDS、S3、ECR 的整合
- 第三方服務整合 (Firebase FCM、台灣金流)
- 監控與日誌管理
架構概覽
整體架構圖
核心技術棧
基礎設施層:
- AWS EKS 1.32.9 (Kubernetes 託管服務)
- AWS EC2 (ARM64 架構 - t4g.medium)
- AWS RDS PostgreSQL (託管資料庫)
- AWS S3 (物件儲存)
- AWS ECR (容器映像倉儲)
- AWS ELB (負載均衡器)
CI/CD 層:
- Jenkins (Mac mini 本地部署)
- Docker (容器建置)
- kubectl (Kubernetes 部署工具)
應用層:
- Strapi v5.15.1 (Headless CMS)
- Vue.js 3 (前端 SPA)
- NGINX Ingress Controller (反向代理)
- Cert-Manager (SSL 憑證自動化)
監控與日誌:
- Amazon CloudWatch
- Fluent Bit (日誌收集)
- Metrics Server (資源監控)
EKS 叢集架構
叢集基本資訊
Cluster Name: mycom-taipei-cluster
Region: ap-southeast-1 (Asia Pacific - Hong Kong)
Kubernetes Version: v1.32.9-eks-113cf36
Cluster Endpoint: 151FF270201594366F4072D7F2D31E98.sk1.ap-southeast-1.eks.amazonaws.com
Account ID: AWS_Account_ID
設計考量:
- 選擇 ap-southeast-1(新加坡)區域,作為亞太主要節點之一,提供穩定服務,對台灣用戶延遲可接受
- 使用最新的 EKS 版本確保安全性和功能更新
- 單一叢集設計,透過 namespace 隔離不同功能
節點配置
# 節點詳細資訊
NAME: ip-192-168-250-55.ap-southeast-1.compute.internal
INSTANCE TYPE: t4g.medium (ARM64)
CPU: 2 核心
RAM: 4GB
OS: Amazon Linux 2
Kernel: 5.10.244-240.965.amzn2.aarch64
Container Runtime: containerd 1.7.27
資源分配:
| 資源 | 總容量 | 可分配 | 已使用 | 使用率 |
|---|---|---|---|---|
| CPU | 2000m | 1930m | 51m | 2% |
| Memory | 3.9Gi | 3.3Gi | 1.5Gi | 47% |
| Pods | 17 | 17 | 14 | 82% |
節點選型分析:
✅ 優勢:
- ARM64 架構 (Graviton) 提供更好的性價比
- t4g.medium 適合中小型應用,成本效益高
- 記憶體使用率 47% 留有充足緩衝空間
⚠️ 注意事項:
- Pod 數量接近上限 (14/17),需要監控
- 單節點設計沒有高可用性,建議未來擴展為 2-3 節點
- CPU 使用率極低 (2%),可能存在資源浪費
命名空間架構與資源分布
命名空間設計
kubectl get namespaces
| Namespace | 用途 | Pod 數量 | 關鍵服務 |
|---|---|---|---|
| default | 應用程式主要部署 | 3 | Strapi, Vue.js |
| ingress-nginx | 流量入口管理 | 1 | Ingress Controller |
| cert-manager | SSL 憑證管理 | 3 | Cert Manager |
| kube-system | Kubernetes 核心服務 | 4 | CoreDNS, Metrics |
| amazon-cloudwatch | 日誌和監控 | 1 | Fluent Bit |
| kube-node-lease | 節點心跳管理 | 0 | (系統用) |
| kube-public | 公開資訊 | 0 | (系統用) |
設計模式:
這是一個典型的單體叢集多命名空間設計,透過 namespace 實現邏輯隔離:
- 應用層 (default)
- 流量層 (ingress-nginx)
- 安全層 (cert-manager)
- 系統層 (kube-system)
- 監控層 (amazon-cloudwatch)
Jenkins CI/CD 自動化部署
Jenkins 環境配置
部署位置: Mac mini (本地機房)
Jenkins 版本: LTS
用途: 自動化建置和部署應用程式
安裝的外掛程式:
- Docker Pipeline
- Kubernetes CLI
- AWS Steps (ECR 推送)
- Git
- Pipeline
CI/CD 流程架構
Jenkins Pipeline 建置流程說明
Strapi 後端部署流程:
- Checkout - 從 Git Repository 拉取最新程式碼
- Get Version - 從 Git tag 取得版本號(格式:prod-1.117)
- Build Docker Image - 建置 Docker 映像檔並標記版本
- Push to ECR - 登入 AWS ECR 並推送映像檔
- Deploy to EKS - 使用 kubectl 更新 Kubernetes Deployment
- Verify Deployment - 檢查 Pod 狀態和健康檢查端點
- Post Actions - 成功時通知團隊,失敗時自動回滾
Vue.js 前端部署流程:
- Checkout - 從 Git Repository 拉取最新程式碼
- Get Version - 從 Git tag 取得版本號
- Build Application - 執行
npm install和npm run build_prod - Build Docker Image - 將打包後的靜態檔案建置成 Docker 映像檔
- Push to ECR - 推送映像檔到 AWS ECR
- Deploy to EKS - 更新 Kubernetes Deployment
- Post Actions - 成功/失敗通知與自動回滾機制
環境變數配置:
| 變數名稱 | 說明 |
|---|---|
| AWS_REGION | AWS 區域 (ap-southeast-1) |
| ECR_REGISTRY | ECR 倉儲位址 |
| IMAGE_NAME | Docker 映像檔名稱 |
| K8S_NAMESPACE | Kubernetes 命名空間 |
| K8S_DEPLOYMENT | Deployment 名稱 |
版本管理策略
Git Tag 驅動部署:
# 開發人員建立新版本
git tag -a prod-1.117 -m "Release version 1.117"
git push origin prod-1.117
# Jenkins 自動觸發 Pipeline
# Pipeline 從 tag 擷取版本號 (1.117)
# 建置映像檔: mycom-strapi:1.117
# 部署到 EKS
版本號規則:
- 格式:
prod-主版本.次版本 - 範例:
prod-1.117,prod-1.118 - 每次部署遞增次版本號
映像檔標籤策略:
# ECR 映像檔標籤
AWS_Account_ID.dkr.ecr.ap-southeast-1.amazonaws.com/mycom-strapi:1.117 # 版本標籤
AWS_Account_ID.dkr.ecr.ap-southeast-1.amazonaws.com/mycom-strapi:latest # 最新標籤
Jenkins 與 AWS 整合
IAM 權限設定:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ecr:GetAuthorizationToken",
"ecr:BatchCheckLayerAvailability",
"ecr:GetDownloadUrlForLayer",
"ecr:PutImage",
"ecr:InitiateLayerUpload",
"ecr:UploadLayerPart",
"ecr:CompleteLayerUpload"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"eks:DescribeCluster"
],
"Resource": "arn:aws:eks:ap-southeast-1:AWS_Account_ID:cluster/mycom-taipei-cluster"
}
]
}
Jenkins Credentials 設定:
AWS Credentials:
- Type: AWS Credentials
- ID: aws-credentials
- Access Key ID: (存放在 Jenkins)
- Secret Access Key: (存放在 Jenkins)
Kubeconfig:
- Type: Secret file
- ID: kubeconfig
- File: ~/.kube/config (EKS 叢集存取設定)
應用服務部署
Strapi CMS 後端 (mycom-strapi-prod)
apiVersion: apps/v1
kind: Deployment
metadata:
name: mycom-strapi-prod
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: mycom-strapi-prod
template:
metadata:
labels:
app: mycom-strapi-prod
spec:
containers:
- name: mycom-strapi-prod
image: AWS_Account_ID.dkr.ecr.ap-southeast-1.amazonaws.com/mycom-strapi:1.117
ports:
- containerPort: 1337
resources:
requests:
cpu: 300m
memory: 512Mi
limits:
cpu: 1500m
memory: 2Gi
livenessProbe:
httpGet:
path: /_health
port: 1337
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /_health
port: 1337
initialDelaySeconds: 30
periodSeconds: 10
環境變數配置 (部分):
env:
# Strapi 核心設定
- name: APP_KEYS
valueFrom:
secretKeyRef:
name: mycom-strapi-prod-secrets
key: app-keys
# 資料庫連線
- name: DATABASE_CLIENT
value: "postgres"
- name: DATABASE_HOST
value: "postgres-strapi-sg.Resource_ID.ap-southeast-1.rds.amazonaws.com"
- name: DATABASE_PORT
value: "5432"
- name: DATABASE_NAME
value: "strapi_DB"
# AWS S3 設定
- name: AWS_REGION
value: "ap-southeast-1"
- name: AWS_BUCKET
value: "mycom-strapi-prod-s3-taipei"
# 金流整合
- name: NEWEBPAY_MERCHANT_ID
value: "MS123456789"
- name: NEWEBPAY_API_URL
value: "https://core.newebpay.com/MPG/mpg_gateway"
# Firebase 推播通知
- name: FIREBASE_PROJECT_ID
value: "ella"
- name: GOOGLE_APPLICATION_CREDENTIALS
value: "/etc/gcp/firebase/firebase-adminsdk.json"
volumeMounts:
- name: firebase-secret
mountPath: /etc/gcp/firebase
readOnly: true
volumes:
- name: firebase-secret
secret:
secretName: firebase-mycom-admin-secret
關鍵特性分析:
健康檢查機制
- Liveness Probe: 確保容器持續運行
- Readiness Probe: 確保服務就緒後才接收流量
- 30 秒啟動延遲,避免頻繁重啟
資源配置策略
- Request: 300m CPU / 512Mi RAM (最低保證)
- Limit: 1.5 CPU / 2Gi RAM (最高上限)
- 實際使用: ~1m CPU / 281Mi RAM
- 觀察: CPU 嚴重低估 (1m vs 300m request),可能造成資源浪費
安全性設計
- 所有敏感資訊 (密碼、API 金鑰) 存放在 Kubernetes Secret
- Firebase 憑證透過 Volume Mount 注入
- 資料庫連線啟用 SSL (DATABASE_SSL: true)
版本管理
- 映像檔版本: v1.117 (已執行 112 次版本更新)
- 使用 AWS ECR 私有倉儲
- RollingUpdate 策略確保零停機部署
Vue.js 前端 (mycom-web)
apiVersion: apps/v1
kind: Deployment
metadata:
name: mycom-web
namespace: default
labels:
app: mycom-web
env: prod
spec:
replicas: 1
selector:
matchLabels:
app: mycom-web
env: prod
template:
spec:
containers:
- name: mycom-web-prod
image: AWS_Account_ID.dkr.ecr.ap-southeast-1.amazonaws.com/mycom-web:1.61
ports:
- containerPort: 80
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 512Mi
livenessProbe:
httpGet:
path: /_health
port: 80
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /_health
port: 80
initialDelaySeconds: 30
periodSeconds: 10
架構特點:
- 靜態資產託管: Vue.js SPA 打包後透過 NGINX 容器提供服務
- 輕量化設計: 相比 Strapi,資源需求更低 (100m CPU / 128Mi RAM)
- 環境標籤: 使用
env: prod標籤區分環境 - 實際使用: ~1m CPU / 26Mi RAM (資源利用率極低)
流量入口與負載均衡
Ingress NGINX Controller
# Ingress Controller Service
kind: Service
metadata:
name: ingress-nginx-controller
namespace: ingress-nginx
spec:
type: LoadBalancer
externalTrafficPolicy: Local
ports:
- name: http
port: 80
targetPort: http
nodePort: 30869
- name: https
port: 443
targetPort: https
nodePort: 31328
selector:
app.kubernetes.io/component: controller
app.kubernetes.io/instance: ingress-nginx
AWS ELB 資訊:
External IP: af0e5d61d38d3425399c76bfcd0e9dcd-703f7869948813ee.elb.ap-southeast-1.amazonaws.com
Type: Classic Load Balancer (CLB)
Ports: 80 (HTTP) → 443 (HTTPS 重定向)
Ingress 路由規則
CMS 管理後台路由
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: mycom-strapi-ingress
namespace: default
annotations:
# SSL 強制重定向
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
# 大檔案上傳支援 (4GB)
nginx.ingress.kubernetes.io/proxy-body-size: "4096m"
nginx.ingress.kubernetes.io/client-max-body-size: "4096m"
# 長時間請求支援 (1小時)
nginx.ingress.kubernetes.io/proxy-read-timeout: "3600"
nginx.ingress.kubernetes.io/proxy-send-timeout: "3600"
nginx.ingress.kubernetes.io/client-body-timeout: "3600"
nginx.ingress.kubernetes.io/client-header-timeout: "3600"
# 代理緩衝設定
nginx.ingress.kubernetes.io/proxy-buffering: "off"
nginx.ingress.kubernetes.io/proxy-request-buffering: "off"
nginx.ingress.kubernetes.io/proxy-buffer-size: "64k"
nginx.ingress.kubernetes.io/proxy-buffers-number: "16"
# 轉發標頭
nginx.ingress.kubernetes.io/use-forwarded-headers: "true"
nginx.ingress.kubernetes.io/rewrite-target: "/"
spec:
ingressClassName: nginx
tls:
- hosts:
- cms.example.com
secretName: cms-tls-secret
rules:
- host: cms.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: mycom-strapi-service-prod
port:
number: 80
設定解析:
這些 annotation 針對 Strapi CMS 的特殊需求進行優化:
大檔案上傳 (4GB)
- 支援影片、高解析度圖片上傳
proxy-body-size: 4096m設定最大請求大小
長時間連線 (1小時)
- 影片轉檔、大量資料匯入等長時間操作
- 所有 timeout 設定為 3600 秒 (1小時)
代理緩衝關閉
proxy-buffering: off避免記憶體溢位- 大檔案串流上傳不透過記憶體緩衝
SSL 強制重定向
- 所有 HTTP 請求自動重定向到 HTTPS
- 確保管理後台連線安全
前端網站路由
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: mycom-web-ingress
namespace: default
spec:
ingressClassName: nginx
tls:
- hosts:
- www.example.com
secretName: www-example-com-cert
rules:
- host: www.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: mycom-web-service-prod
port:
number: 80
設定特點:
- 使用預設的 NGINX 設定 (無特殊 annotation)
- 靜態資產服務不需要大檔案或長時間連線支援
- 同樣啟用 SSL/TLS 加密
SSL/TLS 憑證管理
Cert-Manager 架構
Cert-Manager 是一個 Kubernetes 原生的憑證管理解決方案,自動處理 SSL/TLS 憑證的簽發、更新和輪換。
# Cert-Manager 元件
kubectl get pods -n cert-manager
| 元件 | 用途 | Replicas |
|---|---|---|
| cert-manager | 核心控制器,處理 Certificate 資源 | 1 |
| cert-manager-cainjector | 注入 CA bundle 到 Webhook/APIService | 1 |
| cert-manager-webhook | 驗證和變更 Cert-Manager 資源 | 1 |
TWCA OV SSL 憑證整合 (規劃中)
當前狀態:
- 使用 Let’s Encrypt 自動簽發憑證
- 已購買 TWCA OV SSL 憑證,尚未部署
TWCA OV SSL 部署步驟:
- 取得憑證檔案
# TWCA 提供的檔案
certificate.crt # 網域憑證
ca_bundle.crt # 中繼憑證
private.key # 私鑰 (由申請單位持有)
- 建立 Kubernetes Secret
# 合併完整憑證鏈
cat certificate.crt ca_bundle.crt > fullchain.crt
# 建立 TLS Secret
kubectl create secret tls cms-tls-secret \
--cert=fullchain.crt \
--key=private.key \
-n default
kubectl create secret tls www-example-com-cert \
--cert=fullchain.crt \
--key=private.key \
-n default
- 更新 Ingress 設定
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: mycom-strapi-ingress
annotations:
# 移除 cert-manager 自動簽發
# cert-manager.io/cluster-issuer: "letsencrypt-prod"
spec:
tls:
- hosts:
- cms.example.com
secretName: cms-tls-secret # 使用手動建立的 Secret
- 驗證憑證
# 檢查憑證資訊
openssl x509 -in certificate.crt -text -noout
# 測試 HTTPS 連線
curl -vI https://cms.example.com
TWCA OV SSL vs Let’s Encrypt 比較:
| 特性 | TWCA OV SSL | Let’s Encrypt |
|---|---|---|
| 憑證類型 | OV (組織驗證) | DV (網域驗證) |
| 信任度 | 更高 (顯示組織名稱) | 一般 |
| 有效期 | 1-2 年 | 90 天 |
| 自動更新 | 需手動更新 | 自動更新 |
| 成本 | 付費 | 免費 |
| 適用場景 | 企業官網、電商平台 | 一般網站 |
為什麼選擇 TWCA OV SSL:
- ✅ 台灣本地憑證機構,符合法規要求
- ✅ OV 憑證提供更高的信任度
- ✅ 適合醫療健康產業的資安標準
- ✅ 瀏覽器顯示組織名稱,提升品牌形象
憑證自動化流程 (Let’s Encrypt)
資料庫與儲存架構
AWS RDS PostgreSQL
Host: postgres-strapi-sg.Resource_ID.ap-southeast-1.rds.amazonaws.com
Port: 5432
Database: strapi_DB
Engine: PostgreSQL
Region: ap-southeast-1
SSL: Enabled (SSL_REJECT_UNAUTHORIZED: false)
連線配置 (Strapi):
// config/database.js
module.exports = ({ env }) => ({
connection: {
client: 'postgres',
connection: {
host: env('DATABASE_HOST'),
port: env.int('DATABASE_PORT', 5432),
database: env('DATABASE_NAME'),
user: env('DATABASE_USERNAME'),
password: env('DATABASE_PASSWORD'),
ssl: env.bool('DATABASE_SSL', false) && {
rejectUnauthorized: env.bool('DATABASE_SSL_REJECT_UNAUTHORIZED', false)
}
},
pool: {
min: 2,
max: 10
}
}
})
設計考量:
✅ 優勢:
- 託管服務,無需維護資料庫伺服器
- 自動備份和時間點恢復 (PITR)
- 與 EKS 叢集位於同一區域 (ap-southeast-1),低延遲
- SSL 加密連線,資料傳輸安全
⚠️ 潛在改進:
- 使用 RDS Proxy 可以改善連線池管理
- 考慮啟用 Multi-AZ 部署提升可用性
- 監控慢查詢並建立適當索引
AWS S3 儲存
Bucket: mycom-strapi-prod-s3-taipei
Region: ap-southeast-1
Purpose: 媒體檔案儲存 (圖片、影片、文件)
Strapi S3 整合配置:
// config/plugins.js
module.exports = ({ env }) => ({
upload: {
config: {
provider: 'aws-s3',
providerOptions: {
accessKeyId: env('AWS_ACCESS_KEY_ID'),
secretAccessKey: env('AWS_ACCESS_SECRET'),
region: env('AWS_REGION'),
params: {
Bucket: env('AWS_BUCKET'),
},
},
},
},
})
S3 使用場景:
使用者上傳內容
- 會員大頭照
- 課程影片和教材
- 服務相關圖片
CMS 管理內容
- 文章封面圖
- Banner 圖片
- 行銷素材
系統生成內容
- 影片縮圖 (透過 FFmpeg 處理)
- 多尺寸圖片 (responsive images)
第三方服務整合
Firebase Cloud Messaging (FCM)
用途: 推播通知服務
環境變數:
FIREBASE_PROJECT_ID: ella
GOOGLE_APPLICATION_CREDENTIALS: /etc/gcp/firebase/firebase-adminsdk.json
Volume Mount:
Secret: firebase-mycom-admin-secret
Mount Path: /etc/gcp/firebase
Read Only: true
通知場景:
- 預約提醒 (預約前 1 天、1 小時)
- 課程上架通知
- 訂單狀態更新
- 系統重要公告
安全性設計:
- Firebase Admin SDK 憑證儲存在 Kubernetes Secret
- 透過 Volume Mount 注入容器
- Read-only 掛載,防止憑證被修改
Newebpay 金流整合
用途: 台灣信用卡、ATM、超商支付
環境變數:
NEWEBPAY_MERCHANT_ID: MS1234567890
NEWEBPAY_HASH_KEY: (存放在 Secret)
NEWEBPAY_HASH_IV: (存放在 Secret)
NEWEBPAY_API_URL: https://core.newebpay.com/MPG/mpg_gateway
金流處理流程:
EZPay 電子發票整合
用途: 開立和管理電子發票
環境變數:
EZPAY_MERCHANT_ID: 123456789
EZPAY_HASH_KEY: (存放在 Secret)
EZPAY_HASH_IV: (存放在 Secret)
EZPAY_API_URL: https://inv.ezpay.com.tw/Api/invoice_issue
發票開立流程:
- 訂單付款成功後自動觸發
- Strapi 呼叫 EZPay API 開立發票
- 回傳發票號碼和連結
- 透過 Email 和推播通知使用者
SendGrid 郵件服務
用途: 交易郵件和行銷郵件
環境變數:
SENDGRID_API_KEY: (存放在 Secret)
SENDGRID_DEFAULT_FROM: no-reply@example.com
SENDGRID_DEFAULT_REPLY_TO: info@example.com
# 備用 SMTP (Gmail)
SMTP_HOST: smtp.gmail.com
SMTP_PORT: 465
SMTP_USERNAME: info@example.com
SMTP_PASSWORD: (存放在 Secret)
郵件類型:
- 會員註冊驗證信
- 密碼重設連結
- 訂單確認信
- 發票通知信
- 預約提醒信
- 行銷活動 EDM
監控與日誌管理
Amazon CloudWatch 整合
Namespace: amazon-cloudwatch
DaemonSet: fluent-bit (在每個節點上運行)
Fluent Bit 配置:
apiVersion: v1
kind: ConfigMap
metadata:
name: fluent-bit-config
namespace: amazon-cloudwatch
data:
fluent-bit.conf: |
[SERVICE]
Flush 5
Daemon off
Log_Level info
[INPUT]
Name tail
Path /var/log/containers/*.log
Parser docker
Tag kube.*
Refresh_Interval 5
[FILTER]
Name kubernetes
Match kube.*
Kube_URL https://kubernetes.default.svc:443
Merge_Log On
K8S-Logging.Parser On
[OUTPUT]
Name cloudwatch_logs
Match *
region ap-southeast-1
log_group_name /aws/eks/mycom-taipei-cluster/containers
auto_create_group true
日誌收集範圍:
- 所有 Pod 的 stdout/stderr 輸出
- Kubernetes 系統元件日誌
- 應用程式錯誤和警告訊息
Metrics Server
kubectl get deployment metrics-server -n kube-system
用途:
- 提供
kubectl top命令的資料來源 - HPA (Horizontal Pod Autoscaler) 的指標來源
- 監控 CPU 和記憶體使用率
實際使用範例:
# 檢視節點資源使用情況
kubectl top nodes
NAME CPU(cores) CPU% MEMORY(bytes) MEMORY%
ip-192-168-1-55.ap-southeast-1.compute.internal 51m 2% 1572Mi 47%
# 檢視 Pod 資源使用情況
kubectl top pods -n default
NAME CPU(cores) MEMORY(bytes)
mycom-strapi-prod-1234567890-lmmm4 1m 281Mi
mycom-web-1234567890-x6fmx 1m 26Mi
psql-client 0m 15Mi
成本分析與優化
當前資源使用總覽
| 資源類型 | 規格 | 數量 | 月成本估算 (USD) |
|---|---|---|---|
| EKS Cluster | 控制平面 | 1 | $73 |
| EC2 (t4g.medium) | 2 vCPU / 4GB RAM | 1 | $24 |
| RDS PostgreSQL | db.t3.micro | 1 | $15-30 |
| S3 | 標準儲存 | ~100GB | $2-5 |
| ELB (CLB) | 負載均衡器 | 1 | $18 |
| ECR | 映像檔儲存 | ~10GB | $1 |
| Jenkins (Mac mini) | 本地部署 | 1 | $0 (已有硬體) |
| 總計 | $133-151 |
資源利用率分析
CPU 使用率:
節點總容量: 2000m
已使用: 51m (2.5%)
浪費: 1949m (97.5%) ❌
記憶體使用率:
節點總容量: 3.9Gi
已使用: 1.5Gi (38%)
浪費: 2.4Gi (62%) ⚠️
優化建議
1. 降低 Pod 資源 Request
目前配置 vs 實際使用:
| Pod | Request CPU | 實際使用 | 浪費 | 建議調整 |
|---|---|---|---|---|
| Strapi | 300m | 1m | 299m | 50m |
| Vue.js | 100m | 1m | 99m | 20m |
# 建議的 Strapi 資源配置
resources:
requests:
cpu: 50m # 從 300m 降至 50m
memory: 256Mi # 從 512Mi 降至 256Mi
limits:
cpu: 1000m # 從 1500m 降至 1000m
memory: 1Gi # 從 2Gi 降至 1Gi
預期效益:
- 節省 ~350m CPU request
- 節省 ~256Mi 記憶體 request
- 可以在同一節點上運行更多 Pod
結語
架構優勢總結
✅ 已實現的優勢:
- 容器化部署: Docker + Kubernetes 確保環境一致性
- 自動化 CI/CD: Jenkins 自動建置和部署
- 託管服務: EKS、RDS 降低營運負擔
- 日誌集中: CloudWatch 統一監控
- 零停機部署: RollingUpdate 策略
✅ 架構亮點:
- ARM64 節點降低成本 20-30%
- Ingress 精細化設定支援大檔案和長時間請求
- 完整的第三方整合 (FCM、Newebpay、SendGrid)
- Jenkins 與 AWS ECR/EKS 無縫整合
改進優先級
短期 (1-2 個月):
- ⚡ 最高優先: 調整 Pod 資源 request/limit (立即節省成本)
- ⚡ 最高優先: 增加節點和 Pod 副本數 (提升可用性)
- 🔧 部署 TWCA OV SSL 憑證
- 🔧 啟用 RDS 自動備份和快照
中期 (3-6 個月):
- 🚀 啟用 RDS Multi-AZ 部署
- 🚀 整合 Redis 快取
- 🚀 部署 CloudFront CDN
- 🛡️ 實施 Pod Security Standards
長期 (6-12 個月):
- 🌐 跨區域災難復原
- 🌐 多叢集架構 (開發/測試/生產)
- 🤖 完整的 GitOps 流程 (ArgoCD)
- 🤖 自動化容量規劃和成本優化
參考資源
AWS 官方文件
Kubernetes 資源
CI/CD 與自動化
應用框架
文章撰寫日期: 2024-06-05 架構掃描日期: 2024-06-05 叢集版本: EKS 1.32.9 應用版本: Strapi v5.15, Vue.js v1.61
