golang 使用 “sigs.k8s.io/controller-runtime/pkg/client“ sdk, 操作k8s资源。使用metrics查询pod占用cpu,占用内存

1、概述
golang使用controller-runtime框架进行kubernetes二次开发, 操作k8s资源,使用metrics查询pod占用cpu,占用内存。
使用版本: sigs.k8s.io/controller-runtime v0.14.5; k8s.io/metrics v0.26.0; k8s.io/api v0.26.2
废话不多说,直接上代码,有用点赞评论加收藏。

2、Demo code

// Dashboard UI default values for client configs.
const (
	// High enough QPS to fit all expected use cases. QPS=0 is not set here, because
	// client code is overriding it.
	DefaultQPS = 1e6
	// High enough Burst to fit all expected use cases. Burst=0 is not set here, because
	// client code is overriding it.
	DefaultBurst = 1e6
	// Use kubernetes protobuf as content type by default
	DefaultContentType = "application/vnd.kubernetes.protobuf"
	// Default cluster/context/auth name to be set in clientcmd config
	DefaultCmdConfigName = "kubernetes"
)

var (
	scheme   = runtime.NewScheme()
	setupLog = ctrl.Log.WithName("setup")
	mgr      Manager
)

type Manager struct {
	client  controller_runtime.Client
	metircs *metrics.Clientset
}

// ClientCmdConfig creates ClientCmd Config based on authentication information extracted from request.
// Currently request header is only checked for existence of 'Authentication: BearerToken'
func (m *Manager) ClientCmdConfig(apiserverHost, apiserverToken string) (clientcmd.ClientConfig, error) {
	cfg, err := m.buildConfigFromFlags(apiserverHost, "")
	if err != nil {
		return nil, err
	}
	return m.buildCmdConfig(&api.AuthInfo{Token: apiserverToken}, cfg), nil
}

// get rest.Config
func (m *Manager) GetRestConfig(apiserverHost, apiserverToken string) (*rest.Config, error) {
	cfg, err := m.buildConfigFromFlags(apiserverHost, "")
	if err != nil {
		return nil, err
	}
	restConfig, err := m.buildCmdConfig(&api.AuthInfo{Token: apiserverToken}, cfg).ClientConfig()
	if err != nil {
		return nil, err
	}
	m.initConfig(restConfig)
	return restConfig, nil
}

// desc   : 为k8s客户端添加默认参数
func (m *Manager) initConfig(cfg *rest.Config) {
	cfg.QPS = DefaultQPS
	cfg.Burst = DefaultBurst
}

// Based on auth info and rest config creates client cmd config.
func (m *Manager) buildCmdConfig(authInfo *api.AuthInfo, cfg *rest.Config) clientcmd.ClientConfig {
	cmdCfg := api.NewConfig()
	insecure := cfg.TLSClientConfig.Insecure
	if len(cfg.TLSClientConfig.CAFile) == 0 && len(cfg.TLSClientConfig.CAData) == 0 {
		insecure = true
	}
	cmdCfg.Clusters[DefaultCmdConfigName] = &api.Cluster{
		Server:                   cfg.Host,
		CertificateAuthority:     cfg.TLSClientConfig.CAFile,
		CertificateAuthorityData: cfg.TLSClientConfig.CAData,
		InsecureSkipTLSVerify:    insecure,
	}
	cmdCfg.AuthInfos[DefaultCmdConfigName] = authInfo
	cmdCfg.Contexts[DefaultCmdConfigName] = &api.Context{
		Cluster:  DefaultCmdConfigName,
		AuthInfo: DefaultCmdConfigName,
	}
	cmdCfg.CurrentContext = DefaultCmdConfigName

	return clientcmd.NewDefaultClientConfig(
		*cmdCfg,
		&clientcmd.ConfigOverrides{},
	)
}

// desc   : 为k8s客户端构建rest config
func (m *Manager) buildConfigFromFlags(apiserverHost, kubeConfigPath string) (*rest.Config, error) {
	if len(kubeConfigPath) > 0 || len(apiserverHost) > 0 {
		return clientcmd.NewNonInteractiveDeferredLoadingClientConfig(
			&clientcmd.ClientConfigLoadingRules{ExplicitPath: kubeConfigPath},
			&clientcmd.ConfigOverrides{ClusterInfo: api.Cluster{Server: apiserverHost}}).ClientConfig()
	}

	return nil, errors.New("could not create client config")
}

// 获取k8sMgr
func GetK8sMgr(restConfig *rest.Config) (Manager, error) {
	runClient, err := controller_runtime.New(restConfig, controller_runtime.Options{
		Scheme: AddToScheme(),
		Mapper: nil,
	})
	if err != nil {
		conf.Logger.Info("init controller_runtime err", zap.Error(err))
		return Manager{}, err
	}
	mgr.client = runClient
	// metics
	mc, err := metrics.NewForConfig(restConfig)
	if err != nil {
		conf.Logger.Info("init metrics.Clientset err", zap.Error(err))
		return mgr, err
	}
	mgr.metircs = mc
	return mgr, nil
}

// 添加 scheme
func AddToScheme() *runtime.Scheme {
	if err := v1.AddToScheme(scheme); err != nil {
		setupLog.Error(err, "add v1 scheme")
		os.Exit(1)
	}

	if err := v1beta1.AddToScheme(scheme); err != nil {
		setupLog.Error(err, "add v1beta2 scheme")
		os.Exit(1)
	}

	if err := corev1.AddToScheme(scheme); err != nil {
		setupLog.Error(err, "add core v1 scheme")
		os.Exit(1)
	}

	return scheme
}

