client-go连接数
单节点k8s集群 v1.19.0
服务创建的https连接数量
client-go用于访问kube-apiserver,可以list/watch k8s资源。
组件名称 |
访问kube-apiserver方式 |
单个实例的https连接数 |
kube-scheduler |
本机ip |
2 |
kube-controller-manager |
本机ip |
2 |
coredns |
service cluster ip |
1 |
kube-proxy |
本机ip |
1 |
kubelet |
本机ip |
1 |
kube-flannel-ds |
service cluster ip |
1 |
client-go走http和https不同点
走http
client-go通过http访问kube-apiserver时,list/watch每种类型的k8s资源,都会创建1条长连接。
clientset发送http请求访问kube-apiserver时,会新起http短连接。因为要走http2复用连接,需要https。
走https
client-go默认通过https访问kube-apiserver时,只建立一条长连接,原因是http2复用连接,maxConcurrentStreams会影响创建的连接数。
http2客户端默认maxConcurrentStreams是100,kube-apiserver默认maxConcurrentStreams是250。
当协商完成之前,maxConcurrentStreams是100,如果瞬间请求量超过100,那么新建连接。
当协商完成之后,maxConcurrentStreams是250,不新建连接。
kube-apiserver从v1.25版本开始,默认maxConcurrentStreams从250改成100,减小服务端压力。
验证只有1条https长连接
创建多个kubeconfig和clientset依然只有1条https长连接。
package main
import (
"os"
"os/signal"
"syscall"
"k8s.io/client-go/informers"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/cache"
"k8s.io/client-go/tools/clientcmd"
klog "k8s.io/klog/v2"
)
func SetupSignalHandler() (stopCh <-chan struct{}) {
stop := make(chan struct{})
c := make(chan os.Signal, 2)
signal.Notify(c, []os.Signal{os.Interrupt, syscall.SIGTERM}...)
go func() {
<-c
close(c)
close(stop)
}()
return stop
}
func addListWatchCfgAndClient(stopCh <-chan struct{}) {
cfg, err := clientcmd.BuildConfigFromFlags("", "/root/.kube/config")
if err != nil {
klog.Fatalf("Error building kubeconfig: %s", err.Error())
}
kubeClient, err := kubernetes.NewForConfig(cfg)
if err != nil {
klog.Fatalf("Error building kubernetes clientset: %s", err.Error())
}
informerFactory := informers.NewSharedInformerFactory(kubeClient, 0)
hasSynced := informerFactory.Core().V1().Nodes().Informer().HasSynced
informerFactory.Core().V1().Nodes().Lister()
informerFactory.Start(stopCh)
// defer informerFactory.Shutdown()
if ok := cache.WaitForCacheSync(stopCh, hasSynced); !ok {
klog.Fatalf("failed to wait for caches to sync")
}
cfg1, err := clientcmd.BuildConfigFromFlags("", "/root/.kube/config")
if err != nil {
klog.Fatalf("Error building kubeconfig: %s", err.Error())
}
kubeClient1, err := kubernetes.NewForConfig(cfg1)
if err != nil {
klog.Fatalf("Error building kubernetes clientset: %s", err.Error())
}
informerFactory1 := informers.NewSharedInformerFactory(kubeClient1, 0)
hasSynced1 := informerFactory1.Core().V1().Endpoints().Informer().HasSynced
informerFactory1.Core().V1().Endpoints().Lister()
informerFactory1.Start(stopCh)
// defer informerFactory.Shutdown()
if ok := cache.WaitForCacheSync(stopCh, hasSynced1); !ok {
klog.Fatalf("failed to wait for caches to sync")
}
}
func main() {
stopCh := SetupSignalHandler()
addListWatchCfgAndClient(stopCh)
<-stopCh
}