use of io.kubernetes.client.openapi.models.V1ResourceRequirements in project heron by twitter.
the class V1Controller method configureContainerResources.
/**
* Configures the resources in the <code>container</code> with values in the <code>config</code> taking precedence.
* @param container The <code>container</code> to be configured.
* @param configuration The <code>Config</code> object to check if a resource request needs to be set.
* @param resource User defined resources limits from input.
* @param isExecutor Flag to indicate configuration for an <code>executor</code> or <code>manager</code>.
*/
@VisibleForTesting
protected void configureContainerResources(final V1Container container, final Config configuration, final Resource resource, boolean isExecutor) {
if (container.getResources() == null) {
container.setResources(new V1ResourceRequirements());
}
final V1ResourceRequirements resourceRequirements = container.getResources();
// Collect Limits and Requests from CLI.
final Map<String, Quantity> limitsCLI = createResourcesRequirement(KubernetesContext.getResourceLimits(configuration, isExecutor));
final Map<String, Quantity> requestsCLI = createResourcesRequirement(KubernetesContext.getResourceRequests(configuration, isExecutor));
if (resourceRequirements.getLimits() == null) {
resourceRequirements.setLimits(new HashMap<>());
}
// Set Limits and Resources from CLI <if> available, <else> use Configs. Deduplicate on name
// with precedence [1] CLI, [2] Config.
final Map<String, Quantity> limits = resourceRequirements.getLimits();
final Quantity limitCPU = limitsCLI.getOrDefault(KubernetesConstants.CPU, Quantity.fromString(Double.toString(KubernetesUtils.roundDecimal(resource.getCpu(), 3))));
final Quantity limitMEMORY = limitsCLI.getOrDefault(KubernetesConstants.MEMORY, Quantity.fromString(KubernetesUtils.Megabytes(resource.getRam())));
limits.put(KubernetesConstants.MEMORY, limitMEMORY);
limits.put(KubernetesConstants.CPU, limitCPU);
// Set the Kubernetes container resource request.
// Order: [1] CLI, [2] EQUAL_TO_LIMIT, [3] NOT_SET
KubernetesContext.KubernetesResourceRequestMode requestMode = KubernetesContext.getKubernetesRequestMode(configuration);
if (!requestsCLI.isEmpty()) {
if (resourceRequirements.getRequests() == null) {
resourceRequirements.setRequests(new HashMap<>());
}
final Map<String, Quantity> requests = resourceRequirements.getRequests();
if (requestsCLI.containsKey(KubernetesConstants.MEMORY)) {
requests.put(KubernetesConstants.MEMORY, requestsCLI.get(KubernetesConstants.MEMORY));
}
if (requestsCLI.containsKey(KubernetesConstants.CPU)) {
requests.put(KubernetesConstants.CPU, requestsCLI.get(KubernetesConstants.CPU));
}
} else if (requestMode == KubernetesContext.KubernetesResourceRequestMode.EQUAL_TO_LIMIT) {
LOG.log(Level.CONFIG, "Setting K8s Request equal to Limit");
resourceRequirements.setRequests(limits);
} else {
LOG.log(Level.CONFIG, "Not setting K8s request because config was NOT_SET");
}
container.setResources(resourceRequirements);
}
use of io.kubernetes.client.openapi.models.V1ResourceRequirements in project twister2 by DSC-SPIDAL.
the class RequestObjectBuilder method constructContainer.
/**
* construct a container
*/
public static V1Container constructContainer(ComputeResource computeResource, int containerIndex) {
// construct container and add it to podSpec
V1Container container = new V1Container();
String containerName = KubernetesUtils.createContainerName(containerIndex);
container.setName(containerName);
String containerImage = KubernetesContext.twister2DockerImageForK8s(config);
if (containerImage == null) {
throw new RuntimeException("Container Image name is null. Config parameter: " + "twister2.resource.kubernetes.docker.image can not be null");
}
container.setImage(containerImage);
container.setImagePullPolicy(KubernetesContext.imagePullPolicy(config));
String startScript = null;
double cpuPerContainer = computeResource.getCpu();
int ramPerContainer = computeResource.getRamMegaBytes();
if (SchedulerContext.usingOpenMPI(config)) {
startScript = "./init_openmpi.sh";
cpuPerContainer = cpuPerContainer * computeResource.getWorkersPerPod();
ramPerContainer = ramPerContainer * computeResource.getWorkersPerPod();
} else {
startScript = "./init.sh";
}
container.setCommand(Arrays.asList("/bin/bash"));
container.setArgs(Arrays.asList("-c", startScript));
V1ResourceRequirements resReq = new V1ResourceRequirements();
if (KubernetesContext.bindWorkerToCPU(config)) {
resReq.putLimitsItem("cpu", new Quantity(String.format("%.2f", cpuPerContainer)));
resReq.putLimitsItem("memory", new Quantity(ramPerContainer + "Mi"));
} else {
resReq.putRequestsItem("cpu", new Quantity(String.format("%.2f", cpuPerContainer)));
resReq.putRequestsItem("memory", new Quantity(ramPerContainer + "Mi"));
}
container.setResources(resReq);
ArrayList<V1VolumeMount> volumeMounts = new ArrayList<>();
V1VolumeMount memoryVolumeMount = new V1VolumeMount();
memoryVolumeMount.setName(KubernetesConstants.POD_MEMORY_VOLUME_NAME);
memoryVolumeMount.setMountPath(KubernetesConstants.POD_MEMORY_VOLUME);
volumeMounts.add(memoryVolumeMount);
if (computeResource.getDiskGigaBytes() > 0) {
V1VolumeMount volatileVolumeMount = new V1VolumeMount();
volatileVolumeMount.setName(KubernetesConstants.POD_VOLATILE_VOLUME_NAME);
volatileVolumeMount.setMountPath(KubernetesConstants.POD_VOLATILE_VOLUME);
volumeMounts.add(volatileVolumeMount);
}
if (SchedulerContext.persistentVolumeRequested(config)) {
V1VolumeMount persVolumeMount = new V1VolumeMount();
persVolumeMount.setName(KubernetesConstants.PERSISTENT_VOLUME_NAME);
persVolumeMount.setMountPath(KubernetesConstants.PERSISTENT_VOLUME_MOUNT);
volumeMounts.add(persVolumeMount);
}
// mount Secret object as a volume
if (SchedulerContext.usingOpenMPI(config)) {
V1VolumeMount persVolumeMount = new V1VolumeMount();
persVolumeMount.setName(KubernetesConstants.SECRET_VOLUME_NAME);
persVolumeMount.setMountPath(KubernetesConstants.SECRET_VOLUME_MOUNT);
volumeMounts.add(persVolumeMount);
}
container.setVolumeMounts(volumeMounts);
int containerPort = KubernetesContext.workerBasePort(config) + containerIndex * (SchedulerContext.numberOfAdditionalPorts(config) + 1);
V1ContainerPort port = new V1ContainerPort();
// currently not used
port.name("port11");
port.containerPort(containerPort);
port.setProtocol(KubernetesContext.workerTransportProtocol(config));
container.setPorts(Arrays.asList(port));
int jvmMemory = (int) (computeResource.getRamMegaBytes() * KubernetesContext.jvmMemoryFraction(config));
container.setEnv(constructEnvironmentVariables(containerName, containerPort, jvmMemory));
return container;
}
use of io.kubernetes.client.openapi.models.V1ResourceRequirements in project heron by twitter.
the class V1Controller method createPersistentVolumeClaims.
/**
* Generates <code>Persistent Volume Claims Templates</code> from a mapping of <code>Volumes</code>
* to <code>key-value</code> pairs of configuration options and values.
* @param mapOfOpts <code>Volume</code> to configuration <code>key-value</code> mappings.
* @return Fully populated list of only dynamically backed <code>Persistent Volume Claims</code>.
*/
@VisibleForTesting
protected List<V1PersistentVolumeClaim> createPersistentVolumeClaims(final Map<String, Map<KubernetesConstants.VolumeConfigKeys, String>> mapOfOpts) {
List<V1PersistentVolumeClaim> listOfPVCs = new LinkedList<>();
// Iterate over all the PVC Volumes.
for (Map.Entry<String, Map<KubernetesConstants.VolumeConfigKeys, String>> pvc : mapOfOpts.entrySet()) {
// Only create claims for `OnDemand` volumes.
final String claimName = pvc.getValue().get(KubernetesConstants.VolumeConfigKeys.claimName);
if (claimName != null && !KubernetesConstants.LABEL_ON_DEMAND.equalsIgnoreCase(claimName)) {
continue;
}
V1PersistentVolumeClaim claim = new V1PersistentVolumeClaimBuilder().withNewMetadata().withName(pvc.getKey()).withLabels(getPersistentVolumeClaimLabels(getTopologyName())).endMetadata().withNewSpec().withStorageClassName("").endSpec().build();
// Populate PVC options.
for (Map.Entry<KubernetesConstants.VolumeConfigKeys, String> option : pvc.getValue().entrySet()) {
String optionValue = option.getValue();
switch(option.getKey()) {
case storageClassName:
claim.getSpec().setStorageClassName(optionValue);
break;
case sizeLimit:
claim.getSpec().setResources(new V1ResourceRequirements().putRequestsItem("storage", new Quantity(optionValue)));
break;
case accessModes:
claim.getSpec().setAccessModes(Arrays.asList(optionValue.split(",")));
break;
case volumeMode:
claim.getSpec().setVolumeMode(optionValue);
break;
// Valid ignored options not used in a PVC.
default:
break;
}
}
listOfPVCs.add(claim);
}
return listOfPVCs;
}
use of io.kubernetes.client.openapi.models.V1ResourceRequirements in project heron by twitter.
the class V1ControllerTest method testConfigureContainerResources.
@Test
public void testConfigureContainerResources() {
final boolean isExecutor = true;
final Resource resourceDefault = new Resource(9, ByteAmount.fromMegabytes(19000), ByteAmount.fromMegabytes(99000));
final Resource resourceCustom = new Resource(4, ByteAmount.fromMegabytes(34000), ByteAmount.fromMegabytes(400000));
final Quantity defaultRAM = Quantity.fromString(KubernetesUtils.Megabytes(resourceDefault.getRam()));
final Quantity defaultCPU = Quantity.fromString(Double.toString(KubernetesUtils.roundDecimal(resourceDefault.getCpu(), 3)));
final Quantity customRAM = Quantity.fromString(KubernetesUtils.Megabytes(resourceCustom.getRam()));
final Quantity customCPU = Quantity.fromString(Double.toString(KubernetesUtils.roundDecimal(resourceCustom.getCpu(), 3)));
final Quantity customDisk = Quantity.fromString(KubernetesUtils.Megabytes(resourceCustom.getDisk()));
final Config configNoLimit = Config.newBuilder().put(KubernetesContext.KUBERNETES_RESOURCE_REQUEST_MODE, "NOT_SET").build();
final Config configWithLimit = Config.newBuilder().put(KubernetesContext.KUBERNETES_RESOURCE_REQUEST_MODE, "EQUAL_TO_LIMIT").build();
final V1ResourceRequirements expectDefaultRequirements = new V1ResourceRequirements().putLimitsItem(KubernetesConstants.MEMORY, defaultRAM).putLimitsItem(KubernetesConstants.CPU, defaultCPU);
final V1ResourceRequirements expectCustomRequirements = new V1ResourceRequirements().putLimitsItem(KubernetesConstants.MEMORY, defaultRAM).putLimitsItem(KubernetesConstants.CPU, defaultCPU).putLimitsItem("disk", customDisk);
final V1ResourceRequirements customRequirements = new V1ResourceRequirements().putLimitsItem(KubernetesConstants.MEMORY, customRAM).putLimitsItem(KubernetesConstants.CPU, customCPU).putLimitsItem("disk", customDisk);
// Default. Null resources.
V1Container containerNull = new V1ContainerBuilder().build();
v1ControllerWithPodTemplate.configureContainerResources(containerNull, configNoLimit, resourceDefault, isExecutor);
Assert.assertTrue("Default LIMITS should be set in container with null LIMITS", containerNull.getResources().getLimits().entrySet().containsAll(expectDefaultRequirements.getLimits().entrySet()));
// Empty resources.
V1Container containerEmpty = new V1ContainerBuilder().withNewResources().endResources().build();
v1ControllerWithPodTemplate.configureContainerResources(containerEmpty, configNoLimit, resourceDefault, isExecutor);
Assert.assertTrue("Default LIMITS should be set in container with empty LIMITS", containerNull.getResources().getLimits().entrySet().containsAll(expectDefaultRequirements.getLimits().entrySet()));
// Custom resources.
V1Container containerCustom = new V1ContainerBuilder().withResources(customRequirements).build();
v1ControllerWithPodTemplate.configureContainerResources(containerCustom, configNoLimit, resourceDefault, isExecutor);
Assert.assertTrue("Custom LIMITS should be set in container with custom LIMITS", containerCustom.getResources().getLimits().entrySet().containsAll(expectCustomRequirements.getLimits().entrySet()));
// Custom resources with request.
V1Container containerRequests = new V1ContainerBuilder().withResources(customRequirements).build();
v1ControllerWithPodTemplate.configureContainerResources(containerRequests, configWithLimit, resourceDefault, isExecutor);
Assert.assertTrue("Custom LIMITS should be set in container with custom LIMITS and REQUEST", containerRequests.getResources().getLimits().entrySet().containsAll(expectCustomRequirements.getLimits().entrySet()));
Assert.assertTrue("Custom REQUEST should be set in container with custom LIMITS and REQUEST", containerRequests.getResources().getRequests().entrySet().containsAll(expectCustomRequirements.getLimits().entrySet()));
}
use of io.kubernetes.client.openapi.models.V1ResourceRequirements in project twister2 by DSC-SPIDAL.
the class JobMasterRequestObject method constructContainer.
/**
* construct a container
*/
public static V1Container constructContainer() {
// construct container and add it to podSpec
V1Container container = new V1Container();
container.setName("twister2-job-master-0");
String containerImage = KubernetesContext.twister2DockerImageForK8s(config);
if (containerImage == null) {
throw new RuntimeException("Container Image name is null. Config parameter: " + "twister2.resource.kubernetes.docker.image can not be null");
}
container.setImage(containerImage);
container.setImagePullPolicy(KubernetesContext.imagePullPolicy(config));
container.setCommand(Arrays.asList("/bin/bash"));
container.setArgs(Arrays.asList("-c", "./init.sh"));
int jmRam = JobMasterContext.jobMasterRAM(config) + 128;
V1ResourceRequirements resReq = new V1ResourceRequirements();
resReq.putRequestsItem("cpu", new Quantity(JobMasterContext.jobMasterCpu(config) + ""));
resReq.putRequestsItem("memory", new Quantity(jmRam + "Mi"));
container.setResources(resReq);
ArrayList<V1VolumeMount> volumeMounts = new ArrayList<>();
V1VolumeMount memoryVolumeMount = new V1VolumeMount();
memoryVolumeMount.setName(KubernetesConstants.POD_MEMORY_VOLUME_NAME);
memoryVolumeMount.setMountPath(KubernetesConstants.POD_MEMORY_VOLUME);
volumeMounts.add(memoryVolumeMount);
if (JobMasterContext.volatileVolumeRequested(config)) {
V1VolumeMount volatileVolumeMount = new V1VolumeMount();
volatileVolumeMount.setName(KubernetesConstants.POD_VOLATILE_VOLUME_NAME);
volatileVolumeMount.setMountPath(KubernetesConstants.POD_VOLATILE_VOLUME);
volumeMounts.add(volatileVolumeMount);
}
if (JobMasterContext.persistentVolumeRequested(config)) {
V1VolumeMount persVolumeMount = new V1VolumeMount();
persVolumeMount.setName(KubernetesConstants.PERSISTENT_VOLUME_NAME);
persVolumeMount.setMountPath(KubernetesConstants.PERSISTENT_VOLUME_MOUNT);
volumeMounts.add(persVolumeMount);
}
container.setVolumeMounts(volumeMounts);
V1ContainerPort port = new V1ContainerPort();
port.name("job-master-port");
port.containerPort(JobMasterContext.jobMasterPort(config));
port.setProtocol("TCP");
container.setPorts(Arrays.asList(port));
container.setEnv(constructEnvironmentVariables(JobMasterContext.jobMasterRAM(config)));
return container;
}
Aggregations