Documentation ¶
Overview ¶
package externalmetrics provides a dirt simple, lightweight, easily exstensible external metrics api server for Kubernetes.
Why?
The officially supported method (https://github.com/kubernetes-sigs/custom-metrics-apiserver) is just f-ing inscruitable.
Not only that, but the documentation for what these servers need to do are awful. The best bet is a design doc on an old branch of some random kubernetes repo. The second bet is a medium article where someone describes how they discovered what one of these APIs needs to do, but not what that is.
This package is pretty simple; it has a New() function, an AddMetric() function, and a Serve() function.
No thrills, no tunables, bugger all excitement.
A complete form of the following example can be found in `./example`, but the nuts and bolts look like:
func main() { s := externalmetrics.New() s.AddMetric(context.Background(), externalmetrics.NamespaceAll, "my-metric", externalmetrics.Tick(time.Second), someIncrementingMetric) panic(s.Serve(listenAddr)) }
The function `someIncrementingMetric` might look like:
func someIncrementingMetric(ctx context.Context, namespace, name string) (result externalmetrics.Value, err error) { v := externalmetrics.NewValue(counterA) v.AddSelector("some-key", "A", counterA) v.AddSelector("some-key", "B", counterB) v.AddSelector("some-key", "C", counterC) return v, nil }
The metrics exposed by this service can then be exposed in an HPA
Index ¶
Constants ¶
const ( NamespaceAll = "*" NamespaceDefault = "default" )
Variables ¶
This section is empty.
Functions ¶
Types ¶
type MetricFunc ¶
MetricFunc is a function which is run on events to update the latest value of a metric
type Server ¶
type Server struct {
// contains filtered or unexported fields
}
Server provides an HTTP server, which provides metrics to horizontal pod autoscalers in the way which they expect.
This server handles things like retry logic, caching results, and handling namespacing of metrics, should they need it
func (*Server) AddMetric ¶
func (s *Server) AddMetric(ctx context.Context, namespace, name string, c <-chan context.Context, f MetricFunc)
AddMetric registers a new metric function against the server, along with and runs it every in a go func every time something triggers `c`
`c` could be anything from a time.Tick, to something listening out for external events
type Value ¶
type Value struct {
// contains filtered or unexported fields
}
Value is the value of a metric, either as a basic value, or as a set of selectors for more granular selections
func NewValue ¶
NewValue creates a simple Value, with an int64; this value is returned when an HPA makes a call without a specific selector, and so can be thought of as the base value
func (*Value) AddSelector ¶
AddSelector allows a value to contain a more granular value for HPAs that use labels
Why might you want this? Because each value creates a new go routine, with tickers, and notifiers, and so on, they can be quite expensive to run. If each metric requires a call to an external API, too, then the whole thing becomes a lot.
Not to mention the annoying thing of exposing a million dimensions like "/namespace/default/foo_A", "/namespace/default/foo_B", and "/namespace/default/foo_C" where they all do the same thing.
In this case, your MetricFunc merely needs to do:
v := NewValue(aValue) v.AddSelector("dimension", "A", aValue) v.AddSelector("dimension", "B", bValue) v.AddSelector("dimension", "C", cValue)
Which exposes the metric "/namespace/default/foo?labelSelector=dimension=A" (etc.)