Kubernetes Pod Evicted

一、背景以及措施

近日 Kubernetes 测试集群 Pod 状态出现 Evicted 现象 , 但是项目还是能正常提供服务 , 最先的解决办法是手动将 Evicted 状态的 Pod 删除。

# 查看 Evicted 状态的 Pod
[ops@dev-gate ~]# kubectl get pods  -n staging-services | grep Evicted 
eureka-server-02-7f658c4dfc-zwtqk             0/1     Evicted            0          288d
fica-service-5fcd4d777d-k2bsp                 0/1     Evicted            0          176d
search-engine-79c875cbc8-q4hfx                0/1     Evicted            0          6d3h

# describe 查看其中一个 Pod 的详细信息
[ops@dev-gate ~]# kubectl describe pod eureka-server-02-7f658c4dfc-zwtqk -n staging-services
Name:           eureka-server-02-7f658c4dfc-zwtqk
Namespace:      staging-services
Priority:       0
Node:           ap-southeast-5.192.168.80.25/
Start Time:     Tue, 30 Jul 2019 15:30:38 +0800
Labels:         app=eureka-server-02
                pod-template-hash=7f658c4dfc
Annotations:    <none>
Status:         Failed
Reason:         Evicted
Message:        The node was low on resource: ephemeral-storage. Container eureka-server-02 was using 961720Ki, which exceeds its request of 0. 
IP:             
IPs:            <none>
Controlled By:  ReplicaSet/eureka-server-02-7f658c4dfc
Containers:
  eureka-server-02:
    Image:      registry-vpc.ap-southeast-5.aliyuncs.com/jakarta-services/eureka-server:staging
    Port:       <none>
    Host Port:  <none>
    Requests:
      cpu:     250m
      memory:  512Mi
    Environment:
      LANG:                             en_US.UTF-8
      LANGUAGE:                         en_US:en
      LC_ALL:                           en_US.UTF-8
      JAVA_HOME:                        /usr/local/jdk1.8.0_152
      aliyun_logs_eureka-server-error:  /data/serviceLogs/eureka-server/eureka-server-error*
      aliyun_logs_eureka-server-info:   /data/serviceLogs/eureka-server/eureka-server-info*
    Mounts:
      /data/serviceLogs/eureka-server/ from volumn-sls-15644718371690 (rw)
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-t8rfx (ro)
Volumes:
  volumn-sls-15644718371690:
    Type:       EmptyDir (a temporary directory that shares a pod's lifetime)
    Medium:     
    SizeLimit:  <unset>
  default-token-t8rfx:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-t8rfx
    Optional:    false
QoS Class:       Burstable
Node-Selectors:  <none>
Tolerations:     node.kubernetes.io/not-ready:NoExecute for 300s
                 node.kubernetes.io/unreachable:NoExecute for 300s
Events:          <none>

注意观察 Message 信息: The node was low on resource: ephemeral-storage. Container eureka-server-02 was using 961720Ki, which exceeds its request of 0。 

由此可见是 Node 节点资源过低造成的 Pod 驱逐 , 先去 Node 节点查看 Disk / Memory / CPU 的使用情况 , 然后做相应的处理。

[ops@iZk1aj2xznytv5w52w8r7kZ ~]# df -Th
Filesystem                                                              Type      Size  Used Avail Use% Mounted on
/dev/vda1                                                               ext4       50G   42G  5.0G  90% /

此次的故障原因是磁盘使用率过高 , 处理好 Node 节点后 , 再去 Master 节点删除 Evicted 状态的Pod。

[ops@dev-gate ~]# kubectl get pods -n staging-services | grep 'Evicted' | awk '{print $1}' | xargs kubectl delete pod -n staging
pod "eureka-server-02-7f658c4dfc-zwtqk" deleted
pod "fica-service-5fcd4d777d-k2bsp" deleted
pod "search-engine-79c875cbc8-q4hfx" deleted

二、为什么 Pod 会被驱逐

Kubernetes 节点上的资源会被 Pod 以及系统进程所使用 , 如果没有做任何限制的话 , 节点上的资源会被耗尽 , 相应的后果也可想而知:

1、集群问题: 如果节点上调度了很多的 Pod , 而且没有做 limit(限制容器使用资源) 限制 , 节点资源肯定被耗尽 , 系统进程也会发生OOM , 因为 Pod 是 Deployment 在控制 , 它会重新调度到其它 Node 节点运行 , 这就造成了一个恶性循环 , 引起集群的雪崩。

2、系统进程问题: 如果在设置了 limit 限制 , 那如果 Node 节点资源不足 , 容器也会出现问题。

因此 , Kubernetes 要做资源的预留和 Pod 的驱逐 , 以保证节点的正常运行。

三、Kubernetes 的做法

经过翻阅资料得知 , 此限制是通过Node组件 kubelet 进行配置

[ops@iZ8vb409m8717rqugzuqylZ kubernetes]# vim /etc/systemd/system/kubelet.service.d/10-kubeadm.conf
[Service]
Environment="KUBELET_KUBECONFIG_ARGS=--bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --kubeconfig=/etc/kubernetes/kubelet.conf"
Environment="KUBELET_SYSTEM_PODS_ARGS=--pod-manifest-path=/etc/kubernetes/manifests"
Environment="KUBELET_NETWORK_ARGS=--network-plugin=cni --cni-conf-dir=/etc/cni/net.d --cni-bin-dir=/opt/cni/bin"
Environment="KUBELET_DNS_ARGS=--enable-controller-attach-detach=false --cluster-dns=1.2.3.4         --pod-infra-container-image=registry-vpc.cn-zhangjiakou.aliyuncs.com/acs/pause-amd64:3.0                --enable-load-reader         --cluster-domain=cluster.local --cloud-provider=external         --hostname-override=cn-zhangjiakou.1.2.3.4 --provider-id=cn-zhangjiakou.i-8vb409m8717rqugzuqyl"
Environment="KUBELET_AUTHZ_ARGS=--authorization-mode=Webhook --client-ca-file=/etc/kubernetes/pki/ca.crt"
Environment="KUBELET_CGROUP_ARGS=--system-reserved=memory=300Mi         --kube-reserved=memory=400Mi         --eviction-hard=imagefs.available<15%,memory.available<300Mi,nodefs.available<10%,nodefs.inodesFree<5% --cgroup-driver=systemd"
Environment="KUBELET_CERTIFICATE_ARGS=--tls-cert-file=/var/lib/kubelet/pki/kubelet.crt --tls-private-key-file=/var/lib/kubelet/pki/kubelet.key --anonymous-auth=false --rotate-certificates=true --cert-dir=/var/lib/kubelet/pki"
ExecStart=
ExecStart=/usr/bin/kubelet $KUBELET_KUBECONFIG_ARGS $KUBELET_SYSTEM_PODS_ARGS $KUBELET_NETWORK_ARGS $KUBELET_DNS_ARGS $KUBELET_AUTHZ_ARGS $KUBELET_CGROUP_ARGS $KUBELET_CERTIFICATE_ARGS $KUBELET_EXTRA_ARGS

主要参数说明:

--system-reserved=memory=300Mi     # 为system进程预留内存300M   
--kube-reserved=memory=400Mi       # 为kube组件预留内存 400M  
imagefs.available<15%              # 指docker daemon用于存储image和容器可写层(writable layer)的磁盘
memory.available<300Mi             # 内存小于300M时 , 驱逐Pod
nodefs.available<10%               # 指node自身的存储,存储daemon的运行日志等,一般指root分区 /
nodefs.inodesFree<5%               # inode小于%5 , 驱逐Pod

既然知道了配置文件的配置方法 , 我们就可以根据自己的需求去修改这些阈值。

四、Kubernetes以什么标准去驱逐Pod

答案是QoS(服务质量等级) , 是作用在 Pod 上的一个配置 , Qos等级包括:

  • Guaranteed: limits 和 request 相等
  • Burstable: limit 和 request 不相等
  • BestEffort: 没有限制

由此可见 , Kubernetes是通过配置 limits 和 requests 的值大小来评定 QoS。

三种等级示例:

# Guaranteed 等级
    spec:
      containers:
      - name: nginx-demo
        image: nginx
        resources:
          limits:
            cpu: 200m
            memory: 200Mi
          requests:
            cpu: 200m
            memory: 200Mi
        ports:
        - containerPort: 80
#  Burstable 等级
   spec:
      containers:
      - name: nginx-demo
        image: nginx
        resources:
          limits:
            cpu: 200m
            memory: 200Mi
          requests:
            cpu: 20m
            memory: 20Mi
        ports:
        - containerPort: 80
# BestEffort 等级
    spec:
      containers:
      - name: nginx-demo
        image: nginx
        ports:
        - containerPort: 80

对于CPU而言: 当 Pod 使用 CPU 超过设置的 limits 限制 , Pod不会被 Kill 但是会被限制

对于内存而言: 当 Pod 使用 Memory 超过了 limits 限制 ,Pod 中的 容器中进程会被 Kill , Kubernetes会尝试重启或调度到其它Node节点

当集群监控到 Node 节点的内存或者CPU资源到达阈值时 , 就会触发资源回收策略 , 通过驱逐节点上的Pod来减少资源占用。

QoS驱逐优先级:

BestEffort --> Burstable --> Guaranteed

五、配置建议

将不是很关键的服务 Qos 等级设置为 Burstable 或者 BestEffort。

资源充足的话 , Pod 等级可以设置为 Guaranteed。

在KubeSphere中,Pod状态为“Evicted”通常表明该Pod所在的节点资源不足,或者Pod本身违反了某些资源限制策略。为了有效排查和优化此类问题,可以从以下几个方面入手: ### 检查Pod被驱逐的原因 1. **查看Pod的事件信息** 使用`kubectl describe pod <pod-name>`命令可以获取Pod的详细信息,其中包括导致Pod被驱逐的具体原因。这些信息对于理解为何Pod会被标记为“Evicted”至关重要。 2. **检查节点资源使用情况** 当节点上的可用资源不足以满足新调度的Pod需求时,可能会触发驱逐机制。可以通过`kubectl top node`命令监控各节点的CPU和内存使用率,以判断是否存在资源瓶颈[^4]。 3. **分析Pod的资源请求与限制** 确保Pod定义中的资源请求(`.spec.containers[].resources.requests`)和限制(`.spec.containers[].resources.limits`)合理。不合理的资源配置可能导致不必要的驱逐。 ### 解决方案 1. **增加集群资源** 如果发现是因为节点资源不足而导致的Pod被驱逐,可以考虑扩展集群规模,即添加更多的工作节点,或升级现有节点的硬件配置。 2. **调整Pod的资源请求与限制** 根据实际应用的需求,合理设置Pod的资源请求与限制。如果Pod的实际资源消耗远低于其请求值,可以适当降低请求值;反之,则需要提高请求值以确保Pod能够获得足够的资源[^1]。 3. **优化应用程序性能** 对于那些频繁触发驱逐的应用程序,应该审查其代码逻辑,寻找可能存在的性能瓶颈,并进行优化。这不仅可以减少资源消耗,还能提升应用的整体响应速度和服务质量。 4. **定期清理不再需要的Pod** 长时间保留处于“Evicted”状态的Pod不仅占用存储空间,还可能影响集群性能。可以定期执行以下命令来清理这些Pod: ```bash kubectl get pods -n <namespace> | grep Evicted | awk '{print $1}' | xargs kubectl delete pod -n <namespace> ``` 5. **配置合适的驱逐策略** Kubernetes允许通过设置`eviction-max-pod-grace-period`参数来控制软驱逐条件下的Pod优雅终止期限。合理配置这一参数有助于减少因突然终止Pod而造成的业务中断风险[^3]。 6. **启用自动伸缩功能** 利用Horizontal Pod Autoscaler (HPA) 或者Vertical Pod Autoscaler (VPA),可以根据实际负载动态调整Pod的数量或资源请求,从而更好地适应变化的工作负载需求。 ### 示例:创建一个带有资源请求和限制的Pod 下面是一个简单的例子,展示了如何在一个Pod定义中指定容器的资源请求和限制: ```yaml apiVersion: v1 kind: Pod metadata: name: myapp-pod labels: app: myapp spec: containers: - name: myapp-container image: nginx resources: requests: memory: "256Mi" cpu: "500m" limits: memory: "512Mi" cpu: "1" ``` 在这个例子中,我们为名为`myapp-container`的容器指定了最低限度的内存和CPU请求,同时也设置了最高限度的资源使用上限。这样的配置有助于避免单个Pod过度消耗资源,进而保护整个集群的稳定性。 ---
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值