-
Notifications
You must be signed in to change notification settings - Fork 46
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #148 from axif0/Backend
Karmada Metrics Backend
- Loading branch information
Showing
16 changed files
with
1,426 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -28,3 +28,7 @@ charts/*/charts | |
cmd/ops | ||
.turbo | ||
.dockerconfigjson | ||
|
||
#local db files | ||
*.db | ||
*.db-journal |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package db | ||
|
||
const ( | ||
Namespace = "karmada-system" | ||
KarmadaAgent = "karmada-agent" | ||
KarmadaScheduler = "karmada-scheduler" | ||
KarmadaSchedulerEstimator = "karmada-scheduler-estimator" | ||
KarmadaControllerManager = "karmada-controller-manager" | ||
SchedulerPort = "10351" | ||
ControllerManagerPort = "8080" | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
package db | ||
|
||
type PodInfo struct { | ||
Name string `json:"name"` | ||
} | ||
|
||
type Metric struct { | ||
Name string `json:"name"` | ||
Help string `json:"help"` | ||
Type string `json:"type"` | ||
Values []MetricValue `json:"values,omitempty"` | ||
} | ||
|
||
type MetricValue struct { | ||
Labels map[string]string `json:"labels,omitempty"` | ||
Value string `json:"value"` | ||
Measure string `json:"measure"` | ||
} | ||
|
||
type ParsedData struct { | ||
CurrentTime string `json:"currentTime"` | ||
Metrics map[string]*Metric `json:"metrics"` | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
package app | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"github.com/spf13/cobra" | ||
cliflag "k8s.io/component-base/cli/flag" | ||
"k8s.io/klog/v2" | ||
"os" | ||
|
||
"github.com/karmada-io/dashboard/pkg/client" | ||
"github.com/karmada-io/dashboard/pkg/config" | ||
"github.com/karmada-io/dashboard/pkg/environment" | ||
"github.com/karmada-io/karmada/pkg/sharedcli/klogflag" | ||
"github.com/karmada-io/dashboard/cmd/metrics-scraper/app/router" | ||
"github.com/karmada-io/dashboard/cmd/metrics-scraper/app/scrape" | ||
"github.com/karmada-io/dashboard/cmd/metrics-scraper/app/routes/metrics" | ||
"github.com/karmada-io/dashboard/cmd/metrics-scraper/app/options" | ||
) | ||
|
||
// NewMetricsScraperCommand creates a *cobra.Command object with default parameters | ||
func NewMetricsScraperCommand(ctx context.Context) *cobra.Command { | ||
opts := options.NewOptions() | ||
cmd := &cobra.Command{ | ||
Use: "karmada-dashboard-metrics-scraper", | ||
Long: `The karmada-dashboard-metrics-scraper responsible for scraping and visualizing the metrics of karmada components. `, | ||
RunE: func(cmd *cobra.Command, args []string) error { | ||
if err := run(ctx, opts); err != nil { | ||
return err | ||
} | ||
return nil | ||
}, | ||
Args: func(cmd *cobra.Command, args []string) error { | ||
for _, arg := range args { | ||
if len(arg) > 0 { | ||
return fmt.Errorf("%q does not take any arguments, got %q", cmd.CommandPath(), args) | ||
} | ||
} | ||
return nil | ||
}, | ||
} | ||
fss := cliflag.NamedFlagSets{} | ||
|
||
genericFlagSet := fss.FlagSet("generic") | ||
opts.AddFlags(genericFlagSet) | ||
|
||
// Set klog flags | ||
logsFlagSet := fss.FlagSet("logs") | ||
klogflag.Add(logsFlagSet) | ||
|
||
cmd.Flags().AddFlagSet(genericFlagSet) | ||
cmd.Flags().AddFlagSet(logsFlagSet) | ||
return cmd | ||
} | ||
|
||
func run(ctx context.Context, opts *options.Options) error { | ||
klog.InfoS("Starting Karmada Dashboard API", "version", environment.Version) | ||
|
||
client.InitKarmadaConfig( | ||
client.WithUserAgent(environment.UserAgent()), | ||
client.WithKubeconfig(opts.KarmadaKubeConfig), | ||
client.WithKubeContext(opts.KarmadaContext), | ||
client.WithInsecureTLSSkipVerify(opts.SkipKarmadaApiserverTLSVerify), | ||
) | ||
|
||
client.InitKubeConfig( | ||
client.WithUserAgent(environment.UserAgent()), | ||
client.WithKubeconfig(opts.KubeConfig), | ||
client.WithKubeContext(opts.KubeContext), | ||
client.WithInsecureTLSSkipVerify(opts.SkipKubeApiserverTLSVerify), | ||
) | ||
ensureAPIServerConnectionOrDie() | ||
serve(opts) | ||
go scrape.InitDatabase() | ||
|
||
config.InitDashboardConfig(client.InClusterClient(), ctx.Done()) | ||
select { | ||
case <-ctx.Done(): | ||
os.Exit(0) | ||
} | ||
return nil | ||
} | ||
|
||
func serve(opts *options.Options) { | ||
insecureAddress := fmt.Sprintf("%s:%d", opts.InsecureBindAddress, opts.InsecurePort) | ||
klog.V(1).InfoS("Listening and serving on", "address", insecureAddress) | ||
go func() { | ||
klog.Fatal(router.Router().Run(insecureAddress)) | ||
}() | ||
} | ||
|
||
|
||
func ensureAPIServerConnectionOrDie() { | ||
versionInfo, err := client.InClusterClient().Discovery().ServerVersion() | ||
if err != nil { | ||
klog.Fatalf("Error while initializing connection to Kubernetes apiserver. "+ | ||
"This most likely means that the cluster is misconfigured. Reason: %s\n", err) | ||
os.Exit(1) | ||
} | ||
klog.InfoS("Successful initial request to the Kubernetes apiserver", "version", versionInfo.String()) | ||
|
||
karmadaVersionInfo, err := client.InClusterKarmadaClient().Discovery().ServerVersion() | ||
if err != nil { | ||
klog.Fatalf("Error while initializing connection to Karmada apiserver. "+ | ||
"This most likely means that the cluster is misconfigured. Reason: %s\n", err) | ||
os.Exit(1) | ||
} | ||
klog.InfoS("Successful initial request to the Karmada apiserver", "version", karmadaVersionInfo.String()) | ||
} | ||
|
||
func init() { | ||
r := router.V1() | ||
r.GET("/metrics", metrics.GetMetrics) | ||
r.GET("/metrics/:app_name", metrics.GetMetrics) | ||
r.GET("/metrics/:app_name/:pod_name", metrics.QueryMetrics) | ||
} | ||
|
||
// http://localhost:8000/api/v1/metrics/karmada-scheduler?type=metricsdetails //from sqlite details bar | ||
|
||
// http://localhost:8000/api/v1/metrics/karmada-scheduler/karmada-scheduler-7bd4659f9f-hh44f?type=details&mname=workqueue_queue_duration_seconds | ||
|
||
// http://localhost:8000/api/v1/metrics?type=sync_off // to skip all metrics | ||
|
||
// http://localhost:8000/api/v1/metrics/karmada-scheduler?type=sync_off // to skip specific metrics |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
package options | ||
|
||
import ( | ||
"github.com/spf13/pflag" | ||
"net" | ||
) | ||
|
||
// Options contains everything necessary to create and run api. | ||
type Options struct { | ||
BindAddress net.IP | ||
Port int | ||
InsecureBindAddress net.IP | ||
InsecurePort int | ||
KubeConfig string | ||
KubeContext string | ||
SkipKubeApiserverTLSVerify bool | ||
KarmadaKubeConfig string | ||
KarmadaContext string | ||
SkipKarmadaApiserverTLSVerify bool | ||
Namespace string | ||
DisableCSRFProtection bool | ||
OpenAPIEnabled bool | ||
} | ||
|
||
func NewOptions() *Options { | ||
return &Options{} | ||
} | ||
|
||
// AddFlags adds flags of api to the specified FlagSet | ||
func (o *Options) AddFlags(fs *pflag.FlagSet) { | ||
if o == nil { | ||
return | ||
} | ||
fs.IPVar(&o.BindAddress, "bind-address", net.IPv4(127, 0, 0, 1), "IP address on which to serve the --port, set to 0.0.0.0 for all interfaces") | ||
fs.IntVar(&o.Port, "port", 8001, "secure port to listen to for incoming HTTPS requests") | ||
fs.IPVar(&o.InsecureBindAddress, "insecure-bind-address", net.IPv4(127, 0, 0, 1), "IP address on which to serve the --insecure-port, set to 0.0.0.0 for all interfaces") | ||
fs.IntVar(&o.InsecurePort, "insecure-port", 8000, "port to listen to for incoming HTTP requests") | ||
fs.StringVar(&o.KubeConfig, "kubeconfig", "", "Path to the host cluster kubeconfig file.") | ||
fs.StringVar(&o.KubeContext, "context", "", "The name of the kubeconfig context to use.") | ||
fs.BoolVar(&o.SkipKubeApiserverTLSVerify, "skip-kube-apiserver-tls-verify", false, "enable if connection with remote Kubernetes API server should skip TLS verify") | ||
fs.StringVar(&o.KarmadaKubeConfig, "karmada-kubeconfig", "", "Path to the karmada control plane kubeconfig file.") | ||
fs.StringVar(&o.KarmadaContext, "karmada-context", "", "The name of the karmada-kubeconfig context to use.") | ||
fs.BoolVar(&o.SkipKarmadaApiserverTLSVerify, "skip-karmada-apiserver-tls-verify", false, "enable if connection with remote Karmada API server should skip TLS verify") | ||
fs.StringVar(&o.Namespace, "namespace", "karmada-dashboard", "Namespace to use when accessing Dashboard specific resources, i.e. configmap") | ||
fs.BoolVar(&o.DisableCSRFProtection, "disable-csrf-protection", false, "allows disabling CSRF protection") | ||
fs.BoolVar(&o.OpenAPIEnabled, "openapi-enabled", false, "enables OpenAPI v2 endpoint under '/apidocs.json'") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
package router | ||
|
||
import ( | ||
"github.com/gin-gonic/gin" | ||
"github.com/karmada-io/dashboard/pkg/environment" | ||
) | ||
|
||
var ( | ||
router *gin.Engine | ||
v1 *gin.RouterGroup | ||
) | ||
|
||
func init() { | ||
if !environment.IsDev() { | ||
gin.SetMode(gin.ReleaseMode) | ||
} | ||
|
||
router = gin.Default() | ||
_ = router.SetTrustedProxies(nil) | ||
v1 = router.Group("/api/v1") | ||
|
||
router.GET("/livez", func(c *gin.Context) { | ||
c.String(200, "livez") | ||
}) | ||
router.GET("/readyz", func(c *gin.Context) { | ||
c.String(200, "readyz") | ||
}) | ||
} | ||
|
||
func V1() *gin.RouterGroup { | ||
return v1 | ||
} | ||
|
||
func Router() *gin.Engine { | ||
return router | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
package metrics | ||
|
||
import ( | ||
"net/http" | ||
"github.com/karmada-io/dashboard/cmd/metrics-scraper/app/scrape" | ||
"github.com/gin-gonic/gin" | ||
) | ||
|
||
var requests = make(chan scrape.SaveRequest) | ||
|
||
func GetMetrics(c *gin.Context) { | ||
appName := c.Param("app_name") | ||
queryType := c.Query("type") | ||
|
||
if queryType == "sync_on" || queryType == "sync_off" { | ||
syncValue := 0 | ||
if queryType == "sync_on" { | ||
syncValue = 1 | ||
} | ||
scrape.HandleSyncOperation(c, appName, syncValue, queryType) | ||
return | ||
} | ||
|
||
if queryType == "metricsdetails" { | ||
QueryMetrics(c) | ||
return | ||
} | ||
|
||
if queryType == "sync_status" { | ||
scrape.CheckAppStatus(c) | ||
return | ||
} | ||
|
||
allMetrics, errors, err := scrape.FetchMetrics(c.Request.Context(), appName, requests) | ||
if err != nil { | ||
c.JSON(http.StatusInternalServerError, gin.H{"errors": errors, "error": err.Error()}) | ||
return | ||
} | ||
if len(allMetrics) > 0 { | ||
c.JSON(http.StatusOK, allMetrics) | ||
} else { | ||
c.JSON(http.StatusInternalServerError, gin.H{"error": "No metrics data found", "errors": errors}) | ||
} | ||
} |
Oops, something went wrong.