mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-09 12:07:47 +00:00
Merge pull request #119561 from payall4u/fix-kubelet-panic-when-allocate-device
Fix kubelet panic when allocate resource for pod.
This commit is contained in:
commit
70383f3701
@ -623,6 +623,13 @@ func (m *ManagerImpl) devicesToAllocate(podUID, contName, resource string, requi
|
|||||||
// Create a closure to help with device allocation
|
// Create a closure to help with device allocation
|
||||||
// Returns 'true' once no more devices need to be allocated.
|
// Returns 'true' once no more devices need to be allocated.
|
||||||
allocateRemainingFrom := func(devices sets.Set[string]) bool {
|
allocateRemainingFrom := func(devices sets.Set[string]) bool {
|
||||||
|
// When we call callGetPreferredAllocationIfAvailable below, we will release
|
||||||
|
// the lock and call the device plugin. If someone calls ListResource concurrently,
|
||||||
|
// device manager will recalculate the allocatedDevices map. Some entries with
|
||||||
|
// empty sets may be removed, so we reinit here.
|
||||||
|
if m.allocatedDevices[resource] == nil {
|
||||||
|
m.allocatedDevices[resource] = sets.New[string]()
|
||||||
|
}
|
||||||
for device := range devices.Difference(allocated) {
|
for device := range devices.Difference(allocated) {
|
||||||
m.allocatedDevices[resource].Insert(device)
|
m.allocatedDevices[resource].Insert(device)
|
||||||
allocated.Insert(device)
|
allocated.Insert(device)
|
||||||
@ -634,11 +641,6 @@ func (m *ManagerImpl) devicesToAllocate(podUID, contName, resource string, requi
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// Needs to allocate additional devices.
|
|
||||||
if m.allocatedDevices[resource] == nil {
|
|
||||||
m.allocatedDevices[resource] = sets.New[string]()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Allocates from reusableDevices list first.
|
// Allocates from reusableDevices list first.
|
||||||
if allocateRemainingFrom(reusableDevices) {
|
if allocateRemainingFrom(reusableDevices) {
|
||||||
return allocated, nil
|
return allocated, nil
|
||||||
|
@ -1184,6 +1184,66 @@ func TestPodContainerDeviceToAllocate(t *testing.T) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestDevicesToAllocateConflictWithUpdateAllocatedDevices(t *testing.T) {
|
||||||
|
podToAllocate := "podToAllocate"
|
||||||
|
containerToAllocate := "containerToAllocate"
|
||||||
|
podToRemove := "podToRemove"
|
||||||
|
containerToRemove := "containerToRemove"
|
||||||
|
deviceID := "deviceID"
|
||||||
|
resourceName := "domain1.com/resource"
|
||||||
|
|
||||||
|
socket := filepath.Join(os.TempDir(), esocketName())
|
||||||
|
devs := []*pluginapi.Device{
|
||||||
|
{ID: deviceID, Health: pluginapi.Healthy},
|
||||||
|
}
|
||||||
|
p, e := esetup(t, devs, socket, resourceName, func(n string, d []pluginapi.Device) {})
|
||||||
|
|
||||||
|
waitUpdateAllocatedDevicesChan := make(chan struct{})
|
||||||
|
waitSetGetPreferredAllocChan := make(chan struct{})
|
||||||
|
|
||||||
|
p.SetGetPreferredAllocFunc(func(r *pluginapi.PreferredAllocationRequest, devs map[string]pluginapi.Device) (*pluginapi.PreferredAllocationResponse, error) {
|
||||||
|
waitSetGetPreferredAllocChan <- struct{}{}
|
||||||
|
<-waitUpdateAllocatedDevicesChan
|
||||||
|
return &pluginapi.PreferredAllocationResponse{
|
||||||
|
ContainerResponses: []*pluginapi.ContainerPreferredAllocationResponse{
|
||||||
|
{
|
||||||
|
DeviceIDs: []string{deviceID},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}, nil
|
||||||
|
})
|
||||||
|
|
||||||
|
testManager := &ManagerImpl{
|
||||||
|
endpoints: make(map[string]endpointInfo),
|
||||||
|
healthyDevices: make(map[string]sets.Set[string]),
|
||||||
|
unhealthyDevices: make(map[string]sets.Set[string]),
|
||||||
|
allocatedDevices: make(map[string]sets.Set[string]),
|
||||||
|
podDevices: newPodDevices(),
|
||||||
|
activePods: func() []*v1.Pod { return []*v1.Pod{} },
|
||||||
|
sourcesReady: &sourcesReadyStub{},
|
||||||
|
topologyAffinityStore: topologymanager.NewFakeManager(),
|
||||||
|
}
|
||||||
|
|
||||||
|
testManager.endpoints[resourceName] = endpointInfo{
|
||||||
|
e: e,
|
||||||
|
opts: &pluginapi.DevicePluginOptions{
|
||||||
|
GetPreferredAllocationAvailable: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
testManager.healthyDevices[resourceName] = sets.New[string](deviceID)
|
||||||
|
testManager.podDevices.insert(podToRemove, containerToRemove, resourceName, nil, nil)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
<-waitSetGetPreferredAllocChan
|
||||||
|
testManager.UpdateAllocatedDevices()
|
||||||
|
waitUpdateAllocatedDevicesChan <- struct{}{}
|
||||||
|
}()
|
||||||
|
|
||||||
|
set, err := testManager.devicesToAllocate(podToAllocate, containerToAllocate, resourceName, 1, sets.New[string]())
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, set, sets.New[string](deviceID))
|
||||||
|
}
|
||||||
|
|
||||||
func TestGetDeviceRunContainerOptions(t *testing.T) {
|
func TestGetDeviceRunContainerOptions(t *testing.T) {
|
||||||
res1 := TestResource{
|
res1 := TestResource{
|
||||||
resourceName: "domain1.com/resource1",
|
resourceName: "domain1.com/resource1",
|
||||||
|
Loading…
Reference in New Issue
Block a user