Kubernetes集群搭建与Pod调度策略深度实战

Kubernetes(简称K8s)已成为容器编排领域的事实标准,无论是互联网巨头还是传统企业都在积极拥抱这一技术。K8s的核心价值在于自动化部署、弹性伸缩和故障恢复,而Pod调度策略则是实现这些能力的关键机制。本文将从集群搭建入手,逐步深入Pod调度的各种高级配置。

一、K8s集群架构概述

K8s集群由控制平面(Control Plane)和工作节点(Worker Node)组成。控制平面负责集群的全局决策和事件响应,包括API Server、etcd、Scheduler和Controller Manager。工作节点负责运行Pod,其上运行kubelet、kube-proxy和容器运行时(如containerd)。

在生产环境中,控制平面通常部署3个或5个节点以保证高可用,etcd作为分布式键值存储保存整个集群的状态数据。理解这一架构对于后续的调度策略配置至关重要,因为调度决策正是由控制平面中的Scheduler组件完成的。

二、使用kubeadm快速搭建集群

kubeadm是官方推荐的集群引导工具,可以快速搭建生产级K8s集群。以下是完整的搭建流程:

# 在所有节点上执行的基础配置
# 关闭swap
sudo swapoff -a
sudo sed -i '/swap/d' /etc/fstab

# 加载内核模块
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF
sudo modprobe overlay
sudo modprobe br_netfilter

# 设置内核参数
cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-iptables  = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward                 = 1
EOF
sudo sysctl --system

# 安装containerd
sudo apt-get update && sudo apt-get install -y containerd
sudo containerd config default | sudo tee /etc/containerd/config.toml
sudo sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml
sudo systemctl restart containerd

# 安装kubeadm、kubelet、kubectl
sudo apt-get install -y apt-transport-https ca-certificates curl
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.30/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.30/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list
sudo apt-get update
sudo apt-get install -y kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl
# 在Master节点上初始化集群
sudo kubeadm init \
  --apiserver-advertise-address=192.168.1.10 \
  --pod-network-cidr=10.244.0.0/16 \
  --service-cidr=10.96.0.0/12

# 配置kubectl
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

# 安装网络插件(Calico)
kubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.27/manifests/calico.yaml

# 在Worker节点上加入集群
sudo kubeadm join 192.168.1.10:6443 \
  --token <token> \
  --discovery-token-ca-cert-hash <hash>

初始化完成后,通过kubectl get nodes确认所有节点就绪。pod-network-cidr指定Pod网络的IP范围,必须与Calico配置一致。service-cidr则定义Service的虚拟IP范围。

三、节点选择器与亲和性调度

K8s调度器默认将Pod随机分配到可用节点上,但在生产环境中,我们通常需要更精细的控制。nodeSelector是最简单的节点选择方式,而亲和性(Affinity)则提供了更强大的表达能力。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      # 节点亲和性:优先调度到SSD节点
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: disktype
                operator: In
                values:
                - ssd
          preferredDuringSchedulingIgnoredDuringExecution:
          - weight: 80
            preference:
              matchExpressions:
              - key: zone
                operator: In
                values:
                - east
          - weight: 20
            preference:
              matchExpressions:
              - key: zone
                operator: In
                values:
                - west
      containers:
      - name: nginx
        image: nginx:1.25
        resources:
          requests:
            cpu: 500m
            memory: 512Mi
          limits:
            cpu: 1000m
            memory: 1Gi

上述配置中,requiredDuringScheduling表示硬性约束:Pod必须调度到带有disktype=ssd标签的节点上。preferredDuringScheduling表示软性偏好:优先调度到east区域(权重80),其次west区域(权重20)。调度器会综合计算各节点的权重得分,选择最优节点。

四、Pod间亲和与反亲和

