mirror of https://github.com/k3s-io/k3s
move disk lock process to azure cloud provider
fix comments fix import keymux check error add unit test for attach/detach disk funcsk3s-v1.15.3
parent
39c239c308
commit
6c70ca61be
|
@ -8,7 +8,8 @@
|
||||||
"k8s.io/utils/io",
|
"k8s.io/utils/io",
|
||||||
"k8s.io/utils/strings",
|
"k8s.io/utils/strings",
|
||||||
"k8s.io/utils/exec",
|
"k8s.io/utils/exec",
|
||||||
"k8s.io/utils/path"
|
"k8s.io/utils/path",
|
||||||
|
"k8s.io/utils/keymutex"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -69,6 +69,7 @@ go_library(
|
||||||
"//vendor/github.com/prometheus/client_golang/prometheus:go_default_library",
|
"//vendor/github.com/prometheus/client_golang/prometheus:go_default_library",
|
||||||
"//vendor/github.com/rubiojr/go-vhd/vhd:go_default_library",
|
"//vendor/github.com/rubiojr/go-vhd/vhd:go_default_library",
|
||||||
"//vendor/k8s.io/klog:go_default_library",
|
"//vendor/k8s.io/klog:go_default_library",
|
||||||
|
"//vendor/k8s.io/utils/keymutex:go_default_library",
|
||||||
"//vendor/sigs.k8s.io/yaml:go_default_library",
|
"//vendor/sigs.k8s.io/yaml:go_default_library",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
@ -78,6 +79,7 @@ go_test(
|
||||||
srcs = [
|
srcs = [
|
||||||
"azure_backoff_test.go",
|
"azure_backoff_test.go",
|
||||||
"azure_cache_test.go",
|
"azure_cache_test.go",
|
||||||
|
"azure_controller_common_test.go",
|
||||||
"azure_instances_test.go",
|
"azure_instances_test.go",
|
||||||
"azure_loadbalancer_test.go",
|
"azure_loadbalancer_test.go",
|
||||||
"azure_metrics_test.go",
|
"azure_metrics_test.go",
|
||||||
|
|
|
@ -17,6 +17,7 @@ limitations under the License.
|
||||||
package azure
|
package azure
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -26,6 +27,7 @@ import (
|
||||||
"k8s.io/apimachinery/pkg/types"
|
"k8s.io/apimachinery/pkg/types"
|
||||||
kwait "k8s.io/apimachinery/pkg/util/wait"
|
kwait "k8s.io/apimachinery/pkg/util/wait"
|
||||||
cloudprovider "k8s.io/cloud-provider"
|
cloudprovider "k8s.io/cloud-provider"
|
||||||
|
"k8s.io/utils/keymutex"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -50,6 +52,9 @@ var defaultBackOff = kwait.Backoff{
|
||||||
Jitter: 0.0,
|
Jitter: 0.0,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// acquire lock to attach/detach disk in one node
|
||||||
|
var diskOpMutex = keymutex.NewHashed(0)
|
||||||
|
|
||||||
type controllerCommon struct {
|
type controllerCommon struct {
|
||||||
subscriptionID string
|
subscriptionID string
|
||||||
location string
|
location string
|
||||||
|
@ -85,13 +90,29 @@ func (c *controllerCommon) getNodeVMSet(nodeName types.NodeName) (VMSet, error)
|
||||||
return ss, nil
|
return ss, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// AttachDisk attaches a vhd to vm. The vhd must exist, can be identified by diskName, diskURI, and lun.
|
// AttachDisk attaches a vhd to vm. The vhd must exist, can be identified by diskName, diskURI.
|
||||||
func (c *controllerCommon) AttachDisk(isManagedDisk bool, diskName, diskURI string, nodeName types.NodeName, lun int32, cachingMode compute.CachingTypes) error {
|
func (c *controllerCommon) AttachDisk(isManagedDisk bool, diskName, diskURI string, nodeName types.NodeName, cachingMode compute.CachingTypes) error {
|
||||||
vmset, err := c.getNodeVMSet(nodeName)
|
vmset, err := c.getNodeVMSet(nodeName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
instanceid, err := c.cloud.InstanceID(context.TODO(), nodeName)
|
||||||
|
if err != nil {
|
||||||
|
klog.Warningf("failed to get azure instance id (%v)", err)
|
||||||
|
return fmt.Errorf("failed to get azure instance id for node %q (%v)", nodeName, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
diskOpMutex.LockKey(instanceid)
|
||||||
|
defer diskOpMutex.UnlockKey(instanceid)
|
||||||
|
|
||||||
|
lun, err := c.GetNextDiskLun(nodeName)
|
||||||
|
if err != nil {
|
||||||
|
klog.Warningf("no LUN available for instance %q (%v)", nodeName, err)
|
||||||
|
return fmt.Errorf("all LUNs are used, cannot attach volume (%s, %s) to instance %q (%v)", diskName, diskURI, instanceid, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
klog.V(2).Infof("Trying to attach volume %q lun %d to node %q.", diskURI, lun, nodeName)
|
||||||
return vmset.AttachDisk(isManagedDisk, diskName, diskURI, nodeName, lun, cachingMode)
|
return vmset.AttachDisk(isManagedDisk, diskName, diskURI, nodeName, lun, cachingMode)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,11 +123,25 @@ func (c *controllerCommon) DetachDisk(diskName, diskURI string, nodeName types.N
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
instanceid, err := c.cloud.InstanceID(context.TODO(), nodeName)
|
||||||
|
if err != nil {
|
||||||
|
klog.Warningf("failed to get azure instance id (%v)", err)
|
||||||
|
return fmt.Errorf("failed to get azure instance id for node %q (%v)", nodeName, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
klog.V(2).Infof("detach %v from node %q", diskURI, nodeName)
|
||||||
|
|
||||||
|
// make the lock here as small as possible
|
||||||
|
diskOpMutex.LockKey(instanceid)
|
||||||
resp, err := vmset.DetachDisk(diskName, diskURI, nodeName)
|
resp, err := vmset.DetachDisk(diskName, diskURI, nodeName)
|
||||||
|
diskOpMutex.UnlockKey(instanceid)
|
||||||
|
|
||||||
if c.cloud.CloudProviderBackoff && shouldRetryHTTPRequest(resp, err) {
|
if c.cloud.CloudProviderBackoff && shouldRetryHTTPRequest(resp, err) {
|
||||||
klog.V(2).Infof("azureDisk - update backing off: detach disk(%s, %s), err: %v", diskName, diskURI, err)
|
klog.V(2).Infof("azureDisk - update backing off: detach disk(%s, %s), err: %v", diskName, diskURI, err)
|
||||||
retryErr := kwait.ExponentialBackoff(c.cloud.requestBackoff(), func() (bool, error) {
|
retryErr := kwait.ExponentialBackoff(c.cloud.requestBackoff(), func() (bool, error) {
|
||||||
|
diskOpMutex.LockKey(instanceid)
|
||||||
resp, err := vmset.DetachDisk(diskName, diskURI, nodeName)
|
resp, err := vmset.DetachDisk(diskName, diskURI, nodeName)
|
||||||
|
diskOpMutex.UnlockKey(instanceid)
|
||||||
return c.cloud.processHTTPRetryResponse(nil, "", resp, err)
|
return c.cloud.processHTTPRetryResponse(nil, "", resp, err)
|
||||||
})
|
})
|
||||||
if retryErr != nil {
|
if retryErr != nil {
|
||||||
|
|
|
@ -0,0 +1,66 @@
|
||||||
|
/*
|
||||||
|
Copyright 2019 The Kubernetes Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package azure
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2018-10-01/compute"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestAttachDisk(t *testing.T) {
|
||||||
|
c := getTestCloud()
|
||||||
|
|
||||||
|
common := &controllerCommon{
|
||||||
|
location: c.Location,
|
||||||
|
storageEndpointSuffix: c.Environment.StorageEndpointSuffix,
|
||||||
|
resourceGroup: c.ResourceGroup,
|
||||||
|
subscriptionID: c.SubscriptionID,
|
||||||
|
cloud: c,
|
||||||
|
}
|
||||||
|
|
||||||
|
diskURI := fmt.Sprintf("/subscriptions/%s/resourceGroups/%s/providers/Microsoft.Compute/disks/disk-name", c.SubscriptionID, c.ResourceGroup)
|
||||||
|
|
||||||
|
err := common.AttachDisk(true, "", diskURI, "node1", compute.CachingTypesReadOnly)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("TestAttachDisk return expected error: %v", err)
|
||||||
|
} else {
|
||||||
|
t.Errorf("TestAttachDisk unexpected nil err")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDetachDisk(t *testing.T) {
|
||||||
|
c := getTestCloud()
|
||||||
|
|
||||||
|
common := &controllerCommon{
|
||||||
|
location: c.Location,
|
||||||
|
storageEndpointSuffix: c.Environment.StorageEndpointSuffix,
|
||||||
|
resourceGroup: c.ResourceGroup,
|
||||||
|
subscriptionID: c.SubscriptionID,
|
||||||
|
cloud: c,
|
||||||
|
}
|
||||||
|
|
||||||
|
diskURI := fmt.Sprintf("/subscriptions/%s/resourceGroups/%s/providers/Microsoft.Compute/disks/disk-name", c.SubscriptionID, c.ResourceGroup)
|
||||||
|
|
||||||
|
err := common.DetachDisk("", diskURI, "node1")
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("TestAttachDisk return expected error: %v", err)
|
||||||
|
} else {
|
||||||
|
t.Errorf("TestAttachDisk unexpected nil err")
|
||||||
|
}
|
||||||
|
}
|
|
@ -40,7 +40,6 @@ go_library(
|
||||||
"//vendor/github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2018-10-01/compute:go_default_library",
|
"//vendor/github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2018-10-01/compute:go_default_library",
|
||||||
"//vendor/github.com/Azure/azure-sdk-for-go/services/storage/mgmt/2018-07-01/storage:go_default_library",
|
"//vendor/github.com/Azure/azure-sdk-for-go/services/storage/mgmt/2018-07-01/storage:go_default_library",
|
||||||
"//vendor/k8s.io/klog:go_default_library",
|
"//vendor/k8s.io/klog:go_default_library",
|
||||||
"//vendor/k8s.io/utils/keymutex:go_default_library",
|
|
||||||
"//vendor/k8s.io/utils/strings:go_default_library",
|
"//vendor/k8s.io/utils/strings:go_default_library",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
|
@ -17,7 +17,6 @@ limitations under the License.
|
||||||
package azure_dd
|
package azure_dd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
@ -36,7 +35,6 @@ import (
|
||||||
"k8s.io/kubernetes/pkg/util/mount"
|
"k8s.io/kubernetes/pkg/util/mount"
|
||||||
"k8s.io/kubernetes/pkg/volume"
|
"k8s.io/kubernetes/pkg/volume"
|
||||||
"k8s.io/kubernetes/pkg/volume/util"
|
"k8s.io/kubernetes/pkg/volume/util"
|
||||||
"k8s.io/utils/keymutex"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type azureDiskDetacher struct {
|
type azureDiskDetacher struct {
|
||||||
|
@ -55,9 +53,6 @@ var _ volume.Detacher = &azureDiskDetacher{}
|
||||||
var _ volume.DeviceMounter = &azureDiskAttacher{}
|
var _ volume.DeviceMounter = &azureDiskAttacher{}
|
||||||
var _ volume.DeviceUnmounter = &azureDiskDetacher{}
|
var _ volume.DeviceUnmounter = &azureDiskDetacher{}
|
||||||
|
|
||||||
// acquire lock to get an lun number
|
|
||||||
var getLunMutex = keymutex.NewHashed(0)
|
|
||||||
|
|
||||||
// Attach attaches a volume.Spec to an Azure VM referenced by NodeName, returning the disk's LUN
|
// Attach attaches a volume.Spec to an Azure VM referenced by NodeName, returning the disk's LUN
|
||||||
func (a *azureDiskAttacher) Attach(spec *volume.Spec, nodeName types.NodeName) (string, error) {
|
func (a *azureDiskAttacher) Attach(spec *volume.Spec, nodeName types.NodeName) (string, error) {
|
||||||
volumeSource, _, err := getVolumeSource(spec)
|
volumeSource, _, err := getVolumeSource(spec)
|
||||||
|
@ -66,12 +61,6 @@ func (a *azureDiskAttacher) Attach(spec *volume.Spec, nodeName types.NodeName) (
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
instanceid, err := a.cloud.InstanceID(context.TODO(), nodeName)
|
|
||||||
if err != nil {
|
|
||||||
klog.Warningf("failed to get azure instance id (%v)", err)
|
|
||||||
return "", fmt.Errorf("failed to get azure instance id for node %q (%v)", nodeName, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
diskController, err := getDiskController(a.plugin.host)
|
diskController, err := getDiskController(a.plugin.host)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
|
@ -82,30 +71,22 @@ func (a *azureDiskAttacher) Attach(spec *volume.Spec, nodeName types.NodeName) (
|
||||||
// Log error and continue with attach
|
// Log error and continue with attach
|
||||||
klog.Warningf(
|
klog.Warningf(
|
||||||
"Error checking if volume is already attached to current node (%q). Will continue and try attach anyway. err=%v",
|
"Error checking if volume is already attached to current node (%q). Will continue and try attach anyway. err=%v",
|
||||||
instanceid, err)
|
nodeName, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err == nil {
|
if err == nil {
|
||||||
// Volume is already attached to node.
|
// Volume is already attached to node.
|
||||||
klog.V(2).Infof("Attach operation is successful. volume %q is already attached to node %q at lun %d.", volumeSource.DiskName, instanceid, lun)
|
klog.V(2).Infof("Attach operation is successful. volume %q is already attached to node %q at lun %d.", volumeSource.DiskName, nodeName, lun)
|
||||||
} else {
|
} else {
|
||||||
klog.V(2).Infof("GetDiskLun returned: %v. Initiating attaching volume %q to node %q.", err, volumeSource.DataDiskURI, nodeName)
|
klog.V(2).Infof("GetDiskLun returned: %v. Initiating attaching volume %q to node %q.", err, volumeSource.DataDiskURI, nodeName)
|
||||||
getLunMutex.LockKey(instanceid)
|
|
||||||
defer getLunMutex.UnlockKey(instanceid)
|
|
||||||
|
|
||||||
lun, err = diskController.GetNextDiskLun(nodeName)
|
|
||||||
if err != nil {
|
|
||||||
klog.Warningf("no LUN available for instance %q (%v)", nodeName, err)
|
|
||||||
return "", fmt.Errorf("all LUNs are used, cannot attach volume %q to instance %q (%v)", volumeSource.DiskName, instanceid, err)
|
|
||||||
}
|
|
||||||
klog.V(2).Infof("Trying to attach volume %q lun %d to node %q.", volumeSource.DataDiskURI, lun, nodeName)
|
|
||||||
isManagedDisk := (*volumeSource.Kind == v1.AzureManagedDisk)
|
isManagedDisk := (*volumeSource.Kind == v1.AzureManagedDisk)
|
||||||
err = diskController.AttachDisk(isManagedDisk, volumeSource.DiskName, volumeSource.DataDiskURI, nodeName, lun, compute.CachingTypes(*volumeSource.CachingMode))
|
err = diskController.AttachDisk(isManagedDisk, volumeSource.DiskName, volumeSource.DataDiskURI, nodeName, compute.CachingTypes(*volumeSource.CachingMode))
|
||||||
if err == nil {
|
if err == nil {
|
||||||
klog.V(2).Infof("Attach operation successful: volume %q attached to node %q.", volumeSource.DataDiskURI, nodeName)
|
klog.V(2).Infof("Attach operation successful: volume %q attached to node %q.", volumeSource.DataDiskURI, nodeName)
|
||||||
} else {
|
} else {
|
||||||
klog.V(2).Infof("Attach volume %q to instance %q failed with %v", volumeSource.DataDiskURI, instanceid, err)
|
klog.V(2).Infof("Attach volume %q to instance %q failed with %v", volumeSource.DataDiskURI, nodeName, err)
|
||||||
return "", fmt.Errorf("Attach volume %q to instance %q failed with %v", volumeSource.DiskName, instanceid, err)
|
return "", fmt.Errorf("Attach volume %q to instance %q failed with %v", volumeSource.DiskName, nodeName, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -285,22 +266,11 @@ func (d *azureDiskDetacher) Detach(diskURI string, nodeName types.NodeName) erro
|
||||||
return fmt.Errorf("invalid disk to detach: %q", diskURI)
|
return fmt.Errorf("invalid disk to detach: %q", diskURI)
|
||||||
}
|
}
|
||||||
|
|
||||||
instanceid, err := d.cloud.InstanceID(context.TODO(), nodeName)
|
|
||||||
if err != nil {
|
|
||||||
klog.Warningf("no instance id for node %q, skip detaching (%v)", nodeName, err)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
klog.V(2).Infof("detach %v from node %q", diskURI, nodeName)
|
|
||||||
|
|
||||||
diskController, err := getDiskController(d.plugin.host)
|
diskController, err := getDiskController(d.plugin.host)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
getLunMutex.LockKey(instanceid)
|
|
||||||
defer getLunMutex.UnlockKey(instanceid)
|
|
||||||
|
|
||||||
err = diskController.DetachDisk("", diskURI, nodeName)
|
err = diskController.DetachDisk("", diskURI, nodeName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("failed to detach azure disk %q, err %v", diskURI, err)
|
klog.Errorf("failed to detach azure disk %q, err %v", diskURI, err)
|
||||||
|
|
|
@ -44,7 +44,7 @@ type DiskController interface {
|
||||||
DeleteManagedDisk(diskURI string) error
|
DeleteManagedDisk(diskURI string) error
|
||||||
|
|
||||||
// Attaches the disk to the host machine.
|
// Attaches the disk to the host machine.
|
||||||
AttachDisk(isManagedDisk bool, diskName, diskUri string, nodeName types.NodeName, lun int32, cachingMode compute.CachingTypes) error
|
AttachDisk(isManagedDisk bool, diskName, diskUri string, nodeName types.NodeName, cachingMode compute.CachingTypes) error
|
||||||
// Detaches the disk, identified by disk name or uri, from the host machine.
|
// Detaches the disk, identified by disk name or uri, from the host machine.
|
||||||
DetachDisk(diskName, diskUri string, nodeName types.NodeName) error
|
DetachDisk(diskName, diskUri string, nodeName types.NodeName) error
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue