github.com/galamsiva2020/kubernetes-heapster-monitoring@v0.0.0-20210823134957-3c1baa7c1e70/events/sources/kubernetes/kubernetes_source.go (about)

     1  // Copyright 2015 Google Inc. All Rights Reserved.
     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 kubernetes
    16  
    17  import (
    18  	"net/url"
    19  	"time"
    20  
    21  	"github.com/golang/glog"
    22  	"github.com/prometheus/client_golang/prometheus"
    23  
    24  	kubeapi "k8s.io/api/core/v1"
    25  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    26  	kubewatch "k8s.io/apimachinery/pkg/watch"
    27  	kubeclient "k8s.io/client-go/kubernetes"
    28  	kubev1core "k8s.io/client-go/kubernetes/typed/core/v1"
    29  	kubeconfig "k8s.io/heapster/common/kubernetes"
    30  	"k8s.io/heapster/events/core"
    31  )
    32  
    33  const (
    34  	// Number of object pointers. Big enough so it won't be hit anytime soon with reasonable GetNewEvents frequency.
    35  	LocalEventsBufferSize = 100000
    36  )
    37  
    38  var (
    39  	// Last time of event since unix epoch in seconds
    40  	lastEventTimestamp = prometheus.NewGauge(
    41  		prometheus.GaugeOpts{
    42  			Namespace: "eventer",
    43  			Subsystem: "scraper",
    44  			Name:      "last_time_seconds",
    45  			Help:      "Last time of event since unix epoch in seconds.",
    46  		})
    47  	totalEventsNum = prometheus.NewCounter(
    48  		prometheus.CounterOpts{
    49  			Namespace: "eventer",
    50  			Subsystem: "scraper",
    51  			Name:      "events_total_number",
    52  			Help:      "The total number of events.",
    53  		})
    54  	scrapEventsDuration = prometheus.NewSummary(
    55  		prometheus.SummaryOpts{
    56  			Namespace: "eventer",
    57  			Subsystem: "scraper",
    58  			Name:      "duration_milliseconds",
    59  			Help:      "Time spent scraping events in milliseconds.",
    60  		})
    61  )
    62  
    63  func init() {
    64  	prometheus.MustRegister(lastEventTimestamp)
    65  	prometheus.MustRegister(totalEventsNum)
    66  	prometheus.MustRegister(scrapEventsDuration)
    67  }
    68  
    69  // Implements core.EventSource interface.
    70  type KubernetesEventSource struct {
    71  	// Large local buffer, periodically read.
    72  	localEventsBuffer chan *kubeapi.Event
    73  
    74  	stopChannel chan struct{}
    75  
    76  	eventClient kubev1core.EventInterface
    77  }
    78  
    79  func (this *KubernetesEventSource) GetNewEvents() *core.EventBatch {
    80  	startTime := time.Now()
    81  	defer func() {
    82  		lastEventTimestamp.Set(float64(time.Now().Unix()))
    83  		scrapEventsDuration.Observe(float64(time.Since(startTime)) / float64(time.Millisecond))
    84  	}()
    85  	result := core.EventBatch{
    86  		Timestamp: time.Now(),
    87  		Events:    []*kubeapi.Event{},
    88  	}
    89  	// Get all data from the buffer.
    90  event_loop:
    91  	for {
    92  		select {
    93  		case event := <-this.localEventsBuffer:
    94  			result.Events = append(result.Events, event)
    95  		default:
    96  			break event_loop
    97  		}
    98  	}
    99  
   100  	totalEventsNum.Add(float64(len(result.Events)))
   101  
   102  	return &result
   103  }
   104  
   105  func (this *KubernetesEventSource) watch() {
   106  	// Outer loop, for reconnections.
   107  	for {
   108  		events, err := this.eventClient.List(metav1.ListOptions{})
   109  		if err != nil {
   110  			glog.Errorf("Failed to load events: %v", err)
   111  			time.Sleep(time.Second)
   112  			continue
   113  		}
   114  		// Do not write old events.
   115  
   116  		resourceVersion := events.ResourceVersion
   117  
   118  		watcher, err := this.eventClient.Watch(
   119  			metav1.ListOptions{
   120  				Watch:           true,
   121  				ResourceVersion: resourceVersion})
   122  		if err != nil {
   123  			glog.Errorf("Failed to start watch for new events: %v", err)
   124  			time.Sleep(time.Second)
   125  			continue
   126  		}
   127  
   128  		watchChannel := watcher.ResultChan()
   129  		// Inner loop, for update processing.
   130  	inner_loop:
   131  		for {
   132  			select {
   133  			case watchUpdate, ok := <-watchChannel:
   134  				if !ok {
   135  					glog.Errorf("Event watch channel closed")
   136  					break inner_loop
   137  				}
   138  
   139  				if watchUpdate.Type == kubewatch.Error {
   140  					if status, ok := watchUpdate.Object.(*metav1.Status); ok {
   141  						glog.Errorf("Error during watch: %#v", status)
   142  						break inner_loop
   143  					}
   144  					glog.Errorf("Received unexpected error: %#v", watchUpdate.Object)
   145  					break inner_loop
   146  				}
   147  
   148  				if event, ok := watchUpdate.Object.(*kubeapi.Event); ok {
   149  					switch watchUpdate.Type {
   150  					case kubewatch.Added, kubewatch.Modified:
   151  						select {
   152  						case this.localEventsBuffer <- event:
   153  							// Ok, buffer not full.
   154  						default:
   155  							// Buffer full, need to drop the event.
   156  							glog.Errorf("Event buffer full, dropping event")
   157  						}
   158  					case kubewatch.Deleted:
   159  						// Deleted events are silently ignored.
   160  					default:
   161  						glog.Warningf("Unknown watchUpdate.Type: %#v", watchUpdate.Type)
   162  					}
   163  				} else {
   164  					glog.Errorf("Wrong object received: %v", watchUpdate)
   165  				}
   166  
   167  			case <-this.stopChannel:
   168  				glog.Infof("Event watching stopped")
   169  				return
   170  			}
   171  		}
   172  	}
   173  }
   174  
   175  func NewKubernetesSource(uri *url.URL) (*KubernetesEventSource, error) {
   176  	kubeConfig, err := kubeconfig.GetKubeClientConfig(uri)
   177  	if err != nil {
   178  		return nil, err
   179  	}
   180  	kubeClient, err := kubeclient.NewForConfig(kubeConfig)
   181  	if err != nil {
   182  		return nil, err
   183  	}
   184  	eventClient := kubeClient.CoreV1().Events(kubeapi.NamespaceAll)
   185  	result := KubernetesEventSource{
   186  		localEventsBuffer: make(chan *kubeapi.Event, LocalEventsBufferSize),
   187  		stopChannel:       make(chan struct{}),
   188  		eventClient:       eventClient,
   189  	}
   190  	go result.watch()
   191  	return &result, nil
   192  }