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 }