Search in sources :

Example 1 with Quantity

use of io.kubernetes.client.custom.Quantity 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);
}
Also used : Quantity(io.kubernetes.client.custom.Quantity) V1ResourceRequirements(io.kubernetes.client.openapi.models.V1ResourceRequirements) VisibleForTesting(com.google.common.annotations.VisibleForTesting)

Example 2 with Quantity

use of io.kubernetes.client.custom.Quantity in project heron by twitter.

the class V1ControllerTest method testCreateResourcesRequirement.

@Test
public void testCreateResourcesRequirement() {
    final String managerCpuLimit = "3000m";
    final String managerMemLimit = "256Gi";
    final Quantity memory = Quantity.fromString(managerMemLimit);
    final Quantity cpu = Quantity.fromString(managerCpuLimit);
    final List<TestTuple<Map<String, String>, Map<String, Quantity>>> testCases = new LinkedList<>();
    // No input.
    Map<String, String> inputEmpty = new HashMap<>();
    testCases.add(new TestTuple<>("Empty input.", inputEmpty, new HashMap<>()));
    // Only memory.
    Map<String, String> inputMemory = new HashMap<String, String>() {

        {
            put(KubernetesConstants.MEMORY, managerMemLimit);
        }
    };
    Map<String, Quantity> expectedMemory = new HashMap<String, Quantity>() {

        {
            put(KubernetesConstants.MEMORY, memory);
        }
    };
    testCases.add(new TestTuple<>("Only memory input.", inputMemory, expectedMemory));
    // Only CPU.
    Map<String, String> inputCPU = new HashMap<String, String>() {

        {
            put(KubernetesConstants.CPU, managerCpuLimit);
        }
    };
    Map<String, Quantity> expectedCPU = new HashMap<String, Quantity>() {

        {
            put(KubernetesConstants.CPU, cpu);
        }
    };
    testCases.add(new TestTuple<>("Only CPU input.", inputCPU, expectedCPU));
    // CPU and memory.
    Map<String, String> inputMemoryCPU = new HashMap<String, String>() {

        {
            put(KubernetesConstants.MEMORY, managerMemLimit);
            put(KubernetesConstants.CPU, managerCpuLimit);
        }
    };
    Map<String, Quantity> expectedMemoryCPU = new HashMap<String, Quantity>() {

        {
            put(KubernetesConstants.MEMORY, memory);
            put(KubernetesConstants.CPU, cpu);
        }
    };
    testCases.add(new TestTuple<>("Memory and CPU input.", inputMemoryCPU, expectedMemoryCPU));
    // Invalid.
    Map<String, String> inputInvalid = new HashMap<String, String>() {

        {
            put("invalid input", "will not be ignored");
            put(KubernetesConstants.CPU, managerCpuLimit);
        }
    };
    Map<String, Quantity> expectedInvalid = new HashMap<String, Quantity>() {

        {
            put(KubernetesConstants.CPU, cpu);
        }
    };
    testCases.add(new TestTuple<>("Invalid input.", inputInvalid, expectedInvalid));
    // Test loop.
    for (TestTuple<Map<String, String>, Map<String, Quantity>> testCase : testCases) {
        Map<String, Quantity> actual = v1ControllerPodTemplate.createResourcesRequirement(testCase.input);
        Assert.assertEquals(testCase.description, testCase.expected, actual);
    }
}
Also used : HashMap(java.util.HashMap) TestTuple(org.apache.heron.scheduler.kubernetes.KubernetesUtils.TestTuple) Quantity(io.kubernetes.client.custom.Quantity) Matchers.anyString(org.mockito.Matchers.anyString) HashMap(java.util.HashMap) V1ConfigMap(io.kubernetes.client.openapi.models.V1ConfigMap) Map(java.util.Map) ImmutableMap(com.google.common.collect.ImmutableMap) LinkedList(java.util.LinkedList) Test(org.junit.Test)

Example 3 with Quantity

use of io.kubernetes.client.custom.Quantity 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;
}
Also used : V1PersistentVolumeClaim(io.kubernetes.client.openapi.models.V1PersistentVolumeClaim) Quantity(io.kubernetes.client.custom.Quantity) Map(java.util.Map) HashMap(java.util.HashMap) V1ConfigMap(io.kubernetes.client.openapi.models.V1ConfigMap) LinkedList(java.util.LinkedList) V1PersistentVolumeClaimBuilder(io.kubernetes.client.openapi.models.V1PersistentVolumeClaimBuilder) V1ResourceRequirements(io.kubernetes.client.openapi.models.V1ResourceRequirements) VisibleForTesting(com.google.common.annotations.VisibleForTesting)

Example 4 with Quantity

use of io.kubernetes.client.custom.Quantity in project heron by twitter.

the class V1Controller method createVolumeAndMountsEmptyDirCLI.

/**
 * Generates the <code>Volume</code>s and <code>Volume Mounts</code> for <code>emptyDir</code>s to be
 * placed in the <code>Executor</code> and <code>Manager</code> from options on the CLI.
 * @param mapOfOpts Mapping of <code>Volume</code> option <code>key-value</code> configuration pairs.
 * @param volumes A list of <code>Volume</code> to append to.
 * @param volumeMounts A list of <code>Volume Mounts</code> to append to.
 */
@VisibleForTesting
protected void createVolumeAndMountsEmptyDirCLI(final Map<String, Map<KubernetesConstants.VolumeConfigKeys, String>> mapOfOpts, final List<V1Volume> volumes, final List<V1VolumeMount> volumeMounts) {
    for (Map.Entry<String, Map<KubernetesConstants.VolumeConfigKeys, String>> configs : mapOfOpts.entrySet()) {
        final String volumeName = configs.getKey();
        final V1Volume volume = new V1VolumeBuilder().withName(volumeName).withNewEmptyDir().endEmptyDir().build();
        for (Map.Entry<KubernetesConstants.VolumeConfigKeys, String> config : configs.getValue().entrySet()) {
            switch(config.getKey()) {
                case medium:
                    volume.getEmptyDir().medium(config.getValue());
                    break;
                case sizeLimit:
                    volume.getEmptyDir().sizeLimit(new Quantity(config.getValue()));
                    break;
                default:
                    break;
            }
        }
        volumes.add(volume);
        volumeMounts.add(createVolumeMountsCLI(volumeName, configs.getValue()));
    }
}
Also used : V1VolumeBuilder(io.kubernetes.client.openapi.models.V1VolumeBuilder) V1Volume(io.kubernetes.client.openapi.models.V1Volume) Quantity(io.kubernetes.client.custom.Quantity) Map(java.util.Map) HashMap(java.util.HashMap) V1ConfigMap(io.kubernetes.client.openapi.models.V1ConfigMap) VisibleForTesting(com.google.common.annotations.VisibleForTesting)

Example 5 with Quantity

use of io.kubernetes.client.custom.Quantity 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()));
}
Also used : V1Container(io.kubernetes.client.openapi.models.V1Container) Config(org.apache.heron.spi.common.Config) Resource(org.apache.heron.spi.packing.Resource) Quantity(io.kubernetes.client.custom.Quantity) V1ContainerBuilder(io.kubernetes.client.openapi.models.V1ContainerBuilder) V1ResourceRequirements(io.kubernetes.client.openapi.models.V1ResourceRequirements) Test(org.junit.Test)

Aggregations

Quantity (io.kubernetes.client.custom.Quantity)8 V1ConfigMap (io.kubernetes.client.openapi.models.V1ConfigMap)4 HashMap (java.util.HashMap)4 Map (java.util.Map)4 Test (org.junit.Test)4 VisibleForTesting (com.google.common.annotations.VisibleForTesting)3 V1ResourceRequirements (io.kubernetes.client.openapi.models.V1ResourceRequirements)3 LinkedList (java.util.LinkedList)3 Matchers.anyString (org.mockito.Matchers.anyString)3 ImmutableMap (com.google.common.collect.ImmutableMap)2 V1Container (io.kubernetes.client.openapi.models.V1Container)2 V1ContainerBuilder (io.kubernetes.client.openapi.models.V1ContainerBuilder)2 V1PersistentVolumeClaim (io.kubernetes.client.openapi.models.V1PersistentVolumeClaim)2 V1PersistentVolumeClaimBuilder (io.kubernetes.client.openapi.models.V1PersistentVolumeClaimBuilder)2 Config (org.apache.heron.spi.common.Config)2 Resource (org.apache.heron.spi.packing.Resource)2 Metrics (io.kubernetes.client.Metrics)1 ContainerMetrics (io.kubernetes.client.custom.ContainerMetrics)1 NodeMetrics (io.kubernetes.client.custom.NodeMetrics)1 NodeMetricsList (io.kubernetes.client.custom.NodeMetricsList)1