mirror of
https://github.com/zalando-incubator/kube-metrics-adapter.git
synced 2026-07-11 23:31:00 +00:00
Compare commits
26
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
24b7276282 | ||
|
|
542d90d9fe | ||
|
|
0f359920af | ||
|
|
54e2d2d564 | ||
|
|
16ec43c361 | ||
|
|
ffcbfcee48 | ||
|
|
69f95534e8 | ||
|
|
c2179a35ba | ||
|
|
35e3fe83e8 | ||
|
|
69df60e724 | ||
|
|
d171e049bf | ||
|
|
b89ca19e6a | ||
|
|
a276b64576 | ||
|
|
ff6d479f1a | ||
|
|
cd986058e4 | ||
|
|
d6a33fed63 | ||
|
|
b8532b756b | ||
|
|
f28653de74 | ||
|
|
2f5d3f5a42 | ||
|
|
153d754353 | ||
|
|
02ec2282ab | ||
|
|
65dd585813 | ||
|
|
aa7b64e637 | ||
|
|
7633ac551e | ||
|
|
a103a3295e | ||
|
|
f63915f7ff |
@@ -4,7 +4,6 @@ run:
|
||||
linters:
|
||||
disable-all: true
|
||||
enable:
|
||||
- deadcode
|
||||
- errcheck
|
||||
- gosimple
|
||||
- govet
|
||||
@@ -12,4 +11,3 @@ linters:
|
||||
- staticcheck
|
||||
- typecheck
|
||||
- unused
|
||||
- varcheck
|
||||
|
||||
+1
-1
@@ -50,7 +50,7 @@ contribution is in line with our goals.
|
||||
- Make sure you sign-off on your commits `git commit -s -m "adding X to change Y"`
|
||||
- Write good commit messages (see below).
|
||||
- Push your changes to a topic branch in your fork of the repository.
|
||||
- As you push your changes, update the pull request with new infomation and tasks as you complete them
|
||||
- As you push your changes, update the pull request with new information and tasks as you complete them
|
||||
- Project maintainers might comment on your work as you progress
|
||||
- When you are done, remove the `work in progess` label and ping the maintainers for a review
|
||||
- Your pull request must receive a :thumbsup: from two [maintainers](MAINTAINERS)
|
||||
|
||||
@@ -402,6 +402,64 @@ the `backend` label under `matchLabels` for the metric. The ingress annotation
|
||||
where the backend weights can be obtained can be specified through the flag
|
||||
`--skipper-backends-annotation`.
|
||||
|
||||
## External RPS collector
|
||||
|
||||
The External RPS collector, like Skipper collector, is a simple wrapper around the Prometheus collector to
|
||||
make it easy to define an HPA for scaling based on the RPS measured for a given hostname. When
|
||||
[skipper](https://github.com/zalando/skipper) is used as the ingress
|
||||
implementation in your cluster everything should work automatically, in case another reverse proxy is used as ingress, like [Nginx](https://github.com/kubernetes/ingress-nginx) for example, its necessary to configure which prometheus metric should be used through `--external-rps-metric-name <metric-name>` flag. Assuming `skipper-ingress` is being used or the appropriate metric name is passed using the flag mentioned previously this collector provides the correct Prometheus queries out of the
|
||||
box so users don't have to define those manually.
|
||||
|
||||
### Supported metrics
|
||||
|
||||
| Metric | Description | Type | Kind | K8s Versions |
|
||||
| ------------ | -------------- | ------- | -- | -- |
|
||||
| `requests-per-second` | Scale based on requests per second for a certain hostname. | External | | `>=1.12` |
|
||||
|
||||
### Example: External Metric
|
||||
|
||||
This is an example of an HPA that will scale based on `requests-per-second` for the RPS measured in the hostnames called: `www.example1.com` and `www.example2.com`; and weighted by 42%.
|
||||
|
||||
```yaml
|
||||
apiVersion: autoscaling/v2
|
||||
kind: HorizontalPodAutoscaler
|
||||
metadata:
|
||||
name: myapp-hpa
|
||||
annotations:
|
||||
metric-config.external.example-rps.requests-per-second/hostname: www.example1.com,www.example2.com
|
||||
metric-config.external.example-rps.requests-per-second/weight: "42"
|
||||
spec:
|
||||
scaleTargetRef:
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
name: custom-metrics-consumer
|
||||
minReplicas: 1
|
||||
maxReplicas: 10
|
||||
metrics:
|
||||
- type: External
|
||||
external:
|
||||
metric:
|
||||
name: example-rps
|
||||
selector:
|
||||
matchLabels:
|
||||
type: requests-per-second
|
||||
target:
|
||||
type: AverageValue
|
||||
averageValue: "42"
|
||||
```
|
||||
### Multiple hostnames per metric
|
||||
|
||||
This metric supports a relation of n:1 between hostnames and metrics. The way it works is the measured RPS is the sum of the RPS rate of each of the specified hostnames. This value is further modified by the weight parameter explained below.
|
||||
|
||||
### Metric weighting based on backend
|
||||
|
||||
There are ingress-controllers, like skipper-ingress, that supports sending traffic to different backends based on some kind of configuration, in case of skipper annotations
|
||||
present on the `Ingress` object, or weights on the RouteGroup backends. By
|
||||
default the number of replicas will be calculated based on the full traffic
|
||||
served by these components. If however only the traffic being routed to
|
||||
a specific hostname should be used then the weight for the configured hostname(s) might be specified via the `weight` annotation `metric-config.external.<metric-name>.request-per-second/weight` for the metric being configured.
|
||||
|
||||
|
||||
## InfluxDB collector
|
||||
|
||||
The InfluxDB collector maps [Flux](https://github.com/influxdata/flux) queries to metrics that can be used for scaling.
|
||||
|
||||
@@ -56,7 +56,7 @@ spec:
|
||||
properties:
|
||||
date:
|
||||
description: Defines the starting date of a OneTime schedule.
|
||||
It has to be a RFC3339 formated date.
|
||||
It has to be a RFC3339 formatted date.
|
||||
format: date-time
|
||||
type: string
|
||||
durationMinutes:
|
||||
@@ -65,7 +65,7 @@ spec:
|
||||
type: integer
|
||||
endDate:
|
||||
description: Defines the ending date of a OneTime schedule.
|
||||
It must be a RFC3339 formated date.
|
||||
It must be a RFC3339 formatted date.
|
||||
format: date-time
|
||||
type: string
|
||||
period:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
apiVersion: v2
|
||||
name: kube-metrics-adapter
|
||||
version: 0.1.18
|
||||
version: 0.2.0
|
||||
description: kube-metrics-adapter helm chart
|
||||
home: https://github.com/zalando-incubator/kube-metrics-adapter
|
||||
maintainers:
|
||||
|
||||
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.5.0
|
||||
controller-gen.kubebuilder.io/version: v0.8.0
|
||||
creationTimestamp: null
|
||||
name: clusterscalingschedules.zalando.org
|
||||
spec:
|
||||
@@ -15,7 +15,12 @@ spec:
|
||||
singular: clusterscalingschedule
|
||||
scope: Cluster
|
||||
versions:
|
||||
- name: v1
|
||||
- additionalPrinterColumns:
|
||||
- description: Whether one or more schedules are currently active.
|
||||
jsonPath: .status.active
|
||||
name: Active
|
||||
type: boolean
|
||||
name: v1
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
description: ClusterScalingSchedule describes a cluster scoped time based
|
||||
@@ -36,6 +41,11 @@ spec:
|
||||
spec:
|
||||
description: ScalingScheduleSpec is the spec part of the ScalingSchedule.
|
||||
properties:
|
||||
scalingWindowDurationMinutes:
|
||||
description: Fade the scheduled values in and out over this many minutes.
|
||||
If unset, the default per-cluster value will be used.
|
||||
format: int64
|
||||
type: integer
|
||||
schedules:
|
||||
description: Schedules is the list of schedules for this ScalingSchedule
|
||||
resource. All the schedules defined here will result on the value
|
||||
@@ -46,13 +56,18 @@ spec:
|
||||
properties:
|
||||
date:
|
||||
description: Defines the starting date of a OneTime schedule.
|
||||
It has to be a RFC3339 formated date.
|
||||
It has to be a RFC3339 formatted date.
|
||||
format: date-time
|
||||
type: string
|
||||
durationMinutes:
|
||||
description: The duration in minutes that the configured value
|
||||
will be returned for the defined schedule.
|
||||
description: The duration in minutes (default 0) that the configured
|
||||
value will be returned for the defined schedule.
|
||||
type: integer
|
||||
endDate:
|
||||
description: Defines the ending date of a OneTime schedule.
|
||||
It must be a RFC3339 formatted date.
|
||||
format: date-time
|
||||
type: string
|
||||
period:
|
||||
description: Defines the details of a Repeating schedule.
|
||||
properties:
|
||||
@@ -71,6 +86,10 @@ spec:
|
||||
- Sat
|
||||
type: string
|
||||
type: array
|
||||
endTime:
|
||||
description: The endTime has the format HH:MM
|
||||
pattern: (([0-1][0-9])|([2][0-3])):([0-5][0-9])
|
||||
type: string
|
||||
startTime:
|
||||
description: The startTime has the format HH:MM
|
||||
pattern: (([0-1][0-9])|([2][0-3])):([0-5][0-9])
|
||||
@@ -95,9 +114,9 @@ spec:
|
||||
value:
|
||||
description: The metric value that will be returned for the
|
||||
defined schedule.
|
||||
format: int64
|
||||
type: integer
|
||||
required:
|
||||
- durationMinutes
|
||||
- type
|
||||
- value
|
||||
type: object
|
||||
@@ -105,11 +124,22 @@ spec:
|
||||
required:
|
||||
- schedules
|
||||
type: object
|
||||
status:
|
||||
description: ScalingScheduleStatus is the status section of the ScalingSchedule.
|
||||
properties:
|
||||
active:
|
||||
default: false
|
||||
description: Active is true if at least one of the schedules defined
|
||||
in the scaling schedule is currently active.
|
||||
type: boolean
|
||||
type: object
|
||||
required:
|
||||
- spec
|
||||
type: object
|
||||
served: true
|
||||
storage: true
|
||||
subresources:
|
||||
status: {}
|
||||
status:
|
||||
acceptedNames:
|
||||
kind: ""
|
||||
|
||||
@@ -164,6 +164,9 @@ spec:
|
||||
{{- if .Values.skipperIngressMetrics }}
|
||||
- --skipper-ingress-metrics={{ .Values.skipperIngressMetrics }}
|
||||
{{- end}}
|
||||
{{- if .Values.skipperRouteGroupMetrics }}
|
||||
- --skipper-routegroup-metrics={{ .Values.skipperRouteGroupMetrics }}
|
||||
{{- end}}
|
||||
{{- if .Values.log.stderrThreshold }}
|
||||
- --stderrthreshold={{ .Values.log.stderrThreshold }}
|
||||
{{- end}}
|
||||
|
||||
@@ -59,12 +59,22 @@ rules:
|
||||
- statefulsets
|
||||
verbs:
|
||||
- get
|
||||
{{- if .Values.skipperRouteGroupMetrics }}
|
||||
- apiGroups:
|
||||
- networking.k8s.io
|
||||
resources:
|
||||
- ingresses
|
||||
verbs:
|
||||
- get
|
||||
{{- end }}
|
||||
{{- if .Values.skipperRouteGroupMetrics }}
|
||||
- apiGroups:
|
||||
- zalando.org
|
||||
resources:
|
||||
- routegroups
|
||||
verbs:
|
||||
- get
|
||||
{{- end }}
|
||||
- apiGroups:
|
||||
- autoscaling
|
||||
resources:
|
||||
@@ -83,6 +93,13 @@ rules:
|
||||
- get
|
||||
- list
|
||||
- watch
|
||||
- apiGroups:
|
||||
- zalando.org
|
||||
resources:
|
||||
- clusterscalingschedules/status
|
||||
- scalingschedules/status
|
||||
verbs:
|
||||
- update
|
||||
{{- end}}
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
|
||||
@@ -3,19 +3,26 @@ apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.5.0
|
||||
controller-gen.kubebuilder.io/version: v0.8.0
|
||||
creationTimestamp: null
|
||||
name: scalingschedules.zalando.org
|
||||
spec:
|
||||
group: zalando.org
|
||||
names:
|
||||
categories:
|
||||
- all
|
||||
kind: ScalingSchedule
|
||||
listKind: ScalingScheduleList
|
||||
plural: scalingschedules
|
||||
singular: scalingschedule
|
||||
scope: Namespaced
|
||||
versions:
|
||||
- name: v1
|
||||
- additionalPrinterColumns:
|
||||
- description: Whether one or more schedules are currently active.
|
||||
jsonPath: .status.active
|
||||
name: Active
|
||||
type: boolean
|
||||
name: v1
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
description: ScalingSchedule describes a namespaced time based metric to be
|
||||
@@ -36,6 +43,11 @@ spec:
|
||||
spec:
|
||||
description: ScalingScheduleSpec is the spec part of the ScalingSchedule.
|
||||
properties:
|
||||
scalingWindowDurationMinutes:
|
||||
description: Fade the scheduled values in and out over this many minutes.
|
||||
If unset, the default per-cluster value will be used.
|
||||
format: int64
|
||||
type: integer
|
||||
schedules:
|
||||
description: Schedules is the list of schedules for this ScalingSchedule
|
||||
resource. All the schedules defined here will result on the value
|
||||
@@ -46,13 +58,18 @@ spec:
|
||||
properties:
|
||||
date:
|
||||
description: Defines the starting date of a OneTime schedule.
|
||||
It has to be a RFC3339 formated date.
|
||||
It has to be a RFC3339 formatted date.
|
||||
format: date-time
|
||||
type: string
|
||||
durationMinutes:
|
||||
description: The duration in minutes that the configured value
|
||||
will be returned for the defined schedule.
|
||||
description: The duration in minutes (default 0) that the configured
|
||||
value will be returned for the defined schedule.
|
||||
type: integer
|
||||
endDate:
|
||||
description: Defines the ending date of a OneTime schedule.
|
||||
It must be a RFC3339 formatted date.
|
||||
format: date-time
|
||||
type: string
|
||||
period:
|
||||
description: Defines the details of a Repeating schedule.
|
||||
properties:
|
||||
@@ -71,6 +88,10 @@ spec:
|
||||
- Sat
|
||||
type: string
|
||||
type: array
|
||||
endTime:
|
||||
description: The endTime has the format HH:MM
|
||||
pattern: (([0-1][0-9])|([2][0-3])):([0-5][0-9])
|
||||
type: string
|
||||
startTime:
|
||||
description: The startTime has the format HH:MM
|
||||
pattern: (([0-1][0-9])|([2][0-3])):([0-5][0-9])
|
||||
@@ -95,9 +116,9 @@ spec:
|
||||
value:
|
||||
description: The metric value that will be returned for the
|
||||
defined schedule.
|
||||
format: int64
|
||||
type: integer
|
||||
required:
|
||||
- durationMinutes
|
||||
- type
|
||||
- value
|
||||
type: object
|
||||
@@ -105,11 +126,22 @@ spec:
|
||||
required:
|
||||
- schedules
|
||||
type: object
|
||||
status:
|
||||
description: ScalingScheduleStatus is the status section of the ScalingSchedule.
|
||||
properties:
|
||||
active:
|
||||
default: false
|
||||
description: Active is true if at least one of the schedules defined
|
||||
in the scaling schedule is currently active.
|
||||
type: boolean
|
||||
type: object
|
||||
required:
|
||||
- spec
|
||||
type: object
|
||||
served: true
|
||||
storage: true
|
||||
subresources:
|
||||
status: {}
|
||||
status:
|
||||
acceptedNames:
|
||||
kind: ""
|
||||
|
||||
@@ -4,7 +4,7 @@ replicas: 1
|
||||
|
||||
registry:
|
||||
image: registry.opensource.zalan.do/teapot/kube-metrics-adapter
|
||||
imageTag: v0.1.10
|
||||
imageTag: v0.2.0
|
||||
imagePullPolicy: IfNotPresent
|
||||
|
||||
service:
|
||||
@@ -22,6 +22,7 @@ http2MaxStreamsPerConnection:
|
||||
listerKubeConfig:
|
||||
skipperBackendsAnnotation:
|
||||
skipperIngressMetrics:
|
||||
skipperRouteGroupMetrics:
|
||||
token:
|
||||
vmodule:
|
||||
|
||||
|
||||
@@ -58,7 +58,7 @@ spec:
|
||||
properties:
|
||||
date:
|
||||
description: Defines the starting date of a OneTime schedule.
|
||||
It has to be a RFC3339 formated date.
|
||||
It has to be a RFC3339 formatted date.
|
||||
format: date-time
|
||||
type: string
|
||||
durationMinutes:
|
||||
@@ -67,7 +67,7 @@ spec:
|
||||
type: integer
|
||||
endDate:
|
||||
description: Defines the ending date of a OneTime schedule.
|
||||
It must be a RFC3339 formated date.
|
||||
It must be a RFC3339 formatted date.
|
||||
format: date-time
|
||||
type: string
|
||||
period:
|
||||
|
||||
@@ -1,34 +1,33 @@
|
||||
module github.com/zalando-incubator/kube-metrics-adapter
|
||||
|
||||
require (
|
||||
github.com/aws/aws-sdk-go v1.44.254
|
||||
github.com/aws/aws-sdk-go v1.44.299
|
||||
github.com/influxdata/influxdb-client-go v0.2.0
|
||||
github.com/prometheus/client_golang v1.15.0
|
||||
github.com/prometheus/common v0.42.0
|
||||
github.com/sirupsen/logrus v1.9.0
|
||||
github.com/prometheus/client_golang v1.16.0
|
||||
github.com/prometheus/common v0.44.0
|
||||
github.com/sirupsen/logrus v1.9.3
|
||||
github.com/spf13/cobra v1.7.0
|
||||
github.com/spyzhov/ajson v0.7.2
|
||||
github.com/stretchr/testify v1.8.2
|
||||
github.com/spyzhov/ajson v0.8.0
|
||||
github.com/stretchr/testify v1.8.4
|
||||
github.com/szuecs/routegroup-client v0.21.1
|
||||
github.com/zalando-incubator/cluster-lifecycle-manager v0.0.0-20230223125308-aff25efae501
|
||||
golang.org/x/net v0.9.0
|
||||
golang.org/x/oauth2 v0.7.0
|
||||
golang.org/x/sync v0.1.0
|
||||
k8s.io/api v0.23.0
|
||||
k8s.io/apimachinery v0.23.0
|
||||
k8s.io/apiserver v0.23.0
|
||||
k8s.io/client-go v0.23.0
|
||||
k8s.io/code-generator v0.23.0
|
||||
k8s.io/component-base v0.23.0
|
||||
github.com/zalando-incubator/cluster-lifecycle-manager v0.0.0-20230601114834-6ed1bba3c85d
|
||||
golang.org/x/net v0.12.0
|
||||
golang.org/x/oauth2 v0.10.0
|
||||
golang.org/x/sync v0.3.0
|
||||
k8s.io/api v0.23.17
|
||||
k8s.io/apimachinery v0.23.17
|
||||
k8s.io/apiserver v0.23.17
|
||||
k8s.io/client-go v0.23.17
|
||||
k8s.io/code-generator v0.23.17
|
||||
k8s.io/component-base v0.23.17
|
||||
k8s.io/klog v1.0.0
|
||||
k8s.io/kube-openapi v0.0.0-20220124234850-424119656bbf
|
||||
k8s.io/metrics v0.22.17
|
||||
k8s.io/kube-openapi v0.0.0-20230614213217-ba0abe644833
|
||||
k8s.io/metrics v0.23.17
|
||||
sigs.k8s.io/controller-tools v0.8.0
|
||||
sigs.k8s.io/custom-metrics-apiserver v1.22.0
|
||||
)
|
||||
|
||||
require (
|
||||
cloud.google.com/go/compute/metadata v0.2.3 // indirect
|
||||
github.com/NYTimes/gziphandler v1.1.1 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/blang/semver v3.5.1+incompatible // indirect
|
||||
@@ -41,10 +40,10 @@ require (
|
||||
github.com/fatih/color v1.13.0 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.3 // indirect
|
||||
github.com/fsnotify/fsnotify v1.6.0 // indirect
|
||||
github.com/go-logr/logr v1.2.3 // indirect
|
||||
github.com/go-logr/logr v1.2.4 // indirect
|
||||
github.com/go-openapi/jsonpointer v0.19.6 // indirect
|
||||
github.com/go-openapi/jsonreference v0.20.2 // indirect
|
||||
github.com/go-openapi/swag v0.22.3 // indirect
|
||||
github.com/go-openapi/swag v0.22.4 // indirect
|
||||
github.com/gobuffalo/flect v0.2.3 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
|
||||
@@ -56,7 +55,7 @@ require (
|
||||
github.com/googleapis/gnostic v0.5.5 // indirect
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 // indirect
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect
|
||||
github.com/imdario/mergo v0.3.13 // indirect
|
||||
github.com/imdario/mergo v0.3.16 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/influxdata/line-protocol v0.0.0-20210922203350-b1ad95c89adf // indirect
|
||||
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
||||
@@ -71,47 +70,48 @@ require (
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/prometheus/client_model v0.3.0 // indirect
|
||||
github.com/prometheus/procfs v0.9.0 // indirect
|
||||
github.com/prometheus/client_model v0.4.0 // indirect
|
||||
github.com/prometheus/procfs v0.10.1 // indirect
|
||||
github.com/rogpeppe/go-internal v1.11.0 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
go.etcd.io/etcd/api/v3 v3.5.6 // indirect
|
||||
go.etcd.io/etcd/client/pkg/v3 v3.5.6 // indirect
|
||||
go.etcd.io/etcd/client/v2 v2.305.6 // indirect
|
||||
go.etcd.io/etcd/client/v3 v3.5.6 // indirect
|
||||
go.etcd.io/etcd/api/v3 v3.5.9 // indirect
|
||||
go.etcd.io/etcd/client/pkg/v3 v3.5.9 // indirect
|
||||
go.etcd.io/etcd/client/v2 v2.305.7 // indirect
|
||||
go.etcd.io/etcd/client/v3 v3.5.9 // indirect
|
||||
go.opentelemetry.io/contrib v0.20.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.20.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.20.0 // indirect
|
||||
go.opentelemetry.io/otel v1.11.1 // indirect
|
||||
go.opentelemetry.io/otel v1.14.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp v0.20.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v0.20.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk v1.11.1 // indirect
|
||||
go.opentelemetry.io/otel/sdk v1.14.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk/export/metric v0.20.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk/metric v0.20.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.11.1 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.14.0 // indirect
|
||||
go.opentelemetry.io/proto/otlp v0.7.0 // indirect
|
||||
go.uber.org/atomic v1.9.0 // indirect
|
||||
go.uber.org/multierr v1.8.0 // indirect
|
||||
go.uber.org/zap v1.21.0 // indirect
|
||||
golang.org/x/crypto v0.6.0 // indirect
|
||||
golang.org/x/mod v0.8.0 // indirect
|
||||
golang.org/x/sys v0.7.0 // indirect
|
||||
golang.org/x/term v0.7.0 // indirect
|
||||
golang.org/x/text v0.9.0 // indirect
|
||||
golang.org/x/crypto v0.11.0 // indirect
|
||||
golang.org/x/mod v0.12.0 // indirect
|
||||
golang.org/x/sys v0.10.0 // indirect
|
||||
golang.org/x/term v0.10.0 // indirect
|
||||
golang.org/x/text v0.11.0 // indirect
|
||||
golang.org/x/time v0.3.0 // indirect
|
||||
golang.org/x/tools v0.6.0 // indirect
|
||||
golang.org/x/tools v0.11.0 // indirect
|
||||
google.golang.org/appengine v1.6.7 // indirect
|
||||
google.golang.org/genproto v0.0.0-20221227171554-f9683d7f8bef // indirect
|
||||
google.golang.org/grpc v1.52.0 // indirect
|
||||
google.golang.org/protobuf v1.30.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect
|
||||
google.golang.org/grpc v1.55.0 // indirect
|
||||
google.golang.org/protobuf v1.31.0 // indirect
|
||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
k8s.io/apiextensions-apiserver v0.23.0 // indirect
|
||||
k8s.io/gengo v0.0.0-20210813121822-485abfe95c7c // indirect
|
||||
k8s.io/klog/v2 v2.90.0 // indirect
|
||||
k8s.io/utils v0.0.0-20230220204549-a5ecb0141aa5 // indirect
|
||||
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.30 // indirect
|
||||
k8s.io/klog/v2 v2.100.1 // indirect
|
||||
k8s.io/utils v0.0.0-20230711102312-30195339c3c7 // indirect
|
||||
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.35 // indirect
|
||||
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect
|
||||
sigs.k8s.io/yaml v1.3.0 // indirect
|
||||
@@ -121,6 +121,7 @@ replace (
|
||||
go.opentelemetry.io/otel => go.opentelemetry.io/otel v0.20.0
|
||||
go.opentelemetry.io/otel/sdk => go.opentelemetry.io/otel/sdk v0.20.0
|
||||
go.opentelemetry.io/otel/trace => go.opentelemetry.io/otel/trace v0.20.0
|
||||
k8s.io/kube-openapi => k8s.io/kube-openapi v0.0.0-20211115234752-e816edb12b65
|
||||
)
|
||||
|
||||
go 1.20
|
||||
|
||||
@@ -2366,7 +2366,7 @@ func schema_k8sio_api_core_v1_EndpointSubset(ref common.ReferenceCallback) commo
|
||||
return common.OpenAPIDefinition{
|
||||
Schema: spec.Schema{
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "EndpointSubset is a group of addresses with a common set of ports. The expanded set of endpoints is the Cartesian product of Addresses x Ports. For example, given:\n {\n Addresses: [{\"ip\": \"10.10.1.1\"}, {\"ip\": \"10.10.2.2\"}],\n Ports: [{\"name\": \"a\", \"port\": 8675}, {\"name\": \"b\", \"port\": 309}]\n }\nThe resulting set of endpoints can be viewed as:\n a: [ 10.10.1.1:8675, 10.10.2.2:8675 ],\n b: [ 10.10.1.1:309, 10.10.2.2:309 ]",
|
||||
Description: "EndpointSubset is a group of addresses with a common set of ports. The expanded set of endpoints is the Cartesian product of Addresses x Ports. For example, given:\n\n\t{\n\t Addresses: [{\"ip\": \"10.10.1.1\"}, {\"ip\": \"10.10.2.2\"}],\n\t Ports: [{\"name\": \"a\", \"port\": 8675}, {\"name\": \"b\", \"port\": 309}]\n\t}\n\nThe resulting set of endpoints can be viewed as:\n\n\ta: [ 10.10.1.1:8675, 10.10.2.2:8675 ],\n\tb: [ 10.10.1.1:309, 10.10.2.2:309 ]",
|
||||
Type: []string{"object"},
|
||||
Properties: map[string]spec.Schema{
|
||||
"addresses": {
|
||||
@@ -2423,7 +2423,7 @@ func schema_k8sio_api_core_v1_Endpoints(ref common.ReferenceCallback) common.Ope
|
||||
return common.OpenAPIDefinition{
|
||||
Schema: spec.Schema{
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "Endpoints is a collection of endpoints that implement the actual service. Example:\n Name: \"mysvc\",\n Subsets: [\n {\n Addresses: [{\"ip\": \"10.10.1.1\"}, {\"ip\": \"10.10.2.2\"}],\n Ports: [{\"name\": \"a\", \"port\": 8675}, {\"name\": \"b\", \"port\": 309}]\n },\n {\n Addresses: [{\"ip\": \"10.10.3.3\"}],\n Ports: [{\"name\": \"a\", \"port\": 93}, {\"name\": \"b\", \"port\": 76}]\n },\n ]",
|
||||
Description: "Endpoints is a collection of endpoints that implement the actual service. Example:\n\n\t Name: \"mysvc\",\n\t Subsets: [\n\t {\n\t Addresses: [{\"ip\": \"10.10.1.1\"}, {\"ip\": \"10.10.2.2\"}],\n\t Ports: [{\"name\": \"a\", \"port\": 8675}, {\"name\": \"b\", \"port\": 309}]\n\t },\n\t {\n\t Addresses: [{\"ip\": \"10.10.3.3\"}],\n\t Ports: [{\"name\": \"a\", \"port\": 93}, {\"name\": \"b\", \"port\": 76}]\n\t },\n\t]",
|
||||
Type: []string{"object"},
|
||||
Properties: map[string]spec.Schema{
|
||||
"kind": {
|
||||
@@ -4327,11 +4327,11 @@ func schema_k8sio_api_core_v1_LimitRangeItem(ref common.ReferenceCallback) commo
|
||||
Properties: map[string]spec.Schema{
|
||||
"type": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "Type of resource that this limit applies to.\n\nPossible enum values:\n - `\"Container\"` Limit that applies to all containers in a namespace\n - `\"PersistentVolumeClaim\"` Limit that applies to all persistent volume claims in a namespace\n - `\"Pod\"` Limit that applies to all pods in a namespace",
|
||||
Description: "Type of resource that this limit applies to.",
|
||||
Default: "",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
Enum: []interface{}{"Container", "PersistentVolumeClaim", "Pod"}},
|
||||
},
|
||||
},
|
||||
"max": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
@@ -4776,11 +4776,11 @@ func schema_k8sio_api_core_v1_NamespaceCondition(ref common.ReferenceCallback) c
|
||||
Properties: map[string]spec.Schema{
|
||||
"type": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "Type of namespace controller condition.\n\nPossible enum values:\n - `\"NamespaceContentRemaining\"` contains information about resources remaining in a namespace.\n - `\"NamespaceDeletionContentFailure\"` contains information about namespace deleter errors during deletion of resources.\n - `\"NamespaceDeletionDiscoveryFailure\"` contains information about namespace deleter errors during resource discovery.\n - `\"NamespaceDeletionGroupVersionParsingFailure\"` contains information about namespace deleter errors parsing GV for legacy types.\n - `\"NamespaceFinalizersRemaining\"` contains information about which finalizers are on resources remaining in a namespace.",
|
||||
Description: "Type of namespace controller condition.",
|
||||
Default: "",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
Enum: []interface{}{"NamespaceContentRemaining", "NamespaceDeletionContentFailure", "NamespaceDeletionDiscoveryFailure", "NamespaceDeletionGroupVersionParsingFailure", "NamespaceFinalizersRemaining"}},
|
||||
},
|
||||
},
|
||||
"status": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
@@ -4997,11 +4997,11 @@ func schema_k8sio_api_core_v1_NodeAddress(ref common.ReferenceCallback) common.O
|
||||
Properties: map[string]spec.Schema{
|
||||
"type": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "Node address type, one of Hostname, ExternalIP or InternalIP.\n\nPossible enum values:\n - `\"ExternalDNS\"` identifies a DNS name which resolves to an IP address which has the characteristics of a NodeExternalIP. The IP it resolves to may or may not be a listed NodeExternalIP address.\n - `\"ExternalIP\"` identifies an IP address which is, in some way, intended to be more usable from outside the cluster then an internal IP, though no specific semantics are defined. It may be a globally routable IP, though it is not required to be. External IPs may be assigned directly to an interface on the node, like a NodeInternalIP, or alternatively, packets sent to the external IP may be NAT'ed to an internal node IP rather than being delivered directly (making the IP less efficient for node-to-node traffic than a NodeInternalIP).\n - `\"Hostname\"` identifies a name of the node. Although every node can be assumed to have a NodeAddress of this type, its exact syntax and semantics are not defined, and are not consistent between different clusters.\n - `\"InternalDNS\"` identifies a DNS name which resolves to an IP address which has the characteristics of a NodeInternalIP. The IP it resolves to may or may not be a listed NodeInternalIP address.\n - `\"InternalIP\"` identifies an IP address which is assigned to one of the node's network interfaces. Every node should have at least one address of this type. An internal IP is normally expected to be reachable from every other node, but may not be visible to hosts outside the cluster. By default it is assumed that kube-apiserver can reach node internal IPs, though it is possible to configure clusters where this is not the case. NodeInternalIP is the default type of node IP, and does not necessarily imply that the IP is ONLY reachable internally. If a node has multiple internal IPs, no specific semantics are assigned to the additional IPs.",
|
||||
Description: "Node address type, one of Hostname, ExternalIP or InternalIP.",
|
||||
Default: "",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
Enum: []interface{}{"ExternalDNS", "ExternalIP", "Hostname", "InternalDNS", "InternalIP"}},
|
||||
},
|
||||
},
|
||||
"address": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
@@ -5062,11 +5062,11 @@ func schema_k8sio_api_core_v1_NodeCondition(ref common.ReferenceCallback) common
|
||||
Properties: map[string]spec.Schema{
|
||||
"type": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "Type of node condition.\n\nPossible enum values:\n - `\"DiskPressure\"` means the kubelet is under pressure due to insufficient available disk.\n - `\"MemoryPressure\"` means the kubelet is under pressure due to insufficient available memory.\n - `\"NetworkUnavailable\"` means that network for the node is not correctly configured.\n - `\"PIDPressure\"` means the kubelet is under pressure due to insufficient available PID.\n - `\"Ready\"` means kubelet is healthy and ready to accept pods.",
|
||||
Description: "Type of node condition.",
|
||||
Default: "",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
Enum: []interface{}{"DiskPressure", "MemoryPressure", "NetworkUnavailable", "PIDPressure", "Ready"}},
|
||||
},
|
||||
},
|
||||
"status": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
@@ -5982,11 +5982,10 @@ func schema_k8sio_api_core_v1_PersistentVolumeClaimCondition(ref common.Referenc
|
||||
Properties: map[string]spec.Schema{
|
||||
"type": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "\n\n\nPossible enum values:\n - `\"FileSystemResizePending\"` - controller resize is finished and a file system resize is pending on node\n - `\"Resizing\"` - a user trigger resize of pvc has been started",
|
||||
Default: "",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
Enum: []interface{}{"FileSystemResizePending", "Resizing"}},
|
||||
Default: "",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
"status": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
@@ -7056,11 +7055,11 @@ func schema_k8sio_api_core_v1_PodCondition(ref common.ReferenceCallback) common.
|
||||
Properties: map[string]spec.Schema{
|
||||
"type": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "Type is the type of the condition. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-conditions\n\nPossible enum values:\n - `\"ContainersReady\"` indicates whether all containers in the pod are ready.\n - `\"Initialized\"` means that all init containers in the pod have started successfully.\n - `\"PodScheduled\"` represents status of the scheduling process for this pod.\n - `\"Ready\"` means the pod is able to service requests and should be added to the load balancing pools of all matching services.",
|
||||
Description: "Type is the type of the condition. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-conditions",
|
||||
Default: "",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
Enum: []interface{}{"ContainersReady", "Initialized", "PodScheduled", "Ready"}},
|
||||
},
|
||||
},
|
||||
"status": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
@@ -7274,7 +7273,7 @@ func schema_k8sio_api_core_v1_PodIP(ref common.ReferenceCallback) common.OpenAPI
|
||||
return common.OpenAPIDefinition{
|
||||
Schema: spec.Schema{
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "IP address information for entries in the (plural) PodIPs field. Each entry includes:\n IP: An IP address allocated to the pod. Routable at least within the cluster.",
|
||||
Description: "IP address information for entries in the (plural) PodIPs field. Each entry includes:\n\n\tIP: An IP address allocated to the pod. Routable at least within the cluster.",
|
||||
Type: []string{"object"},
|
||||
Properties: map[string]spec.Schema{
|
||||
"ip": {
|
||||
@@ -7539,11 +7538,11 @@ func schema_k8sio_api_core_v1_PodReadinessGate(ref common.ReferenceCallback) com
|
||||
Properties: map[string]spec.Schema{
|
||||
"conditionType": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "ConditionType refers to a condition in the pod's condition list with matching type.\n\nPossible enum values:\n - `\"ContainersReady\"` indicates whether all containers in the pod are ready.\n - `\"Initialized\"` means that all init containers in the pod have started successfully.\n - `\"PodScheduled\"` represents status of the scheduling process for this pod.\n - `\"Ready\"` means the pod is able to service requests and should be added to the load balancing pools of all matching services.",
|
||||
Description: "ConditionType refers to a condition in the pod's condition list with matching type.",
|
||||
Default: "",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
Enum: []interface{}{"ContainersReady", "Initialized", "PodScheduled", "Ready"}},
|
||||
},
|
||||
},
|
||||
},
|
||||
Required: []string{"conditionType"},
|
||||
@@ -12019,7 +12018,7 @@ func schema_apimachinery_pkg_api_resource_Quantity(ref common.ReferenceCallback)
|
||||
return common.OpenAPIDefinition{
|
||||
Schema: spec.Schema{
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "Quantity is a fixed-point representation of a number. It provides convenient marshaling/unmarshaling in JSON and YAML, in addition to String() and AsInt64() accessors.\n\nThe serialization format is:\n\n<quantity> ::= <signedNumber><suffix>\n (Note that <suffix> may be empty, from the \"\" case in <decimalSI>.)\n<digit> ::= 0 | 1 | ... | 9 <digits> ::= <digit> | <digit><digits> <number> ::= <digits> | <digits>.<digits> | <digits>. | .<digits> <sign> ::= \"+\" | \"-\" <signedNumber> ::= <number> | <sign><number> <suffix> ::= <binarySI> | <decimalExponent> | <decimalSI> <binarySI> ::= Ki | Mi | Gi | Ti | Pi | Ei\n (International System of units; See: http://physics.nist.gov/cuu/Units/binary.html)\n<decimalSI> ::= m | \"\" | k | M | G | T | P | E\n (Note that 1024 = 1Ki but 1000 = 1k; I didn't choose the capitalization.)\n<decimalExponent> ::= \"e\" <signedNumber> | \"E\" <signedNumber>\n\nNo matter which of the three exponent forms is used, no quantity may represent a number greater than 2^63-1 in magnitude, nor may it have more than 3 decimal places. Numbers larger or more precise will be capped or rounded up. (E.g.: 0.1m will rounded up to 1m.) This may be extended in the future if we require larger or smaller quantities.\n\nWhen a Quantity is parsed from a string, it will remember the type of suffix it had, and will use the same type again when it is serialized.\n\nBefore serializing, Quantity will be put in \"canonical form\". This means that Exponent/suffix will be adjusted up or down (with a corresponding increase or decrease in Mantissa) such that:\n a. No precision is lost\n b. No fractional digits will be emitted\n c. The exponent (or suffix) is as large as possible.\nThe sign will be omitted unless the number is negative.\n\nExamples:\n 1.5 will be serialized as \"1500m\"\n 1.5Gi will be serialized as \"1536Mi\"\n\nNote that the quantity will NEVER be internally represented by a floating point number. That is the whole point of this exercise.\n\nNon-canonical values will still parse as long as they are well formed, but will be re-emitted in their canonical form. (So always use canonical form, or don't diff.)\n\nThis format is intended to make it difficult to use these numbers without writing some sort of special handling code in the hopes that that will cause implementors to also use a fixed point implementation.",
|
||||
Description: "Quantity is a fixed-point representation of a number. It provides convenient marshaling/unmarshaling in JSON and YAML, in addition to String() and AsInt64() accessors.\n\nThe serialization format is:\n\n<quantity> ::= <signedNumber><suffix>\n\n\t(Note that <suffix> may be empty, from the \"\" case in <decimalSI>.)\n\n<digit> ::= 0 | 1 | ... | 9 <digits> ::= <digit> | <digit><digits> <number> ::= <digits> | <digits>.<digits> | <digits>. | .<digits> <sign> ::= \"+\" | \"-\" <signedNumber> ::= <number> | <sign><number> <suffix> ::= <binarySI> | <decimalExponent> | <decimalSI> <binarySI> ::= Ki | Mi | Gi | Ti | Pi | Ei\n\n\t(International System of units; See: http://physics.nist.gov/cuu/Units/binary.html)\n\n<decimalSI> ::= m | \"\" | k | M | G | T | P | E\n\n\t(Note that 1024 = 1Ki but 1000 = 1k; I didn't choose the capitalization.)\n\n<decimalExponent> ::= \"e\" <signedNumber> | \"E\" <signedNumber>\n\nNo matter which of the three exponent forms is used, no quantity may represent a number greater than 2^63-1 in magnitude, nor may it have more than 3 decimal places. Numbers larger or more precise will be capped or rounded up. (E.g.: 0.1m will rounded up to 1m.) This may be extended in the future if we require larger or smaller quantities.\n\nWhen a Quantity is parsed from a string, it will remember the type of suffix it had, and will use the same type again when it is serialized.\n\nBefore serializing, Quantity will be put in \"canonical form\". This means that Exponent/suffix will be adjusted up or down (with a corresponding increase or decrease in Mantissa) such that:\n\n\ta. No precision is lost\n\tb. No fractional digits will be emitted\n\tc. The exponent (or suffix) is as large as possible.\n\nThe sign will be omitted unless the number is negative.\n\nExamples:\n\n\t1.5 will be serialized as \"1500m\"\n\t1.5Gi will be serialized as \"1536Mi\"\n\nNote that the quantity will NEVER be internally represented by a floating point number. That is the whole point of this exercise.\n\nNon-canonical values will still parse as long as they are well formed, but will be re-emitted in their canonical form. (So always use canonical form, or don't diff.)\n\nThis format is intended to make it difficult to use these numbers without writing some sort of special handling code in the hopes that that will cause implementors to also use a fixed point implementation.",
|
||||
Type: resource.Quantity{}.OpenAPISchemaType(),
|
||||
Format: resource.Quantity{}.OpenAPISchemaFormat(),
|
||||
},
|
||||
@@ -14942,8 +14941,9 @@ func schema_pkg_apis_metrics_v1beta1_NodeMetrics(ref common.ReferenceCallback) c
|
||||
},
|
||||
"metadata": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Default: map[string]interface{}{},
|
||||
Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"),
|
||||
Description: "Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata",
|
||||
Default: map[string]interface{}{},
|
||||
Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"),
|
||||
},
|
||||
},
|
||||
"timestamp": {
|
||||
@@ -15057,8 +15057,9 @@ func schema_pkg_apis_metrics_v1beta1_PodMetrics(ref common.ReferenceCallback) co
|
||||
},
|
||||
"metadata": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Default: map[string]interface{}{},
|
||||
Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"),
|
||||
Description: "Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata",
|
||||
Default: map[string]interface{}{},
|
||||
Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"),
|
||||
},
|
||||
},
|
||||
"timestamp": {
|
||||
|
||||
@@ -68,11 +68,11 @@ type Schedule struct {
|
||||
// +optional
|
||||
Period *SchedulePeriod `json:"period,omitempty"`
|
||||
// Defines the starting date of a OneTime schedule. It has to
|
||||
// be a RFC3339 formated date.
|
||||
// be a RFC3339 formatted date.
|
||||
// +optional
|
||||
Date *ScheduleDate `json:"date,omitempty"`
|
||||
// Defines the ending date of a OneTime schedule. It must be
|
||||
// a RFC3339 formated date.
|
||||
// a RFC3339 formatted date.
|
||||
// +optional
|
||||
EndDate *ScheduleDate `json:"endDate,omitempty"`
|
||||
// The duration in minutes (default 0) that the configured value will be
|
||||
|
||||
@@ -61,6 +61,10 @@ func (c *Clientset) Discovery() discovery.DiscoveryInterface {
|
||||
func NewForConfig(c *rest.Config) (*Clientset, error) {
|
||||
configShallowCopy := *c
|
||||
|
||||
if configShallowCopy.UserAgent == "" {
|
||||
configShallowCopy.UserAgent = rest.DefaultKubernetesUserAgent()
|
||||
}
|
||||
|
||||
// share the transport between all clients
|
||||
httpClient, err := rest.HTTPClientFor(&configShallowCopy)
|
||||
if err != nil {
|
||||
|
||||
@@ -0,0 +1,125 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
autoscalingv2 "k8s.io/api/autoscaling/v2"
|
||||
)
|
||||
|
||||
const (
|
||||
ExternalRPSMetricType = "requests-per-second"
|
||||
ExternalRPSQuery = `scalar(sum(rate(%s{host=~"%s"}[1m])) * %.4f)`
|
||||
)
|
||||
|
||||
type ExternalRPSCollectorPlugin struct {
|
||||
metricName string
|
||||
promPlugin CollectorPlugin
|
||||
pattern *regexp.Regexp
|
||||
}
|
||||
|
||||
type ExternalRPSCollector struct {
|
||||
interval time.Duration
|
||||
promCollector Collector
|
||||
}
|
||||
|
||||
func NewExternalRPSCollectorPlugin(
|
||||
promPlugin CollectorPlugin,
|
||||
metricName string,
|
||||
) (*ExternalRPSCollectorPlugin, error) {
|
||||
if metricName == "" {
|
||||
return nil, fmt.Errorf("failed to initialize hostname collector plugin, metric name was not defined")
|
||||
}
|
||||
|
||||
p, err := regexp.Compile("^[a-zA-Z0-9.-]+$")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create regular expression to match hostname format")
|
||||
}
|
||||
|
||||
return &ExternalRPSCollectorPlugin{
|
||||
metricName: metricName,
|
||||
promPlugin: promPlugin,
|
||||
pattern: p,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// NewCollector initializes a new skipper collector from the specified HPA.
|
||||
func (p *ExternalRPSCollectorPlugin) NewCollector(
|
||||
hpa *autoscalingv2.HorizontalPodAutoscaler,
|
||||
config *MetricConfig,
|
||||
interval time.Duration,
|
||||
) (Collector, error) {
|
||||
if config == nil {
|
||||
return nil, fmt.Errorf("metric config not present, it is not possible to initialize the collector")
|
||||
}
|
||||
// Need to copy config and add a promQL query in order to get
|
||||
// RPS data from a specific hostname from prometheus. The idea
|
||||
// of the copy is to not modify the original config struct.
|
||||
confCopy := *config
|
||||
|
||||
if _, ok := config.Config["hostnames"]; !ok {
|
||||
return nil, fmt.Errorf("Hostname is not specified, unable to create collector")
|
||||
}
|
||||
|
||||
hostnames := strings.Split(config.Config["hostnames"], ",")
|
||||
if p.pattern == nil {
|
||||
return nil, fmt.Errorf("plugin did not specify hostname regex pattern, unable to create collector")
|
||||
}
|
||||
for _, h := range hostnames {
|
||||
if ok := p.pattern.MatchString(h); !ok {
|
||||
return nil, fmt.Errorf(
|
||||
"invalid hostname format, unable to create collector: %s",
|
||||
h,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
weight := 1.0
|
||||
if w, ok := config.Config["weight"]; ok {
|
||||
num, err := strconv.ParseFloat(w, 64)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not parse weight annotation, unable to create collector: %s", w)
|
||||
}
|
||||
weight = num / 100.0
|
||||
}
|
||||
|
||||
confCopy.Config = map[string]string{
|
||||
"query": fmt.Sprintf(
|
||||
ExternalRPSQuery,
|
||||
p.metricName,
|
||||
strings.ReplaceAll(strings.Join(hostnames, "|"), ".", "_"),
|
||||
weight,
|
||||
),
|
||||
}
|
||||
|
||||
c, err := p.promPlugin.NewCollector(hpa, &confCopy, interval)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &ExternalRPSCollector{
|
||||
interval: interval,
|
||||
promCollector: c,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GetMetrics gets hostname metrics from Prometheus
|
||||
func (c *ExternalRPSCollector) GetMetrics() ([]CollectedMetric, error) {
|
||||
v, err := c.promCollector.GetMetrics()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(v) != 1 {
|
||||
return nil, fmt.Errorf("expected to only get one metric value, got %d", len(v))
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// Interval returns the interval at which the collector should run.
|
||||
func (c *ExternalRPSCollector) Interval() time.Duration {
|
||||
return c.interval
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,57 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
autoscalingv2 "k8s.io/api/autoscaling/v2"
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
"k8s.io/metrics/pkg/apis/custom_metrics"
|
||||
)
|
||||
|
||||
type FakeCollectorPlugin struct {
|
||||
metrics []CollectedMetric
|
||||
config map[string]string
|
||||
}
|
||||
|
||||
type FakeCollector struct {
|
||||
metrics []CollectedMetric
|
||||
interval time.Duration
|
||||
stub func() ([]CollectedMetric, error)
|
||||
}
|
||||
|
||||
func (c *FakeCollector) GetMetrics() ([]CollectedMetric, error) {
|
||||
if c.stub != nil {
|
||||
v, err := c.stub()
|
||||
return v, err
|
||||
}
|
||||
|
||||
return c.metrics, nil
|
||||
}
|
||||
|
||||
func (FakeCollector) Interval() time.Duration {
|
||||
return time.Minute
|
||||
}
|
||||
|
||||
func (p *FakeCollectorPlugin) NewCollector(
|
||||
hpa *autoscalingv2.HorizontalPodAutoscaler,
|
||||
config *MetricConfig,
|
||||
interval time.Duration,
|
||||
) (Collector, error) {
|
||||
|
||||
p.config = config.Config
|
||||
return &FakeCollector{metrics: p.metrics, interval: interval}, nil
|
||||
}
|
||||
|
||||
func makePlugin(metric int) *FakeCollectorPlugin {
|
||||
return &FakeCollectorPlugin{
|
||||
metrics: []CollectedMetric{
|
||||
{
|
||||
Custom: custom_metrics.MetricValue{Value: *resource.NewQuantity(int64(metric), resource.DecimalSI)},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func makeCollectorWithStub(f func() ([]CollectedMetric, error)) *FakeCollector {
|
||||
return &FakeCollector{stub: f}
|
||||
}
|
||||
@@ -61,10 +61,10 @@ func TestTargetRefReplicasStatefulSets(t *testing.T) {
|
||||
require.Equal(t, statefulSet.Status.Replicas, replicas)
|
||||
}
|
||||
|
||||
func newHPA(namesapce string, refName string, refKind string) *autoscalingv2.HorizontalPodAutoscaler {
|
||||
func newHPA(namespace string, refName string, refKind string) *autoscalingv2.HorizontalPodAutoscaler {
|
||||
return &autoscalingv2.HorizontalPodAutoscaler{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: namesapce,
|
||||
Name: namespace,
|
||||
},
|
||||
Spec: autoscalingv2.HorizontalPodAutoscalerSpec{
|
||||
ScaleTargetRef: autoscalingv2.CrossVersionObjectReference{
|
||||
@@ -658,38 +658,3 @@ func makeConfig(resourceName, namespace, kind, backend string, fakedAverage bool
|
||||
}
|
||||
return config
|
||||
}
|
||||
|
||||
type FakeCollectorPlugin struct {
|
||||
metrics []CollectedMetric
|
||||
config map[string]string
|
||||
}
|
||||
|
||||
type FakeCollector struct {
|
||||
metrics []CollectedMetric
|
||||
}
|
||||
|
||||
func (c *FakeCollector) GetMetrics() ([]CollectedMetric, error) {
|
||||
return c.metrics, nil
|
||||
}
|
||||
|
||||
func (FakeCollector) Interval() time.Duration {
|
||||
return time.Minute
|
||||
}
|
||||
|
||||
func (p *FakeCollectorPlugin) NewCollector(hpa *autoscalingv2.HorizontalPodAutoscaler, config *MetricConfig, interval time.Duration) (Collector, error) {
|
||||
if p.config != nil {
|
||||
return nil, fmt.Errorf("config already assigned once: %v", p.config)
|
||||
}
|
||||
p.config = config.Config
|
||||
return &FakeCollector{metrics: p.metrics}, nil
|
||||
}
|
||||
|
||||
func makePlugin(metric int) *FakeCollectorPlugin {
|
||||
return &FakeCollectorPlugin{
|
||||
metrics: []CollectedMetric{
|
||||
{
|
||||
Custom: custom_metrics.MetricValue{Value: *resource.NewQuantity(int64(metric), resource.DecimalSI)},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -363,7 +363,7 @@ func collectorRunner(ctx context.Context, collector collector.Collector, metrics
|
||||
}
|
||||
}
|
||||
|
||||
// Remove removes a collector from the Collector schduler. The collector is
|
||||
// Remove removes a collector from the Collector scheduler. The collector is
|
||||
// stopped before it's removed.
|
||||
func (t *CollectorScheduler) Remove(resourceRef resourceReference) {
|
||||
t.Lock()
|
||||
|
||||
+23
-2
@@ -65,6 +65,7 @@ func NewCommandStartAdapterServer(stopCh <-chan struct{}) *cobra.Command {
|
||||
MetricsAddress: ":7979",
|
||||
ZMONTokenName: "zmon",
|
||||
CredentialsDir: "/meta/credentials",
|
||||
ExternalRPSMetricName: "skipper_serve_host_duration_seconds_count",
|
||||
}
|
||||
|
||||
cmd := &cobra.Command{
|
||||
@@ -132,6 +133,10 @@ func NewCommandStartAdapterServer(stopCh <-chan struct{}) *cobra.Command {
|
||||
flags.DurationVar(&o.DefaultScheduledScalingWindow, "scaling-schedule-default-scaling-window", 10*time.Minute, "Default rampup and rampdown window duration for ScalingSchedules")
|
||||
flags.IntVar(&o.RampSteps, "scaling-schedule-ramp-steps", 10, "Number of steps used to rampup and rampdown ScalingSchedules. It's used to guarantee won't avoid reaching the max scaling due to the 10% minimum change rule.")
|
||||
flags.StringVar(&o.DefaultTimeZone, "scaling-schedule-default-time-zone", "Europe/Berlin", "Default time zone to use for ScalingSchedules.")
|
||||
flags.StringVar(&o.ExternalRPSMetricName, "external-rps-metric-name", o.ExternalRPSMetricName, ""+
|
||||
"The name of the metric that should be used to query prometheus for RPS per hostname.")
|
||||
flags.BoolVar(&o.ExternalRPSMetrics, "external-rps-metrics", o.ExternalRPSMetrics, ""+
|
||||
"whether to enable external RPS metric collector or not")
|
||||
return cmd
|
||||
}
|
||||
|
||||
@@ -218,6 +223,18 @@ func (o AdapterServerOptions) RunCustomMetricsAdapterServer(stopCh <-chan struct
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// External RPS collector, like skipper's, depends on prometheus being enabled.
|
||||
// Also, to enable hostname metric its necessary to pass the metric name that
|
||||
// will be used. This was built this way so we can support hostname metrics to
|
||||
// any ingress provider, e.g. Skipper, Nginx, envoy etc, in a simple way.
|
||||
if o.ExternalRPSMetrics && o.ExternalRPSMetricName != "" {
|
||||
externalRPSPlugin, err := collector.NewExternalRPSCollectorPlugin(promPlugin, o.ExternalRPSMetricName)
|
||||
collectorFactory.RegisterExternalCollector([]string{collector.ExternalRPSMetricType}, externalRPSPlugin)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to register hostname collector plugin: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if o.InfluxDBAddress != "" {
|
||||
@@ -315,7 +332,7 @@ func (o AdapterServerOptions) RunCustomMetricsAdapterServer(stopCh <-chan struct
|
||||
return fmt.Errorf("failed to register ScalingSchedule object collector plugin: %v", err)
|
||||
}
|
||||
|
||||
// setup ScheduledScaling controller to continously update
|
||||
// setup ScheduledScaling controller to continuously update
|
||||
// status of ScalingSchedule and ClusterScalingSchedule
|
||||
// resources.
|
||||
scheduledScalingController := scheduledscaling.NewController(scalingScheduleClient.ZalandoV1(), scalingSchedulesStore, clusterScalingSchedulesStore, time.Now, o.DefaultScheduledScalingWindow, o.DefaultTimeZone)
|
||||
@@ -383,7 +400,7 @@ func newOauth2HTTPClient(ctx context.Context, tokenSource oauth2.TokenSource) *h
|
||||
// add HTTP client to context (this is how the oauth2 lib gets it).
|
||||
ctx = context.WithValue(ctx, oauth2.HTTPClient, client)
|
||||
|
||||
// instantiate an http.Client containg the token source.
|
||||
// instantiate an http.Client containing the token source.
|
||||
return oauth2.NewClient(ctx, tokenSource)
|
||||
}
|
||||
|
||||
@@ -445,4 +462,8 @@ type AdapterServerOptions struct {
|
||||
RampSteps int
|
||||
// Default time zone to use for ScalingSchedules.
|
||||
DefaultTimeZone string
|
||||
// Feature flag to enable external rps metric collector
|
||||
ExternalRPSMetrics bool
|
||||
// Name of the Prometheus metric that stores RPS by hostname for external RPS metrics.
|
||||
ExternalRPSMetricName string
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user