-
Notifications
You must be signed in to change notification settings - Fork 188
VMDistributedCluster CR: orchestrate VMCluster upgrades #1556
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
|
initially thought distributed CR is needed for full distributed setup management, but looks like it only performs version upgrade. In this case just curious why we need different CRs for VM, VT and VL? |
eaeacd4 to
c02b24c
Compare
|
Yes, so far we're focusing on upgrades - existing CRs provide sufficient flexibility IMO - and we didn't get a request for other actions so far.
VL and VT don't have agents (yet) so their specs would be different. However we can reuse the same approach and probably even some helper functions |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, so far we're focusing on upgrades - existing CRs provide sufficient flexibility IMO - and we didn't get a request for other actions so far.
I believe users would expect to modify the vmcluster spec value or apply extra flags to the vmclusters.
And since vmclusterSpec.ClusterVersion is optional, users could specify component versions inside vmclusterSpec which overrides the vmclusterSpec.ClusterVersion.
And currently, it seems VMDistributedCluster only covers a limited scenario where resources like vmcluster, vmuser, vmauth are defined and configured as needed.
Could you please provide an example of how to config them to achieve similar topology described in victoria-metrics-distributed chart? I expect VMDistributedCluster to be supported there when released.
internal/controller/operator/factory/vmdistributedcluster/vmdistributedcluster.go
Outdated
Show resolved
Hide resolved
internal/controller/operator/factory/vmdistributedcluster/vmdistributedcluster.go
Show resolved
Hide resolved
Yup, setting generic |
280b2e6 to
04b44f9
Compare
04b44f9 to
1336f73
Compare
1336f73 to
c3b3e24
Compare
| } | ||
| } | ||
|
|
||
| // Fetch global vmagent |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
are we going to have a single VMAgent? are there any requirements to amount of replicas it should have according to zones count?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Single VMAgent iiuc, however, later we may want to support zone-specific agents
|
|
||
| // Loop until VMAgent metrics show that disk buffer is empty | ||
| err := wait.PollUntilContextTimeout(ctx, 1*time.Second, deadline, true, func(ctx context.Context) (done bool, err error) { | ||
| metricValue, err := fetchVMAgentDiskBufferMetric(ctx, httpClient, vmAgentPath) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The vmAgentPath uses vmagent service address, what if the vmagent deployment has multiple replicas?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it a common configuration? I don't see the value in running several identical replicas of vmagent, usually (redundancy?).
TODO: fetch endpoints to be sure
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see the value in running several identical replicas of vmagent, usually (redundancy?).
It's common for large setups, for HA or increase cluster capacity.
| type VMDistributedClusterSpec struct { | ||
| // ParsingError contents error with context if operator was failed to parse json object from kubernetes api server | ||
| ParsingError string `json:"-" yaml:"-"` | ||
| // VMAgent points to the VMAgent object for collecting metrics from multiple VMClusters |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The main role of this vmagent is the global write entrypoint(which buffers data if one of the vmcluster is down). It might not be used to scrape targets(including vmclusters), but only to proxy data.
What about renaming it to something like GlobalWriteEntryVMAgent?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd prefer to keep the name short - there is no need to write a long one as there is no other VMAgent to confuse this setting with.
I agree however this should have a better description.
| // VMUsers is a list of VMUser objects controlling traffic distribution between multiple VMClusters | ||
| VMUsers []corev1.LocalObjectReference `json:"vmUsers,omitempty"` | ||
| // Zones is a list of VMCluster instances to update. Each VMCluster in the list represents a "zone" within the distributed cluster. | ||
| Zones []VMClusterRefOrSpec `json:"zones,omitempty"` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
zones is ambiguous without contexts, and since it only contains vmcluster resources, I think we can call it something like vmclusterList to be more clear.
| // +kubebuilder:printcolumn:name="Status",type="string",JSONPath=".status.updateStatus",description="current status of update rollout" | ||
| // +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp" | ||
| // VMDistributedClusterSpec is progressively rolling out updates to multiple VMClusters. | ||
| type VMDistributedCluster struct { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The feature isn’t limited to vmcluster, it can also be applied to vmsingle.
Later, we can support vmsingle with the same CRD by replacing vmcluster objects under VMDistributedClusterSpec with vmsingle.
What about calling it VMDistributed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I think it's fair to extend this to VMSingle too. I think it would be trivial to extend this to VMSingles - by adding VMType to Zones property. We didn't get a request to extend this to VMSingle though, so I'd prefer to focus on VMClusters.
Not quite sure about VMDistributed - its fair to treat multiple zones as a cluster (so VMCluster would be a fantastic name :) ), while VMDistributed doesn't really pinpoint it.
| // VMAgent points to the VMAgent object for collecting metrics from multiple VMClusters | ||
| VMAgent corev1.LocalObjectReference `json:"vmAgent,omitempty"` | ||
| // VMUsers is a list of VMUser objects controlling traffic distribution between multiple VMClusters | ||
| VMUsers []corev1.LocalObjectReference `json:"vmUsers,omitempty"` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please name the field more specifically.
As I understand, we don't need VMUser objects controlling traffic distribution between multiple VMClusters, but only the vmuser which proxies query requests between two vmcluster.
For example, the vmuser for vmauth-read-proxy in below diagram(without the vmauth-read-balancer since it changes the target for vmauth-read-proxy).

Later, We should also support vmauth's unauthorized_user.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree on documentation update, but it would be convenient to keep the property name short (there are no other VMUsers specified there too)
| // Name specifies the static name to be used for the VMCluster when Spec is provided. | ||
| // If Ref is used, this field is ignored. | ||
| // +optional | ||
| Name string `json:"name,omitempty"` | ||
| // Ref points to the VMCluster object. | ||
| // +optional | ||
| Ref *corev1.LocalObjectReference `json:"ref,omitempty"` | ||
| // Spec defines the desired state of a new VMCluster. | ||
| // +optional | ||
| Spec *vmv1beta1.VMClusterSpec `json:"spec,omitempty"` | ||
| // OverrideSpec specifies an override to the VMClusterSpec of the referenced object. | ||
| // This field is ignored if `Spec` is specified. | ||
| // This override is applied to the referenced object if `Ref` is specified. | ||
| // +kubebuilder:validation:Type=object | ||
| // +kubebuilder:validation:XPreserveUnknownFields | ||
| // +optional | ||
| OverrideSpec *apiextensionsv1.JSON `json:"overrideSpec,omitempty"` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So Name and Spec define a new vmcluster, while Ref and OverrideSpec go to an existing one. Please put related fields closer for readability:
// Name creates a new VMCluster with the below spec.
// Only one of Ref or Name can be used.
// +optional
Name string `json:"name,omitempty"`
// Spec defines the spec with a new vmcluster.
// +optional
Spec *vmv1beta1.VMClusterSpec `json:"spec,omitempty"`
// Ref points to an existing VMCluster object.
// Only one of Ref or Name can be used.
// +optional
Ref *corev1.LocalObjectReference `json:"ref,omitempty"`
// OverrideSpec specifies spec overrides for the existing vmcluster.
// +optional
OverrideSpec *apiextensionsv1.JSON `json:"overrideSpec,omitempty"`
Also the comments are conflicted, it says:
// If Ref is used, this field is ignored.
Name stringjson:"name,omitempty"
which means Ref takes precedence. But
// This field is ignored if
Specis specified.
OverrideSpec *apiextensionsv1.JSONjson:"overrideSpec,omitempty"
means Spec(Name) takes precedence.
Since we don't allow to have both Name and Ref, let's just highlight this in the doc.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please put related fields closer for readability
Good idea. Rearranged and added better description in 95bc654
internal/controller/operator/factory/vmdistributedcluster/vmdistributedcluster.go
Outdated
Show resolved
Hide resolved
| if !needsToBeCreated && !modified { | ||
| continue | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the vmcluster was created by VMDistributedCluster, then user changed its spec, the change won't be detected by the check, and the vmcluster won't be updated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch, we'll need to set up an informer for VMClusters in this controller - do you know if there is some nice example on how to do that?
| } | ||
|
|
||
| // +k8s:openapi-gen=true | ||
| // VMClusterRefOrSpec is either a reference to existing VMCluster or a specification of a new VMCluster. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be nice to tag the newly created vmcluster as managed by VMDistributed, and not allowed to modify the spec in vmcluster reconcile.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we setup watchers for VMClusters the users are allowed to modify them (although results may be unexpected).
It is worth setting ownerRef for affected clusters, I agree
… uses server-side apply This prevents kubectl from creating an annotation which is too large and failing with `The CustomResourceDefinition "vmdistributedclusters.operator.victoriametrics.com" is invalid: metadata.annotations: Too long: may not be more than 262144 bytes` error
c3b3e24 to
95bc654
Compare
9919c2b to
42b277d
Compare
Add a new CR -
VMDistributedCluster-so that multiple VMClusters could be upgraded in orchestrated fashion, ensuring the read VMAuth is disabled before upgrade and VMAgent (if available) doesn't have pending bytes to send.See #1515 (comment) for agreed limitations for v1alpha1 version.
Fixes #1515
TODO:
Keeping original commits for review as its useful to show how the feature was developed
During development I realized VMAuth / VMClusters may be in different namespaces. The initial version requires all objects to be in the same namespace as VMDistributedCluster. Do we want to keep it that way for API simplicity or worth having the initial version with cross-namespace support?