Kubernetes節點親和性與污點容忍:實現Web服務與數據庫的分組部署

在Kubernetes(K8s)中,節點親和性(Node Affinity)用於控制Pod調度到特定節點組,而污點容忍(Toleration)允許Pod在有污點的節點上運行。這可以幫助實現資源隔離,例如將Web服務和數據庫服務部署到不同的節點組,以提高性能、安全性和可靠性。以下是逐步實現方案,確保結構清晰、易於操作。

1. 核心概念簡述
  • 節點親和性:通過節點標籤(Labels)指定Pod應調度到哪些節點。例如,給節點添加標籤 role=webrole=db,然後Pod使用親和性規則匹配這些標籤。
  • 污點容忍:節點污點(Taint)用於排斥Pod調度(如 dedicated=db:NoSchedule),只有添加了容忍(Toleration)的Pod才能被調度到該節點。這強制了節點專用性。
  • 目標場景
  • Web服務Pod(如Nginx或應用服務)部署到一組節點(標籤 role=web)。
  • 數據庫服務Pod(如MySQL或PostgreSQL)部署到另一組節點(標籤 role=db)。
  • 通過親和性和污點,確保兩類服務完全隔離,避免資源競爭。
2. 實現步驟

以下步驟基於Kubernetes集羣操作,使用 kubectl 命令和YAML配置文件。假設集羣中有多個節點,我們將它們分為兩組。

步驟1: 為節點添加標籤和污點

首先,將節點分組並設置污點,確保節點只運行指定類型的Pod。

  • Web節點組:添加標籤 role=web,並設置污點排斥非Web Pod。
# 為節點添加標籤(例如節點名為node-web-1)
kubectl label nodes node-web-1 role=web

# 設置污點:只有容忍此污點的Pod才能調度
kubectl taint nodes node-web-1 dedicated=web:NoSchedule
  • 數據庫節點組:添加標籤 role=db,並設置污點排斥非數據庫 Pod。
# 為節點添加標籤(例如節點名為node-db-1)
kubectl label nodes node-db-1 role=db

# 設置污點:只有容忍此污點的Pod才能調度
kubectl taint nodes node-db-1 dedicated=db:NoSchedule
  • 驗證節點配置
kubectl get nodes --show-labels  # 查看所有節點標籤
kubectl describe node node-web-1 | grep Taints  # 查看節點污點
步驟2: 配置Web服務Pod的親和性和容忍

在Web服務的Deployment配置中,使用節點親和性匹配 role=web 的節點,並添加容忍以忽略Web節點的污點。

  • 示例YAML(web-deployment.yaml)
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-service
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: role
                operator: In
                values:
                - web  # 強制Pod調度到role=web的節點
      tolerations:
      - key: "dedicated"
        operator: "Equal"
        value: "web"
        effect: "NoSchedule"  # 容忍污點dedicated=web:NoSchedule
      containers:
      - name: nginx
        image: nginx:latest
        ports:
        - containerPort: 80
  • 應用配置
kubectl apply -f web-deployment.yaml
步驟3: 配置數據庫服務Pod的親和性和容忍

在數據庫服務的Deployment配置中,使用節點親和性匹配 role=db 的節點,並添加容忍以忽略數據庫節點的污點。

  • 示例YAML(db-deployment.yaml)
apiVersion: apps/v1
kind: Deployment
metadata:
  name: db-service
spec:
  replicas: 2
  selector:
    matchLabels:
      app: db
  template:
    metadata:
      labels:
        app: db
    spec:
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: role
                operator: In
                values:
                - db  # 強制Pod調度到role=db的節點
      tolerations:
      - key: "dedicated"
        operator: "Equal"
        value: "db"
        effect: "NoSchedule"  # 容忍污點dedicated=db:NoSchedule
      containers:
      - name: mysql
        image: mysql:latest
        env:
        - name: MYSQL_ROOT_PASSWORD
          value: "password"
        ports:
        - containerPort: 3306
  • 應用配置
kubectl apply -f db-deployment.yaml
步驟4: 驗證部署結果

檢查Pod是否調度到正確節點組。

  • 查看Pod分佈
kubectl get pods -o wide  # 查看Pod所在節點
  • 預期輸出:所有 web-service Pod在 node-web-* 節點,所有 db-service Pod在 node-db-* 節點。
  • 測試隔離性
  • 嘗試刪除一個數據庫Pod:它應重新調度到 role=db 的節點。
  • 如果添加新節點但未配置標籤/污點,Pod不會調度到該節點。
3. 注意事項
  • 節點資源匹配:確保節點有足夠資源(CPU/內存)。可以通過節點親和性的 preferredDuringSchedulingIgnoredDuringExecution 添加軟約束。
  • 污點效果NoSchedule 僅影響新調度;PreferNoSchedule 是軟約束;NoExecute 會驅逐現有Pod。
  • 高可用性:為每個節點組添加多個節點,並在親和性中使用 topologySpreadConstraints 避免Pod集中。
  • 錯誤處理:如果Pod無法調度,檢查節點標籤、污點和Pod容忍是否匹配。使用 kubectl describe pod <pod-name> 查看事件。
  • 擴展性:此方案可擴展到更多分組(如緩存服務),只需添加新標籤和污點。

通過以上步驟,您可以實現Web服務和數據庫服務的完全隔離部署,提升集羣的穩定性和效率。如果需要進一步優化,請提供具體場景!