Skip to content

Commit

Permalink
Remove the assumption that a node's name == its hostname
Browse files Browse the repository at this point in the history
As per https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#built-in-node-labels
[[[
Note:
The value of these labels is cloud provider specific and is not guaranteed to be reliable. For example, the value of kubernetes.io/hostname may be the same as the node name in some environments and a different value in other environments.
]]]
  • Loading branch information
jan-g committed Jun 7, 2024
1 parent 4a77e7c commit cc0d387
Showing 1 changed file with 32 additions and 29 deletions.
61 changes: 32 additions & 29 deletions provisioner.go
Original file line number Diff line number Diff line change
Expand Up @@ -422,20 +422,16 @@ func (p *LocalPathProvisioner) provisionFor(opts pvController.ProvisionOptions,
// affinity, as path is accessible from any node
nodeAffinity = nil
} else {
valueNode, ok := node.GetLabels()[KeyNode]
if !ok {
valueNode = nodeName
}
nodeAffinity = &v1.VolumeNodeAffinity{
Required: &v1.NodeSelector{
NodeSelectorTerms: []v1.NodeSelectorTerm{
{
MatchExpressions: []v1.NodeSelectorRequirement{
MatchFields: []v1.NodeSelectorRequirement{
{
Key: KeyNode,
Key: metav1.ObjectNameField,
Operator: v1.NodeSelectorOpIn,
Values: []string{
valueNode,
node.Name,
},
},
},
Expand Down Expand Up @@ -475,7 +471,7 @@ func (p *LocalPathProvisioner) deleteFor(pv *v1.PersistentVolume, c *StorageClas
err = errors.Wrapf(err, "failed to delete volume %v", pv.Name)
}()

path, node, err := p.getPathAndNodeForPV(pv, c)
path, node, nodeLabels, err := p.getPathAndNodeForPV(pv, c)
if err != nil {
return err
}
Expand All @@ -498,6 +494,7 @@ func (p *LocalPathProvisioner) deleteFor(pv *v1.PersistentVolume, c *StorageClas
Mode: *pv.Spec.VolumeMode,
SizeInBytes: storage.Value(),
Node: node,
NodeLabels: nodeLabels,
}, c); err != nil {
logrus.Infof("clean up volume %v failed: %v", pv.Name, err)
return err
Expand All @@ -508,7 +505,7 @@ func (p *LocalPathProvisioner) deleteFor(pv *v1.PersistentVolume, c *StorageClas
return nil
}

func (p *LocalPathProvisioner) getPathAndNodeForPV(pv *v1.PersistentVolume, cfg *StorageClassConfig) (path, node string, err error) {
func (p *LocalPathProvisioner) getPathAndNodeForPV(pv *v1.PersistentVolume, cfg *StorageClassConfig) (path, node string, nodeLabels map[string]string, err error) {
defer func() {
err = errors.Wrapf(err, "failed to delete volume %v", pv.Name)
}()
Expand All @@ -519,49 +516,55 @@ func (p *LocalPathProvisioner) getPathAndNodeForPV(pv *v1.PersistentVolume, cfg
} else if volumeSource.Local != nil && volumeSource.HostPath == nil {
path = volumeSource.Local.Path
} else {
return "", "", fmt.Errorf("no path set")
return "", "", nil, fmt.Errorf("no path set")
}

sharedFS, err := p.isSharedFilesystem(cfg)
if err != nil {
return "", "", err
return "", "", nil, err
}

if sharedFS {
// We don't have affinity and can use any node
return path, "", nil
return path, "", nil, nil
}

// Dealing with local filesystem

nodeAffinity := pv.Spec.NodeAffinity
if nodeAffinity == nil {
return "", "", fmt.Errorf("no NodeAffinity set")
return "", "", nil, fmt.Errorf("no NodeAffinity set")
}
required := nodeAffinity.Required
if required == nil {
return "", "", fmt.Errorf("no NodeAffinity.Required set")
return "", "", nil, fmt.Errorf("no NodeAffinity.Required set")
}

node = ""
// If we have an explicit node, use that; otherwise use the selector.
for _, selectorTerm := range required.NodeSelectorTerms {
for _, expression := range selectorTerm.MatchFields {
if expression.Key == metav1.ObjectNameField && expression.Operator == v1.NodeSelectorOpIn {
if len(expression.Values) != 1 {
return "", "", nil, fmt.Errorf("multiple values for the node affinity")
}
return path, expression.Values[0], nil, nil
}
}
}
// The scheduler must use the PV's node selector to schedule a helper pod.
for _, selectorTerm := range required.NodeSelectorTerms {
for _, expression := range selectorTerm.MatchExpressions {
if expression.Key == KeyNode && expression.Operator == v1.NodeSelectorOpIn {
if len(expression.Values) != 1 {
return "", "", fmt.Errorf("multiple values for the node affinity")
return "", "", nil, fmt.Errorf("multiple values for the node affinity")
}
node = expression.Values[0]
break
return path, "", map[string]string{
KeyNode: expression.Values[0],
}, nil
}
}
if node != "" {
break
}
}
if node == "" {
return "", "", fmt.Errorf("cannot find affinited node")
}
return path, node, nil
return "", "", nil, fmt.Errorf("cannot find affinited node")
}

type volumeOptions struct {
Expand All @@ -570,6 +573,7 @@ type volumeOptions struct {
Mode v1.PersistentVolumeMode
SizeInBytes int64
Node string
NodeLabels map[string]string
}

func (p *LocalPathProvisioner) createHelperPod(action ActionType, cmd []string, o volumeOptions, cfg *StorageClassConfig) (err error) {
Expand All @@ -580,7 +584,7 @@ func (p *LocalPathProvisioner) createHelperPod(action ActionType, cmd []string,
if err != nil {
return err
}
if o.Name == "" || o.Path == "" || (!sharedFS && o.Node == "") {
if o.Name == "" || o.Path == "" || (!sharedFS && o.Node == "" && o.NodeLabels == nil) {
return fmt.Errorf("invalid empty name or path or node")
}
if !filepath.IsAbs(o.Path) {
Expand Down Expand Up @@ -661,9 +665,8 @@ func (p *LocalPathProvisioner) createHelperPod(action ActionType, cmd []string,
helperPod.Name = helperPod.Name[:HelperPodNameMaxLength]
}
helperPod.Namespace = p.namespace
if o.Node != "" {
helperPod.Spec.NodeName = o.Node
}
helperPod.Spec.NodeName = o.Node
helperPod.Spec.NodeSelector = o.NodeLabels
helperPod.Spec.ServiceAccountName = p.serviceAccountName
helperPod.Spec.RestartPolicy = v1.RestartPolicyNever
helperPod.Spec.Tolerations = append(helperPod.Spec.Tolerations, lpvTolerations...)
Expand Down

0 comments on commit cc0d387

Please sign in to comment.