k8s.io/kubernetes@v1.29.3/pkg/kubelet/active_deadline.go (about) 1 /* 2 Copyright 2016 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package kubelet 18 19 import ( 20 "fmt" 21 "time" 22 23 "k8s.io/api/core/v1" 24 "k8s.io/client-go/tools/record" 25 "k8s.io/kubernetes/pkg/kubelet/lifecycle" 26 "k8s.io/kubernetes/pkg/kubelet/status" 27 "k8s.io/utils/clock" 28 ) 29 30 const ( 31 reason = "DeadlineExceeded" 32 message = "Pod was active on the node longer than the specified deadline" 33 ) 34 35 // activeDeadlineHandler knows how to enforce active deadlines on pods. 36 type activeDeadlineHandler struct { 37 // the clock to use for deadline enforcement 38 clock clock.Clock 39 // the provider of pod status 40 podStatusProvider status.PodStatusProvider 41 // the recorder to dispatch events when we identify a pod has exceeded active deadline 42 recorder record.EventRecorder 43 } 44 45 // newActiveDeadlineHandler returns an active deadline handler that can enforce pod active deadline 46 func newActiveDeadlineHandler( 47 podStatusProvider status.PodStatusProvider, 48 recorder record.EventRecorder, 49 clock clock.Clock, 50 ) (*activeDeadlineHandler, error) { 51 52 // check for all required fields 53 if clock == nil || podStatusProvider == nil || recorder == nil { 54 return nil, fmt.Errorf("required arguments must not be nil: %v, %v, %v", clock, podStatusProvider, recorder) 55 } 56 return &activeDeadlineHandler{ 57 clock: clock, 58 podStatusProvider: podStatusProvider, 59 recorder: recorder, 60 }, nil 61 } 62 63 // ShouldSync returns true if the pod is past its active deadline. 64 func (m *activeDeadlineHandler) ShouldSync(pod *v1.Pod) bool { 65 return m.pastActiveDeadline(pod) 66 } 67 68 // ShouldEvict returns true if the pod is past its active deadline. 69 // It dispatches an event that the pod should be evicted if it is past its deadline. 70 func (m *activeDeadlineHandler) ShouldEvict(pod *v1.Pod) lifecycle.ShouldEvictResponse { 71 if !m.pastActiveDeadline(pod) { 72 return lifecycle.ShouldEvictResponse{Evict: false} 73 } 74 m.recorder.Eventf(pod, v1.EventTypeNormal, reason, message) 75 return lifecycle.ShouldEvictResponse{Evict: true, Reason: reason, Message: message} 76 } 77 78 // pastActiveDeadline returns true if the pod has been active for more than its ActiveDeadlineSeconds 79 func (m *activeDeadlineHandler) pastActiveDeadline(pod *v1.Pod) bool { 80 // no active deadline was specified 81 if pod.Spec.ActiveDeadlineSeconds == nil { 82 return false 83 } 84 // get the latest status to determine if it was started 85 podStatus, ok := m.podStatusProvider.GetPodStatus(pod.UID) 86 if !ok { 87 podStatus = pod.Status 88 } 89 // we have no start time so just return 90 if podStatus.StartTime.IsZero() { 91 return false 92 } 93 // determine if the deadline was exceeded 94 start := podStatus.StartTime.Time 95 duration := m.clock.Since(start) 96 allowedDuration := time.Duration(*pod.Spec.ActiveDeadlineSeconds) * time.Second 97 return duration >= allowedDuration 98 }