iT邦幫忙

2025 iThome 鐵人賽

DAY 4
0
自我挑戰組

雲端與資料平台實戰:從抽象概念到落地技術系列 第 4

Day4 過度抽象 vs 過度具體:設計的平衡點

  • 分享至 

  • xImage
  •  

1. 抽象與具體的張力

在工程設計中,我們常在「抽象」與「具體」之間徘徊:

  • 過度抽象 → 空談或黑箱
module "network" {
  source = "git::ssh://git@repo.git//modules/network"
  # 什麼都沒有,使用者完全猜
}

對新進團隊而言,這種模組就像魔法箱,無法維護。

  • 過度具體 → 僵硬或難以延展
# CI/CD pipeline example
deploy:
  script:
    - kubectl apply -f dev-deployment.yaml
    - kubectl apply -f dev-service.yaml

每次切換環境都要改 YAML,缺乏彈性。

核心概念:抽象是壓縮複雜性,具體是落地的橋樑。太極端都不好。


2. 工程實務中的「平衡點」

Terraform Module 設計

# 過度抽象
module "db" {
  source = "./modules/db"
  user   = var.db_user
  pw     = var.db_pw
  host   = var.db_host
  port   = var.db_port
  # 還有十幾個參數...
}

# 過度具體
resource "aws_db_instance" "prod" {
  engine = "mysql"
  instance_class = "db.t3.medium"
  name = "prod_db"
}

平衡點:模組提供必要參數,內部隱藏可復用邏輯,不暴露全部細節。

我幫你把這段文字與 YAML 範例重新整理與優化,使敘述更流暢、結構更清楚,同時強調「抽象化的原則與落地實務」:


Helm Chart 設計

以下是一個 過度具體 的 values.yaml 範例,展示三個微服務(auth、user、payment)完全寫死 replicas、資源、環境與 Ingress 配置的情況:

replicaCount:
  auth: 3
  user: 2
  payment: 4

auth:
  image:
    repository: "mycompany/auth"
    tag: "v1.2.3"
  resources:
    limits:
      cpu: "500m"
      memory: "512Mi"
    requests:
      cpu: "250m"
      memory: "256Mi"
  env:
    DB_HOST: "postgres-auth"
    DB_PORT: "5432"
  service:
    type: ClusterIP
    port: 8080
  ingress:
    host: "auth.example.com"

user:
  image:
    repository: "mycompany/user"
    tag: "v3.1.0"
  resources:
    limits:
      cpu: "300m"
      memory: "256Mi"
    requests:
      cpu: "150m"
      memory: "128Mi"
  env:
    DB_HOST: "postgres-user"
    DB_PORT: "5432"
  service:
    type: ClusterIP
    port: 8081
  ingress:
    host: "user.example.com"

payment:
  image:
    repository: "mycompany/payment"
    tag: "v2.5.1"
  resources:
    limits:
      cpu: "700m"
      memory: "1024Mi"
    requests:
      cpu: "350m"
      memory: "512Mi"
  env:
    DB_HOST: "postgres-payment"
    DB_PORT: "5432"
  service:
    type: ClusterIP
    port: 8082
  ingress:
    host: "payment.example.com"

對應的 template 也過度依賴 values.yaml:

{{- range $name, $svc := .Values }}
apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ $name }}
spec:
  replicas: {{ $svc.replicaCount }}
  template:
    spec:
      containers:
        - name: {{ $name }}
          image: "{{ $svc.image.repository }}:{{ $svc.image.tag }}"
          resources:
            limits:
              cpu: {{ $svc.resources.limits.cpu }}
              memory: {{ $svc.resources.limits.memory }}
            requests:
              cpu: {{ $svc.resources.requests.cpu }}
              memory: {{ $svc.resources.requests.memory }}
          env:
            - name: DB_HOST
              value: "{{ $svc.env.DB_HOST }}"
            - name: DB_PORT
              value: "{{ $svc.env.DB_PORT }}"
---
{{- end }}

⚠️ 問題點:
每個服務都完全寫死配置 → 失去共通抽象。
新增服務或切換環境需要複製整份 values.yaml → 高維護成本。
template 幾乎沒有抽象,修改 replicas、image tag 或 ingress host 必須改多個地方。
若要多 Chart 部署,這種過度具體設定會重複出現 → 冗餘、低復用。


抽象化優化思路

Helm Chart 的目的就是 減少管理負擔,因此設計上可以:

  1. 將共通管理的屬性集中,例如:

    • DB_HOST 可由 {service}-postgres 自動生成
    • ingress host 可由 {service}.example.com 自動生成
    • DB_PORT 統一默認為 5432,只在特殊情況下 override
  2. 留下必要可變參數,減少管理項目:

changeDBPort: { auth: 5421 }

auth:
  replica: 3
  image: mycompany/auth-v1.2.3
  limit-cpu: 500m
  limit-mem: 512Mi
  request-cpu: 250m
  request-mem: 256Mi
  servicePort: 8080

user:
  ...

payment:
  ...

保留最重要的可變參數,簡化 values.yaml 結構
共通邏輯隱去或自動生成 → 減少維護成本
易於團隊協作,避免「黑箱化」的抽象,也避免完全寫死的過度具體


從抽象思考進入工程實務

今天已進入系列文章的第四天,延續上一章節對抽象價值的探討,我們進一步呈現了 抽象與具體之間的平衡取捨。透過對比案例,更清楚地理解到:抽象不只是隱藏細節,更是一種 高層級的後設視角,讓我們能從全局審視設計。

當然,錯誤的抽象也可能讓觀點模糊、不易落地。這將是後續實作章節中,我們需要關注的重點——如何運用抽象與具體的思維方式,真正 幫助我們在工作中做出可落地、可維護的設計

很高興在第一部分中,帶領各位重新認識工程中的抽象概念,並循序漸進地展現其在 DevOps 工程中的實務價值。接下來,我們將進入 實戰,希望在分享操作與實作技巧的同時,也能得到各位的回饋與指教。


上一篇
Day3 從工程案例看「抽象」的實用價值
下一篇
Day5 從宣告式配置理解helm的運作
系列文
雲端與資料平台實戰:從抽象概念到落地技術9
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言