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服务和数据库服务的完全隔离部署,提升集群的稳定性和效率。如果需要进一步优化,请提供具体场景!

更多推荐