Repository: mesos Updated Branches: refs/heads/master 78567c553 -> 869b8f06b
Reported per-container metrics for network bandwidth throttling. Review: https://reviews.apache.org/r/35229 Project: http://git-wip-us.apache.org/repos/asf/mesos/repo Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/541bba77 Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/541bba77 Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/541bba77 Branch: refs/heads/master Commit: 541bba77c08a7e0349ac45e71c2998abce27ef55 Parents: 78567c5 Author: Paul Brett <[email protected]> Authored: Wed Jun 17 16:08:09 2015 -0700 Committer: Jie Yu <[email protected]> Committed: Wed Jun 17 16:24:39 2015 -0700 ---------------------------------------------------------------------- .../isolators/network/port_mapping.cpp | 85 ++++++++++++++++++++ .../isolators/network/port_mapping.hpp | 7 ++ src/tests/port_mapping_tests.cpp | 1 + 3 files changed, 93 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/mesos/blob/541bba77/src/slave/containerizer/isolators/network/port_mapping.cpp ---------------------------------------------------------------------- diff --git a/src/slave/containerizer/isolators/network/port_mapping.cpp b/src/slave/containerizer/isolators/network/port_mapping.cpp index f97e960..85a84df 100644 --- a/src/slave/containerizer/isolators/network/port_mapping.cpp +++ b/src/slave/containerizer/isolators/network/port_mapping.cpp @@ -72,7 +72,9 @@ #include "linux/routing/link/link.hpp" #include "linux/routing/queueing/fq_codel.hpp" +#include "linux/routing/queueing/htb.hpp" #include "linux/routing/queueing/ingress.hpp" +#include "linux/routing/queueing/statistics.hpp" #include "mesos/resources.hpp" @@ -87,6 +89,7 @@ using namespace process; using namespace routing; using namespace routing::filter; using namespace routing::queueing; +using namespace routing::queueing::statistics; using std::cerr; using std::cout; @@ -663,6 +666,10 @@ const char* PortMappingStatistics::NAME = "statistics"; PortMappingStatistics::Flags::Flags() { + add(ð0_name, + "eth0_name", + "The name of the public network interface (e.g., eth0)"); + add(&pid, "pid", "The pid of the process whose namespaces we will enter"); @@ -680,6 +687,48 @@ PortMappingStatistics::Flags::Flags() } +// A helper that copies the traffic control statistics from the +// statistics hashmap into the ResourceStatistics protocol buffer. +static void addTrafficControlStatistics( + const string& id, + const hashmap<string, uint64_t>& statistics, + ResourceStatistics* result) +{ + TrafficControlStatistics *tc = result->add_net_traffic_control_statistics(); + + tc->set_id(id); + + // TODO(pbrett) Use protobuf reflection here. + if (statistics.contains(BACKLOG)) { + tc->set_backlog(statistics.at(BACKLOG)); + } + if (statistics.contains(BYTES)) { + tc->set_bytes(statistics.at(BYTES)); + } + if (statistics.contains(DROPS)) { + tc->set_drops(statistics.at(DROPS)); + } + if (statistics.contains(OVERLIMITS)) { + tc->set_overlimits(statistics.at(OVERLIMITS)); + } + if (statistics.contains(PACKETS)) { + tc->set_packets(statistics.at(PACKETS)); + } + if (statistics.contains(QLEN)) { + tc->set_qlen(statistics.at(QLEN)); + } + if (statistics.contains(RATE_BPS)) { + tc->set_ratebps(statistics.at(RATE_BPS)); + } + if (statistics.contains(RATE_PPS)) { + tc->set_ratepps(statistics.at(RATE_PPS)); + } + if (statistics.contains(REQUEUES)) { + tc->set_requeues(statistics.at(REQUEUES)); + } +} + + int PortMappingStatistics::execute() { if (flags.help) { @@ -694,6 +743,11 @@ int PortMappingStatistics::execute() return 1; } + if (flags.eth0_name.isNone()) { + cerr << "The public interface name (e.g., eth0) is not specified" << endl; + return 1; + } + // Enter the network namespace. Try<Nothing> setns = ns::setns(flags.pid.get(), "net"); if (setns.isError()) { @@ -825,6 +879,36 @@ int PortMappingStatistics::execute() } } + // Collect traffic statistics for the container from the container + // virtual interface and export them in JSON. + const string& eth0 = flags.eth0_name.get(); + + // Overlimits are reported on the HTB qdisc at the egress root. + Result<hashmap<string, uint64_t>> statistics = + htb::statistics(eth0, EGRESS_ROOT); + + if (statistics.isSome()) { + addTrafficControlStatistics( + NET_ISOLATOR_BW_LIMIT, + statistics.get(), + &result); + } else { + cerr << "Failed to get the network statistics for " + << "the htb qdisc on " << eth0 << endl; + } + + // Drops due to the bandwidth limit should be reported at the leaf. + statistics = fq_codel::statistics(eth0, CONTAINER_TX_HTB_CLASS_ID); + if (statistics.isSome()) { + addTrafficControlStatistics( + NET_ISOLATOR_BLOAT_REDUCTION, + statistics.get(), + &result); + } else { + cerr << "Failed to get the network statistics for " + << "the fq_codel qdisc on " << eth0 << endl; + } + cout << stringify(JSON::Protobuf(result)); return 0; } @@ -2696,6 +2780,7 @@ Future<ResourceStatistics> PortMappingIsolatorProcess::usage( // Retrieve the socket information from inside the container. PortMappingStatistics statistics; statistics.flags.pid = info->pid.get(); + statistics.flags.eth0_name = eth0; statistics.flags.enable_socket_statistics_summary = flags.network_enable_socket_statistics_summary; statistics.flags.enable_socket_statistics_details = http://git-wip-us.apache.org/repos/asf/mesos/blob/541bba77/src/slave/containerizer/isolators/network/port_mapping.hpp ---------------------------------------------------------------------- diff --git a/src/slave/containerizer/isolators/network/port_mapping.hpp b/src/slave/containerizer/isolators/network/port_mapping.hpp index 2a988b3..7777ee8 100644 --- a/src/slave/containerizer/isolators/network/port_mapping.hpp +++ b/src/slave/containerizer/isolators/network/port_mapping.hpp @@ -74,6 +74,12 @@ inline std::string PORT_MAPPING_BIND_MOUNT_SYMLINK_ROOT() } +// These names are used to identify the traffic control statistics +// output for each of the Linux Traffic Control Qdiscs we report. +constexpr char NET_ISOLATOR_BW_LIMIT[] = "bw_limit"; +constexpr char NET_ISOLATOR_BLOAT_REDUCTION[] = "bloat_reduction"; + + // Responsible for allocating ephemeral ports for the port mapping // network isolator. This class is exposed mainly for unit testing. class EphemeralPortsAllocator @@ -376,6 +382,7 @@ public: { Flags(); + Option<std::string> eth0_name; Option<pid_t> pid; bool enable_socket_statistics_summary; bool enable_socket_statistics_details; http://git-wip-us.apache.org/repos/asf/mesos/blob/541bba77/src/tests/port_mapping_tests.cpp ---------------------------------------------------------------------- diff --git a/src/tests/port_mapping_tests.cpp b/src/tests/port_mapping_tests.cpp index 835a0f2..6caab13 100644 --- a/src/tests/port_mapping_tests.cpp +++ b/src/tests/port_mapping_tests.cpp @@ -349,6 +349,7 @@ protected: // Retrieve the socket information from inside the container. PortMappingStatistics statistics; statistics.flags.pid = pid; + statistics.flags.eth0_name = eth0; statistics.flags.enable_socket_statistics_summary = enable_summary; statistics.flags.enable_socket_statistics_details = enable_details;
