prometheus: Introduce RuleFile Custom Resource Definition #1333
prometheus: Introduce RuleFile Custom Resource Definition #1333brancz merged 1 commit intoprometheus-operator:masterfrom
Conversation
4cee375 to
674b1d0
Compare
| name: k8s | ||
| namespace: monitoring | ||
| spec: | ||
| Rules: "123" |
|
|
||
| // AlertingRuleFile defines alerting rules for a Prometheus instance | ||
| // TODO: Should we go with v1 instead of v1alpha1 right away? | ||
| type AlertingRuleFile struct { |
There was a problem hiding this comment.
If AlertingRuleFile is used only to hold the serialized contents of an alerting rule file (the type for which is not represented in this API), how does AlertingRuleFile compare to using a ConfigMap?
There was a problem hiding this comment.
@ironcladlou My plan is to vendor the upstream Prometheus alerting rule struct. Thereby we would have full OpenAPI generated deep validation on creation time (instant feedback). What do you think?
There was a problem hiding this comment.
I still have a couple TODOs on my list :/
There was a problem hiding this comment.
That makes sense to me- cool!
5784859 to
c09c3f3
Compare
brancz
left a comment
There was a problem hiding this comment.
Awesome start! Really looking forward to this!
| | externalUrl | The external URL the Prometheus instances will be available under. This is necessary to generate correct URLs. This is necessary if Prometheus is not served from root of a DNS name. | string | false | | ||
| | routePrefix | The route prefix Prometheus registers HTTP handlers for. This is useful, if using ExternalURL and a proxy is rewriting HTTP routes of a request, and the actual ExternalURL is still true, but the server serves requests under a different route prefix. For example for use with `kubectl proxy`. | string | false | | ||
| | storage | Storage spec to specify how storage shall be used. | *[StorageSpec](#storagespec) | false | | ||
| | ruleSelector | A selector to select which ConfigMaps to mount for loading rule files from. | *[metav1.LabelSelector](https://v1-6.docs.kubernetes.io/docs/api-reference/v1.6/#labelselector-v1-meta) | false | |
There was a problem hiding this comment.
We will need to continue to support this for the time being, I suggest this should select both configmaps and Rule CRDs for the forseeable future and the configmap selector stays local to the namespace and the CRD selector is respective to the ruleNamespaceSelector.
In fact we should actually do a migration where we re-create rule CRDs from the content of the configmaps.
There was a problem hiding this comment.
I brought back the field and added the following to the rule retrieval logic:
// With Prometheus Operator v0.20.0 the 'RuleSelector' field in the Prometheus
// CRD Spec is deprecated. Any value in 'RuleSelector' is just copied to the new
// field 'RuleFileSelector'.
if p.Spec.RuleFileSelector == nil && p.Spec.RuleSelector != nil {
p.Spec.RuleFileSelector = p.Spec.RuleSelector
}@brancz Do you mind if we add the migration logic in a separate PR (of course before the release)?
Documentation/api.md
Outdated
| | routePrefix | The route prefix Prometheus registers HTTP handlers for. This is useful, if using ExternalURL and a proxy is rewriting HTTP routes of a request, and the actual ExternalURL is still true, but the server serves requests under a different route prefix. For example for use with `kubectl proxy`. | string | false | | ||
| | storage | Storage spec to specify how storage shall be used. | *[StorageSpec](#storagespec) | false | | ||
| | ruleSelector | A selector to select which ConfigMaps to mount for loading rule files from. | *[metav1.LabelSelector](https://v1-6.docs.kubernetes.io/docs/api-reference/v1.6/#labelselector-v1-meta) | false | | ||
| | alertingRuleFileSelector | A selector to select which AlertingRuleFiles to mount for loading alerting rules from. | *[metav1.LabelSelector](https://v1-6.docs.kubernetes.io/docs/api-reference/v1.6/#labelselector-v1-meta) | false | |
There was a problem hiding this comment.
It's not just alerting rules, it's also recording rules, therefore usually referred to as "rule"
cmd/operator/main.go
Outdated
| return 1 | ||
| } | ||
|
|
||
| fmt.Println("image: ", cfg.ConfigReloaderImage) |
pkg/k8sutil/k8sutil.go
Outdated
| ResourceScope: string(extensionsobj.NamespaceScoped), | ||
| Group: group, | ||
| Kind: crdKind.Kind, | ||
| // Version: monitoringv1.Version, |
|
|
||
| // AlertingRuleFile defines alerting rules for a Prometheus instance | ||
| // TODO: Should we go with v1 instead of v1alpha1 right away? | ||
| type AlertingRuleFile struct { |
There was a problem hiding this comment.
I already commented on the name above, I think this should probably be "PrometheusRule" instead.
Dockerfile
Outdated
| FROM quay.io/prometheus/busybox:latest | ||
|
|
||
| ADD .build/linux-amd64/operator /bin/operator | ||
| ADD ./contrib/prometheus-config-reloader/prometheus-config-reloader /bin/prometheus-config-reloader |
There was a problem hiding this comment.
I've thought of this as well, but I'm not sure I like it, especially if the container image repo is the same, then people will be maximum confused I think. Even today people think the operator runs as a sidecar. It also has a large impact on the container size, the reload container is very very small whereas operator+reloader is a pretty large image.
|
@brancz |
|
I have a general question about this feature: How does this align with the current work going on to make jsonnet bases monitoring mixins with alerts? Are these features orthogonal? I guess it tries to solves the problem with a different approach, but on the other hand can also be combined? |
|
@metalmatze they're unrelated, this CRD is merely so that we can collect Prometheus rules from across namespaces similar to cross namespace ServiceMonitors. In fact as these rules are identical to the Prometheus rule definition they are compatible. |
|
@mxinden do they work alongside each other? I seem to recall there was some problem as some point. Otherwise v1alpha1 sounds good as it's a new resource. |
|
AFAIK, CRD are painful to upgrade (from v1alpha1 to v1), I would save us and users this additional migration. Also there is no plan to keep both at the same time alive (configmap + crd), so as soon as we release this, the CRD will replace the configmap, then I would go for v1. |
|
Yeah after thinking about it once more I think putting it in v1 is fine, given that the spec we're using is identical to the Prometheus rule spec, which cannot be broken until the next Prometheus major version anyways. |
|
General design document can be found here. Feedback by the community is very welcome. |
0ab77a7 to
91c9329
Compare
be283e2 to
e6620b2
Compare
e6620b2 to
3836dd2
Compare
|
@brancz @ant31 @ironcladlou @metalmatze this PR is ready for review. Would you mind taking another look? |
pkg/client/monitoring/v1/types.go
Outdated
| // +k8s:openapi-gen=true | ||
| type RuleFileSpec struct { | ||
| // Content of Prometheus rule file | ||
| Content RuleGroups `json:"content,omitempty"` |
There was a problem hiding this comment.
What speaks against having the Groups field here instead of nested into the RuleGroups struct? Seems double encapsulated.
There was a problem hiding this comment.
True. I will address that.
pkg/client/monitoring/v1/types.go
Outdated
| } | ||
|
|
||
| func (l *RuleFile) DeepCopyObject() runtime.Object { | ||
| panic("DeepCopyObject not implemented for ServiceMonitorList") |
There was a problem hiding this comment.
yeah we should start to actually implement these * hides *
There was a problem hiding this comment.
Not entirely sure, but we are auto-generating these, right?
I have replaced the panic with return l.DeepCopy().
pkg/prometheus/operator.go
Outdated
| return nil | ||
| } | ||
|
|
||
| // TODO: All handleXXX do the same |
There was a problem hiding this comment.
this doesn't work for update, which is why we chose duplication over confusion
There was a problem hiding this comment.
handleSmonUpdate and handleRuleUpdate seem equal to me, no?
There was a problem hiding this comment.
yes, that's true, we can look into deduping those
pkg/prometheus/operator.go
Outdated
| k8sutil.NewCustomResourceDefinition(c.config.CrdKinds.Prometheus, c.config.CrdGroup, c.config.Labels.LabelsMap, c.config.EnableValidation), | ||
| k8sutil.NewCustomResourceDefinition(c.config.CrdKinds.ServiceMonitor, c.config.CrdGroup, c.config.Labels.LabelsMap, c.config.EnableValidation), | ||
| k8sutil.NewCustomResourceDefinition( | ||
| monitoringv1.CrdKind{ |
There was a problem hiding this comment.
This should be configured from the config like the other CRDs.
There was a problem hiding this comment.
👍 thanks, I forgot that.
pkg/prometheus/operator.go
Outdated
| }{ | ||
| {"Prometheus", c.mclient.MonitoringV1().Prometheuses(c.config.Namespace).List}, | ||
| {"ServiceMonitor", c.mclient.MonitoringV1().ServiceMonitors(c.config.Namespace).List}, | ||
| {"Rule", c.mclient.MonitoringV1().RuleFiles(c.config.Namespace).List}, |
pkg/prometheus/statefulset.go
Outdated
| return nil, err | ||
| } | ||
|
|
||
| // TODO: No need to return an error |
There was a problem hiding this comment.
this doesn't return an error
There was a problem hiding this comment.
Fixed it and forgot to remove the TODO 🤦♂️
pkg/prometheus/statefulset.go
Outdated
| }, nil | ||
| } | ||
|
|
||
| // TODO: Is this used by anyone else? |
There was a problem hiding this comment.
not sure what this comment is referring to
pkg/prometheus/rulefile.go
Outdated
| return ruleFiles, err | ||
| } | ||
| if marshalErr != nil { | ||
| return ruleFiles, marshalErr |
There was a problem hiding this comment.
on error return nil explicitly
There was a problem hiding this comment.
I don't understand what you mean.
There are two types of possible errors here:
1. Error thrown by ListAllByNamespace
2. Error thrown by yaml.Marshal
Not very proud of the structure of my code here. Happy for suggestions.
Never mind, understood.
pkg/prometheus/rulefile.go
Outdated
| ruleFiles[fmt.Sprintf("%v-%v.yaml", file.Namespace, file.Name)] = string(content) | ||
| }) | ||
| if err != nil { | ||
| return ruleFiles, err |
There was a problem hiding this comment.
on error return nil explicitly
| marshalErr = err | ||
| return | ||
| } | ||
| ruleFiles[fmt.Sprintf("%v-%v.yaml", file.Namespace, file.Name)] = string(content) |
There was a problem hiding this comment.
I'm not entirely sure about the behavior, when file name is different but rule group name is the same, we might have to add the namespace as a prefix to the rule group name. Let's make sure and investigate this.
There was a problem hiding this comment.
I have just started a Prometheus with two unique rule files, with matching rule group names. Both the alerts from file one, as well as file two show up in the Prometheus UI.
There was a problem hiding this comment.
Perfect, thanks for making sure!
|
One more thing, the |
4797d78 to
8bdb7f7
Compare
This patch introduces a new Custom Resource Definition to the Prometheus Operator - the Rule CRD. It addresses two main needs: 1. Prometheus (alerting and recording) Rule validation during creation time via Kubernetes Custom Resource Definition validation. 2. Life-cycle management of Prometheus application Rules alongside the application itself, inside the applications Kubernetes namespace, not necessarily the namespace of the scraping Prometheus instance. A user defines Prometheus alerting and recording Rules via a Kubernetes Custom Resource Definition. These Custom Resource Definitions can be fully validated by the Kubernetes API server during creation time via automatically generated OpenAPI specifications. Instead of the restriction of a Prometheus instance to only select Rule definitions inside its own namespace, the Prometheus specification is extended to also specify namespaces to look for Rule Custom Resource Definitions outside its own namespace. --- Dependent technical changes: - prometheus: Use github.com/jimmidyson/configmap-reload to reload rules - prometheus: Remove Prometheus Statefulset deletion function. Starting with K8s >=1.8 this is handled via OwnerReferences. - prometheus: Do not add rule files checksum to Prometheus configuration secret - prometheus: Update StatefulSet only on relevant changes. Instead of updating the Prometheus StatefulSet on every `sync()` run, only update it if the input parameters to `makeStatefulSet` change. Enforce this via a checksum of the parameters which is saved inside the annotations of the statefulset. - e2e/prometheus: Check how often resources (Secret, ConfigMap, Prometheus CRD, Service) are updated to enforce that Prometheus Operator only updated created resources if necessary. - contrib/prometheus-config-reloader: Remove logic to retriev K8s ConfigMaps. These are mounted into the pod right away now.
8bdb7f7 to
89fc4e3
Compare
|
@brancz Thanks for all the comments! Would you mind taking another look? |
|
Nice job! lgtm 👍 |
| | ruleSelector | A selector to select which ConfigMaps to mount for loading rule files from. | *[metav1.LabelSelector](https://v1-6.docs.kubernetes.io/docs/api-reference/v1.6/#labelselector-v1-meta) | false | | ||
| | ruleFileSelector | A selector to select which RuleFiles to mount for loading alerting rules from. | *[metav1.LabelSelector](https://v1-6.docs.kubernetes.io/docs/api-reference/v1.6/#labelselector-v1-meta) | false | | ||
| | ruleSelector | DEPRECATED with Prometheus Operator 'v0.20.0'. Any value in this field will just be copied to 'RuleFileSelector' field | *[metav1.LabelSelector](https://v1-6.docs.kubernetes.io/docs/api-reference/v1.6/#labelselector-v1-meta) | false | | ||
| | ruleFileNamespaceSelector | Namespaces to be selected for RuleFiles discovery. If empty, only check own namespace. | *[metav1.LabelSelector](https://v1-6.docs.kubernetes.io/docs/api-reference/v1.6/#labelselector-v1-meta) | false | |
There was a problem hiding this comment.
here is written if empy only check own namespace, more down it's written empty will match all objects. so which is it ? :)
There was a problem hiding this comment.
There was a problem hiding this comment.
Most likely to match the behavior of the ServiceMonitor one:
https://github.com/coreos/prometheus-operator/blob/f9676ddc5b55ae47dcdfa43d9290cb28e5504649/pkg/prometheus/promcfg.go#L468
Although @mxinden will confirm but in the RuleFile it seems to implement a standard selector which may offer the possibility to match all namespaces somehow.
There was a problem hiding this comment.
Sorry for the confusion. When it is not set, then it will select the same namespace as the Prometheus server is in. With an empty selector explicitly set ({} is the empty selector), it will select all namespaces (maybe better referred to as the "all" selector). Hope this makes it clearer. 🙂 Also note that we will be renaming the resource before releasing it, see #1425.
There was a problem hiding this comment.
yes that makes sense :) thanks for explanation
This patch introduces a new Custom Resource Definition to the
Prometheus Operator - the Rule CRD. It addresses two main
needs:
Prometheus (alerting and recording) Rule validation during creation time
via Kubernetes Custom Resource Definition validation.
Life-cycle management of Prometheus application Rules alongside the
application itself, inside the applications Kubernetes namespace, not
necessarily the namespace of the scraping Prometheus instance.
A user defines Prometheus alerting and recording Rules via a Kubernetes
Custom Resource Definition. These Custom Resource Definitions can be
fully validated by the Kubernetes API server during creation time via
automatically generated OpenAPI specifications. Instead of the
restriction of a Prometheus instance to only select Rule definitions
inside its own namespace, the Prometheus specification is extended to
also specify namespaces to look for Rule Custom Resource Definitions
outside its own namespace.
Dependent technical changes:
prometheus: Use github.com/jimmidyson/configmap-reload to reload rules
prometheus: Remove Prometheus Statefulset deletion function. Starting
with K8s >=1.8 this is handled via OwnerReferences.
prometheus: Do not add rule files checksum to Prometheus configuration
secret
prometheus: Update StatefulSet only on relevant changes. Instead of
updating the Prometheus StatefulSet on every
sync()run, only updateit if the input parameters to
makeStatefulSetchange. Enforce thisvia a checksum of the parameters which is saved inside the annotations
of the statefulset.
e2e/prometheus: Check how often resources (Secret, ConfigMap,
Prometheus CRD, Service) are updated to enforce that Prometheus Operator
only updated created resources if necessary.
contrib/prometheus-config-reloader: Remove logic to retriev K8s
ConfigMaps. These are mounted into the pod right away now.
Design Document