mirror of https://github.com/apache/cloudstack.git
CKS: Fix issue with scaling down CKS Nodes when deployed in HA mode (#12302)
This commit is contained in:
parent
6a2d91ed8a
commit
7a11bd2f98
|
|
@ -441,16 +441,30 @@ public class KubernetesClusterScaleWorker extends KubernetesClusterResourceModif
|
||||||
if (this.nodeIds != null) {
|
if (this.nodeIds != null) {
|
||||||
vmList = getKubernetesClusterVMMapsForNodes(this.nodeIds).stream().filter(vm -> !vm.isExternalNode()).collect(Collectors.toList());
|
vmList = getKubernetesClusterVMMapsForNodes(this.nodeIds).stream().filter(vm -> !vm.isExternalNode()).collect(Collectors.toList());
|
||||||
} else {
|
} else {
|
||||||
vmList = getKubernetesClusterVMMaps();
|
vmList = getWorkerNodesToRemove();
|
||||||
vmList = vmList.stream()
|
if (vmList.isEmpty()) {
|
||||||
.filter(vm -> !vm.isExternalNode() && !vm.isControlNode() && !vm.isEtcdNode())
|
logger.info("No nodes to remove from Kubernetes cluster: {}", kubernetesCluster);
|
||||||
.collect(Collectors.toList());
|
return;
|
||||||
vmList = vmList.subList((int) (kubernetesCluster.getControlNodeCount() + clusterSize - 1), vmList.size());
|
}
|
||||||
}
|
}
|
||||||
Collections.reverse(vmList);
|
Collections.reverse(vmList);
|
||||||
removeNodesFromCluster(vmList);
|
removeNodesFromCluster(vmList);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<KubernetesClusterVmMapVO> getWorkerNodesToRemove() {
|
||||||
|
List<KubernetesClusterVmMapVO> workerVMsMap = getKubernetesClusterVMMaps().stream()
|
||||||
|
.filter(vm -> !vm.isExternalNode() && !vm.isControlNode() && !vm.isEtcdNode())
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
int totalWorkerNodes = workerVMsMap.size();
|
||||||
|
int desiredWorkerNodes = clusterSize == null ? (int) kubernetesCluster.getNodeCount() : clusterSize.intValue();
|
||||||
|
int toRemoveCount = Math.max(0, totalWorkerNodes - desiredWorkerNodes);
|
||||||
|
if (toRemoveCount == 0) {
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
int startIndex = Math.max(0, totalWorkerNodes - toRemoveCount);
|
||||||
|
return new ArrayList<>(workerVMsMap.subList(startIndex, totalWorkerNodes));
|
||||||
|
}
|
||||||
|
|
||||||
private void scaleUpKubernetesClusterSize(final long newVmCount) throws CloudRuntimeException {
|
private void scaleUpKubernetesClusterSize(final long newVmCount) throws CloudRuntimeException {
|
||||||
if (!kubernetesCluster.getState().equals(KubernetesCluster.State.Scaling)) {
|
if (!kubernetesCluster.getState().equals(KubernetesCluster.State.Scaling)) {
|
||||||
stateTransitTo(kubernetesCluster.getId(), KubernetesCluster.Event.ScaleUpRequested);
|
stateTransitTo(kubernetesCluster.getId(), KubernetesCluster.Event.ScaleUpRequested);
|
||||||
|
|
|
||||||
|
|
@ -17,8 +17,8 @@
|
||||||
package com.cloud.kubernetes.cluster.actionworkers;
|
package com.cloud.kubernetes.cluster.actionworkers;
|
||||||
|
|
||||||
import com.cloud.kubernetes.cluster.KubernetesCluster;
|
import com.cloud.kubernetes.cluster.KubernetesCluster;
|
||||||
import com.cloud.kubernetes.cluster.KubernetesClusterManagerImpl;
|
|
||||||
import com.cloud.kubernetes.cluster.KubernetesClusterVmMapVO;
|
import com.cloud.kubernetes.cluster.KubernetesClusterVmMapVO;
|
||||||
|
import com.cloud.kubernetes.cluster.KubernetesClusterManagerImpl;
|
||||||
import com.cloud.kubernetes.cluster.dao.KubernetesClusterVmMapDao;
|
import com.cloud.kubernetes.cluster.dao.KubernetesClusterVmMapDao;
|
||||||
import com.cloud.offering.ServiceOffering;
|
import com.cloud.offering.ServiceOffering;
|
||||||
import com.cloud.service.ServiceOfferingVO;
|
import com.cloud.service.ServiceOfferingVO;
|
||||||
|
|
@ -29,15 +29,17 @@ import com.cloud.vm.dao.UserVmDao;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
import org.mockito.Mockito;
|
import org.mockito.Mockito;
|
||||||
import org.mockito.junit.MockitoJUnitRunner;
|
import org.mockito.junit.MockitoJUnitRunner;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static com.cloud.kubernetes.cluster.KubernetesServiceHelper.KubernetesClusterNodeType.DEFAULT;
|
|
||||||
import static com.cloud.kubernetes.cluster.KubernetesServiceHelper.KubernetesClusterNodeType.CONTROL;
|
import static com.cloud.kubernetes.cluster.KubernetesServiceHelper.KubernetesClusterNodeType.CONTROL;
|
||||||
|
import static com.cloud.kubernetes.cluster.KubernetesServiceHelper.KubernetesClusterNodeType.DEFAULT;
|
||||||
|
|
||||||
@RunWith(MockitoJUnitRunner.class)
|
@RunWith(MockitoJUnitRunner.class)
|
||||||
public class KubernetesClusterScaleWorkerTest {
|
public class KubernetesClusterScaleWorkerTest {
|
||||||
|
|
@ -125,4 +127,64 @@ public class KubernetesClusterScaleWorkerTest {
|
||||||
Assert.assertEquals(expectedCores, newClusterCapacity.first().longValue());
|
Assert.assertEquals(expectedCores, newClusterCapacity.first().longValue());
|
||||||
Assert.assertEquals(expectedMemory, newClusterCapacity.second().longValue());
|
Assert.assertEquals(expectedMemory, newClusterCapacity.second().longValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetWorkerNodesToRemoveForDownsize_singleRemoval() {
|
||||||
|
KubernetesCluster kubernetesCluster = Mockito.mock(KubernetesCluster.class);
|
||||||
|
KubernetesClusterManagerImpl clusterManager = Mockito.mock(KubernetesClusterManagerImpl.class);
|
||||||
|
KubernetesClusterScaleWorker worker = new KubernetesClusterScaleWorker(kubernetesCluster, new java.util.HashMap<>(), 2L, null, false, null, null, clusterManager);
|
||||||
|
KubernetesClusterScaleWorker spyWorker = Mockito.spy(worker);
|
||||||
|
|
||||||
|
KubernetesClusterVmMapVO vm1 = Mockito.mock(KubernetesClusterVmMapVO.class);
|
||||||
|
Mockito.when(vm1.isExternalNode()).thenReturn(false);
|
||||||
|
Mockito.when(vm1.isControlNode()).thenReturn(false);
|
||||||
|
Mockito.when(vm1.isEtcdNode()).thenReturn(false);
|
||||||
|
|
||||||
|
KubernetesClusterVmMapVO vm2 = Mockito.mock(KubernetesClusterVmMapVO.class);
|
||||||
|
Mockito.when(vm2.isExternalNode()).thenReturn(false);
|
||||||
|
Mockito.when(vm2.isControlNode()).thenReturn(false);
|
||||||
|
Mockito.when(vm2.isEtcdNode()).thenReturn(false);
|
||||||
|
|
||||||
|
KubernetesClusterVmMapVO vm3 = Mockito.mock(KubernetesClusterVmMapVO.class);
|
||||||
|
Mockito.when(vm3.isExternalNode()).thenReturn(false);
|
||||||
|
Mockito.when(vm3.isControlNode()).thenReturn(false);
|
||||||
|
Mockito.when(vm3.isEtcdNode()).thenReturn(false);
|
||||||
|
|
||||||
|
Mockito.doReturn(Arrays.asList(vm1, vm2, vm3)).when(spyWorker).getKubernetesClusterVMMaps();
|
||||||
|
|
||||||
|
List<KubernetesClusterVmMapVO> toRemove = spyWorker.getWorkerNodesToRemove();
|
||||||
|
|
||||||
|
Assert.assertEquals(1, toRemove.size());
|
||||||
|
Assert.assertSame(vm3, toRemove.get(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetWorkerNodesToRemoveForDownsize_noRemoval() {
|
||||||
|
KubernetesCluster kubernetesCluster = Mockito.mock(KubernetesCluster.class);
|
||||||
|
|
||||||
|
KubernetesClusterScaleWorker worker = new KubernetesClusterScaleWorker(kubernetesCluster, new java.util.HashMap<>(), 3L, null, false, null, null, clusterManager);
|
||||||
|
KubernetesClusterScaleWorker spyWorker = Mockito.spy(worker);
|
||||||
|
|
||||||
|
KubernetesClusterVmMapVO vm1 = Mockito.mock(KubernetesClusterVmMapVO.class);
|
||||||
|
Mockito.when(vm1.isExternalNode()).thenReturn(false);
|
||||||
|
Mockito.when(vm1.isControlNode()).thenReturn(false);
|
||||||
|
Mockito.when(vm1.isEtcdNode()).thenReturn(false);
|
||||||
|
|
||||||
|
KubernetesClusterVmMapVO vm2 = Mockito.mock(KubernetesClusterVmMapVO.class);
|
||||||
|
Mockito.when(vm2.isExternalNode()).thenReturn(false);
|
||||||
|
Mockito.when(vm2.isControlNode()).thenReturn(false);
|
||||||
|
Mockito.when(vm2.isEtcdNode()).thenReturn(false);
|
||||||
|
|
||||||
|
KubernetesClusterVmMapVO vm3 = Mockito.mock(KubernetesClusterVmMapVO.class);
|
||||||
|
Mockito.when(vm3.isExternalNode()).thenReturn(false);
|
||||||
|
Mockito.when(vm3.isControlNode()).thenReturn(false);
|
||||||
|
Mockito.when(vm3.isEtcdNode()).thenReturn(false);
|
||||||
|
|
||||||
|
Mockito.doReturn(Arrays.asList(vm1, vm2, vm3)).when(spyWorker).getKubernetesClusterVMMaps();
|
||||||
|
|
||||||
|
List<KubernetesClusterVmMapVO> toRemove = spyWorker.getWorkerNodesToRemove();
|
||||||
|
|
||||||
|
Assert.assertTrue(toRemove.isEmpty());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue