diff --git a/assembly/assembly-wsmaster-war/src/main/webapp/WEB-INF/classes/codenvy/che.properties b/assembly/assembly-wsmaster-war/src/main/webapp/WEB-INF/classes/codenvy/che.properties index b7c1b752d43..0b96f0457c0 100644 --- a/assembly/assembly-wsmaster-war/src/main/webapp/WEB-INF/classes/codenvy/che.properties +++ b/assembly/assembly-wsmaster-war/src/main/webapp/WEB-INF/classes/codenvy/che.properties @@ -294,6 +294,9 @@ che.openshift.liveness.probe.delay=300 che.openshift.liveness.probe.timeout=1 che.openshift.workspaces.pvc.name=claim-che-workspace che.openshift.workspaces.pvc.quantity=10Gi +che.openshift.workspace.cpu.limit=1 +# Override memory limit used for openshift workspaces. String, e.g. 1300Mi +che.openshift.workspace.memory.override=NULL # Which implementation of DockerConnector to use in managing containers. In general, # the base implementation of DockerConnector is appropriate, but OpenShiftConnector diff --git a/plugins/plugin-docker/che-plugin-openshift-client/src/main/java/org/eclipse/che/plugin/openshift/client/OpenShiftConnector.java b/plugins/plugin-docker/che-plugin-openshift-client/src/main/java/org/eclipse/che/plugin/openshift/client/OpenShiftConnector.java index b518efa4247..d7599f148e7 100644 --- a/plugins/plugin-docker/che-plugin-openshift-client/src/main/java/org/eclipse/che/plugin/openshift/client/OpenShiftConnector.java +++ b/plugins/plugin-docker/che-plugin-openshift-client/src/main/java/org/eclipse/che/plugin/openshift/client/OpenShiftConnector.java @@ -170,6 +170,8 @@ public class OpenShiftConnector extends DockerConnector { private final String cheWorkspaceStorage; private final String cheWorkspaceProjectsStorage; private final String cheServerExternalAddress; + private final String cheWorkspaceCpuLimit; + private final String cheWorkspaceMemory; @Inject public OpenShiftConnector(DockerConnectorConfiguration connectorConfiguration, @@ -183,7 +185,10 @@ public OpenShiftConnector(DockerConnectorConfiguration connectorConfiguration, @Named("che.openshift.workspaces.pvc.name") String workspacesPersistentVolumeClaim, @Named("che.openshift.workspaces.pvc.quantity") String workspacesPvcQuantity, @Named("che.workspace.storage") String cheWorkspaceStorage, - @Named("che.workspace.projects.storage") String cheWorkspaceProjectsStorage) { + @Named("che.workspace.projects.storage") String cheWorkspaceProjectsStorage, + @Named("che.openshift.workspace.cpu.limit") String cheWorkspaceCpuLimit, + @Nullable @Named("che.openshift.workspace.memory.override") String cheWorkspaceMemory) { + super(connectorConfiguration, connectionFactory, authResolver, dockerApiVersionPathPrefixProvider); this.cheServerExternalAddress = cheServerExternalAddress; @@ -194,6 +199,8 @@ public OpenShiftConnector(DockerConnectorConfiguration connectorConfiguration, this.workspacesPvcQuantity = workspacesPvcQuantity; this.cheWorkspaceStorage = cheWorkspaceStorage; this.cheWorkspaceProjectsStorage = cheWorkspaceProjectsStorage; + this.cheWorkspaceCpuLimit = cheWorkspaceCpuLimit; + this.cheWorkspaceMemory = cheWorkspaceMemory; this.openShiftClient = new DefaultOpenShiftClient(); } @@ -252,6 +259,21 @@ public ContainerCreated createContainer(CreateContainerParams createContainerPar String[] volumes = createContainerParams.getContainerConfig().getHostConfig().getBinds(); Map additionalLabels = createContainerParams.getContainerConfig().getLabels(); + + String memoryLimit; + if (!isNullOrEmpty(cheWorkspaceMemory)) { + LOG.info("Che property 'che.openshift.workspace.memory.override' " + + "used to override workspace memory limit to {}.", cheWorkspaceMemory); + memoryLimit = cheWorkspaceMemory; + } else { + long memoryLimitBytes = createContainerParams.getContainerConfig().getHostConfig().getMemory(); + memoryLimit = Long.toString(memoryLimitBytes / 1048576) + "Mi"; + LOG.info("Creating workspace pod with memory limit of {}.", memoryLimit); + } + Map resourceLimits = new HashMap<>(); + resourceLimits.put("memory", new Quantity(memoryLimit)); + resourceLimits.put("cpu", new Quantity(cheWorkspaceCpuLimit)); + String containerID; try { createOpenShiftService(workspaceID, exposedPorts, additionalLabels); @@ -260,16 +282,18 @@ public ContainerCreated createContainer(CreateContainerParams createContainerPar containerName, exposedPorts, envVariables, - volumes); + volumes, + resourceLimits); containerID = waitAndRetrieveContainerID(deploymentName); if (containerID == null) { throw new OpenShiftException("Failed to get the ID of the container running in the OpenShift pod"); } - } catch (IOException e) { + } catch (IOException | KubernetesClientException e) { // Make sure we clean up deployment and service in case of an error -- otherwise Che can end up // in an inconsistent state. LOG.info("Error while creating Pod, removing deployment"); + LOG.info(e.getMessage()); String deploymentName = CHE_OPENSHIFT_RESOURCES_PREFIX + workspaceID; cleanUpWorkspaceResources(deploymentName); openShiftClient.resource(imageStreamTag).delete(); @@ -990,7 +1014,8 @@ private String createOpenShiftDeployment(String workspaceID, String sanitizedContainerName, Set exposedPorts, String[] envVariables, - String[] volumes) { + String[] volumes, + Map resourceLimits) { String deploymentName = CHE_OPENSHIFT_RESOURCES_PREFIX + workspaceID; LOG.info("Creating OpenShift deployment {}", deploymentName); @@ -1018,7 +1043,8 @@ private String createOpenShiftDeployment(String workspaceID, deploymentName, selector, command, - false); + false, + resourceLimits); try { waitAndRetrieveContainerID(deploymentName); @@ -1043,7 +1069,8 @@ private String createOpenShiftDeployment(String workspaceID, deploymentName, selector, null, - true); + true, + resourceLimits); LOG.info("OpenShift deployment {} created", deploymentName); return deployment.getMetadata().getName(); } @@ -1079,7 +1106,8 @@ private Deployment createOpenShiftDeploymentInternal(String workspaceID, Map selector, String[] command, - boolean withSubpath) { + boolean withSubpath, + Map resourceLimits) { Container container = new ContainerBuilder() .withName(sanitizedContainerName) @@ -1093,6 +1121,9 @@ private Deployment createOpenShiftDeploymentInternal(String workspaceID, .withLivenessProbe(getLivenessProbeFrom(exposedPorts)) .withCommand(command) .withVolumeMounts(getVolumeMountsFrom(volumes, workspaceID, withSubpath)) + .withNewResources() + .withLimits(resourceLimits) + .endResources() .build(); PodSpec podSpec = new PodSpecBuilder() @@ -1196,7 +1227,6 @@ private ContainerInfo createContainerInfo(Service svc, // HostConfig HostConfig hostConfig = new HostConfig(); hostConfig.setBinds(new String[0]); - hostConfig.setMemory(imageInfo.getConfig().getMemory()); // Env vars List imageEnv = Arrays.asList(imageContainerConfig.getEnv()); diff --git a/plugins/plugin-docker/che-plugin-openshift-client/src/test/java/org/eclipse/che/plugin/openshift/client/OpenShiftConnectorTest.java b/plugins/plugin-docker/che-plugin-openshift-client/src/test/java/org/eclipse/che/plugin/openshift/client/OpenShiftConnectorTest.java index cc917a61972..dcf1ebb902b 100644 --- a/plugins/plugin-docker/che-plugin-openshift-client/src/test/java/org/eclipse/che/plugin/openshift/client/OpenShiftConnectorTest.java +++ b/plugins/plugin-docker/che-plugin-openshift-client/src/test/java/org/eclipse/che/plugin/openshift/client/OpenShiftConnectorTest.java @@ -37,8 +37,9 @@ public class OpenShiftConnectorTest { private static final String OPENSHIFT_DEFAULT_WORKSPACE_QUANTITY = "10Gi"; private static final String OPENSHIFT_DEFAULT_WORKSPACE_STORAGE = "/data/workspaces"; private static final String OPENSHIFT_DEFAULT_WORKSPACE_PROJECTS_STORAGE = "/projects"; - private static final String CHE_DEFAULT_SERVER_EXTERNAL_ADDRESS = "che.openshift.mini"; - + private static final String CHE_DEFAULT_SERVER_EXTERNAL_ADDRESS = "che.openshift.mini"; + private static final String CHE_WORKSPACE_CPU_LIMIT = "1"; + @Mock private DockerConnectorConfiguration dockerConnectorConfiguration; @Mock @@ -73,7 +74,9 @@ public void shouldGetWorkspaceIDWhenAValidOneIsProvidedInCreateContainerParams() OPENSHIFT_DEFAULT_WORKSPACE_PERSISTENT_VOLUME_CLAIM, OPENSHIFT_DEFAULT_WORKSPACE_QUANTITY, OPENSHIFT_DEFAULT_WORKSPACE_STORAGE, - OPENSHIFT_DEFAULT_WORKSPACE_PROJECTS_STORAGE); + OPENSHIFT_DEFAULT_WORKSPACE_PROJECTS_STORAGE, + CHE_WORKSPACE_CPU_LIMIT, + null); String workspaceID = openShiftConnector.getCheWorkspaceId(createContainerParams); //Then