iT邦幫忙

2025 iThome 鐵人賽

DAY 20
0

延續昨天的討論,今天我們將深入 Kubernetes 中兩個對叢集穩定運作至關重要的概念:配置管理(ConfigMap)節點調度策略(Affinity / Taint)。這兩項功能不僅決定了應用程式的配置彈性,也影響 Pod 的排程效率與叢集穩定性。透過實務範例,我們將展示如何在多服務環境中應用這些工具,提升部署一致性與高可用性。


ConfigMap:解耦配置與程式碼

在應用程式開發中,「設定不應該寫死在程式碼裡」是基本原則。
Kubernetes 提供的 ConfigMap,正是為了讓設定與應用程式分離,讓部署時可以依不同環境靈活調整。

以下以實務案例說明:在多服務共用設定時,如何用 ConfigMap 作為唯一設定值來源。


範例一:Kafka 與 Flink Session Cluster 共用 bootstrap

Flink Session Mode 中,每個 Job 的執行都依賴已存在的 SessionCluster
若 Job 需要連接 Kafka,通常必須取得 bootstrap.servers 等連線資訊。

若透過 Helm 或 CI 流程將變數注入至 SessionJob,這些參數會在 部署階段才被寫入,導致 無法在 Flink 啟動階段(ClassLoader 初始化或 Connector 啟動) 建立唯一且一致的 Kafka 連線。

更穩定的作法,是透過 ConfigMap 定義共用連線參數,讓 SessionCluster 與所有 Job 共用同一份設定:

# configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: kafka-bootstrap-config
data:
  BOOTSTRAP_SERVERS: "kafka-service:9092"

在 Flink Session Cluster 的 Deployment 中掛載這份設定:

# flink-sessioncluster.yaml
spec:
  template:
    spec:
      containers:
        - name: flink-main
          envFrom:
            - configMapRef:
                name: kafka-bootstrap-config

🔹 說明
任何透過 SessionCluster 提交的 Job 都能在初始化階段(open()configure())即取得 Kafka 連線設定,確保連線一致性,也避免 pipeline 中多次注入參數造成的不一致。


範例二:kube-state-metrics 在多個 Helm release 下共用同一份 config

情境:
你有多個 Helm release(例如不同命名空間或環境),希望每個 release 啟動的 kube-state-metrics 都依同一份設定,擷取一致指標。

做法(同 namespace 範例):

  1. 在同一 namespace 建立一份 ConfigMap(例如 ksm-config),內容為 kube-state-metrics 所需的設定檔。
  2. 各 Helm chart 的 ksm Deployment 範本掛載該 ConfigMap 至預期路徑(例如 /etc/ksm/config.yaml),或將必要 key 注入環境變數。
apiVersion: v1
kind: ConfigMap
metadata:
  name: ksm-config
data:
  ksm-config.yaml: |
    collect:
      - pods
      - deployments
# Deployment 掛載 ConfigMap
volumeMounts:
  - name: ksm-config-volume
    mountPath: /etc/ksm
    readOnly: true
volumes:
  - name: ksm-config-volume
    configMap:
      name: ksm-config

注意事項:

  • ConfigMap 是 namespace-scoped:若 Helm release 位於不同 namespace,無法直接掛載相同 ConfigMap,可透過 GitOps 或 CI 流程同步設定。
  • 若程式支援 reload,可藉由檔案掛載自動更新設定內容,而無需重新部署。

總結:ConfigMap 將「參數注入」抽象為一份唯一檔案或 key-value 集合,讓多個服務在初始化階段一致地取得相同設定。這不僅是配置解耦,也讓「部署時序」明確化。


Affinity / Taint:用「人性」理解調度邏輯

接下來介紹 Affinity / Taint,用擬人化的方式理解更直覺。

Taint

Taint 設定在 Node 上,類比「屋子有髒汙」:
只有願意 容忍(Toleration) 髒汙的人(Pod)才能進入。

Affinity / Anti-Affinity

Affinity 以 Pod 為單位判斷:

  • Affinity:Pod 喜歡靠近另一個 Pod,就像「有人想跟喜歡的人待在一起」。
  • Anti-Affinity:Pod 避開某個 Pod,就像「不喜歡某人,選擇不一起住」。