除了节点级别的亲和性,K8s还支持Pod间的亲和性(Pod Affinity)和反亲和性(Pod Anti-Affinity)。这对于实现服务的高可用部署至关重要。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: redis-cluster
spec:
  replicas: 3
  selector:
    matchLabels:
      app: redis
  template:
    metadata:
      labels:
        app: redis
    spec:
      affinity:
        # Pod反亲和:确保Redis副本分布在不同节点
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: app
                operator: In
                values:
                - redis
            topologyKey: kubernetes.io/hostname
      containers:
      - name: redis
        image: redis:7.2-alpine
        ports:
        - containerPort: 6379

这段配置通过podAntiAffinity确保3个Redis副本不会调度到同一个节点上。topologyKey设置为kubernetes.io/hostname意味着以节点为拓扑域。如果改为topology.kubernetes.io/zone,则可以实现跨可用区分布,进一步提升容灾能力。

五、污点与容忍度

污点(Taint)允许节点排斥一类Pod,而容忍度(Toleration)则允许Pod调度到带有特定污点的节点上。这种机制常用于专用节点的管理。

# 给节点打污点,使其只运行特定Pod
kubectl taint nodes gpu-node-01 gpu=true:NoSchedule

# Pod配置容忍度
apiVersion: v1
kind: Pod
metadata:
  name: ml-training
spec:
  tolerations:
  - key: "gpu"
    operator: "Equal"
    value: "true"
    effect: "NoSchedule"
  containers:
  - name: training
    image: tensorflow/tensorflow:2.16.0-gpu
    resources:
      limits:
        nvidia.com/gpu: 1

NoSchedule表示已有Pod不受影响,但新Pod如果没有容忍度则不会调度到该节点。另外两种effect选项:PreferNoSchedule是软性版本,调度器会尽量避免但不强制;NoExecute则会驱逐不存在容忍度的已运行Pod。

六、资源限制与QoS等级

K8s根据Pod的资源请求和限制将其分为三个QoS等级:Guaranteed、Burstable和BestEffort。当节点资源不足时,低QoS等级的Pod会优先被驱逐。

apiVersion: v1
kind: Pod
metadata:
  name: critical-service
spec:
  containers:
  - name: app
    image: myapp:latest
    # Guaranteed等级:requests和limits完全相等
    resources:
      requests:
        cpu: 1000m
        memory: 2Gi
      limits:
        cpu: 1000m
        memory: 2Gi
  # 优先级类别
  priorityClassName: high-priority

当requests和limits完全相等时,Pod获得Guaranteed等级,具有最高的调度优先级和最低的被驱逐概率。建议为关键服务设置Guaranteed等级,并为非关键服务设置Burstable或BestEffort等级,以实现资源的弹性利用。

七、水平自动伸缩(HPA)

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: web-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: web-app
  minReplicas: 3
  maxReplicas: 20
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 70
  - type: Resource
    resource:
      name: memory
      target:
        type: Utilization
        averageUtilization: 80
  behavior:
    scaleUp:
      stabilizationWindowSeconds: 30
      policies:
      - type: Percent
        value: 100
        periodSeconds: 30
    scaleDown:
      stabilizationWindowSeconds: 300
      policies:
      - type: Percent
        value: 50
        periodSeconds: 60

HPA根据CPU和内存利用率自动调整Pod副本数量。scaleDown的stabilizationWindowSeconds设置为300秒,意味着Pod数量下降后至少观察5分钟才会继续缩容,避免了流量波动导致的频繁伸缩。scaleUp则更激进,允许30秒内翻倍扩容以快速应对流量突增。

总结

Kubernetes的Pod调度策略是其作为容器编排平台的核心竞争力。通过节点亲和性、Pod反亲和性、污点与容忍度、QoS等级和HPA等机制的组合使用,可以实现精细化的资源分配、高可用部署和弹性伸缩。在实际生产中,建议根据服务的关键性等级制定差异化的调度策略,同时结合监控指标持续优化调度配置,以达到资源利用率和服务稳定性的最佳平衡。