add kube state metrics
This commit is contained in:
194
plugins/inputs/kube_state/kubernetes_state_metrics.go
Normal file
194
plugins/inputs/kube_state/kubernetes_state_metrics.go
Normal file
@@ -0,0 +1,194 @@
|
||||
package kube_state
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/md5"
|
||||
"fmt"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"github.com/influxdata/telegraf"
|
||||
"github.com/influxdata/telegraf/filter"
|
||||
"github.com/influxdata/telegraf/internal"
|
||||
"github.com/influxdata/telegraf/internal/tls"
|
||||
"github.com/influxdata/telegraf/plugins/inputs"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
// KubenetesState represents the config object for the plugin.
|
||||
type KubenetesState struct {
|
||||
URL string
|
||||
|
||||
// Bearer Token authorization file path
|
||||
BearerToken string `toml:"bearer_token"`
|
||||
|
||||
// MaxConnections for worker pool tcp connections
|
||||
MaxConnections int `toml:"max_connections"`
|
||||
|
||||
// HTTP Timeout specified as a string - 3s, 1m, 1h
|
||||
ResponseTimeout internal.Duration `toml:"response_timeout"`
|
||||
|
||||
tls.ClientConfig
|
||||
|
||||
client *client
|
||||
rListHash string
|
||||
filter filter.Filter
|
||||
lastFilterBuilt int64
|
||||
ResourceListCheckInterval *internal.Duration `toml:"resouce_list_check_interval"`
|
||||
ResourceExclude []string `toml:"resource_exclude"`
|
||||
|
||||
DisablePodNonGenericResourceMetrics bool `json:"disable_pod_non_generic_resource_metrics"`
|
||||
DisableNodeNonGenericResourceMetrics bool `json:"disable_node_non_generic_resource_metrics"`
|
||||
}
|
||||
|
||||
var sampleConfig = `
|
||||
## URL for the kubelet
|
||||
url = "http://1.1.1.1:10255"
|
||||
|
||||
## Use bearer token for authorization
|
||||
# bearer_token = /path/to/bearer/token
|
||||
|
||||
## Set response_timeout (default 5 seconds)
|
||||
# response_timeout = "5s"
|
||||
|
||||
## Optional TLS Config
|
||||
# tls_ca = /path/to/cafile
|
||||
# tls_cert = /path/to/certfile
|
||||
# tls_key = /path/to/keyfile
|
||||
## Use TLS but skip chain & host verification
|
||||
# insecure_skip_verify = false
|
||||
|
||||
## Woker pool for kube_state_metric plugin only
|
||||
# empty this field will use default value 30
|
||||
# max_connections = 30
|
||||
`
|
||||
|
||||
//SampleConfig returns a sample config
|
||||
func (k *KubenetesState) SampleConfig() string {
|
||||
return sampleConfig
|
||||
}
|
||||
|
||||
//Description returns the description of this plugin
|
||||
func (k *KubenetesState) Description() string {
|
||||
return "Read metrics from the kubernetes kubelet api"
|
||||
}
|
||||
|
||||
//Gather collects kubernetes metrics from a given URL
|
||||
func (k *KubenetesState) Gather(acc telegraf.Accumulator) (err error) {
|
||||
var rList *metav1.APIResourceList
|
||||
if k.client == nil {
|
||||
if k.client, rList, err = k.initClient(); err != nil {
|
||||
return err
|
||||
}
|
||||
goto buildFilter
|
||||
}
|
||||
|
||||
if k.lastFilterBuilt > 0 && time.Now().Unix()-k.lastFilterBuilt < int64(k.ResourceListCheckInterval.Duration.Seconds()) {
|
||||
println("! skip to gather")
|
||||
goto doGather
|
||||
}
|
||||
|
||||
rList, err = k.client.getAPIResourceList(context.Background())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
buildFilter:
|
||||
k.lastFilterBuilt = time.Now().Unix()
|
||||
if err = k.buildFilter(rList); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
doGather:
|
||||
for n, f := range availableCollectors {
|
||||
ctx := context.Background()
|
||||
if k.filter.Match(n) {
|
||||
println("!", n)
|
||||
go f(ctx, acc, k)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (k *KubenetesState) buildFilter(rList *metav1.APIResourceList) error {
|
||||
hash, err := genHash(rList)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if k.rListHash == hash {
|
||||
return nil
|
||||
}
|
||||
k.rListHash = hash
|
||||
include := make([]string, len(rList.APIResources))
|
||||
for k, v := range rList.APIResources {
|
||||
include[k] = v.Name
|
||||
}
|
||||
k.filter, err = filter.NewIncludeExcludeFilter(include, k.ResourceExclude)
|
||||
return err
|
||||
}
|
||||
|
||||
func genHash(rList *metav1.APIResourceList) (string, error) {
|
||||
buf := new(bytes.Buffer)
|
||||
for _, v := range rList.APIResources {
|
||||
if _, err := buf.WriteString(v.Name + "|"); err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
sum := md5.Sum(buf.Bytes())
|
||||
return string(sum[:]), nil
|
||||
}
|
||||
|
||||
var availableCollectors = map[string]func(ctx context.Context, acc telegraf.Accumulator, k *KubenetesState){
|
||||
// "cronjobs": RegisterCronJobCollector,
|
||||
// "daemonsets": RegisterDaemonSetCollector,
|
||||
// "deployments": RegisterDeploymentCollector,
|
||||
// "jobs": RegisterJobCollector,
|
||||
// "limitranges": RegisterLimitRangeCollector,
|
||||
"nodes": registerNodeCollector,
|
||||
"pods": registerPodCollector,
|
||||
// "replicasets": RegisterReplicaSetCollector,
|
||||
// "replicationcontrollers": RegisterReplicationControllerCollector,
|
||||
// "resourcequotas": RegisterResourceQuotaCollector,
|
||||
// "services": RegisterServiceCollector,
|
||||
// "statefulsets": RegisterStatefulSetCollector,
|
||||
// "persistentvolumes": RegisterPersistentVolumeCollector,
|
||||
// "persistentvolumeclaims": RegisterPersistentVolumeClaimCollector,
|
||||
// "namespaces": RegisterNamespaceCollector,
|
||||
// "horizontalpodautoscalers": RegisterHorizontalPodAutoScalerCollector,
|
||||
// "endpoints": RegisterEndpointCollector,
|
||||
// "secrets": RegisterSecretCollector,
|
||||
"configmaps": registerConfigMapCollector,
|
||||
}
|
||||
|
||||
func (k *KubenetesState) initClient() (*client, *metav1.APIResourceList, error) {
|
||||
tlsCfg, err := k.ClientConfig.TLSConfig()
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("error parse kube state metrics config[%s]: %v", k.URL, err)
|
||||
}
|
||||
// default 30 concurrent TCP connections
|
||||
if k.MaxConnections == 0 {
|
||||
k.MaxConnections = 30
|
||||
}
|
||||
|
||||
// default check resourceList every hour
|
||||
if k.ResourceListCheckInterval == nil {
|
||||
k.ResourceListCheckInterval = &internal.Duration{
|
||||
Duration: time.Hour,
|
||||
}
|
||||
}
|
||||
c := newClient(k.URL, k.ResponseTimeout.Duration, k.MaxConnections, k.BearerToken, tlsCfg)
|
||||
rList, err := c.getAPIResourceList(context.Background())
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("error connect to kubenetes api endpoint[%s]: %v", k.URL, err)
|
||||
}
|
||||
log.Printf("I! Kubenetes API group version is %s", rList.GroupVersion)
|
||||
return c, rList, nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
inputs.Add("kubernetes_state", func() telegraf.Input {
|
||||
return &KubenetesState{}
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user