若用於 Node,表示「人想住哪間屋子就住哪裡」。
值得注意的是,Kubernetes 沒有 Node Anti-Affinity,因為這種排斥已由 Taint / Toleration 覆蓋。

小技巧:建議從 Pod 角度理解這些機制,更容易掌握排程行為。

偏好是否強制可用:

  • requiredDuringSchedulingIgnoredDuringExecution強制條件 (Pod: 必需的!)
  • preferredDuringSchedulingIgnoredDuringExecution偏好條件 (Pod: 我妥協)

範例一:Node Affinity(Pod 想去哪間屋子)

apiVersion: v1
kind: Pod
metadata:
  name: affinity-example
spec:
  containers:
    - name: app
      image: nginx
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
          - matchExpressions:
              - key: node-role.kubernetes.io/type
                operator: In
                values:
                  - data-node

🔹 說明
Pod 只會被排到標記為 data-node 的節點,就像「人喜歡某間屋子,所以住進去」。


範例二:Taint / Toleration(屋子有髒汙,必須容忍才能進)

# 節點上加 taint
kubectl taint nodes node1 dedicated=flink:NoSchedule

對應 Pod 需加 toleration:

apiVersion: v1
kind: Pod
metadata:
  name: taint-example
spec:
  containers:
    - name: flink-job
      image: flink:latest
  tolerations:
    - key: "dedicated"
      operator: "Equal"
      value: "flink"
      effect: "NoSchedule"

🔹 說明
只有帶有對應 toleration 的 Pod 才能進入「髒屋子」。


範例三:Pod Anti-Affinity(避開不喜歡的人)

apiVersion: v1
kind: Pod
metadata:
  name: pod-anti-example
spec:
  containers:
    - name: web
      image: nginx
  affinity:
    podAntiAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        - labelSelector:
            matchExpressions:
              - key: app
                operator: In
                values:
                  - web-service
          topologyKey: "kubernetes.io/hostname"

🔹 說明
相同標籤的 Pod 不會被排在同一節點,就像「不喜歡某人,所以不跟他住一起」。
適合高可用或避免單點故障的服務。


Affinity / Taint 對照表

機制 設定位置 功能 類比
Node Affinity Pod spec Pod 選擇節點 想住哪間屋子
Pod Affinity Pod spec Pod 靠近另一個 Pod 想跟誰待在一起
Pod Anti-Affinity Pod spec Pod 避開另一個 Pod 不喜歡某人,選擇不在一起
Taint / Toleration Node/Pod Node 有特殊標記,限制 Pod 容忍特殊要求才能進

小結

今天介紹了 Kubernetes 中兩個對穩定運作至關重要的概念:配置管理(ConfigMap)節點調度策略(Affinity / Taint)

在 ConfigMap 部分,我們說明了如何將設定與程式碼解耦,並透過實務範例展示了多服務共用配置的方法,包括 Flink Session Cluster 與 Kafka 的 bootstrap 連線,以及多個 Helm release 下的 kube-state-metrics 配置共享。透過 ConfigMap,可以將參數注入抽象為唯一來源,確保服務在初始化階段就能取得一致設定,提升部署可控性與可重現性。

在 Affinity / Taint 部分,我們用擬人化方式理解調度邏輯:

  • Node Affinity:Pod 選擇想住的節點。
  • Pod Affinity / Anti-Affinity:Pod 喜歡或避開其他 Pod,就像人際間的相處。
  • Taint / Toleration:節點設有特殊限制,Pod 必須「容忍」才能進入。

透過今天的介紹,相信讀者已經能掌握如何使用 ConfigMap 來解耦配置,確保多服務在初始化階段取得一致設定,提高部署可控性與重現性。
同時,也能運用 Affinity / Taint 精準控制 Pod 的調度,提升叢集的穩定性與高可用性,並在實務操作中更靈活地管理資源。
希望今天的分享,能讓大家對 Kubernetes 的 ConfigMap 與 Affinity / Taint 有更清晰的理解,也能在實務操作中更有效地管理配置與調度策略。

謝謝各位的閱讀,祝福中秋佳節愉快,我們明天見!


上一篇
Day 19 Kubernetes 實務分享 (1)
系列文
雲端與資料平台實戰:從抽象概念到落地技術20
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言