diff --git a/docs/configuration/uds-monitoring-metrics.md b/docs/configuration/uds-monitoring-metrics.md index 5274d3225..bad32a6fa 100644 --- a/docs/configuration/uds-monitoring-metrics.md +++ b/docs/configuration/uds-monitoring-metrics.md @@ -4,10 +4,12 @@ type: docs weight: 1 --- -UDS Core leverages Pepr to handle setup of Prometheus scraping metrics endpoints, with the particular configuration necessary to work in a STRICT mTLS (Istio) environment. We handle this with both mutations of existing service monitors and generation of service monitors via the `Package` CR. +UDS Core leverages Pepr to handle setup of Prometheus scraping metrics endpoints, with the particular configuration necessary to work in a STRICT mTLS (Istio) environment. We handle this via a default scrapeClass in prometheus to add the istio certs. When a monitor needs to be exempt from that tlsConfig a mutation is performed to leverage a plain scrape class without istio certs. ## Mutations +Note: The below implementation has been deprecated in favor of a default `scrapeClass` with the file-based `tlsConfig` required for istio mTLS in prometheus automatically, supplemented with a mutation of `scrapeClass: exempt` that exempts monitors from the `tlsConfig` required for istio if the destination namespace is not istio injected (e.g. kube-system), unless the `uds/skip-sm-mutate` annotation is specified. The mutation behavior stated in the paragraph immediately below this section will be removed in a later release. + All service monitors are mutated to set the scrape scheme to HTTPS and set the TLS Config to what is required for Istio mTLS scraping (see [this doc](https://istio.io/latest/docs/ops/integrations/prometheus/#tls-settings) for details). Beyond this, no other fields are mutated. Supporting existing service monitors is useful since some charts include service monitors by default with more advanced configurations, and it is in our best interest to enable those and use them where possible. Assumptions are made about STRICT mTLS here for simplicity, based on the `istio-injection` namespace label. Without making these assumptions we would need to query `PeerAuthentication` resources or another resource to determine the exact workload mTLS posture. @@ -16,7 +18,7 @@ Note: This mutation is the default behavior for all service monitors but can be ## Package CR `monitor` field -UDS Core also supports generating service monitors from the `monitor` list in the `Package` spec. Charts do not always support service monitors, so generating them can be useful. This also provides a simplified way for other users to create service monitors, similar to the way we handle `VirtualServices` today. A full example of this can be seen below: +UDS Core also supports generating `ServiceMonitors` and/or `PodMonitors` from the `monitor` list in the `Package` spec. Charts do not always support monitors, so generating them can be useful. This also provides a simplified way for other users to create monitors, similar to the way we handle `VirtualServices` today. A full example of this can be seen below: ```yaml ... @@ -28,9 +30,16 @@ spec: targetPort: 1234 # Corresponding target port on the pod/container (for network policy) # Optional properties depending on your application description: "Metrics" # Add to customize the service monitor name + kind: ServiceMonitor # optional, kind defaults to service monitor if not specified. PodMonitor is the other valid option. podSelector: # Add if pod labels are different than `selector` (for network policy) app: barfoo path: "/mymetrics" # Add if metrics are exposed on a different path than "/metrics" + authorization: # Add if authorization is required for the metrics endpoint + credentials: + key: "example-key" + name: "example-secret" + optional: false + type: "Bearer" ``` This config is used to generate service monitors and corresponding network policies to setup scraping for your applications. The `ServiceMonitor`s will go through the mutation process to add `tlsConfig` and `scheme` to work in an istio environment. diff --git a/src/metrics-server/chart/templates/service-monitor.yaml b/src/metrics-server/chart/templates/service-monitor.yaml index d7c603693..390875164 100644 --- a/src/metrics-server/chart/templates/service-monitor.yaml +++ b/src/metrics-server/chart/templates/service-monitor.yaml @@ -3,7 +3,7 @@ apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor metadata: - annotation: + annotations: uds/skip-sm-mutate: "true" name: metrics-server-metrics namespace: metrics-server diff --git a/src/pepr/operator/controllers/monitoring/common.ts b/src/pepr/operator/controllers/monitoring/common.ts new file mode 100644 index 000000000..a8afa5d1f --- /dev/null +++ b/src/pepr/operator/controllers/monitoring/common.ts @@ -0,0 +1,12 @@ +import { Monitor } from "../../crd"; +import { sanitizeResourceName } from "../utils"; + +export function generateMonitorName(pkgName: string, monitor: Monitor) { + const { selector, portName, description } = monitor; + + // Ensure the resource name is valid + const nameSuffix = description || `${Object.values(selector)}-${portName}`; + const name = sanitizeResourceName(`${pkgName}-${nameSuffix}`); + + return name; +} diff --git a/src/pepr/operator/controllers/monitoring/pod-monitor.spec.ts b/src/pepr/operator/controllers/monitoring/pod-monitor.spec.ts new file mode 100644 index 000000000..acba54e26 --- /dev/null +++ b/src/pepr/operator/controllers/monitoring/pod-monitor.spec.ts @@ -0,0 +1,41 @@ +import { describe, expect, it } from "@jest/globals"; +import { Monitor } from "../../crd"; +import { generatePodMonitor } from "./pod-monitor"; + +describe("test generate Pod monitor", () => { + it("should return a valid Pod Monitor object", () => { + const ownerRefs = [ + { + apiVersion: "uds.dev/v1alpha1", + kind: "Package", + name: "test", + uid: "f50120aa-2713-4502-9496-566b102b1174", + }, + ]; + const portName = "http-metrics"; + const metricsPath = "/test"; + const selectorApp = "test"; + const monitor: Monitor = { + portName: portName, + path: metricsPath, + targetPort: 1234, + selector: { + app: selectorApp, + }, + }; + const namespace = "test"; + const pkgName = "test"; + const generation = "1"; + const payload = generatePodMonitor(monitor, namespace, pkgName, generation, ownerRefs); + + expect(payload).toBeDefined(); + expect(payload.metadata?.name).toEqual(`${pkgName}-${selectorApp}-${portName}`); + expect(payload.metadata?.namespace).toEqual(namespace); + expect(payload.spec?.podMetricsEndpoints).toBeDefined(); + if (payload.spec?.podMetricsEndpoints) { + expect(payload.spec.podMetricsEndpoints[0].port).toEqual(portName); + expect(payload.spec.podMetricsEndpoints[0].path).toEqual(metricsPath); + } + expect(payload.spec?.selector.matchLabels).toHaveProperty("app", "test"); + }); +}); diff --git a/src/pepr/operator/controllers/monitoring/pod-monitor.ts b/src/pepr/operator/controllers/monitoring/pod-monitor.ts new file mode 100644 index 000000000..2ac1c2e11 --- /dev/null +++ b/src/pepr/operator/controllers/monitoring/pod-monitor.ts @@ -0,0 +1,103 @@ +import { V1OwnerReference } from "@kubernetes/client-node"; +import { K8s } from "pepr"; +import { Component, setupLogger } from "../../../logger"; +import { Monitor, PrometheusPodMonitor, UDSPackage } from "../../crd"; +import { Kind } from "../../crd/generated/package-v1alpha1"; +import { getOwnerRef } from "../utils"; +import { generateMonitorName } from "./common"; + +// configure subproject logger +const log = setupLogger(Component.OPERATOR_MONITORING); + +/** + * Generate a pod monitor for a pod + * + * @param pkg UDS Package + * @param namespace + */ +export async function podMonitor(pkg: UDSPackage, namespace: string) { + const pkgName = pkg.metadata!.name!; + const generation = (pkg.metadata?.generation ?? 0).toString(); + const ownerRefs = getOwnerRef(pkg); + + log.debug(`Reconciling PodMonitors for ${pkgName}`); + + // Get the list of monitored services + const monitorList = pkg.spec?.monitor ?? []; + + // Create a list of generated PodMonitors + const payloads: PrometheusPodMonitor[] = []; + + try { + for (const monitor of monitorList) { + if (monitor.kind === Kind.PodMonitor) { + const payload = generatePodMonitor(monitor, namespace, pkgName, generation, ownerRefs); + + log.debug(payload, `Applying PodMonitor ${payload.metadata?.name}`); + + // Apply the PodMonitor and force overwrite any existing policy + await K8s(PrometheusPodMonitor).Apply(payload, { force: true }); + + payloads.push(payload); + } + } + + // Get all related PodMonitors in the namespace + const podMonitors = await K8s(PrometheusPodMonitor) + .InNamespace(namespace) + .WithLabel("uds/package", pkgName) + .Get(); + + // Find any orphaned PodMonitors (not matching the current generation) + const orphanedMonitor = podMonitors.items.filter( + m => m.metadata?.labels?.["uds/generation"] !== generation, + ); + + // Delete any orphaned PodMonitors + for (const m of orphanedMonitor) { + log.debug(m, `Deleting orphaned PodMonitor ${m.metadata!.name}`); + await K8s(PrometheusPodMonitor).Delete(m); + } + } catch (err) { + throw new Error(`Failed to process PodMonitors for ${pkgName}, cause: ${JSON.stringify(err)}`); + } + + // Return the list of monitor names + return [...payloads.map(m => m.metadata!.name!)]; +} + +export function generatePodMonitor( + monitor: Monitor, + namespace: string, + pkgName: string, + generation: string, + ownerRefs: V1OwnerReference[], +) { + const { selector, portName } = monitor; + const name = generateMonitorName(pkgName, monitor); + const payload: PrometheusPodMonitor = { + metadata: { + name, + namespace, + labels: { + "uds/package": pkgName, + "uds/generation": generation, + }, + ownerReferences: ownerRefs, + }, + spec: { + podMetricsEndpoints: [ + { + port: portName, + path: monitor.path || "/metrics", + authorization: monitor.authorization, + }, + ], + selector: { + matchLabels: selector, + }, + }, + }; + + return payload; +} diff --git a/src/pepr/operator/controllers/monitoring/service-monitor.spec.ts b/src/pepr/operator/controllers/monitoring/service-monitor.spec.ts index 83d4fa03e..e99900409 100644 --- a/src/pepr/operator/controllers/monitoring/service-monitor.spec.ts +++ b/src/pepr/operator/controllers/monitoring/service-monitor.spec.ts @@ -1,6 +1,6 @@ import { describe, expect, it } from "@jest/globals"; -import { generateServiceMonitor } from "./service-monitor"; import { Monitor } from "../../crd"; +import { generateServiceMonitor } from "./service-monitor"; describe("test generate service monitor", () => { it("should return a valid Service Monitor object", () => { diff --git a/src/pepr/operator/controllers/monitoring/service-monitor.ts b/src/pepr/operator/controllers/monitoring/service-monitor.ts index be1ddf9ac..641c9e86c 100644 --- a/src/pepr/operator/controllers/monitoring/service-monitor.ts +++ b/src/pepr/operator/controllers/monitoring/service-monitor.ts @@ -2,8 +2,10 @@ import { K8s } from "pepr"; import { V1OwnerReference } from "@kubernetes/client-node"; import { Component, setupLogger } from "../../../logger"; -import { Monitor, Prometheus, UDSPackage } from "../../crd"; -import { getOwnerRef, sanitizeResourceName } from "../utils"; +import { Monitor, PrometheusServiceMonitor, UDSPackage } from "../../crd"; +import { Kind } from "../../crd/generated/package-v1alpha1"; +import { getOwnerRef } from "../utils"; +import { generateMonitorName } from "./common"; // configure subproject logger const log = setupLogger(Component.OPERATOR_MONITORING); @@ -25,35 +27,37 @@ export async function serviceMonitor(pkg: UDSPackage, namespace: string) { const monitorList = pkg.spec?.monitor ?? []; // Create a list of generated ServiceMonitors - const payloads: Prometheus.ServiceMonitor[] = []; + const payloads: PrometheusServiceMonitor[] = []; try { for (const monitor of monitorList) { - const payload = generateServiceMonitor(monitor, namespace, pkgName, generation, ownerRefs); + if (monitor.kind !== Kind.PodMonitor) { + const payload = generateServiceMonitor(monitor, namespace, pkgName, generation, ownerRefs); - log.debug(payload, `Applying ServiceMonitor ${payload.metadata?.name}`); + log.debug(payload, `Applying ServiceMonitor ${payload.metadata?.name}`); - // Apply the ServiceMonitor and force overwrite any existing policy - await K8s(Prometheus.ServiceMonitor).Apply(payload, { force: true }); + // Apply the ServiceMonitor and force overwrite any existing policy + await K8s(PrometheusServiceMonitor).Apply(payload, { force: true }); - payloads.push(payload); + payloads.push(payload); + } } // Get all related ServiceMonitors in the namespace - const serviceMonitors = await K8s(Prometheus.ServiceMonitor) + const serviceMonitors = await K8s(PrometheusServiceMonitor) .InNamespace(namespace) .WithLabel("uds/package", pkgName) .Get(); // Find any orphaned ServiceMonitors (not matching the current generation) - const orphanedSM = serviceMonitors.items.filter( - sm => sm.metadata?.labels?.["uds/generation"] !== generation, + const orphanedMonitor = serviceMonitors.items.filter( + m => m.metadata?.labels?.["uds/generation"] !== generation, ); // Delete any orphaned ServiceMonitors - for (const sm of orphanedSM) { - log.debug(sm, `Deleting orphaned ServiceMonitor ${sm.metadata!.name}`); - await K8s(Prometheus.ServiceMonitor).Delete(sm); + for (const m of orphanedMonitor) { + log.debug(m, `Deleting orphaned ServiceMonitor ${m.metadata!.name}`); + await K8s(PrometheusServiceMonitor).Delete(m); } } catch (err) { throw new Error( @@ -62,17 +66,7 @@ export async function serviceMonitor(pkg: UDSPackage, namespace: string) { } // Return the list of monitor names - return [...payloads.map(sm => sm.metadata!.name!)]; -} - -export function generateSMName(pkgName: string, monitor: Monitor) { - const { selector, portName, description } = monitor; - - // Ensure the resource name is valid - const nameSuffix = description || `${Object.values(selector)}-${portName}`; - const name = sanitizeResourceName(`${pkgName}-${nameSuffix}`); - - return name; + return [...payloads.map(m => m.metadata!.name!)]; } export function generateServiceMonitor( @@ -83,8 +77,8 @@ export function generateServiceMonitor( ownerRefs: V1OwnerReference[], ) { const { selector, portName } = monitor; - const name = generateSMName(pkgName, monitor); - const payload: Prometheus.ServiceMonitor = { + const name = generateMonitorName(pkgName, monitor); + const payload: PrometheusServiceMonitor = { metadata: { name, namespace, @@ -99,6 +93,7 @@ export function generateServiceMonitor( { port: portName, path: monitor.path || "/metrics", + authorization: monitor.authorization, }, ], selector: { diff --git a/src/pepr/operator/crd/generated/package-v1alpha1.ts b/src/pepr/operator/crd/generated/package-v1alpha1.ts index 7669ca930..a96450297 100644 --- a/src/pepr/operator/crd/generated/package-v1alpha1.ts +++ b/src/pepr/operator/crd/generated/package-v1alpha1.ts @@ -9,7 +9,7 @@ export class Package extends GenericKind { export interface Spec { /** - * Create Service Monitor configurations + * Create Service or Pod Monitor configurations */ monitor?: Monitor[]; /** @@ -23,10 +23,19 @@ export interface Spec { } export interface Monitor { + /** + * Authorization settings. + */ + authorization?: Authorization; /** * A description of this monitor entry, this will become part of the ServiceMonitor name */ description?: string; + /** + * The type of monitor to create; PodMonitor or ServiceMonitor. ServiceMonitor is the + * default. + */ + kind?: Kind; /** * HTTP path from which to scrape for metrics, defaults to `/metrics` */ @@ -51,6 +60,51 @@ export interface Monitor { targetPort: number; } +/** + * Authorization settings. + */ +export interface Authorization { + /** + * Selects a key of a Secret in the namespace that contains the credentials for + * authentication. + */ + credentials: Credentials; + /** + * Defines the authentication type. The value is case-insensitive. "Basic" is not a + * supported value. Default: "Bearer" + */ + type?: string; +} + +/** + * Selects a key of a Secret in the namespace that contains the credentials for + * authentication. + */ +export interface Credentials { + /** + * The key of the secret to select from. Must be a valid secret key. + */ + key: string; + /** + * Name of the referent. More info: + * https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + */ + name?: string; + /** + * Specify whether the Secret or its key must be defined + */ + optional?: boolean; +} + +/** + * The type of monitor to create; PodMonitor or ServiceMonitor. ServiceMonitor is the + * default. + */ +export enum Kind { + PodMonitor = "PodMonitor", + ServiceMonitor = "ServiceMonitor", +} + /** * Network configuration for the package */ diff --git a/src/pepr/operator/crd/generated/prometheus/podmonitor-v1.ts b/src/pepr/operator/crd/generated/prometheus/podmonitor-v1.ts new file mode 100644 index 000000000..d2e9f3f9a --- /dev/null +++ b/src/pepr/operator/crd/generated/prometheus/podmonitor-v1.ts @@ -0,0 +1,1011 @@ +// This file is auto-generated by kubernetes-fluent-client, do not edit manually + +import { GenericKind, RegisterKind } from "kubernetes-fluent-client"; + +/** + * PodMonitor defines monitoring for a set of pods. + */ +export class PodMonitor extends GenericKind { + /** + * Specification of desired Pod selection for target discovery by Prometheus. + */ + spec?: Spec; +} + +/** + * Specification of desired Pod selection for target discovery by Prometheus. + */ +export interface Spec { + /** + * `attachMetadata` defines additional metadata which is added to the + * discovered targets. + * + * + * It requires Prometheus >= v2.37.0. + */ + attachMetadata?: AttachMetadata; + /** + * When defined, bodySizeLimit specifies a job level limit on the size + * of uncompressed response body that will be accepted by Prometheus. + * + * + * It requires Prometheus >= v2.28.0. + */ + bodySizeLimit?: string; + /** + * The label to use to retrieve the job name from. + * `jobLabel` selects the label from the associated Kubernetes `Pod` + * object which will be used as the `job` label for all metrics. + * + * + * For example if `jobLabel` is set to `foo` and the Kubernetes `Pod` + * object is labeled with `foo: bar`, then Prometheus adds the `job="bar"` + * label to all ingested metrics. + * + * + * If the value of this field is empty, the `job` label of the metrics + * defaults to the namespace and name of the PodMonitor object (e.g. `/`). + */ + jobLabel?: string; + /** + * Per-scrape limit on the number of targets dropped by relabeling + * that will be kept in memory. 0 means no limit. + * + * + * It requires Prometheus >= v2.47.0. + */ + keepDroppedTargets?: number; + /** + * Per-scrape limit on number of labels that will be accepted for a sample. + * + * + * It requires Prometheus >= v2.27.0. + */ + labelLimit?: number; + /** + * Per-scrape limit on length of labels name that will be accepted for a sample. + * + * + * It requires Prometheus >= v2.27.0. + */ + labelNameLengthLimit?: number; + /** + * Per-scrape limit on length of labels value that will be accepted for a sample. + * + * + * It requires Prometheus >= v2.27.0. + */ + labelValueLengthLimit?: number; + /** + * Selector to select which namespaces the Kubernetes `Pods` objects + * are discovered from. + */ + namespaceSelector?: NamespaceSelector; + /** + * List of endpoints part of this PodMonitor. + */ + podMetricsEndpoints?: PodMetricsEndpoint[]; + /** + * `podTargetLabels` defines the labels which are transferred from the + * associated Kubernetes `Pod` object onto the ingested metrics. + */ + podTargetLabels?: string[]; + /** + * `sampleLimit` defines a per-scrape limit on the number of scraped samples + * that will be accepted. + */ + sampleLimit?: number; + /** + * The scrape class to apply. + */ + scrapeClass?: string; + /** + * `scrapeProtocols` defines the protocols to negotiate during a scrape. It tells clients + * the + * protocols supported by Prometheus in order of preference (from most to least + * preferred). + * + * + * If unset, Prometheus uses its default value. + * + * + * It requires Prometheus >= v2.49.0. + */ + scrapeProtocols?: ScrapeProtocol[]; + /** + * Label selector to select the Kubernetes `Pod` objects. + */ + selector: Selector; + /** + * `targetLimit` defines a limit on the number of scraped targets that will + * be accepted. + */ + targetLimit?: number; +} + +/** + * `attachMetadata` defines additional metadata which is added to the + * discovered targets. + * + * + * It requires Prometheus >= v2.37.0. + */ +export interface AttachMetadata { + /** + * When set to true, Prometheus must have the `get` permission on the + * `Nodes` objects. + */ + node?: boolean; +} + +/** + * Selector to select which namespaces the Kubernetes `Pods` objects + * are discovered from. + */ +export interface NamespaceSelector { + /** + * Boolean describing whether all namespaces are selected in contrast to a + * list restricting them. + */ + any?: boolean; + /** + * List of namespace names to select from. + */ + matchNames?: string[]; +} + +/** + * PodMetricsEndpoint defines an endpoint serving Prometheus metrics to be scraped by + * Prometheus. + */ +export interface PodMetricsEndpoint { + /** + * `authorization` configures the Authorization header credentials to use when + * scraping the target. + * + * + * Cannot be set at the same time as `basicAuth`, or `oauth2`. + */ + authorization?: Authorization; + /** + * `basicAuth` configures the Basic Authentication credentials to use when + * scraping the target. + * + * + * Cannot be set at the same time as `authorization`, or `oauth2`. + */ + basicAuth?: BasicAuth; + /** + * `bearerTokenSecret` specifies a key of a Secret containing the bearer + * token for scraping targets. The secret needs to be in the same namespace + * as the PodMonitor object and readable by the Prometheus Operator. + * + * + * Deprecated: use `authorization` instead. + */ + bearerTokenSecret?: BearerTokenSecret; + /** + * `enableHttp2` can be used to disable HTTP2 when scraping the target. + */ + enableHttp2?: boolean; + /** + * When true, the pods which are not running (e.g. either in Failed or + * Succeeded state) are dropped during the target discovery. + * + * + * If unset, the filtering is enabled. + * + * + * More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#pod-phase + */ + filterRunning?: boolean; + /** + * `followRedirects` defines whether the scrape requests should follow HTTP + * 3xx redirects. + */ + followRedirects?: boolean; + /** + * When true, `honorLabels` preserves the metric's labels when they collide + * with the target's labels. + */ + honorLabels?: boolean; + /** + * `honorTimestamps` controls whether Prometheus preserves the timestamps + * when exposed by the target. + */ + honorTimestamps?: boolean; + /** + * Interval at which Prometheus scrapes the metrics from the target. + * + * + * If empty, Prometheus uses the global scrape interval. + */ + interval?: string; + /** + * `metricRelabelings` configures the relabeling rules to apply to the + * samples before ingestion. + */ + metricRelabelings?: MetricRelabeling[]; + /** + * `oauth2` configures the OAuth2 settings to use when scraping the target. + * + * + * It requires Prometheus >= 2.27.0. + * + * + * Cannot be set at the same time as `authorization`, or `basicAuth`. + */ + oauth2?: Oauth2; + /** + * `params` define optional HTTP URL parameters. + */ + params?: { [key: string]: string[] }; + /** + * HTTP path from which to scrape for metrics. + * + * + * If empty, Prometheus uses the default value (e.g. `/metrics`). + */ + path?: string; + /** + * Name of the Pod port which this endpoint refers to. + * + * + * It takes precedence over `targetPort`. + */ + port?: string; + /** + * `proxyURL` configures the HTTP Proxy URL (e.g. + * "http://proxyserver:2195") to go through when scraping the target. + */ + proxyUrl?: string; + /** + * `relabelings` configures the relabeling rules to apply the target's + * metadata labels. + * + * + * The Operator automatically adds relabelings for a few standard Kubernetes fields. + * + * + * The original scrape job's name is available via the `__tmp_prometheus_job_name` label. + * + * + * More info: + * https://prometheus.io/docs/prometheus/latest/configuration/configuration/#relabel_config + */ + relabelings?: Relabeling[]; + /** + * HTTP scheme to use for scraping. + * + * + * `http` and `https` are the expected values unless you rewrite the + * `__scheme__` label via relabeling. + * + * + * If empty, Prometheus uses the default value `http`. + */ + scheme?: Scheme; + /** + * Timeout after which Prometheus considers the scrape to be failed. + * + * + * If empty, Prometheus uses the global scrape timeout unless it is less + * than the target's scrape interval value in which the latter is used. + */ + scrapeTimeout?: string; + /** + * Name or number of the target port of the `Pod` object behind the Service, the + * port must be specified with container port property. + * + * + * Deprecated: use 'port' instead. + */ + targetPort?: number | string; + /** + * TLS configuration to use when scraping the target. + */ + tlsConfig?: TLSConfig; + /** + * `trackTimestampsStaleness` defines whether Prometheus tracks staleness of + * the metrics that have an explicit timestamp present in scraped data. + * Has no effect if `honorTimestamps` is false. + * + * + * It requires Prometheus >= v2.48.0. + */ + trackTimestampsStaleness?: boolean; +} + +/** + * `authorization` configures the Authorization header credentials to use when + * scraping the target. + * + * + * Cannot be set at the same time as `basicAuth`, or `oauth2`. + */ +export interface Authorization { + /** + * Selects a key of a Secret in the namespace that contains the credentials for + * authentication. + */ + credentials?: Credentials; + /** + * Defines the authentication type. The value is case-insensitive. + * + * + * "Basic" is not a supported value. + * + * + * Default: "Bearer" + */ + type?: string; +} + +/** + * Selects a key of a Secret in the namespace that contains the credentials for + * authentication. + */ +export interface Credentials { + /** + * The key of the secret to select from. Must be a valid secret key. + */ + key: string; + /** + * Name of the referent. + * This field is effectively required, but due to backwards compatibility is + * allowed to be empty. Instances of this type with an empty value here are + * almost certainly wrong. + * TODO: Add other useful fields. apiVersion, kind, uid? + * More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + * TODO: Drop `kubebuilder:default` when controller-gen doesn't need it + * https://github.com/kubernetes-sigs/kubebuilder/issues/3896. + */ + name?: string; + /** + * Specify whether the Secret or its key must be defined + */ + optional?: boolean; +} + +/** + * `basicAuth` configures the Basic Authentication credentials to use when + * scraping the target. + * + * + * Cannot be set at the same time as `authorization`, or `oauth2`. + */ +export interface BasicAuth { + /** + * `password` specifies a key of a Secret containing the password for + * authentication. + */ + password?: Password; + /** + * `username` specifies a key of a Secret containing the username for + * authentication. + */ + username?: Username; +} + +/** + * `password` specifies a key of a Secret containing the password for + * authentication. + */ +export interface Password { + /** + * The key of the secret to select from. Must be a valid secret key. + */ + key: string; + /** + * Name of the referent. + * This field is effectively required, but due to backwards compatibility is + * allowed to be empty. Instances of this type with an empty value here are + * almost certainly wrong. + * TODO: Add other useful fields. apiVersion, kind, uid? + * More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + * TODO: Drop `kubebuilder:default` when controller-gen doesn't need it + * https://github.com/kubernetes-sigs/kubebuilder/issues/3896. + */ + name?: string; + /** + * Specify whether the Secret or its key must be defined + */ + optional?: boolean; +} + +/** + * `username` specifies a key of a Secret containing the username for + * authentication. + */ +export interface Username { + /** + * The key of the secret to select from. Must be a valid secret key. + */ + key: string; + /** + * Name of the referent. + * This field is effectively required, but due to backwards compatibility is + * allowed to be empty. Instances of this type with an empty value here are + * almost certainly wrong. + * TODO: Add other useful fields. apiVersion, kind, uid? + * More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + * TODO: Drop `kubebuilder:default` when controller-gen doesn't need it + * https://github.com/kubernetes-sigs/kubebuilder/issues/3896. + */ + name?: string; + /** + * Specify whether the Secret or its key must be defined + */ + optional?: boolean; +} + +/** + * `bearerTokenSecret` specifies a key of a Secret containing the bearer + * token for scraping targets. The secret needs to be in the same namespace + * as the PodMonitor object and readable by the Prometheus Operator. + * + * + * Deprecated: use `authorization` instead. + */ +export interface BearerTokenSecret { + /** + * The key of the secret to select from. Must be a valid secret key. + */ + key: string; + /** + * Name of the referent. + * This field is effectively required, but due to backwards compatibility is + * allowed to be empty. Instances of this type with an empty value here are + * almost certainly wrong. + * TODO: Add other useful fields. apiVersion, kind, uid? + * More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + * TODO: Drop `kubebuilder:default` when controller-gen doesn't need it + * https://github.com/kubernetes-sigs/kubebuilder/issues/3896. + */ + name?: string; + /** + * Specify whether the Secret or its key must be defined + */ + optional?: boolean; +} + +/** + * RelabelConfig allows dynamic rewriting of the label set for targets, alerts, + * scraped samples and remote write samples. + * + * + * More info: + * https://prometheus.io/docs/prometheus/latest/configuration/configuration/#relabel_config + */ +export interface MetricRelabeling { + /** + * Action to perform based on the regex matching. + * + * + * `Uppercase` and `Lowercase` actions require Prometheus >= v2.36.0. + * `DropEqual` and `KeepEqual` actions require Prometheus >= v2.41.0. + * + * + * Default: "Replace" + */ + action?: Action; + /** + * Modulus to take of the hash of the source label values. + * + * + * Only applicable when the action is `HashMod`. + */ + modulus?: number; + /** + * Regular expression against which the extracted value is matched. + */ + regex?: string; + /** + * Replacement value against which a Replace action is performed if the + * regular expression matches. + * + * + * Regex capture groups are available. + */ + replacement?: string; + /** + * Separator is the string between concatenated SourceLabels. + */ + separator?: string; + /** + * The source labels select values from existing labels. Their content is + * concatenated using the configured Separator and matched against the + * configured regular expression. + */ + sourceLabels?: string[]; + /** + * Label to which the resulting string is written in a replacement. + * + * + * It is mandatory for `Replace`, `HashMod`, `Lowercase`, `Uppercase`, + * `KeepEqual` and `DropEqual` actions. + * + * + * Regex capture groups are available. + */ + targetLabel?: string; +} + +/** + * Action to perform based on the regex matching. + * + * + * `Uppercase` and `Lowercase` actions require Prometheus >= v2.36.0. + * `DropEqual` and `KeepEqual` actions require Prometheus >= v2.41.0. + * + * + * Default: "Replace" + */ +export enum Action { + ActionDrop = "Drop", + ActionKeep = "Keep", + ActionLowercase = "Lowercase", + ActionReplace = "Replace", + ActionUppercase = "Uppercase", + Drop = "drop", + DropEqual = "DropEqual", + Dropequal = "dropequal", + HashMod = "HashMod", + Hashmod = "hashmod", + Keep = "keep", + KeepEqual = "KeepEqual", + Keepequal = "keepequal", + LabelDrop = "LabelDrop", + LabelKeep = "LabelKeep", + LabelMap = "LabelMap", + Labeldrop = "labeldrop", + Labelkeep = "labelkeep", + Labelmap = "labelmap", + Lowercase = "lowercase", + Replace = "replace", + Uppercase = "uppercase", +} + +/** + * `oauth2` configures the OAuth2 settings to use when scraping the target. + * + * + * It requires Prometheus >= 2.27.0. + * + * + * Cannot be set at the same time as `authorization`, or `basicAuth`. + */ +export interface Oauth2 { + /** + * `clientId` specifies a key of a Secret or ConfigMap containing the + * OAuth2 client's ID. + */ + clientId: ClientID; + /** + * `clientSecret` specifies a key of a Secret containing the OAuth2 + * client's secret. + */ + clientSecret: ClientSecret; + /** + * `endpointParams` configures the HTTP parameters to append to the token + * URL. + */ + endpointParams?: { [key: string]: string }; + /** + * `scopes` defines the OAuth2 scopes used for the token request. + */ + scopes?: string[]; + /** + * `tokenURL` configures the URL to fetch the token from. + */ + tokenUrl: string; +} + +/** + * `clientId` specifies a key of a Secret or ConfigMap containing the + * OAuth2 client's ID. + */ +export interface ClientID { + /** + * ConfigMap containing data to use for the targets. + */ + configMap?: ClientIDConfigMap; + /** + * Secret containing data to use for the targets. + */ + secret?: ClientIDSecret; +} + +/** + * ConfigMap containing data to use for the targets. + */ +export interface ClientIDConfigMap { + /** + * The key to select. + */ + key: string; + /** + * Name of the referent. + * This field is effectively required, but due to backwards compatibility is + * allowed to be empty. Instances of this type with an empty value here are + * almost certainly wrong. + * TODO: Add other useful fields. apiVersion, kind, uid? + * More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + * TODO: Drop `kubebuilder:default` when controller-gen doesn't need it + * https://github.com/kubernetes-sigs/kubebuilder/issues/3896. + */ + name?: string; + /** + * Specify whether the ConfigMap or its key must be defined + */ + optional?: boolean; +} + +/** + * Secret containing data to use for the targets. + */ +export interface ClientIDSecret { + /** + * The key of the secret to select from. Must be a valid secret key. + */ + key: string; + /** + * Name of the referent. + * This field is effectively required, but due to backwards compatibility is + * allowed to be empty. Instances of this type with an empty value here are + * almost certainly wrong. + * TODO: Add other useful fields. apiVersion, kind, uid? + * More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + * TODO: Drop `kubebuilder:default` when controller-gen doesn't need it + * https://github.com/kubernetes-sigs/kubebuilder/issues/3896. + */ + name?: string; + /** + * Specify whether the Secret or its key must be defined + */ + optional?: boolean; +} + +/** + * `clientSecret` specifies a key of a Secret containing the OAuth2 + * client's secret. + */ +export interface ClientSecret { + /** + * The key of the secret to select from. Must be a valid secret key. + */ + key: string; + /** + * Name of the referent. + * This field is effectively required, but due to backwards compatibility is + * allowed to be empty. Instances of this type with an empty value here are + * almost certainly wrong. + * TODO: Add other useful fields. apiVersion, kind, uid? + * More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + * TODO: Drop `kubebuilder:default` when controller-gen doesn't need it + * https://github.com/kubernetes-sigs/kubebuilder/issues/3896. + */ + name?: string; + /** + * Specify whether the Secret or its key must be defined + */ + optional?: boolean; +} + +/** + * RelabelConfig allows dynamic rewriting of the label set for targets, alerts, + * scraped samples and remote write samples. + * + * + * More info: + * https://prometheus.io/docs/prometheus/latest/configuration/configuration/#relabel_config + */ +export interface Relabeling { + /** + * Action to perform based on the regex matching. + * + * + * `Uppercase` and `Lowercase` actions require Prometheus >= v2.36.0. + * `DropEqual` and `KeepEqual` actions require Prometheus >= v2.41.0. + * + * + * Default: "Replace" + */ + action?: Action; + /** + * Modulus to take of the hash of the source label values. + * + * + * Only applicable when the action is `HashMod`. + */ + modulus?: number; + /** + * Regular expression against which the extracted value is matched. + */ + regex?: string; + /** + * Replacement value against which a Replace action is performed if the + * regular expression matches. + * + * + * Regex capture groups are available. + */ + replacement?: string; + /** + * Separator is the string between concatenated SourceLabels. + */ + separator?: string; + /** + * The source labels select values from existing labels. Their content is + * concatenated using the configured Separator and matched against the + * configured regular expression. + */ + sourceLabels?: string[]; + /** + * Label to which the resulting string is written in a replacement. + * + * + * It is mandatory for `Replace`, `HashMod`, `Lowercase`, `Uppercase`, + * `KeepEqual` and `DropEqual` actions. + * + * + * Regex capture groups are available. + */ + targetLabel?: string; +} + +/** + * HTTP scheme to use for scraping. + * + * + * `http` and `https` are the expected values unless you rewrite the + * `__scheme__` label via relabeling. + * + * + * If empty, Prometheus uses the default value `http`. + */ +export enum Scheme { + HTTP = "http", + HTTPS = "https", +} + +/** + * TLS configuration to use when scraping the target. + */ +export interface TLSConfig { + /** + * Certificate authority used when verifying server certificates. + */ + ca?: CA; + /** + * Client certificate to present when doing client-authentication. + */ + cert?: CERT; + /** + * Disable target certificate validation. + */ + insecureSkipVerify?: boolean; + /** + * Secret containing the client key file for the targets. + */ + keySecret?: KeySecret; + /** + * Used to verify the hostname for the targets. + */ + serverName?: string; +} + +/** + * Certificate authority used when verifying server certificates. + */ +export interface CA { + /** + * ConfigMap containing data to use for the targets. + */ + configMap?: CAConfigMap; + /** + * Secret containing data to use for the targets. + */ + secret?: CASecret; +} + +/** + * ConfigMap containing data to use for the targets. + */ +export interface CAConfigMap { + /** + * The key to select. + */ + key: string; + /** + * Name of the referent. + * This field is effectively required, but due to backwards compatibility is + * allowed to be empty. Instances of this type with an empty value here are + * almost certainly wrong. + * TODO: Add other useful fields. apiVersion, kind, uid? + * More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + * TODO: Drop `kubebuilder:default` when controller-gen doesn't need it + * https://github.com/kubernetes-sigs/kubebuilder/issues/3896. + */ + name?: string; + /** + * Specify whether the ConfigMap or its key must be defined + */ + optional?: boolean; +} + +/** + * Secret containing data to use for the targets. + */ +export interface CASecret { + /** + * The key of the secret to select from. Must be a valid secret key. + */ + key: string; + /** + * Name of the referent. + * This field is effectively required, but due to backwards compatibility is + * allowed to be empty. Instances of this type with an empty value here are + * almost certainly wrong. + * TODO: Add other useful fields. apiVersion, kind, uid? + * More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + * TODO: Drop `kubebuilder:default` when controller-gen doesn't need it + * https://github.com/kubernetes-sigs/kubebuilder/issues/3896. + */ + name?: string; + /** + * Specify whether the Secret or its key must be defined + */ + optional?: boolean; +} + +/** + * Client certificate to present when doing client-authentication. + */ +export interface CERT { + /** + * ConfigMap containing data to use for the targets. + */ + configMap?: CERTConfigMap; + /** + * Secret containing data to use for the targets. + */ + secret?: CERTSecret; +} + +/** + * ConfigMap containing data to use for the targets. + */ +export interface CERTConfigMap { + /** + * The key to select. + */ + key: string; + /** + * Name of the referent. + * This field is effectively required, but due to backwards compatibility is + * allowed to be empty. Instances of this type with an empty value here are + * almost certainly wrong. + * TODO: Add other useful fields. apiVersion, kind, uid? + * More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + * TODO: Drop `kubebuilder:default` when controller-gen doesn't need it + * https://github.com/kubernetes-sigs/kubebuilder/issues/3896. + */ + name?: string; + /** + * Specify whether the ConfigMap or its key must be defined + */ + optional?: boolean; +} + +/** + * Secret containing data to use for the targets. + */ +export interface CERTSecret { + /** + * The key of the secret to select from. Must be a valid secret key. + */ + key: string; + /** + * Name of the referent. + * This field is effectively required, but due to backwards compatibility is + * allowed to be empty. Instances of this type with an empty value here are + * almost certainly wrong. + * TODO: Add other useful fields. apiVersion, kind, uid? + * More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + * TODO: Drop `kubebuilder:default` when controller-gen doesn't need it + * https://github.com/kubernetes-sigs/kubebuilder/issues/3896. + */ + name?: string; + /** + * Specify whether the Secret or its key must be defined + */ + optional?: boolean; +} + +/** + * Secret containing the client key file for the targets. + */ +export interface KeySecret { + /** + * The key of the secret to select from. Must be a valid secret key. + */ + key: string; + /** + * Name of the referent. + * This field is effectively required, but due to backwards compatibility is + * allowed to be empty. Instances of this type with an empty value here are + * almost certainly wrong. + * TODO: Add other useful fields. apiVersion, kind, uid? + * More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + * TODO: Drop `kubebuilder:default` when controller-gen doesn't need it + * https://github.com/kubernetes-sigs/kubebuilder/issues/3896. + */ + name?: string; + /** + * Specify whether the Secret or its key must be defined + */ + optional?: boolean; +} + +/** + * ScrapeProtocol represents a protocol used by Prometheus for scraping metrics. + * Supported values are: + * * `OpenMetricsText0.0.1` + * * `OpenMetricsText1.0.0` + * * `PrometheusProto` + * * `PrometheusText0.0.4` + */ +export enum ScrapeProtocol { + OpenMetricsText001 = "OpenMetricsText0.0.1", + OpenMetricsText100 = "OpenMetricsText1.0.0", + PrometheusProto = "PrometheusProto", + PrometheusText004 = "PrometheusText0.0.4", +} + +/** + * Label selector to select the Kubernetes `Pod` objects. + */ +export interface Selector { + /** + * matchExpressions is a list of label selector requirements. The requirements are ANDed. + */ + matchExpressions?: MatchExpression[]; + /** + * matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + * map is equivalent to an element of matchExpressions, whose key field is "key", the + * operator is "In", and the values array contains only "value". The requirements are ANDed. + */ + matchLabels?: { [key: string]: string }; +} + +/** + * A label selector requirement is a selector that contains values, a key, and an operator + * that + * relates the key and values. + */ +export interface MatchExpression { + /** + * key is the label key that the selector applies to. + */ + key: string; + /** + * operator represents a key's relationship to a set of values. + * Valid operators are In, NotIn, Exists and DoesNotExist. + */ + operator: string; + /** + * values is an array of string values. If the operator is In or NotIn, + * the values array must be non-empty. If the operator is Exists or DoesNotExist, + * the values array must be empty. This array is replaced during a strategic + * merge patch. + */ + values?: string[]; +} + +RegisterKind(PodMonitor, { + group: "monitoring.coreos.com", + version: "v1", + kind: "PodMonitor", + plural: "podmonitors", +}); diff --git a/src/pepr/operator/crd/generated/prometheus/servicemonitor-v1.ts b/src/pepr/operator/crd/generated/prometheus/servicemonitor-v1.ts index 4d776ccd4..17c09c2a4 100644 --- a/src/pepr/operator/crd/generated/prometheus/servicemonitor-v1.ts +++ b/src/pepr/operator/crd/generated/prometheus/servicemonitor-v1.ts @@ -7,121 +7,178 @@ import { GenericKind, RegisterKind } from "kubernetes-fluent-client"; */ export class ServiceMonitor extends GenericKind { /** - * Specification of desired Service selection for target discovery by Prometheus. + * Specification of desired Service selection for target discovery by + * Prometheus. */ spec?: Spec; } /** - * Specification of desired Service selection for target discovery by Prometheus. + * Specification of desired Service selection for target discovery by + * Prometheus. */ export interface Spec { /** - * `attachMetadata` defines additional metadata which is added to the discovered targets. + * `attachMetadata` defines additional metadata which is added to the + * discovered targets. + * + * * It requires Prometheus >= v2.37.0. */ attachMetadata?: AttachMetadata; + /** + * When defined, bodySizeLimit specifies a job level limit on the size + * of uncompressed response body that will be accepted by Prometheus. + * + * + * It requires Prometheus >= v2.28.0. + */ + bodySizeLimit?: string; /** * List of endpoints part of this ServiceMonitor. */ endpoints?: Endpoint[]; /** - * `jobLabel` selects the label from the associated Kubernetes `Service` object which will - * be used as the `job` label for all metrics. - * For example if `jobLabel` is set to `foo` and the Kubernetes `Service` object is labeled - * with `foo: bar`, then Prometheus adds the `job="bar"` label to all ingested metrics. - * If the value of this field is empty or if the label doesn't exist for the given Service, - * the `job` label of the metrics defaults to the name of the associated Kubernetes - * `Service`. + * `jobLabel` selects the label from the associated Kubernetes `Service` + * object which will be used as the `job` label for all metrics. + * + * + * For example if `jobLabel` is set to `foo` and the Kubernetes `Service` + * object is labeled with `foo: bar`, then Prometheus adds the `job="bar"` + * label to all ingested metrics. + * + * + * If the value of this field is empty or if the label doesn't exist for + * the given Service, the `job` label of the metrics defaults to the name + * of the associated Kubernetes `Service`. */ jobLabel?: string; /** - * Per-scrape limit on the number of targets dropped by relabeling that will be kept in - * memory. 0 means no limit. + * Per-scrape limit on the number of targets dropped by relabeling + * that will be kept in memory. 0 means no limit. + * + * * It requires Prometheus >= v2.47.0. */ keepDroppedTargets?: number; /** * Per-scrape limit on number of labels that will be accepted for a sample. + * + * * It requires Prometheus >= v2.27.0. */ labelLimit?: number; /** * Per-scrape limit on length of labels name that will be accepted for a sample. + * + * * It requires Prometheus >= v2.27.0. */ labelNameLengthLimit?: number; /** * Per-scrape limit on length of labels value that will be accepted for a sample. + * + * * It requires Prometheus >= v2.27.0. */ labelValueLengthLimit?: number; /** - * Selector to select which namespaces the Kubernetes `Endpoints` objects are discovered - * from. + * Selector to select which namespaces the Kubernetes `Endpoints` objects + * are discovered from. */ namespaceSelector?: NamespaceSelector; /** - * `podTargetLabels` defines the labels which are transferred from the associated Kubernetes - * `Pod` object onto the ingested metrics. + * `podTargetLabels` defines the labels which are transferred from the + * associated Kubernetes `Pod` object onto the ingested metrics. */ podTargetLabels?: string[]; /** - * `sampleLimit` defines a per-scrape limit on the number of scraped samples that will be - * accepted. + * `sampleLimit` defines a per-scrape limit on the number of scraped samples + * that will be accepted. */ sampleLimit?: number; + /** + * The scrape class to apply. + */ + scrapeClass?: string; + /** + * `scrapeProtocols` defines the protocols to negotiate during a scrape. It tells clients + * the + * protocols supported by Prometheus in order of preference (from most to least + * preferred). + * + * + * If unset, Prometheus uses its default value. + * + * + * It requires Prometheus >= v2.49.0. + */ + scrapeProtocols?: ScrapeProtocol[]; /** * Label selector to select the Kubernetes `Endpoints` objects. */ selector: Selector; /** - * `targetLabels` defines the labels which are transferred from the associated Kubernetes - * `Service` object onto the ingested metrics. + * `targetLabels` defines the labels which are transferred from the + * associated Kubernetes `Service` object onto the ingested metrics. */ targetLabels?: string[]; /** - * `targetLimit` defines a limit on the number of scraped targets that will be accepted. + * `targetLimit` defines a limit on the number of scraped targets that will + * be accepted. */ targetLimit?: number; } /** - * `attachMetadata` defines additional metadata which is added to the discovered targets. + * `attachMetadata` defines additional metadata which is added to the + * discovered targets. + * + * * It requires Prometheus >= v2.37.0. */ export interface AttachMetadata { /** - * When set to true, Prometheus must have the `get` permission on the `Nodes` objects. + * When set to true, Prometheus must have the `get` permission on the + * `Nodes` objects. */ node?: boolean; } /** - * Endpoint defines an endpoint serving Prometheus metrics to be scraped by Prometheus. + * Endpoint defines an endpoint serving Prometheus metrics to be scraped by + * Prometheus. */ export interface Endpoint { /** - * `authorization` configures the Authorization header credentials to use when scraping the - * target. + * `authorization` configures the Authorization header credentials to use when + * scraping the target. + * + * * Cannot be set at the same time as `basicAuth`, or `oauth2`. */ authorization?: Authorization; /** - * `basicAuth` configures the Basic Authentication credentials to use when scraping the - * target. + * `basicAuth` configures the Basic Authentication credentials to use when + * scraping the target. + * + * * Cannot be set at the same time as `authorization`, or `oauth2`. */ basicAuth?: BasicAuth; /** * File to read bearer token for scraping the target. + * + * * Deprecated: use `authorization` instead. */ bearerTokenFile?: string; /** - * `bearerTokenSecret` specifies a key of a Secret containing the bearer token for scraping - * targets. The secret needs to be in the same namespace as the ServiceMonitor object and - * readable by the Prometheus Operator. + * `bearerTokenSecret` specifies a key of a Secret containing the bearer + * token for scraping targets. The secret needs to be in the same namespace + * as the ServiceMonitor object and readable by the Prometheus Operator. + * + * * Deprecated: use `authorization` instead. */ bearerTokenSecret?: BearerTokenSecret; @@ -130,39 +187,50 @@ export interface Endpoint { */ enableHttp2?: boolean; /** - * When true, the pods which are not running (e.g. either in Failed or Succeeded state) are - * dropped during the target discovery. + * When true, the pods which are not running (e.g. either in Failed or + * Succeeded state) are dropped during the target discovery. + * + * * If unset, the filtering is enabled. + * + * * More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#pod-phase */ filterRunning?: boolean; /** - * `followRedirects` defines whether the scrape requests should follow HTTP 3xx redirects. + * `followRedirects` defines whether the scrape requests should follow HTTP + * 3xx redirects. */ followRedirects?: boolean; /** - * When true, `honorLabels` preserves the metric's labels when they collide with the - * target's labels. + * When true, `honorLabels` preserves the metric's labels when they collide + * with the target's labels. */ honorLabels?: boolean; /** - * `honorTimestamps` controls whether Prometheus preserves the timestamps when exposed by - * the target. + * `honorTimestamps` controls whether Prometheus preserves the timestamps + * when exposed by the target. */ honorTimestamps?: boolean; /** * Interval at which Prometheus scrapes the metrics from the target. + * + * * If empty, Prometheus uses the global scrape interval. */ interval?: string; /** - * `metricRelabelings` configures the relabeling rules to apply to the samples before - * ingestion. + * `metricRelabelings` configures the relabeling rules to apply to the + * samples before ingestion. */ metricRelabelings?: MetricRelabeling[]; /** * `oauth2` configures the OAuth2 settings to use when scraping the target. + * + * * It requires Prometheus >= 2.27.0. + * + * * Cannot be set at the same time as `authorization`, or `basicAuth`. */ oauth2?: Oauth2; @@ -172,44 +240,60 @@ export interface Endpoint { params?: { [key: string]: string[] }; /** * HTTP path from which to scrape for metrics. + * + * * If empty, Prometheus uses the default value (e.g. `/metrics`). */ path?: string; /** * Name of the Service port which this endpoint refers to. + * + * * It takes precedence over `targetPort`. */ port?: string; /** - * `proxyURL` configures the HTTP Proxy URL (e.g. "http://proxyserver:2195") to go through - * when scraping the target. + * `proxyURL` configures the HTTP Proxy URL (e.g. + * "http://proxyserver:2195") to go through when scraping the target. */ proxyUrl?: string; /** - * `relabelings` configures the relabeling rules to apply the target's metadata labels. + * `relabelings` configures the relabeling rules to apply the target's + * metadata labels. + * + * * The Operator automatically adds relabelings for a few standard Kubernetes fields. + * + * * The original scrape job's name is available via the `__tmp_prometheus_job_name` label. + * + * * More info: * https://prometheus.io/docs/prometheus/latest/configuration/configuration/#relabel_config */ relabelings?: Relabeling[]; /** * HTTP scheme to use for scraping. - * `http` and `https` are the expected values unless you rewrite the `__scheme__` label via - * relabeling. + * + * + * `http` and `https` are the expected values unless you rewrite the + * `__scheme__` label via relabeling. + * + * * If empty, Prometheus uses the default value `http`. */ scheme?: Scheme; /** * Timeout after which Prometheus considers the scrape to be failed. - * If empty, Prometheus uses the global scrape timeout unless it is less than the target's - * scrape interval value in which the latter is used. + * + * + * If empty, Prometheus uses the global scrape timeout unless it is less + * than the target's scrape interval value in which the latter is used. */ scrapeTimeout?: string; /** - * Name or number of the target port of the `Pod` object behind the Service, the port must - * be specified with container port property. - * Deprecated: use `port` instead. + * Name or number of the target port of the `Pod` object behind the + * Service. The port must be specified with the container's port property. */ targetPort?: number | string; /** @@ -217,17 +301,21 @@ export interface Endpoint { */ tlsConfig?: TLSConfig; /** - * `trackTimestampsStaleness` defines whether Prometheus tracks staleness of the metrics - * that have an explicit timestamp present in scraped data. Has no effect if - * `honorTimestamps` is false. + * `trackTimestampsStaleness` defines whether Prometheus tracks staleness of + * the metrics that have an explicit timestamp present in scraped data. + * Has no effect if `honorTimestamps` is false. + * + * * It requires Prometheus >= v2.48.0. */ trackTimestampsStaleness?: boolean; } /** - * `authorization` configures the Authorization header credentials to use when scraping the - * target. + * `authorization` configures the Authorization header credentials to use when + * scraping the target. + * + * * Cannot be set at the same time as `basicAuth`, or `oauth2`. */ export interface Authorization { @@ -238,7 +326,11 @@ export interface Authorization { credentials?: Credentials; /** * Defines the authentication type. The value is case-insensitive. + * + * * "Basic" is not a supported value. + * + * * Default: "Bearer" */ type?: string; @@ -254,9 +346,14 @@ export interface Credentials { */ key: string; /** - * Name of the referent. More info: - * https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names TODO: Add - * other useful fields. apiVersion, kind, uid? + * Name of the referent. + * This field is effectively required, but due to backwards compatibility is + * allowed to be empty. Instances of this type with an empty value here are + * almost certainly wrong. + * TODO: Add other useful fields. apiVersion, kind, uid? + * More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + * TODO: Drop `kubebuilder:default` when controller-gen doesn't need it + * https://github.com/kubernetes-sigs/kubebuilder/issues/3896. */ name?: string; /** @@ -266,23 +363,28 @@ export interface Credentials { } /** - * `basicAuth` configures the Basic Authentication credentials to use when scraping the - * target. + * `basicAuth` configures the Basic Authentication credentials to use when + * scraping the target. + * + * * Cannot be set at the same time as `authorization`, or `oauth2`. */ export interface BasicAuth { /** - * `password` specifies a key of a Secret containing the password for authentication. + * `password` specifies a key of a Secret containing the password for + * authentication. */ password?: Password; /** - * `username` specifies a key of a Secret containing the username for authentication. + * `username` specifies a key of a Secret containing the username for + * authentication. */ username?: Username; } /** - * `password` specifies a key of a Secret containing the password for authentication. + * `password` specifies a key of a Secret containing the password for + * authentication. */ export interface Password { /** @@ -290,9 +392,14 @@ export interface Password { */ key: string; /** - * Name of the referent. More info: - * https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names TODO: Add - * other useful fields. apiVersion, kind, uid? + * Name of the referent. + * This field is effectively required, but due to backwards compatibility is + * allowed to be empty. Instances of this type with an empty value here are + * almost certainly wrong. + * TODO: Add other useful fields. apiVersion, kind, uid? + * More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + * TODO: Drop `kubebuilder:default` when controller-gen doesn't need it + * https://github.com/kubernetes-sigs/kubebuilder/issues/3896. */ name?: string; /** @@ -302,7 +409,8 @@ export interface Password { } /** - * `username` specifies a key of a Secret containing the username for authentication. + * `username` specifies a key of a Secret containing the username for + * authentication. */ export interface Username { /** @@ -310,9 +418,14 @@ export interface Username { */ key: string; /** - * Name of the referent. More info: - * https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names TODO: Add - * other useful fields. apiVersion, kind, uid? + * Name of the referent. + * This field is effectively required, but due to backwards compatibility is + * allowed to be empty. Instances of this type with an empty value here are + * almost certainly wrong. + * TODO: Add other useful fields. apiVersion, kind, uid? + * More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + * TODO: Drop `kubebuilder:default` when controller-gen doesn't need it + * https://github.com/kubernetes-sigs/kubebuilder/issues/3896. */ name?: string; /** @@ -322,9 +435,11 @@ export interface Username { } /** - * `bearerTokenSecret` specifies a key of a Secret containing the bearer token for scraping - * targets. The secret needs to be in the same namespace as the ServiceMonitor object and - * readable by the Prometheus Operator. + * `bearerTokenSecret` specifies a key of a Secret containing the bearer + * token for scraping targets. The secret needs to be in the same namespace + * as the ServiceMonitor object and readable by the Prometheus Operator. + * + * * Deprecated: use `authorization` instead. */ export interface BearerTokenSecret { @@ -333,9 +448,14 @@ export interface BearerTokenSecret { */ key: string; /** - * Name of the referent. More info: - * https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names TODO: Add - * other useful fields. apiVersion, kind, uid? + * Name of the referent. + * This field is effectively required, but due to backwards compatibility is + * allowed to be empty. Instances of this type with an empty value here are + * almost certainly wrong. + * TODO: Add other useful fields. apiVersion, kind, uid? + * More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + * TODO: Drop `kubebuilder:default` when controller-gen doesn't need it + * https://github.com/kubernetes-sigs/kubebuilder/issues/3896. */ name?: string; /** @@ -345,21 +465,29 @@ export interface BearerTokenSecret { } /** - * RelabelConfig allows dynamic rewriting of the label set for targets, alerts, scraped - * samples and remote write samples. + * RelabelConfig allows dynamic rewriting of the label set for targets, alerts, + * scraped samples and remote write samples. + * + * * More info: * https://prometheus.io/docs/prometheus/latest/configuration/configuration/#relabel_config */ export interface MetricRelabeling { /** * Action to perform based on the regex matching. - * `Uppercase` and `Lowercase` actions require Prometheus >= v2.36.0. `DropEqual` and - * `KeepEqual` actions require Prometheus >= v2.41.0. + * + * + * `Uppercase` and `Lowercase` actions require Prometheus >= v2.36.0. + * `DropEqual` and `KeepEqual` actions require Prometheus >= v2.41.0. + * + * * Default: "Replace" */ action?: Action; /** * Modulus to take of the hash of the source label values. + * + * * Only applicable when the action is `HashMod`. */ modulus?: number; @@ -368,8 +496,10 @@ export interface MetricRelabeling { */ regex?: string; /** - * Replacement value against which a Replace action is performed if the regular expression - * matches. + * Replacement value against which a Replace action is performed if the + * regular expression matches. + * + * * Regex capture groups are available. */ replacement?: string; @@ -378,14 +508,19 @@ export interface MetricRelabeling { */ separator?: string; /** - * The source labels select values from existing labels. Their content is concatenated using - * the configured Separator and matched against the configured regular expression. + * The source labels select values from existing labels. Their content is + * concatenated using the configured Separator and matched against the + * configured regular expression. */ sourceLabels?: string[]; /** * Label to which the resulting string is written in a replacement. - * It is mandatory for `Replace`, `HashMod`, `Lowercase`, `Uppercase`, `KeepEqual` and - * `DropEqual` actions. + * + * + * It is mandatory for `Replace`, `HashMod`, `Lowercase`, `Uppercase`, + * `KeepEqual` and `DropEqual` actions. + * + * * Regex capture groups are available. */ targetLabel?: string; @@ -393,8 +528,12 @@ export interface MetricRelabeling { /** * Action to perform based on the regex matching. - * `Uppercase` and `Lowercase` actions require Prometheus >= v2.36.0. `DropEqual` and - * `KeepEqual` actions require Prometheus >= v2.41.0. + * + * + * `Uppercase` and `Lowercase` actions require Prometheus >= v2.36.0. + * `DropEqual` and `KeepEqual` actions require Prometheus >= v2.41.0. + * + * * Default: "Replace" */ export enum Action { @@ -424,20 +563,27 @@ export enum Action { /** * `oauth2` configures the OAuth2 settings to use when scraping the target. + * + * * It requires Prometheus >= 2.27.0. + * + * * Cannot be set at the same time as `authorization`, or `basicAuth`. */ export interface Oauth2 { /** - * `clientId` specifies a key of a Secret or ConfigMap containing the OAuth2 client's ID. + * `clientId` specifies a key of a Secret or ConfigMap containing the + * OAuth2 client's ID. */ clientId: ClientID; /** - * `clientSecret` specifies a key of a Secret containing the OAuth2 client's secret. + * `clientSecret` specifies a key of a Secret containing the OAuth2 + * client's secret. */ clientSecret: ClientSecret; /** - * `endpointParams` configures the HTTP parameters to append to the token URL. + * `endpointParams` configures the HTTP parameters to append to the token + * URL. */ endpointParams?: { [key: string]: string }; /** @@ -451,7 +597,8 @@ export interface Oauth2 { } /** - * `clientId` specifies a key of a Secret or ConfigMap containing the OAuth2 client's ID. + * `clientId` specifies a key of a Secret or ConfigMap containing the + * OAuth2 client's ID. */ export interface ClientID { /** @@ -473,9 +620,14 @@ export interface ClientIDConfigMap { */ key: string; /** - * Name of the referent. More info: - * https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names TODO: Add - * other useful fields. apiVersion, kind, uid? + * Name of the referent. + * This field is effectively required, but due to backwards compatibility is + * allowed to be empty. Instances of this type with an empty value here are + * almost certainly wrong. + * TODO: Add other useful fields. apiVersion, kind, uid? + * More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + * TODO: Drop `kubebuilder:default` when controller-gen doesn't need it + * https://github.com/kubernetes-sigs/kubebuilder/issues/3896. */ name?: string; /** @@ -493,9 +645,14 @@ export interface ClientIDSecret { */ key: string; /** - * Name of the referent. More info: - * https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names TODO: Add - * other useful fields. apiVersion, kind, uid? + * Name of the referent. + * This field is effectively required, but due to backwards compatibility is + * allowed to be empty. Instances of this type with an empty value here are + * almost certainly wrong. + * TODO: Add other useful fields. apiVersion, kind, uid? + * More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + * TODO: Drop `kubebuilder:default` when controller-gen doesn't need it + * https://github.com/kubernetes-sigs/kubebuilder/issues/3896. */ name?: string; /** @@ -505,7 +662,8 @@ export interface ClientIDSecret { } /** - * `clientSecret` specifies a key of a Secret containing the OAuth2 client's secret. + * `clientSecret` specifies a key of a Secret containing the OAuth2 + * client's secret. */ export interface ClientSecret { /** @@ -513,9 +671,14 @@ export interface ClientSecret { */ key: string; /** - * Name of the referent. More info: - * https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names TODO: Add - * other useful fields. apiVersion, kind, uid? + * Name of the referent. + * This field is effectively required, but due to backwards compatibility is + * allowed to be empty. Instances of this type with an empty value here are + * almost certainly wrong. + * TODO: Add other useful fields. apiVersion, kind, uid? + * More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + * TODO: Drop `kubebuilder:default` when controller-gen doesn't need it + * https://github.com/kubernetes-sigs/kubebuilder/issues/3896. */ name?: string; /** @@ -525,21 +688,29 @@ export interface ClientSecret { } /** - * RelabelConfig allows dynamic rewriting of the label set for targets, alerts, scraped - * samples and remote write samples. + * RelabelConfig allows dynamic rewriting of the label set for targets, alerts, + * scraped samples and remote write samples. + * + * * More info: * https://prometheus.io/docs/prometheus/latest/configuration/configuration/#relabel_config */ export interface Relabeling { /** * Action to perform based on the regex matching. - * `Uppercase` and `Lowercase` actions require Prometheus >= v2.36.0. `DropEqual` and - * `KeepEqual` actions require Prometheus >= v2.41.0. + * + * + * `Uppercase` and `Lowercase` actions require Prometheus >= v2.36.0. + * `DropEqual` and `KeepEqual` actions require Prometheus >= v2.41.0. + * + * * Default: "Replace" */ action?: Action; /** * Modulus to take of the hash of the source label values. + * + * * Only applicable when the action is `HashMod`. */ modulus?: number; @@ -548,8 +719,10 @@ export interface Relabeling { */ regex?: string; /** - * Replacement value against which a Replace action is performed if the regular expression - * matches. + * Replacement value against which a Replace action is performed if the + * regular expression matches. + * + * * Regex capture groups are available. */ replacement?: string; @@ -558,14 +731,19 @@ export interface Relabeling { */ separator?: string; /** - * The source labels select values from existing labels. Their content is concatenated using - * the configured Separator and matched against the configured regular expression. + * The source labels select values from existing labels. Their content is + * concatenated using the configured Separator and matched against the + * configured regular expression. */ sourceLabels?: string[]; /** * Label to which the resulting string is written in a replacement. - * It is mandatory for `Replace`, `HashMod`, `Lowercase`, `Uppercase`, `KeepEqual` and - * `DropEqual` actions. + * + * + * It is mandatory for `Replace`, `HashMod`, `Lowercase`, `Uppercase`, + * `KeepEqual` and `DropEqual` actions. + * + * * Regex capture groups are available. */ targetLabel?: string; @@ -573,8 +751,12 @@ export interface Relabeling { /** * HTTP scheme to use for scraping. - * `http` and `https` are the expected values unless you rewrite the `__scheme__` label via - * relabeling. + * + * + * `http` and `https` are the expected values unless you rewrite the + * `__scheme__` label via relabeling. + * + * * If empty, Prometheus uses the default value `http`. */ export enum Scheme { @@ -643,9 +825,14 @@ export interface CAConfigMap { */ key: string; /** - * Name of the referent. More info: - * https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names TODO: Add - * other useful fields. apiVersion, kind, uid? + * Name of the referent. + * This field is effectively required, but due to backwards compatibility is + * allowed to be empty. Instances of this type with an empty value here are + * almost certainly wrong. + * TODO: Add other useful fields. apiVersion, kind, uid? + * More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + * TODO: Drop `kubebuilder:default` when controller-gen doesn't need it + * https://github.com/kubernetes-sigs/kubebuilder/issues/3896. */ name?: string; /** @@ -663,9 +850,14 @@ export interface CASecret { */ key: string; /** - * Name of the referent. More info: - * https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names TODO: Add - * other useful fields. apiVersion, kind, uid? + * Name of the referent. + * This field is effectively required, but due to backwards compatibility is + * allowed to be empty. Instances of this type with an empty value here are + * almost certainly wrong. + * TODO: Add other useful fields. apiVersion, kind, uid? + * More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + * TODO: Drop `kubebuilder:default` when controller-gen doesn't need it + * https://github.com/kubernetes-sigs/kubebuilder/issues/3896. */ name?: string; /** @@ -697,9 +889,14 @@ export interface CERTConfigMap { */ key: string; /** - * Name of the referent. More info: - * https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names TODO: Add - * other useful fields. apiVersion, kind, uid? + * Name of the referent. + * This field is effectively required, but due to backwards compatibility is + * allowed to be empty. Instances of this type with an empty value here are + * almost certainly wrong. + * TODO: Add other useful fields. apiVersion, kind, uid? + * More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + * TODO: Drop `kubebuilder:default` when controller-gen doesn't need it + * https://github.com/kubernetes-sigs/kubebuilder/issues/3896. */ name?: string; /** @@ -717,9 +914,14 @@ export interface CERTSecret { */ key: string; /** - * Name of the referent. More info: - * https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names TODO: Add - * other useful fields. apiVersion, kind, uid? + * Name of the referent. + * This field is effectively required, but due to backwards compatibility is + * allowed to be empty. Instances of this type with an empty value here are + * almost certainly wrong. + * TODO: Add other useful fields. apiVersion, kind, uid? + * More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + * TODO: Drop `kubebuilder:default` when controller-gen doesn't need it + * https://github.com/kubernetes-sigs/kubebuilder/issues/3896. */ name?: string; /** @@ -737,9 +939,14 @@ export interface KeySecret { */ key: string; /** - * Name of the referent. More info: - * https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names TODO: Add - * other useful fields. apiVersion, kind, uid? + * Name of the referent. + * This field is effectively required, but due to backwards compatibility is + * allowed to be empty. Instances of this type with an empty value here are + * almost certainly wrong. + * TODO: Add other useful fields. apiVersion, kind, uid? + * More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + * TODO: Drop `kubebuilder:default` when controller-gen doesn't need it + * https://github.com/kubernetes-sigs/kubebuilder/issues/3896. */ name?: string; /** @@ -749,13 +956,13 @@ export interface KeySecret { } /** - * Selector to select which namespaces the Kubernetes `Endpoints` objects are discovered - * from. + * Selector to select which namespaces the Kubernetes `Endpoints` objects + * are discovered from. */ export interface NamespaceSelector { /** - * Boolean describing whether all namespaces are selected in contrast to a list restricting - * them. + * Boolean describing whether all namespaces are selected in contrast to a + * list restricting them. */ any?: boolean; /** @@ -764,6 +971,21 @@ export interface NamespaceSelector { matchNames?: string[]; } +/** + * ScrapeProtocol represents a protocol used by Prometheus for scraping metrics. + * Supported values are: + * * `OpenMetricsText0.0.1` + * * `OpenMetricsText1.0.0` + * * `PrometheusProto` + * * `PrometheusText0.0.4` + */ +export enum ScrapeProtocol { + OpenMetricsText001 = "OpenMetricsText0.0.1", + OpenMetricsText100 = "OpenMetricsText1.0.0", + PrometheusProto = "PrometheusProto", + PrometheusText004 = "PrometheusText0.0.4", +} + /** * Label selector to select the Kubernetes `Endpoints` objects. */ @@ -773,16 +995,17 @@ export interface Selector { */ matchExpressions?: MatchExpression[]; /** - * matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is - * equivalent to an element of matchExpressions, whose key field is "key", the operator is - * "In", and the values array contains only "value". The requirements are ANDed. + * matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + * map is equivalent to an element of matchExpressions, whose key field is "key", the + * operator is "In", and the values array contains only "value". The requirements are ANDed. */ matchLabels?: { [key: string]: string }; } /** * A label selector requirement is a selector that contains values, a key, and an operator - * that relates the key and values. + * that + * relates the key and values. */ export interface MatchExpression { /** @@ -790,14 +1013,15 @@ export interface MatchExpression { */ key: string; /** - * operator represents a key's relationship to a set of values. Valid operators are In, - * NotIn, Exists and DoesNotExist. + * operator represents a key's relationship to a set of values. + * Valid operators are In, NotIn, Exists and DoesNotExist. */ operator: string; /** - * values is an array of string values. If the operator is In or NotIn, the values array - * must be non-empty. If the operator is Exists or DoesNotExist, the values array must be - * empty. This array is replaced during a strategic merge patch. + * values is an array of string values. If the operator is In or NotIn, + * the values array must be non-empty. If the operator is Exists or DoesNotExist, + * the values array must be empty. This array is replaced during a strategic + * merge patch. */ values?: string[]; } @@ -806,4 +1030,5 @@ RegisterKind(ServiceMonitor, { group: "monitoring.coreos.com", version: "v1", kind: "ServiceMonitor", + plural: "servicemonitors", }); diff --git a/src/pepr/operator/crd/index.ts b/src/pepr/operator/crd/index.ts index 302ba9b5b..d92e14d2a 100644 --- a/src/pepr/operator/crd/index.ts +++ b/src/pepr/operator/crd/index.ts @@ -33,9 +33,19 @@ export { ServiceEntry as IstioServiceEntry, } from "./generated/istio/serviceentry-v1beta1"; +export { + Scheme as PodMonitorScheme, + PodMonitor as PrometheusPodMonitor, +} from "./generated/prometheus/podmonitor-v1"; + +export { + ServiceMonitor as PrometheusServiceMonitor, + Endpoint as ServiceMonitorEndpoint, + Scheme as ServiceMonitorScheme, +} from "./generated/prometheus/servicemonitor-v1"; + export { Action as IstioAction, AuthorizationPolicy as IstioAuthorizationPolicy, } from "./generated/istio/authorizationpolicy-v1beta1"; export { RequestAuthentication as IstioRequestAuthentication } from "./generated/istio/requestauthentication-v1"; -export * as Prometheus from "./generated/prometheus/servicemonitor-v1"; diff --git a/src/pepr/operator/crd/sources/package/v1alpha1.ts b/src/pepr/operator/crd/sources/package/v1alpha1.ts index 3e88ec290..e5628b230 100644 --- a/src/pepr/operator/crd/sources/package/v1alpha1.ts +++ b/src/pepr/operator/crd/sources/package/v1alpha1.ts @@ -2,6 +2,40 @@ import { V1CustomResourceDefinitionVersion, V1JSONSchemaProps } from "@kubernete import { advancedHTTP } from "../istio/virtualservice-v1beta1"; +const AuthorizationSchema: V1JSONSchemaProps = { + description: "Authorization settings.", + type: "object", + properties: { + credentials: { + description: + "Selects a key of a Secret in the namespace that contains the credentials for authentication.", + type: "object", + properties: { + key: { + description: "The key of the secret to select from. Must be a valid secret key.", + type: "string", + }, + name: { + description: + "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names", + type: "string", + }, + optional: { + description: "Specify whether the Secret or its key must be defined", + type: "boolean", + }, + }, + required: ["key"], // Ensure key is required in the schema + }, + type: { + description: + 'Defines the authentication type. The value is case-insensitive. "Basic" is not a supported value. Default: "Bearer"', + type: "string", + }, + }, + required: ["credentials"], // Ensure credentials is required in the schema +}; + const allow = { description: "Allow specific traffic (namespace will have a default-deny policy)", type: "array", @@ -160,7 +194,7 @@ const expose = { } as V1JSONSchemaProps; const monitor = { - description: "Create Service Monitor configurations", + description: "Create Service or Pod Monitor configurations", type: "array", items: { type: "object", @@ -202,6 +236,13 @@ const monitor = { description: "HTTP path from which to scrape for metrics, defaults to `/metrics`", type: "string", }, + kind: { + description: + "The type of monitor to create; PodMonitor or ServiceMonitor. ServiceMonitor is the default.", + enum: ["PodMonitor", "ServiceMonitor"], + type: "string", + }, + authorization: AuthorizationSchema, }, }, }; diff --git a/src/pepr/operator/reconcilers/package-reconciler.ts b/src/pepr/operator/reconcilers/package-reconciler.ts index 27c8df4fc..0312441ed 100644 --- a/src/pepr/operator/reconcilers/package-reconciler.ts +++ b/src/pepr/operator/reconcilers/package-reconciler.ts @@ -5,6 +5,7 @@ import { enableInjection } from "../controllers/istio/injection"; import { istioResources } from "../controllers/istio/istio-resources"; import { authservice } from "../controllers/keycloak/authservice/authservice"; import { keycloak } from "../controllers/keycloak/client-sync"; +import { podMonitor } from "../controllers/monitoring/pod-monitor"; import { serviceMonitor } from "../controllers/monitoring/service-monitor"; import { networkPolicies } from "../controllers/network/policies"; import { Phase, UDSPackage } from "../crd"; @@ -55,12 +56,12 @@ export async function packageReconciler(pkg: UDSPackage) { endpoints = await istioResources(pkg, namespace!); // Only configure the ServiceMonitors if not running in single test mode - let monitors: string[] = []; + const monitors: string[] = []; if (!UDSConfig.isSingleTest) { - // Create the ServiceMonitor for each monitored service - monitors = await serviceMonitor(pkg, namespace!); + monitors.push(...(await podMonitor(pkg, namespace!))); + monitors.push(...(await serviceMonitor(pkg, namespace!))); } else { - log.warn(`Running in single test mode, skipping ${name} ServiceMonitors.`); + log.warn(`Running in single test mode, skipping ${name} Monitors.`); } await updateStatus(pkg, { diff --git a/src/pepr/prometheus/index.ts b/src/pepr/prometheus/index.ts index cc8e022d4..04886748f 100644 --- a/src/pepr/prometheus/index.ts +++ b/src/pepr/prometheus/index.ts @@ -1,6 +1,10 @@ import { Capability, K8s, kind } from "pepr"; import { Component, setupLogger } from "../logger"; -import { Prometheus } from "../operator/crd"; +import { + PrometheusServiceMonitor, + ServiceMonitorEndpoint, + ServiceMonitorScheme, +} from "../operator/crd"; // configure subproject logger const log = setupLogger(Component.PROMETHEUS); @@ -15,11 +19,18 @@ const { When } = prometheus; /** * Mutate a service monitor to enable mTLS metrics */ -When(Prometheus.ServiceMonitor) +When(PrometheusServiceMonitor) .IsCreatedOrUpdated() .Mutate(async sm => { // Provide an opt-out of mutation to handle complicated scenarios if (sm.Raw.metadata?.annotations?.["uds/skip-sm-mutate"]) { + log.info( + `Mutating scrapeClass to exempt ServiceMonitor ${sm.Raw.metadata?.name} from default scrapeClass mTLS config`, + ); + if (sm.Raw.spec === undefined) { + return; + } + sm.Raw.spec.scrapeClass = "exempt"; return; } @@ -28,7 +39,10 @@ When(Prometheus.ServiceMonitor) if (sm.Raw.spec?.endpoints === undefined) { return; } - + /** + * Patching ServiceMonitor tlsConfig is deprecated in favor of default scrapeClass with tls config + * this mutation will be removed in favor of a mutation to opt-out of the default scrapeClass in the future + */ log.info(`Patching service monitor ${sm.Raw.metadata?.name} for mTLS metrics`); const tlsConfig = { caFile: "/etc/prom-certs/root-cert.pem", @@ -36,18 +50,24 @@ When(Prometheus.ServiceMonitor) keyFile: "/etc/prom-certs/key.pem", insecureSkipVerify: true, }; - const endpoints: Prometheus.Endpoint[] = sm.Raw.spec.endpoints; + const endpoints: ServiceMonitorEndpoint[] = sm.Raw.spec.endpoints; endpoints.forEach(endpoint => { - endpoint.scheme = Prometheus.Scheme.HTTPS; + endpoint.scheme = ServiceMonitorScheme.HTTPS; endpoint.tlsConfig = tlsConfig; }); sm.Raw.spec.endpoints = endpoints; } else { - log.info(`No mutations needed for service monitor ${sm.Raw.metadata?.name}`); + log.info( + `Mutating scrapeClass to exempt ServiceMonitor ${sm.Raw.metadata?.name} from default scrapeClass mTLS config`, + ); + if (sm.Raw.spec === undefined) { + return; + } + sm.Raw.spec.scrapeClass = "exempt"; } }); -async function isIstioInjected(sm: Prometheus.ServiceMonitor) { +async function isIstioInjected(sm: PrometheusServiceMonitor) { const namespaces = sm.Raw.spec?.namespaceSelector?.matchNames || [sm.Raw.metadata?.namespace] || [ "default", ]; diff --git a/src/prometheus-stack/chart/templates/istio-monitor.yaml b/src/prometheus-stack/chart/templates/istio-monitor.yaml index e82a0d23e..1311f4658 100644 --- a/src/prometheus-stack/chart/templates/istio-monitor.yaml +++ b/src/prometheus-stack/chart/templates/istio-monitor.yaml @@ -5,6 +5,7 @@ metadata: name: envoy-stats-monitor namespace: istio-system spec: + scrapeClass: exempt selector: matchExpressions: - {key: istio-prometheus-ignore, operator: DoesNotExist} diff --git a/src/prometheus-stack/chart/templates/prometheus-pod-monitor.yaml b/src/prometheus-stack/chart/templates/prometheus-pod-monitor.yaml index 51e17961d..60c3bb615 100644 --- a/src/prometheus-stack/chart/templates/prometheus-pod-monitor.yaml +++ b/src/prometheus-stack/chart/templates/prometheus-pod-monitor.yaml @@ -5,6 +5,7 @@ metadata: name: prometheus-pod-monitor namespace: monitoring spec: + scrapeClass: exempt selector: matchLabels: app: prometheus diff --git a/src/prometheus-stack/values/values.yaml b/src/prometheus-stack/values/values.yaml index 30d2b6559..fe6f21d26 100644 --- a/src/prometheus-stack/values/values.yaml +++ b/src/prometheus-stack/values/values.yaml @@ -24,6 +24,16 @@ prometheus: prometheusSpec: enableFeatures: - remote-write-receiver + additionalConfig: + scrapeClasses: + - name: istio-certs + default: true + tlsConfig: + caFile: /etc/prom-certs/root-cert.pem + certFile: /etc/prom-certs/cert-chain.pem + keyFile: /etc/prom-certs/key.pem + insecureSkipVerify: true + - name: exempt podMetadata: annotations: proxy.istio.io/config: | diff --git a/src/test/app-tenant.yaml b/src/test/app-tenant.yaml index 3eb203b99..a16e89349 100644 --- a/src/test/app-tenant.yaml +++ b/src/test/app-tenant.yaml @@ -3,6 +3,43 @@ kind: Namespace metadata: name: test-tenant-app --- +apiVersion: v1 +kind: Secret +metadata: + name: example-secret + namespace: test-tenant-app +type: Opaque +data: + example-key: ZXhhbXBsZS1rZXk= +--- +apiVersion: monitoring.coreos.com/v1 +kind: PodMonitor +metadata: + name: httpbin-pod-monitor-default-scrape + namespace: test-tenant-app +spec: + podMetricsEndpoints: + - path: /metrics + port: service + scrapeClass: istio-certs + selector: + matchLabels: + app: httpbin +--- +apiVersion: monitoring.coreos.com/v1 +kind: PodMonitor +metadata: + name: httpbin-pod-monitor-no-tls-config + namespace: test-tenant-app +spec: + podMetricsEndpoints: + - path: /metrics + port: service + scrapeClass: exempt + selector: + matchLabels: + app: httpbin +--- apiVersion: uds.dev/v1alpha1 kind: Package metadata: @@ -23,6 +60,47 @@ spec: gateway: tenant host: demo-8081 port: 8081 + monitor: + - selector: + app: httpbin + targetPort: 3000 + portName: service + description: Pod Monitor + kind: PodMonitor + - selector: + app: httpbin + targetPort: 3000 + portName: service + description: Service Monitor Explicit + kind: ServiceMonitor + - selector: + app: httpbin + targetPort: 3000 + portName: service + description: Service Monitor Default + - portName: "http" + selector: + app: "example" + targetPort: 8080 + kind: "PodMonitor" + authorization: + credentials: + key: "example-key" + name: "example-secret" + optional: false + type: "Bearer" + description: Pod Monitor with Authorization + - portName: "http" + selector: + app: "example" + targetPort: 8080 + authorization: + credentials: + key: "example-key" + name: "example-secret" + optional: false + type: "Bearer" + description: Service Monitor with Authorization --- apiVersion: v1 kind: Service