Implementation of LabelSelector
for snapshots #875
Description
This is more a question why they are disabled? And is there an alternative solution to this?
In my scenario I create snapshots on GCP by a cronjob
every x hours. These snapshots are supposed to be used by a StatefulSet volumeClaimTemplates
when spanning new Pods to speed up startup time (dramatically).
Unfortunately I can not modify the volumeClaimTemplates
to match the new snapshot name due to k8s restrictions or reuse the snapshot name as I don't want to mess with the CRDs. I am keeping a history of y-versions.
So it feels very natural to me to use the LabelSelector
within the volumeClaimTemplate
to select by a label rather than a name.
I could have some definition like this in my STS:
...
volumeClaimTemplates:
- metadata:
name: mydir
spec:
accessModes:
- ReadWriteOnce
storageClassName: snapshot-promoter
resources:
requests:
storage: 10Gi
selector:
matchLabels:
group: "my_group"
matchExpressions:
- {key: approved, operator: Exists}
A modification to the provisioner could load the snapshot via Selector. With priority to the SnapshotPVCAnnotation
and for multiple matches to the snapshotMetadataTimeStamp
:
func (p *snapshotProvisioner) loadSnapshot(options controller.VolumeOptions) (crdv1.VolumeSnapshot, error) {
var snapshot crdv1.VolumeSnapshot
snapshotName, ok := options.PVC.Annotations[crdclient.SnapshotPVCAnnotation]
if ok { // by name first
err := p.crdclient.Get().
Resource(crdv1.VolumeSnapshotResourcePlural).
Namespace(options.PVC.Namespace).
Name(snapshotName).
Do().Into(&snapshot)
if err != nil {
return snapshot, fmt.Errorf("failed to retrieve VolumeSnapshot %s: %v", snapshotName, err)
}
} else {
// by selector
selector := options.PVC.Spec.Selector
if selector == nil {
return snapshot, errors.New("no claim selector nor snapshot annotation found on PV")
}
if len(selector.MatchLabels) == 0 || len(selector.MatchExpressions) == 0 {
return snapshot, errors.New("label selector must not be empty")
}
var snapshots crdv1.VolumeSnapshotList
err := p.crdclient.Get().
Resource(crdv1.VolumeSnapshotResourcePlural).
Param("labelSelector", metav1.FormatLabelSelector(selector)).
Do().Into(&snapshots)
if err != nil {
return snapshot, err
}
var latestTimestamp int64
for _, s := range snapshots.Items {
if item, ok := s.Metadata.Labels[snapshotMetadataTimeStamp]; ok {
if newTimestamp, err := strconv.ParseInt(item, 10, 64); err == nil {
if latestTimestamp < newTimestamp {
snapshot = s
latestTimestamp = newTimestamp
}
}
}
}
if latestTimestamp == 0 {
return snapshot, errors.New("not found")
}
}
return snapshot, nil
}