kubernetes的watch包
要理解kuberenetes的list-watch機制,首先應該很熟悉的理解k8s源碼中的watch包中的各種實現以及原理,如果不理解好這個watch包中的內容,在看源碼的過程中,會有很多地方看得雲裏霧裏的。這篇博客主要就是講解watch包,watch包之前是在源碼中的pkg/watch,1.6之後,同一抽取到了apimachinery這個項目下去了。
包文件說明
watch包中主要包含5個文件:watch.go,mux.go,filter.go,streamwatch.go,util.go。對這五個文件作簡單的說明。
- watch.go 主要是對interface的三種實現封裝。
- mux.go 主要是事件廣播器的實現。
- filter.go 主要是對事件的過濾。
- streamwatch.go 主要是對decoder接口實現的封裝。
- util.go 主要是對滿足條件時間的過濾。
watch.go文件的解讀
在k8s中說有的event事件統一都實現了interface接口,interface接口的定義如下:
type Interface interface {
Stop()
ResultChan() <-chan Event
}
type Event struct {
Type EventType
// Object is:
// * If Type is Added or Modified: the new state of the object.
// * If Type is Deleted: the state of the object immediately before deletion.
// * If Type is Error: *api.Status is recommended; other types may make sense
// depending on context.
Object runtime.Object
}
Event結構體,主要包括了事件類型和事件發生的對象,k8s中所有的對象(比如:pod,service,rc,dp。。。)都是runtime.Object。說白了,event對象就代表了k8s中某種資源對象(包括k8s的各個組件)發生的某種操作。
interface中主要有兩個方法,分別是對事件的監聽結果和停止監聽的方法。interface的實現有三種:
emptyWatch
type emptyWatch chan Event
func NewEmptyWatch() Interface {
ch := make(chan Event)
close(ch)
return emptyWatch(ch)
}
// Stop implements Interface
func (w emptyWatch) Stop() {
}
// ResultChan implements Interface
func (w emptyWatch) ResultChan() <-chan Event {
return chan Event(w)
}
emptyWatch是最簡單的interface的實現,提供了stop和resultChan的最簡單實現
fakerWatch
type FakeWatcher struct {
result chan Event
Stopped bool
sync.Mutex
}
func NewFake() *FakeWatcher {
return &FakeWatcher{
result: make(chan Event),
}
}
func NewFakeWithChanSize(size int, blocking bool) *FakeWatcher {
return &FakeWatcher{
result: make(chan Event, size),
}
}
// Stop implements Interface.Stop().
func (f *FakeWatcher) Stop() {
f.Lock()
defer f.Unlock()
if !f.Stopped {
glog.V(4).Infof("Stopping fake watcher.")
close(f.result)
f.Stopped = true
}
}
func (f *FakeWatcher) IsStopped() bool {
f.Lock()
defer f.Unlock()
return f.Stopped
}
// Reset prepares the watcher to be reused.
func (f *FakeWatcher) Reset() {
f.Lock()
defer f.Unlock()
f.Stopped = false
f.result = make(chan Event)
}
func (f *FakeWatcher) ResultChan() <-chan Event {
return f.result
}
// Add sends an add event.
func (f *FakeWatcher) Add(obj runtime.Object) {
f.result <- Event{Added, obj}
}
// Modify sends a modify event.
func (f *FakeWatcher) Modify(obj runtime.Object) {
f.result <- Event{Modified, obj}
}
// Delete sends a delete event.
func (f *FakeWatcher) Delete(lastValue runtime.Object) {
f.result <- Event{Deleted, lastValue}
}
// Error sends an Error event.
func (f *FakeWatcher) Error(errValue runtime.Object) {
f.result <- Event{Error, errValue}
}
// Action sends an event of the requested type, for table-based testing.
func (f *FakeWatcher) Action(action EventType, obj runtime.Object) {
f.result <- Event{action, obj}
}
fakeWatch封裝了interface的實現,並且是線程安全的,提供了watch的一些基本操作,包括對k8s的各種事件的添加(k8s中總的事件類型:ADDED,MODIFIED,DELETED,ERROR),重置watch,停止watch等。其實watch對事件的添加(ADDED,MODIFIED,DELETED,ERROR)可以統一用這個方法實現。
func (f *FakeWatcher) Action(action EventType, obj runtime.Object) {
f.result <- Event{action, obj}
}
racefreeWatch
type RaceFreeFakeWatcher struct {
result chan Event
Stopped bool
sync.Mutex
}
func NewRaceFreeFake() *RaceFreeFakeWatcher {
return &RaceFreeFakeWatcher{
result: make(chan Event, DefaultChanSize),
}
}
// Stop implements Interface.Stop().
func (f *RaceFreeFakeWatcher) Stop() {
f.Lock()
defer f.Unlock()
if !f.Stopped {
glog.V(4).Infof("Stopping fake watcher.")
close(f.result)
f.Stopped = true
}
}
func (f *RaceFreeFakeWatcher) IsStopped() bool {
f.Lock()
defer f.Unlock()
return f.Stopped
}
// Reset prepares the watcher to be reused.
func (f *RaceFreeFakeWatcher) Reset() {
f.Lock()
defer f.Unlock()
f.Stopped = false
f.result = make(chan Event, DefaultChanSize)
}
func (f *RaceFreeFakeWatcher) ResultChan() <-chan Event {
f.Lock()
defer f.Unlock()
return f.result
}
// Add sends an add event.
func (f *RaceFreeFakeWatcher) Add(obj runtime.Object) {
f.Lock()
defer f.Unlock()
if !f.Stopped {
select {
case f.result <- Event{Added, obj}:
return
default:
panic(fmt.Errorf("channel full"))
}
}
}
// Modify sends a modify event.
func (f *RaceFreeFakeWatcher) Modify(obj runtime.Object) {
f.Lock()
defer f.Unlock()
if !f.Stopped {
select {
case f.result <- Event{Modified, obj}:
return
default:
panic(fmt.Errorf("channel full"))
}
}
}
// Delete sends a delete event.
func (f *RaceFreeFakeWatcher) Delete(lastValue runtime.Object) {
f.Lock()
defer f.Unlock()
if !f.Stopped {
select {
case f.result <- Event{Deleted, lastValue}:
return
default:
panic(fmt.Errorf("channel full"))
}
}
}
// Error sends an Error event.
func (f *RaceFreeFakeWatcher) Error(errValue runtime.Object) {
f.Lock()
defer f.Unlock()
if !f.Stopped {
select {
case f.result <- Event{Error, errValue}:
return
default:
panic(fmt.Errorf("channel full"))
}
}
}
// Action sends an event of the requested type, for table-based testing.
func (f *RaceFreeFakeWatcher) Action(action EventType, obj runtime.Object) {
f.Lock()
defer f.Unlock()
if !f.Stopped {
select {
case f.result <- Event{action, obj}:
return
default:
panic(fmt.Errorf("channel full"))
}
}
}
RaceFreeFakeWatcher 封裝了interface的實現,並且是線程安全的,提供了watch的一些基本操作,包括對k8s的各種事件的添加(k8s中總的事件類型:ADDED,MODIFIED,DELETED,ERROR),重置watch,停止watch等,該實現相對fakeWatch更加完善的保證機制,保證在做以上watch的事件操作的時候watch是正常工作的。而fakeWatch在做事件的操作的時候,沒有去判斷watch是否是停止工作,直接進行相關的事件操作,當watch停止工作的時候,該中方式會拋出錯誤。其實watch對事件的添加(ADDED,MODIFIED,DELETED,ERROR)可以統一用這個方法實現。
func (f *RaceFreeFakeWatcher) Action(action EventType, obj runtime.Object) {
f.Lock()
defer f.Unlock()
if !f.Stopped {
select {
case f.result <- Event{action, obj}:
return
default:
panic(fmt.Errorf("channel full"))
}
}
}