You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mesos.apache.org by bm...@apache.org on 2018/07/25 23:20:01 UTC
[1/2] mesos git commit: Updated `Slave::getAvailable()` to return all
shared resources.
Repository: mesos
Updated Branches:
refs/heads/master 56d421d4d -> eeb74c036
Updated `Slave::getAvailable()` to return all shared resources.
Currently, `HierarchicalAllocatorProcess::Slave::getAvailable()`
only exposes the unallocated portion of shared resources. However,
we currently always consider a copy of shared resources to be
available for allocation.
This helps us acheive some cleanup of one-off shared resources logic
in the allocation loop.
Review: https://reviews.apache.org/r/67826/
Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/a9d50efd
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/a9d50efd
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/a9d50efd
Branch: refs/heads/master
Commit: a9d50efd63bf4cc47a49ffe3feaef87dfc0ffa7a
Parents: 56d421d
Author: Meng Zhu <mz...@mesosphere.io>
Authored: Wed Jul 25 15:57:47 2018 -0700
Committer: Benjamin Mahler <bm...@apache.org>
Committed: Wed Jul 25 16:15:30 2018 -0700
----------------------------------------------------------------------
src/master/allocator/mesos/hierarchical.hpp | 41 +++++++++++++++++-------
1 file changed, 30 insertions(+), 11 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/mesos/blob/a9d50efd/src/master/allocator/mesos/hierarchical.hpp
----------------------------------------------------------------------
diff --git a/src/master/allocator/mesos/hierarchical.hpp b/src/master/allocator/mesos/hierarchical.hpp
index c1a6789..02c63b1 100644
--- a/src/master/allocator/mesos/hierarchical.hpp
+++ b/src/master/allocator/mesos/hierarchical.hpp
@@ -372,14 +372,10 @@ protected:
capabilities(_capabilities),
activated(_activated),
total(_total),
- allocated(_allocated)
+ allocated(_allocated),
+ shared(_total.shared())
{
- // In order to subtract from the total,
- // we strip the allocation information.
- Resources allocated_ = allocated;
- allocated_.unallocate();
-
- available = total - allocated_;
+ updateAvailable();
}
const Resources& getTotal() const { return total; }
@@ -390,6 +386,7 @@ protected:
void updateTotal(const Resources& newTotal) {
total = newTotal;
+ shared = total.shared();
updateAvailable();
}
@@ -461,7 +458,21 @@ protected:
Resources allocated_ = allocated;
allocated_.unallocate();
- available = total - allocated_;
+ // Calling `nonShared()` currently copies the underlying resources
+ // and is therefore rather expensive. We avoid it in the common
+ // case that there are no shared resources.
+ //
+ // TODO(mzhu): Ideally there would be a single logical path here.
+ // One solution is to have `Resources` be copy-on-write such that
+ // `nonShared()` performs no copying and instead points to a
+ // subset of the original `Resource` objects.
+ if (shared.empty()) {
+ available = total - allocated_;
+ } else {
+ // Since shared resources are offerable even when they are in use, we
+ // always include them as part of available resources.
+ available = (total.nonShared() - allocated_.nonShared()) + shared;
+ }
}
// Total amount of regular *and* oversubscribed resources.
@@ -480,14 +491,22 @@ protected:
// hasn't reregistered. See MESOS-2919 for details.
Resources allocated;
- // We track the total and allocated resources on the slave, the
- // available resources are computed as follows:
+ // We track the total and allocated resources on the slave to
+ // avoid calculating it in place every time.
//
- // available = total - allocated
+ // Note that `available` always contains all the shared resources on the
+ // agent regardless whether they have ever been allocated or not.
+ // NOTE, however, we currently only offer a shared resource only if it has
+ // not been offered in an allocation cycle to a framework. We do this mainly
+ // to preserve the normal offer behavior. This may change in the future
+ // depending on use cases.
//
// Note that it's possible for the slave to be over-allocated!
// In this case, allocated > total.
Resources available;
+
+ // We keep a copy of the shared resources to avoid unnecessary copying.
+ Resources shared;
};
hashmap<SlaveID, Slave> slaves;
[2/2] mesos git commit: Added a `stripIncapableResources` helper in
the allocator.
Posted by bm...@apache.org.
Added a `stripIncapableResources` helper in the allocator.
This helper removes any resources that the framework is not
capable of receiving based on the given framework capability.
Review: https://reviews.apache.org/r/67827/
Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/eeb74c03
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/eeb74c03
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/eeb74c03
Branch: refs/heads/master
Commit: eeb74c03695a8311a9c3bf2d2f895c6c25f86266
Parents: a9d50ef
Author: Meng Zhu <mz...@mesosphere.io>
Authored: Wed Jul 25 16:15:48 2018 -0700
Committer: Benjamin Mahler <bm...@apache.org>
Committed: Wed Jul 25 16:15:48 2018 -0700
----------------------------------------------------------------------
src/master/allocator/mesos/hierarchical.cpp | 115 ++++++++++-------------
src/master/allocator/mesos/hierarchical.hpp | 9 ++
2 files changed, 59 insertions(+), 65 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/mesos/blob/eeb74c03/src/master/allocator/mesos/hierarchical.cpp
----------------------------------------------------------------------
diff --git a/src/master/allocator/mesos/hierarchical.cpp b/src/master/allocator/mesos/hierarchical.cpp
index 7b4e9db..3599247 100644
--- a/src/master/allocator/mesos/hierarchical.cpp
+++ b/src/master/allocator/mesos/hierarchical.cpp
@@ -1803,21 +1803,14 @@ void HierarchicalAllocatorProcess::__allocate()
continue;
}
- // Calculate the currently available resources on the slave, which
- // is the difference in non-shared resources between total and
- // allocated, plus all shared resources on the agent (if applicable).
- Resources available = slave.getAvailable().nonShared();
-
- // Since shared resources are offerable even when they are in use, we
- // make one copy of the shared resources available regardless of the
- // past allocations. Offer a shared resource only if it has not been
- // offered in this offer cycle to a framework.
- if (framework.capabilities.sharedResources) {
- available += slave.getTotal().shared();
- if (offeredSharedResources.contains(slaveId)) {
- available -= offeredSharedResources[slaveId];
- }
- }
+ // Get the currently available resources on the agent and strip
+ // resources that are incompatible with the framework capabilities.
+ Resources available =
+ stripIncapableResources(slave.getAvailable(), framework.capabilities);
+
+ // Offer a shared resource only if it has not been offered in this
+ // offer cycle to a framework.
+ available -= offeredSharedResources.get(slaveId).getOrElse(Resources());
// In this first stage, we allocate the role's reservations as well as
// any unreserved resources while ensuring the role stays within its
@@ -1947,21 +1940,6 @@ void HierarchicalAllocatorProcess::__allocate()
break;
}
- // When reservation refinements are present, old frameworks without the
- // RESERVATION_REFINEMENT capability won't be able to understand the
- // new format. While it's possible to translate the refined reservations
- // into the old format by "hiding" the intermediate reservations in the
- // "stack", this leads to ambiguity when processing RESERVE / UNRESERVE
- // operations. This is due to the loss of information when we drop the
- // intermediate reservations. Therefore, for now we simply filter out
- // resources with refined reservations if the framework does not have
- // the capability.
- if (!framework.capabilities.reservationRefinement) {
- toAllocate = toAllocate.filter([](const Resource& resource) {
- return !Resources::hasRefinedReservations(resource);
- });
- }
-
// If the framework filters these resources, ignore.
if (isFiltered(frameworkId, role, slaveId, toAllocate)) {
continue;
@@ -2036,21 +2014,14 @@ void HierarchicalAllocatorProcess::__allocate()
continue;
}
- // Calculate the currently available resources on the slave, which
- // is the difference in non-shared resources between total and
- // allocated, plus all shared resources on the agent (if applicable).
- Resources available = slave.getAvailable().nonShared();
-
- // Since shared resources are offerable even when they are in use, we
- // make one copy of the shared resources available regardless of the
- // past allocations. Offer a shared resource only if it has not been
- // offered in this offer cycle to a framework.
- if (framework.capabilities.sharedResources) {
- available += slave.getTotal().shared();
- if (offeredSharedResources.contains(slaveId)) {
- available -= offeredSharedResources[slaveId];
- }
- }
+ // Get the currently available resources on the agent and strip
+ // resources that are incompatible with the framework capabilities.
+ Resources available =
+ stripIncapableResources(slave.getAvailable(), framework.capabilities);
+
+ // Offer a shared resource only if it has not been offered in this offer
+ // cycle to a framework.
+ available -= offeredSharedResources.get(slaveId).getOrElse(Resources());
// The resources we offer are the unreserved resources as well as the
// reserved resources for this particular role and all its ancestors
@@ -2076,26 +2047,6 @@ void HierarchicalAllocatorProcess::__allocate()
break;
}
- // Remove revocable resources if the framework has not opted for them.
- if (!framework.capabilities.revocableResources) {
- toAllocate = toAllocate.nonRevocable();
- }
-
- // When reservation refinements are present, old frameworks without the
- // RESERVATION_REFINEMENT capability won't be able to understand the
- // new format. While it's possible to translate the refined reservations
- // into the old format by "hiding" the intermediate reservations in the
- // "stack", this leads to ambiguity when processing RESERVE / UNRESERVE
- // operations. This is due to the loss of information when we drop the
- // intermediate reservations. Therefore, for now we simply filter out
- // resources with refined reservations if the framework does not have
- // the capability.
- if (!framework.capabilities.reservationRefinement) {
- toAllocate = toAllocate.filter([](const Resource& resource) {
- return !Resources::hasRefinedReservations(resource);
- });
- }
-
// If allocating these resources would reduce the headroom
// below what is required, we will hold them back.
const Resources headroomToAllocate = toAllocate
@@ -2730,6 +2681,40 @@ bool HierarchicalAllocatorProcess::isCapableOfReceivingAgent(
}
+Resources HierarchicalAllocatorProcess::stripIncapableResources(
+ const Resources& resources,
+ const protobuf::framework::Capabilities& frameworkCapabilities) const
+{
+ return resources.filter([&](const Resource& resource) {
+ if (!frameworkCapabilities.sharedResources &&
+ Resources::isShared(resource)) {
+ return false;
+ }
+
+ if (!frameworkCapabilities.revocableResources &&
+ Resources::isRevocable(resource)) {
+ return false;
+ }
+
+ // When reservation refinements are present, old frameworks without the
+ // RESERVATION_REFINEMENT capability won't be able to understand the
+ // new format. While it's possible to translate the refined reservations
+ // into the old format by "hiding" the intermediate reservations in the
+ // "stack", this leads to ambiguity when processing RESERVE / UNRESERVE
+ // operations. This is due to the loss of information when we drop the
+ // intermediate reservations. Therefore, for now we simply filter out
+ // resources with refined reservations if the framework does not have
+ // the capability.
+ if (!frameworkCapabilities.reservationRefinement &&
+ Resources::hasRefinedReservations(resource)) {
+ return false;
+ }
+
+ return true;
+ });
+}
+
+
void HierarchicalAllocatorProcess::trackAllocatedResources(
const SlaveID& slaveId,
const FrameworkID& frameworkId,
http://git-wip-us.apache.org/repos/asf/mesos/blob/eeb74c03/src/master/allocator/mesos/hierarchical.hpp
----------------------------------------------------------------------
diff --git a/src/master/allocator/mesos/hierarchical.hpp b/src/master/allocator/mesos/hierarchical.hpp
index 02c63b1..0cd2fac 100644
--- a/src/master/allocator/mesos/hierarchical.hpp
+++ b/src/master/allocator/mesos/hierarchical.hpp
@@ -674,6 +674,15 @@ private:
const protobuf::framework::Capabilities& frameworkCapabilities,
const Slave& slave) const;
+ // Helper function that removes any resources that the framework is not
+ // capable of receiving based on the given framework capability.
+ //
+ // TODO(mzhu): Make this a `Framework` member function once we pull
+ // `struct Framework` out from being nested.
+ Resources stripIncapableResources(
+ const Resources& resources,
+ const protobuf::framework::Capabilities& frameworkCapabilities) const;
+
// Helper to track allocated resources on an agent.
void trackAllocatedResources(
const SlaveID& slaveId,