diff --git a/cmd/node_problem_detector.go b/cmd/node_problem_detector.go index 9caee0d0..4065cb17 100644 --- a/cmd/node_problem_detector.go +++ b/cmd/node_problem_detector.go @@ -24,6 +24,7 @@ import ( "k8s.io/node-problem-detector/cmd/options" "k8s.io/node-problem-detector/pkg/exporters/k8sexporter" + "k8s.io/node-problem-detector/pkg/exporters/prometheusexporter" "k8s.io/node-problem-detector/pkg/problemdaemon" "k8s.io/node-problem-detector/pkg/problemdetector" "k8s.io/node-problem-detector/pkg/types" @@ -57,6 +58,10 @@ func main() { exporters = append(exporters, ke) glog.Info("K8s exporter started.") } + if pe := prometheusexporter.NewExporterOrDie(npdo); pe != nil { + exporters = append(exporters, pe) + glog.Info("Prometheus exporter started.") + } if len(exporters) == 0 { glog.Fatalf("No exporter is successfully setup") } diff --git a/cmd/options/options.go b/cmd/options/options.go index d613a4fe..49062dc9 100644 --- a/cmd/options/options.go +++ b/cmd/options/options.go @@ -52,6 +52,12 @@ type NodeProblemDetectorOptions struct { // ApiServerOverride is the custom URI used to connect to Kubernetes ApiServer. ApiServerOverride string + // prometheusExporter options + // PrometheusServerPort is the port to bind the Prometheus scrape endpoint. Use 0 to disable. + PrometheusServerPort int + // PrometheusServerAddress is the address to bind the Prometheus scrape endpoint. + PrometheusServerAddress string + // problem daemon options // SystemLogMonitorConfigPaths specifies the list of paths to system log monitor configuration @@ -96,6 +102,11 @@ func (npdo *NodeProblemDetectorOptions) AddFlags(fs *pflag.FlagSet) { fs.StringVar(&npdo.ServerAddress, "address", "127.0.0.1", "The address to bind the node problem detector server.") + fs.IntVar(&npdo.PrometheusServerPort, "prometheus-port", + 20257, "The port to bind the Prometheus scrape endpoint. Prometheus exporter is enabled by default at port 20257. Use 0 to disable.") + fs.StringVar(&npdo.PrometheusServerAddress, "prometheus-address", + "127.0.0.1", "The address to bind the Prometheus scrape endpoint.") + for _, problemDaemonName := range problemdaemon.GetProblemDaemonNames() { npdo.MonitorConfigPaths[problemDaemonName] = &[]string{} fs.StringSliceVar( diff --git a/pkg/exporters/prometheusexporter/prometheus_exporter.go b/pkg/exporters/prometheusexporter/prometheus_exporter.go new file mode 100644 index 00000000..2d42dd69 --- /dev/null +++ b/pkg/exporters/prometheusexporter/prometheus_exporter.go @@ -0,0 +1,60 @@ +/* +Copyright 2019 The Kubernetes Authors All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package prometheusexporter + +import ( + "net" + "net/http" + "strconv" + + "contrib.go.opencensus.io/exporter/prometheus" + "github.com/golang/glog" + "go.opencensus.io/stats/view" + + "k8s.io/node-problem-detector/cmd/options" + "k8s.io/node-problem-detector/pkg/types" +) + +type prometheusExporter struct{} + +// NewExporterOrDie creates an exporter to export metrics to Prometheus, panics if error occurs. +func NewExporterOrDie(npdo *options.NodeProblemDetectorOptions) types.Exporter { + if npdo.PrometheusServerPort <= 0 { + return nil + } + + addr := net.JoinHostPort(npdo.PrometheusServerAddress, strconv.Itoa(npdo.PrometheusServerPort)) + pe, err := prometheus.NewExporter(prometheus.Options{}) + if err != nil { + glog.Fatalf("Failed to create Prometheus exporter: %v", err) + } + go func() { + mux := http.NewServeMux() + mux.Handle("/metrics", pe) + if err := http.ListenAndServe(addr, mux); err != nil { + glog.Fatalf("Failed to start Prometheus scrape endpoint: %v", err) + } + }() + view.RegisterExporter(pe) + return &prometheusExporter{} +} + +// ExportProblems does nothing. +// Prometheus exporter only exports metrics. +func (pe *prometheusExporter) ExportProblems(status *types.Status) { + return +}