0x01 背景
編程者總有想偷懶的傾向。至少我的初衷時,盡量復用現有的代碼。但有時也會變得弄巧成拙。
這不,最近需要在一個Go服務里添加一個CRD的緩存等待。熟悉k8s的同學都知道,向 kube-apiserver 提交一個更新,到同一個進程中的informer 獲取到這個更新,有一定的時延。這個時延比較小,一般使用上沒什么問題,但提交測試自動化時,就會出現各種妖蛾子,自動化跑的快,很容易就能撞到不一致。
我的思路時,在更新對象時,Update接口會返回一個更新后的對象,咱們又不能直接把對象塞到informer里。那只能輪詢informer,看什么時候informer返回的版本號大于或等于新對象的版本號,這時就說明informer已經同步到了更新。
那么既然看到了之前已經有同學初始化好了一個標準的client,很自然寫出了這樣的代碼。
import xxxclientset "xxx/clienset/versioned" // 這是自動生成的CRD的client。func() wrong{client := xxxclientset.New(client.RESTClient) // client 是標記的 client-go中的clientset實例。client.Update(xxx)
}
非常簡潔,省去再加載、解析kubeconfig配置。但當我去測試時,傻眼了。
failed to update UICluster object, err: v1.UpdateOptions is not suitable for converting to "meta.k8s.io/v1" in scheme "pkg/runtime/scheme.go:100
看結果是更新成功了,但自己服務的API請求報錯了。
0x02 折騰
查閱了社區的幾個issue后,認定是我忘記注冊了什么東西。多次嘗試之后,還是報錯,非常痛苦。思來想去不應該,感覺應該注冊的東西都已經注冊了。
最終反應過來,那個New可能不是能隨便用的,至于原因還沒深入研究。總之,老老實實地加載kubeconfig配置文件和使用常規的clientset.NewForConfig
之后,不再報錯了。
0x03 總結——個人直覺
作為開發人員,直覺很重要,有時可以省掉很多麻煩。想起來多年前使用某一個打車軟件時,在午夜時,好像是看到估算的行程時間有點錯亂,直覺告訴我,這是個corner case就是邊界場景,很容易出問題。同樣的,這次遇到的小問題,屬于很少有人直接這樣的用場景,既然很少有人用,它的順暢性沒經過驗證,出問題的可能性就大了。