github.phpd.cn/cilium/cilium@v1.6.12/operator/k8s_pod_controller.go (about) 1 // Copyright 2016-2019 Authors of Cilium 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package main 16 17 import ( 18 "context" 19 "fmt" 20 "time" 21 22 "github.com/cilium/cilium/pkg/controller" 23 "github.com/cilium/cilium/pkg/k8s" 24 25 "k8s.io/apimachinery/pkg/api/errors" 26 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 27 ) 28 29 const ( 30 minimalPodRestartInterval = 5 * time.Minute 31 ) 32 33 var ( 34 unmanagedKubeDnsWatcherInterval int 35 unmanagedKubeDnsMinimalAge = 30 * time.Second 36 lastPodRestart = map[string]time.Time{} 37 ) 38 39 func enableUnmanagedKubeDNSController() { 40 controller.NewManager().UpdateController("restart-unmanaged-kube-dns", 41 controller.ControllerParams{ 42 RunInterval: time.Duration(unmanagedKubeDnsWatcherInterval) * time.Second, 43 DoFunc: func(ctx context.Context) error { 44 for podName, lastRestart := range lastPodRestart { 45 if time.Since(lastRestart) > 2*minimalPodRestartInterval { 46 delete(lastPodRestart, podName) 47 } 48 } 49 50 pods, err := k8s.Client().CoreV1().Pods("").List(metav1.ListOptions{ 51 LabelSelector: "k8s-app=kube-dns", 52 FieldSelector: "status.phase=Running", 53 }) 54 if err != nil { 55 return err 56 } 57 58 for _, pod := range pods.Items { 59 if pod.Spec.HostNetwork { 60 continue 61 } 62 cep, err := ciliumK8sClient.CiliumV2().CiliumEndpoints(pod.Namespace).Get(pod.Name, metav1.GetOptions{}) 63 podID := fmt.Sprintf("%s/%s", pod.Namespace, pod.Name) 64 switch { 65 case err == nil: 66 log.Debugf("Found kube-dns pod %s with identity %d", podID, cep.Status.ID) 67 case errors.IsNotFound(err): 68 log.Debugf("Found unmanaged kube-dns pod %s", podID) 69 if startTime := pod.Status.StartTime; startTime != nil { 70 if age := time.Since((*startTime).Time); age > unmanagedKubeDnsMinimalAge { 71 if lastRestart, ok := lastPodRestart[podID]; ok { 72 if timeSinceRestart := time.Since(lastRestart); timeSinceRestart < minimalPodRestartInterval { 73 log.Debugf("Not restaring %s, only %s since last restart", podID, timeSinceRestart) 74 continue 75 } 76 } 77 78 log.Infof("Restarting unmanaged kube-dns pod %s started %s ago", podID, age) 79 if err := k8s.Client().CoreV1().Pods(pod.Namespace).Delete(pod.Name, &metav1.DeleteOptions{}); err != nil { 80 log.WithError(err).Warningf("Unable to restart pod %s", podID) 81 } else { 82 lastPodRestart[podID] = time.Now() 83 84 // Delete a single pod per iteration to avoid killing all replicas at once 85 return nil 86 } 87 88 } 89 } 90 default: 91 return err 92 } 93 } 94 95 return nil 96 }, 97 }) 98 }