// 查询dp
func (m *Manager) GetDeployment(namespace, name string) (obj *v1.Deployment, err error) {
	obj = &v1.Deployment{}
	ns := types.NamespacedName{Namespace: namespace, Name: name}
	if err = m.client.Get(context.Background(), ns, obj); err != nil {
		conf.Logger.Error("GetDeployment error", zap.Error(err))
		return nil, err
	}
	ls, err := m.metircs.MetricsV1beta1().NodeMetricses().List(context.Background(), metav1.ListOptions{})
	if err != nil {
		conf.Logger.Error("NodeMetricses", zap.Error(err))
	}
	fmt.Println("所有节点信息", ls)
	return obj, err
}

// 添加dp
func (m *Manager) AddDeployment(obj *v1.Deployment) (err error) {
	err = m.client.Create(context.Background(), obj)
	return err
}

// 更新dp
func (m *Manager) UpdateDeployment(obj *v1.Deployment) (err error) {
	return m.client.Update(context.Background(), obj)
}

// 删除dp
func (m *Manager) DeleteDeployment(namespace, name string) (err error) {
	obj := &v1.Deployment{}
	obj.Namespace = namespace
	obj.Name = name
	return m.client.Delete(context.Background(), obj)
}

// 添加svc
func (m *Manager) AddService(obj *corev1.Service) error {
	return m.client.Create(context.Background(), obj)
}

// 删除svc
func (m *Manager) DelService(obj *corev1.Service) error {
	return m.client.Delete(context.Background(), obj)
}

// 创建Endpoints
func (m *Manager) AddEndpoints(obj *corev1.Endpoints) error {
	return m.client.Create(context.Background(), obj)
}

// 删除Endpoints
func (m *Manager) DelEndpoints(obj *corev1.Endpoints) (err error) {
	return m.client.Delete(context.Background(), obj)
}

// 查询命名空间下的dp
func (m *Manager) GetDeploymentList(namespace string) (dps *v1.DeploymentList, err error) {
	dps = &v1.DeploymentList{}
	if err = m.client.List(context.Background(), dps, &client.ListOptions{Namespace: namespace}); err != nil {
		conf.Logger.Info("GetDeploymentList error", zap.Error(err))
		return nil, err
	}

	return
}

// 删除命名空间
func (m *Manager) DeleteNs(namespace string) (err error) {
	ns := &corev1.Namespace{}
	ns.ObjectMeta.Namespace = namespace
	return m.client.Delete(context.Background(), ns, &client.DeleteOptions{})
}

// GetPodsMetricses
func (m *Manager) GetPodsMetricses(namespace string) (obj *beta1.PodMetricsList, err error) {
	ls1, err := m.metircs.MetricsV1beta1().PodMetricses(namespace).List(context.Background(), metav1.ListOptions{})
	if err != nil {
		conf.Logger.Error("GetPodsMetricses err", zap.Error(err))
	}

	return ls1, nil
}

// GetPods
func (m *Manager) GetPods(namespace string) (obj *corev1.PodList, err error) {
	pods := &corev1.PodList{}
	if err = m.client.List(context.Background(), pods, &client.ListOptions{Namespace: namespace}); err != nil {
		conf.Logger.Info("GetPods error", zap.Error(err))
		return nil, err
	}

	return pods, nil
}

// 查询service
func (m *Manager) GetService(namespace, name string) (obj *corev1.Service, err error) {
	obj = &corev1.Service{}
	ns := types.NamespacedName{Namespace: namespace, Name: name}
	if err = m.client.Get(context.Background(), ns, obj); err != nil {
		conf.Logger.Error("GetService error", zap.Error(err))
		return nil, err
	}

	return obj, err
}

// GetServiceList
func (m *Manager) GetServiceList(namespace string) (obj *corev1.ServiceList, err error) {
	serviceList := &corev1.ServiceList{}
	if err = m.client.List(context.Background(), serviceList, &client.ListOptions{Namespace: namespace}); err != nil {
		conf.Logger.Info("GetServiceList error", zap.Error(err))
		return nil, err
	}

	return serviceList, nil
}

// GetIngressList
func (m *Manager) GetIngressList(namespace string) (obj *v12.IngressList, err error) {
	ingressList := &v12.IngressList{}
	if err = m.client.List(context.Background(), ingressList, &client.ListOptions{Namespace: namespace}); err != nil {
		conf.Logger.Info("GetIngressList error", zap.Error(err))
		return nil, err
	}

	return ingressList, nil
}

3、总结
上面GetK8sMgr()函数 ,入参为restConfig ,使用此参数,可以初始化多k8s集群client,切换不同k8s集群操作资源,k8s不同的资源在AddToScheme()函数中AddToScheme即可。如果想使用默认k8s集群(当前运行k8s集群),则可使用如下配置:

// 获取k8sMgr
func GetK8sMgr() (Manager, error) {
	runClient, err := controller_runtime.New(ctrl.GetConfigOrDie(), controller_runtime.Options{
		Scheme: AddToScheme(),
		Mapper: nil,
	})
	if err != nil {
		conf.Logger.Info("init controller_runtime err", zap.Error(err))
		return Manager{}, err
	}
	mgr.client = runClient
	// metics
	mc, err := metrics.NewForConfig(restConfig)
	if err != nil {
		conf.Logger.Info("init metrics.Clientset err", zap.Error(err))
		return mgr, err
	}
	mgr.metircs = mc
	return mgr, nil
}

ctrl.GetConfigOrDie()获取默认集群配置,详情可参考:https://www.cnblogs.com/zhangmingcheng/p/16098662.html

以上如对您有用或存在需纠正改进问题,欢迎评论区沟通交流。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值