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
以上如对您有用或存在需纠正改进问题,欢迎评论区沟通交流。