-
Notifications
You must be signed in to change notification settings - Fork 26
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
interface: add v1beta1 API for eviction & PDB (#1013)
- Loading branch information
1 parent
8a8f6d0
commit 3479ddb
Showing
20 changed files
with
927 additions
and
214 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
/* | ||
Copyright (c) Microsoft Corporation. | ||
Licensed under the MIT license. | ||
*/ | ||
|
||
package v1beta1 | ||
|
||
import ( | ||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
"k8s.io/apimachinery/pkg/util/intstr" | ||
) | ||
|
||
// +kubebuilder:object:root=true | ||
// +kubebuilder:resource:scope=Cluster,categories={fleet,fleet-placement},shortName=crpdb | ||
// +kubebuilder:storageversion | ||
|
||
// ClusterResourcePlacementDisruptionBudget is the policy applied to a ClusterResourcePlacement | ||
// object that specifies its disruption budget, i.e., how many placements (clusters) can be | ||
// down at the same time due to voluntary disruptions (e.g., evictions). Involuntary | ||
// disruptions are not subject to this budget, but will still count against it. | ||
// | ||
// To apply a ClusterResourcePlacementDisruptionBudget to a ClusterResourcePlacement, use the | ||
// same name for the ClusterResourcePlacementDisruptionBudget object as the ClusterResourcePlacement | ||
// object. This guarantees a 1:1 link between the two objects. | ||
type ClusterResourcePlacementDisruptionBudget struct { | ||
metav1.TypeMeta `json:",inline"` | ||
metav1.ObjectMeta `json:"metadata,omitempty"` | ||
|
||
// Spec is the desired state of the ClusterResourcePlacementDisruptionBudget. | ||
// +kubebuilder:validation:XValidation:rule="!(has(self.maxUnavailable) && has(self.minAvailable))",message="Both MaxUnavailable and MinAvailable cannot be specified" | ||
// +required | ||
Spec PlacementDisruptionBudgetSpec `json:"spec"` | ||
} | ||
|
||
// PlacementDisruptionBudgetSpec is the desired state of the PlacementDisruptionBudget. | ||
type PlacementDisruptionBudgetSpec struct { | ||
// MaxUnavailable is the maximum number of placements (clusters) that can be down at the | ||
// same time due to voluntary disruptions. For example, a setting of 1 would imply that | ||
// a voluntary disruption (e.g., an eviction) can only happen if all placements (clusters) | ||
// from the linked Placement object are applied and available. | ||
// | ||
// This can be either an absolute value (e.g., 1) or a percentage (e.g., 10%). | ||
// | ||
// If a percentage is specified, Fleet will calculate the corresponding absolute values | ||
// as follows: | ||
// * if the linked Placement object is of the PickFixed placement type, | ||
// we don't perform any calculation because eviction is not allowed for PickFixed CRP. | ||
// * if the linked Placement object is of the PickAll placement type, MaxUnavailable cannot | ||
// be specified since we cannot derive the total number of clusters selected. | ||
// * if the linked Placement object is of the PickN placement type, | ||
// the percentage is against the number of clusters specified in the placement (i.e., the | ||
// value of the NumberOfClusters fields in the placement policy). | ||
// The end result will be rounded up to the nearest integer if applicable. | ||
// | ||
// One may use a value of 0 for this field; in this case, no voluntary disruption would be | ||
// allowed. | ||
// | ||
// This field is mutually exclusive with the MinAvailable field in the spec; exactly one | ||
// of them can be set at a time. | ||
// | ||
// +kubebuilder:validation:XIntOrString | ||
// +kubebuilder:validation:XValidation:rule="type(self) == string ? self.matches('^(100|[0-9]{1,2})%$') : self >= 0",message="If supplied value is String should match regex '^(100|[0-9]{1,2})%$' or If supplied value is Integer must be greater than or equal to 0" | ||
// +optional | ||
MaxUnavailable *intstr.IntOrString `json:"maxUnavailable,omitempty"` | ||
|
||
// MinAvailable is the minimum number of placements (clusters) that must be available at any | ||
// time despite voluntary disruptions. For example, a setting of 10 would imply that | ||
// a voluntary disruption (e.g., an eviction) can only happen if there are at least 11 | ||
// placements (clusters) from the linked Placement object are applied and available. | ||
// | ||
// This can be either an absolute value (e.g., 1) or a percentage (e.g., 10%). | ||
// | ||
// If a percentage is specified, Fleet will calculate the corresponding absolute values | ||
// as follows: | ||
// * if the linked Placement object is of the PickFixed placement type, | ||
// we don't perform any calculation because eviction is not allowed for PickFixed CRP. | ||
// * if the linked Placement object is of the PickAll placement type, MinAvailable can be | ||
// specified but only as an integer since we cannot derive the total number of clusters selected. | ||
// * if the linked Placement object is of the PickN placement type, | ||
// the percentage is against the number of clusters specified in the placement (i.e., the | ||
// value of the NumberOfClusters fields in the placement policy). | ||
// The end result will be rounded up to the nearest integer if applicable. | ||
// | ||
// One may use a value of 0 for this field; in this case, voluntary disruption would be | ||
// allowed at any time. | ||
// | ||
// This field is mutually exclusive with the MaxUnavailable field in the spec; exactly one | ||
// of them can be set at a time. | ||
// | ||
// +kubebuilder:validation:XIntOrString | ||
// +kubebuilder:validation:XValidation:rule="type(self) == string ? self.matches('^(100|[0-9]{1,2})%$') : self >= 0",message="If supplied value is String should match regex '^(100|[0-9]{1,2})%$' or If supplied value is Integer must be greater than or equal to 0" | ||
// +optional | ||
MinAvailable *intstr.IntOrString `json:"minAvailable,omitempty"` | ||
} | ||
|
||
// ClusterResourcePlacementDisruptionBudgetList contains a list of ClusterResourcePlacementDisruptionBudget objects. | ||
// +kubebuilder:resource:scope=Cluster | ||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object | ||
type ClusterResourcePlacementDisruptionBudgetList struct { | ||
metav1.TypeMeta `json:",inline"` | ||
metav1.ListMeta `json:"metadata,omitempty"` | ||
|
||
// Items is the list of PlacementDisruptionBudget objects. | ||
Items []ClusterResourcePlacementDisruptionBudget `json:"items"` | ||
} | ||
|
||
func init() { | ||
SchemeBuilder.Register( | ||
&ClusterResourcePlacementDisruptionBudget{}, | ||
&ClusterResourcePlacementDisruptionBudgetList{}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
/* | ||
Copyright (c) Microsoft Corporation. | ||
Licensed under the MIT license. | ||
*/ | ||
|
||
package v1beta1 | ||
|
||
import ( | ||
"k8s.io/apimachinery/pkg/api/meta" | ||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
) | ||
|
||
// +kubebuilder:object:root=true | ||
// +kubebuilder:resource:scope=Cluster,categories={fleet,fleet-placement},shortName=crpe | ||
// +kubebuilder:subresource:status | ||
// +kubebuilder:storageversion | ||
|
||
// ClusterResourcePlacementEviction is an eviction attempt on a specific placement from | ||
// a ClusterResourcePlacement object; one may use this API to force the removal of specific | ||
// resources from a cluster. | ||
// | ||
// An eviction is a voluntary disruption; its execution is subject to the disruption budget | ||
// linked with the target ClusterResourcePlacement object (if present). | ||
// | ||
// Beware that an eviction alone does not guarantee that a placement will not re-appear; i.e., | ||
// after an eviction, the Fleet scheduler might still pick the previous target cluster for | ||
// placement. To prevent this, considering adding proper taints to the target cluster before running | ||
// an eviction that will exclude it from future placements; this is especially true in scenarios | ||
// where one would like to perform a cluster replacement. | ||
// | ||
// For safety reasons, Fleet will only execute an eviction once; the spec in this object is immutable, | ||
// and once executed, the object will be ignored after. To trigger another eviction attempt on the | ||
// same placement from the same ClusterResourcePlacement object, one must re-create (delete and | ||
// create) the same Eviction object. Note also that an Eviction object will be | ||
// ignored once it is deemed invalid (e.g., such an object might be targeting a CRP object or | ||
// a placement that does not exist yet), even if it does become valid later | ||
// (e.g., the CRP object or the placement appears later). To fix the situation, re-create the | ||
// Eviction object. | ||
// | ||
// Note: Eviction of resources from a cluster propagated by a PickFixed CRP is not allowed. | ||
// If the user wants to remove resources from a cluster propagated by a PickFixed CRP simply | ||
// remove the cluster name from cluster names field from the CRP spec. | ||
// | ||
// Executed evictions might be kept around for a while for auditing purposes; the Fleet controllers might | ||
// have a TTL set up for such objects and will garbage collect them automatically. For further | ||
// information, see the Fleet documentation. | ||
type ClusterResourcePlacementEviction struct { | ||
metav1.TypeMeta `json:",inline"` | ||
metav1.ObjectMeta `json:"metadata,omitempty"` | ||
|
||
// Spec is the desired state of the ClusterResourcePlacementEviction. | ||
// | ||
// Note that all fields in the spec are immutable. | ||
// +required | ||
Spec PlacementEvictionSpec `json:"spec"` | ||
|
||
// Status is the observed state of the ClusterResourcePlacementEviction. | ||
// +optional | ||
Status PlacementEvictionStatus `json:"status,omitempty"` | ||
} | ||
|
||
// PlacementEvictionSpec is the desired state of the parent PlacementEviction. | ||
type PlacementEvictionSpec struct { | ||
// PlacementName is the name of the Placement object which | ||
// the Eviction object targets. | ||
// +kubebuilder:validation:Required | ||
// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="The PlacementName field is immutable" | ||
// +kubebuilder:validation:MaxLength=255 | ||
PlacementName string `json:"placementName"` | ||
|
||
// ClusterName is the name of the cluster that the Eviction object targets. | ||
// +kubebuilder:validation:Required | ||
// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="The ClusterName field is immutable" | ||
// +kubebuilder:validation:MaxLength=255 | ||
ClusterName string `json:"clusterName"` | ||
} | ||
|
||
// PlacementEvictionStatus is the observed state of the parent PlacementEviction. | ||
type PlacementEvictionStatus struct { | ||
// Conditions is the list of currently observed conditions for the | ||
// PlacementEviction object. | ||
// | ||
// Available condition types include: | ||
// * Valid: whether the Eviction object is valid, i.e., it targets at a valid placement. | ||
// * Executed: whether the Eviction object has been executed. | ||
// +optional | ||
Conditions []metav1.Condition `json:"conditions,omitempty"` | ||
} | ||
|
||
// PlacementEvictionConditionType identifies a specific condition of the | ||
// PlacementEviction. | ||
type PlacementEvictionConditionType string | ||
|
||
const ( | ||
// PlacementEvictionConditionTypeValid indicates whether the Eviction object is valid. | ||
// | ||
// The following values are possible: | ||
// * True: the Eviction object is valid. | ||
// * False: the Eviction object is invalid; it might be targeting a CRP object or a placement | ||
// that does not exist yet. | ||
// Note that this is a terminal state; once an Eviction object is deemed invalid, it will | ||
// not be evaluated again, even if the target appears later. | ||
PlacementEvictionConditionTypeValid PlacementEvictionConditionType = "Valid" | ||
|
||
// PlacementEvictionConditionTypeExecuted indicates whether the Eviction object has been executed. | ||
// | ||
// The following values are possible: | ||
// * True: the Eviction object has been executed. | ||
// Note that this is a terminal state; once an Eviction object is executed, it will not be | ||
// executed again. | ||
// * False: the Eviction object has not been executed yet. | ||
PlacementEvictionConditionTypeExecuted PlacementEvictionConditionType = "Executed" | ||
) | ||
|
||
// ClusterResourcePlacementEvictionList contains a list of ClusterResourcePlacementEviction objects. | ||
// +kubebuilder:resource:scope=Cluster | ||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object | ||
type ClusterResourcePlacementEvictionList struct { | ||
metav1.TypeMeta `json:",inline"` | ||
metav1.ListMeta `json:"metadata,omitempty"` | ||
|
||
// Items is the list of ClusterResourcePlacementEviction objects. | ||
Items []ClusterResourcePlacementEviction `json:"items"` | ||
} | ||
|
||
// SetConditions set the given conditions on the ClusterResourcePlacementEviction. | ||
func (e *ClusterResourcePlacementEviction) SetConditions(conditions ...metav1.Condition) { | ||
for _, c := range conditions { | ||
meta.SetStatusCondition(&e.Status.Conditions, c) | ||
} | ||
} | ||
|
||
// GetCondition returns the condition of the given ClusterResourcePlacementEviction. | ||
func (e *ClusterResourcePlacementEviction) GetCondition(conditionType string) *metav1.Condition { | ||
return meta.FindStatusCondition(e.Status.Conditions, conditionType) | ||
} | ||
|
||
func init() { | ||
SchemeBuilder.Register( | ||
&ClusterResourcePlacementEviction{}, | ||
&ClusterResourcePlacementEvictionList{}) | ||
} |
Oops, something went wrong.