直接使用Client
package mainimport ("context""fmt"v1 "k8s.io/apimachinery/pkg/apis/meta/v1""k8s.io/client-go/kubernetes""k8s.io/client-go/tools/clientcmd""k8s.io/client-go/util/homedir""log""path/filepath")func main() {home := homedir.HomeDir()kubeconfig := filepath.Join(home, ".kube", "config")config, err := clientcmd.BuildConfigFromFlags("", kubeconfig)if err != nil {panic(err)}// 初始化 clientclientset, err := kubernetes.NewForConfig(config)if err != nil {log.Panic(err.Error())}stopCh := make(chan struct{})defer close(stopCh)list, err := clientset.AppsV1().Deployments("default").List(context.TODO(), v1.ListOptions{})if err == nil {for _, k := range list.Items {fmt.Println("deploy:",k.Name)}}}
这样查询数据会给APIServer带来负担。大多数情况下我们应该使用Informer机制。
基本原理如下图:
大致思路是给APIServer套了层缓存,在一开始获取到全量数据,然后基于etcd的watch机制,自动通知client-go的更新,client-go也会搞个本地缓存,所有更新也会作用于此缓存。后续对于资源的list操作将会走缓存。
informer 可以配置回调
import (
"k8s.io/client-go/informers"
)
func main(){
factory := informers.NewSharedInformerFactory(clientset, 60 * time.Second)
podInformer := factory.Core().V1().Pods()
informer := podInformer.Informer()
informer.AddEventHandler(cache.ResourceEventHandlerFuncs{
AddFunc: onAdd,
UpdateFunc: onUpdate,
DeleteFunc: onDelete,
})
}
func onAdd(obj interface{})
klog.Infof("add a pod: %+v", pod.Name)
}
// onUpdate // 此处省略 workqueue 的使用
func onUpdate(oldObj interface{}, newObj interface{}) {
klog.Infof("update a pod")
}
func onDelete(obj interface{}) {
klog.Infof("delete a pod: %+v\n", pod.Name)
}
pod发生变更时我们将会收到回调。
在CRD开发中,这个机制是非常必要的,我们需要把pod的当前状态和目标状态做对比,并尝试将当前状态修正为目标状态。
