You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mesos.apache.org by jp...@apache.org on 2017/10/19 23:34:28 UTC
[07/11] mesos git commit: Optionally isolate only the agent network
ports.
Optionally isolate only the agent network ports.
Normally, the `network/ports` isolator will kill any task that
listens on a port that it does not have resources for. However,
executors that are based on the libprocess API will always
listen on a port in the ephemeral range, and we want to make
it possible to use libprocess-based executors.
Added the `--check_agent_port_range_only` option to only kill
tasks when they listen on un-allocated ports within the port
range published by the agent resources. This still prevents
port collisions between tasks, but doesn't kill them just
because the executor is listening on a port.
Review: https://reviews.apache.org/r/60591/
Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/2fc779bf
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/2fc779bf
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/2fc779bf
Branch: refs/heads/master
Commit: 2fc779bfcdcf511563d7c57a6ee02d8ac5382c5e
Parents: 4868d0b
Author: James Peach <jp...@apache.org>
Authored: Thu Oct 19 15:35:54 2017 -0700
Committer: James Peach <jp...@apache.org>
Committed: Thu Oct 19 16:33:35 2017 -0700
----------------------------------------------------------------------
.../mesos/isolators/network/ports.cpp | 84 +++++++++++++++++++-
.../mesos/isolators/network/ports.hpp | 5 +-
src/slave/flags.cpp | 8 ++
src/slave/flags.hpp | 1 +
4 files changed, 93 insertions(+), 5 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/mesos/blob/2fc779bf/src/slave/containerizer/mesos/isolators/network/ports.cpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos/isolators/network/ports.cpp b/src/slave/containerizer/mesos/isolators/network/ports.cpp
index 5a58d07..243ba01 100644
--- a/src/slave/containerizer/mesos/isolators/network/ports.cpp
+++ b/src/slave/containerizer/mesos/isolators/network/ports.cpp
@@ -36,6 +36,8 @@
#include "linux/cgroups.hpp"
+#include "slave/constants.hpp"
+
#include "slave/containerizer/mesos/linux_launcher.hpp"
using std::list;
@@ -72,6 +74,7 @@ static hashmap<ContainerID, IntervalSet<uint16_t>>
collectContainerListeners(
const string& cgroupsRoot,
const string& freezerHierarchy,
+ const Option<IntervalSet<uint16_t>>& agentPorts,
const hashset<ContainerID>& containerIds)
{
hashmap<ContainerID, IntervalSet<uint16_t>> listeners;
@@ -144,7 +147,11 @@ collectContainerListeners(
}
}
- listeners[containerId].add(address.port);
+ // If we are filtering by agent ports, then we only collect this
+ // listen socket if it falls within the agent port range.
+ if (agentPorts.isNone() || agentPorts->contains(address.port)) {
+ listeners[containerId].add(address.port);
+ }
}
}
}
@@ -250,6 +257,23 @@ Try<vector<uint32_t>> NetworkPortsIsolatorProcess::getProcessSockets(pid_t pid)
}
+// Return true if any "ports" resources are specified in the flags. This
+// is later used to distinguish between empty an unspecified ports.
+static bool havePortsResource(const Flags& flags)
+{
+ vector<Resource> resourceList = Resources::fromString(
+ flags.resources.getOrElse(""), flags.default_role).get();
+
+ foreach(const auto& resource, resourceList) {
+ if (resource.name() == "ports") {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
Try<Isolator*> NetworkPortsIsolatorProcess::create(const Flags& flags)
{
if (flags.launcher != "linux") {
@@ -267,22 +291,73 @@ Try<Isolator*> NetworkPortsIsolatorProcess::create(const Flags& flags)
freezerHierarchy.error());
}
+
+ Option<IntervalSet<uint16_t>> agentPorts = None();
+
+ // If we are only watching the ports in the agent resources, figure
+ // out what the agent ports will be by checking the resources flag
+ // and falling back to the default.
+ if (flags.check_agent_port_range_only) {
+ Try<Resources> resources = Resources::parse(
+ flags.resources.getOrElse(""),
+ flags.default_role);
+
+ if (resources.isError()) {
+ return Error(
+ "Failed to parse agent resources: " + resources.error());
+ }
+
+ // Mirroring the logic in Containerizer::resources(), we need
+ // to distinguish between an empty ports resource and a missing
+ // ports resource.
+ if (!havePortsResource(flags)) {
+ // Apply the defaults, if no ports were specified.
+ resources = Resources(
+ Resources::parse(
+ "ports",
+ stringify(DEFAULT_PORTS),
+ flags.default_role).get());
+
+ agentPorts =
+ rangesToIntervalSet<uint16_t>(resources->ports().get()).get();
+ } else if (resources->ports().isSome()) {
+ // Use the given non-empty ports resource.
+ Try<IntervalSet<uint16_t>> ports =
+ rangesToIntervalSet<uint16_t>(resources->ports().get());
+
+ if (ports.isError()) {
+ return Error(
+ "Invalid ports resource '" +
+ stringify(resources->ports().get()) +
+ "': " + ports.error());
+ }
+
+ agentPorts = ports.get();
+ } else {
+ // An empty ports resource was specified.
+ agentPorts = IntervalSet<uint16_t>{};
+ }
+ }
+
return new MesosIsolator(process::Owned<MesosIsolatorProcess>(
new NetworkPortsIsolatorProcess(
flags.container_ports_watch_interval,
flags.cgroups_root,
- freezerHierarchy.get())));
+ freezerHierarchy.get(),
+ agentPorts)));
}
NetworkPortsIsolatorProcess::NetworkPortsIsolatorProcess(
const Duration& _watchInterval,
const string& _cgroupsRoot,
- const string& _freezerHierarchy)
+ const string& _freezerHierarchy,
+ const Option<IntervalSet<uint16_t>>& _agentPorts)
: ProcessBase(process::ID::generate("network-ports-isolator")),
watchInterval(_watchInterval),
cgroupsRoot(_cgroupsRoot),
- freezerHierarchy(_freezerHierarchy)
+ freezerHierarchy(_freezerHierarchy),
+ agentPorts(_agentPorts)
{
}
@@ -458,6 +533,7 @@ void NetworkPortsIsolatorProcess::initialize()
&collectContainerListeners,
cgroupsRoot,
freezerHierarchy,
+ agentPorts,
infos.keys())
.then(defer(self, &NetworkPortsIsolatorProcess::check, lambda::_1))
.then([]() -> ControlFlow<Nothing> { return Continue(); });
http://git-wip-us.apache.org/repos/asf/mesos/blob/2fc779bf/src/slave/containerizer/mesos/isolators/network/ports.hpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos/isolators/network/ports.hpp b/src/slave/containerizer/mesos/isolators/network/ports.hpp
index 5a1e0e3..6ce35e7 100644
--- a/src/slave/containerizer/mesos/isolators/network/ports.hpp
+++ b/src/slave/containerizer/mesos/isolators/network/ports.hpp
@@ -27,6 +27,7 @@
#include <stout/duration.hpp>
#include <stout/hashmap.hpp>
#include <stout/interval.hpp>
+#include <stout/option.hpp>
#include "linux/routing/diagnosis/diagnosis.hpp"
@@ -84,7 +85,8 @@ private:
NetworkPortsIsolatorProcess(
const Duration& _watchInterval,
const std::string& _cgroupsRoot,
- const std::string& _freezerHierarchy);
+ const std::string& _freezerHierarchy,
+ const Option<IntervalSet<uint16_t>>& agentPorts);
struct Info
{
@@ -95,6 +97,7 @@ private:
const Duration watchInterval;
const std::string cgroupsRoot;
const std::string freezerHierarchy;
+ const Option<IntervalSet<uint16_t>> agentPorts;
hashmap<ContainerID, process::Owned<Info>> infos;
};
http://git-wip-us.apache.org/repos/asf/mesos/blob/2fc779bf/src/slave/flags.cpp
----------------------------------------------------------------------
diff --git a/src/slave/flags.cpp b/src/slave/flags.cpp
index d9116de..789b45b 100644
--- a/src/slave/flags.cpp
+++ b/src/slave/flags.cpp
@@ -1009,6 +1009,14 @@ mesos::internal::slave::Flags::Flags()
"Interval at which the `network/ports` isolator should check for\n"
"containers listening on ports they don't have resources for.",
Seconds(30));
+
+ add(&Flags::check_agent_port_range_only,
+ "check_agent_port_range_only",
+ "When this is true, the `network/ports` isolator allows tasks to\n"
+ "listen on additional ports provided they fall outside the range\n"
+ "published by the agent's resources. Otherwise tasks are restricted\n"
+ "to only listen on ports for which they have been assigned resources.",
+ false);
#endif // ENABLE_NETWORK_PORTS_ISOLATOR
add(&Flags::network_cni_plugins_dir,
http://git-wip-us.apache.org/repos/asf/mesos/blob/2fc779bf/src/slave/flags.hpp
----------------------------------------------------------------------
diff --git a/src/slave/flags.hpp b/src/slave/flags.hpp
index a038e9d..d02edbf 100644
--- a/src/slave/flags.hpp
+++ b/src/slave/flags.hpp
@@ -147,6 +147,7 @@ public:
#ifdef ENABLE_NETWORK_PORTS_ISOLATOR
Duration container_ports_watch_interval;
+ bool check_agent_port_range_only;
#endif // ENABLE_NETWORK_PORTS_ISOLATOR
Option<std::string> network_cni_plugins_dir;