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  }