You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mesos.apache.org by ji...@apache.org on 2016/08/18 22:46:46 UTC
[2/2] mesos git commit: Implemented `CpuSubsystem`.
Implemented `CpuSubsystem`.
Review: https://reviews.apache.org/r/49849/
Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/6698cf86
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/6698cf86
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/6698cf86
Branch: refs/heads/master
Commit: 6698cf866fe2b2d0be6a80cec3d898bcf897aa71
Parents: c701136
Author: haosdent huang <ha...@gmail.com>
Authored: Thu Aug 18 14:45:52 2016 -0700
Committer: Jie Yu <yu...@gmail.com>
Committed: Thu Aug 18 15:46:21 2016 -0700
----------------------------------------------------------------------
src/CMakeLists.txt | 1 +
src/Makefile.am | 2 +
.../mesos/isolators/cgroups/cgroups.cpp | 2 +
.../mesos/isolators/cgroups/constants.hpp | 6 +
.../mesos/isolators/cgroups/subsystem.cpp | 28 ++-
.../mesos/isolators/cgroups/subsystem.hpp | 22 +--
.../mesos/isolators/cgroups/subsystems/cpu.cpp | 176 +++++++++++++++++++
.../mesos/isolators/cgroups/subsystems/cpu.hpp | 67 +++++++
8 files changed, 289 insertions(+), 15 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/mesos/blob/6698cf86/src/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 4362d47..a83dde9 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -167,6 +167,7 @@ set(LINUX_SRC
slave/containerizer/mesos/isolators/cgroups/net_cls.cpp
slave/containerizer/mesos/isolators/cgroups/perf_event.cpp
slave/containerizer/mesos/isolators/cgroups/subsystem.cpp
+ slave/containerizer/mesos/isolators/cgroups/subsystems/cpu.cpp
slave/containerizer/mesos/isolators/docker/runtime.cpp
slave/containerizer/mesos/isolators/docker/volume/driver.cpp
slave/containerizer/mesos/isolators/docker/volume/isolator.cpp
http://git-wip-us.apache.org/repos/asf/mesos/blob/6698cf86/src/Makefile.am
----------------------------------------------------------------------
diff --git a/src/Makefile.am b/src/Makefile.am
index d389e02..bfda83d 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1051,6 +1051,7 @@ MESOS_LINUX_FILES = \
slave/containerizer/mesos/isolators/cgroups/net_cls.cpp \
slave/containerizer/mesos/isolators/cgroups/perf_event.cpp \
slave/containerizer/mesos/isolators/cgroups/subsystem.cpp \
+ slave/containerizer/mesos/isolators/cgroups/subsystems/cpu.cpp \
slave/containerizer/mesos/isolators/docker/runtime.cpp \
slave/containerizer/mesos/isolators/docker/volume/isolator.cpp \
slave/containerizer/mesos/isolators/filesystem/linux.cpp \
@@ -1084,6 +1085,7 @@ MESOS_LINUX_FILES += \
slave/containerizer/mesos/isolators/cgroups/net_cls.hpp \
slave/containerizer/mesos/isolators/cgroups/perf_event.hpp \
slave/containerizer/mesos/isolators/cgroups/subsystem.hpp \
+ slave/containerizer/mesos/isolators/cgroups/subsystems/cpu.hpp \
slave/containerizer/mesos/isolators/docker/runtime.hpp \
slave/containerizer/mesos/isolators/docker/volume/isolator.hpp \
slave/containerizer/mesos/isolators/filesystem/linux.hpp \
http://git-wip-us.apache.org/repos/asf/mesos/blob/6698cf86/src/slave/containerizer/mesos/isolators/cgroups/cgroups.cpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos/isolators/cgroups/cgroups.cpp b/src/slave/containerizer/mesos/isolators/cgroups/cgroups.cpp
index 7e205a3..cae642a 100644
--- a/src/slave/containerizer/mesos/isolators/cgroups/cgroups.cpp
+++ b/src/slave/containerizer/mesos/isolators/cgroups/cgroups.cpp
@@ -31,6 +31,7 @@
#include "linux/cgroups.hpp"
#include "slave/containerizer/mesos/isolators/cgroups/cgroups.hpp"
+#include "slave/containerizer/mesos/isolators/cgroups/constants.hpp"
using mesos::slave::ContainerConfig;
using mesos::slave::ContainerLaunchInfo;
@@ -74,6 +75,7 @@ Try<Isolator*> CgroupsIsolatorProcess::create(const Flags& flags)
// Multimap: isolator name -> subsystem name.
multihashmap<string, string> isolatorMap = {
+ {"cpu", CGROUP_SUBSYSTEM_CPU_NAME},
};
foreach (string isolator, strings::tokenize(flags.isolation, ",")) {
http://git-wip-us.apache.org/repos/asf/mesos/blob/6698cf86/src/slave/containerizer/mesos/isolators/cgroups/constants.hpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos/isolators/cgroups/constants.hpp b/src/slave/containerizer/mesos/isolators/cgroups/constants.hpp
index c45d880..cc402b4 100644
--- a/src/slave/containerizer/mesos/isolators/cgroups/constants.hpp
+++ b/src/slave/containerizer/mesos/isolators/cgroups/constants.hpp
@@ -17,6 +17,8 @@
#ifndef __CGROUPS_ISOLATOR_CONSTANTS_HPP__
#define __CGROUPS_ISOLATOR_CONSTANTS_HPP__
+#include <string>
+
#include <stout/bytes.hpp>
#include <stout/duration.hpp>
@@ -35,6 +37,10 @@ const Duration MIN_CPU_CFS_QUOTA = Milliseconds(1);
// Memory subsystem constants.
const Bytes MIN_MEMORY = Megabytes(32);
+
+// Subsystem names.
+const std::string CGROUP_SUBSYSTEM_CPU_NAME = "cpu";
+
} // namespace slave {
} // namespace internal {
} // namespace mesos {
http://git-wip-us.apache.org/repos/asf/mesos/blob/6698cf86/src/slave/containerizer/mesos/isolators/cgroups/subsystem.cpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos/isolators/cgroups/subsystem.cpp b/src/slave/containerizer/mesos/isolators/cgroups/subsystem.cpp
index 13a6d77..767c56d 100644
--- a/src/slave/containerizer/mesos/isolators/cgroups/subsystem.cpp
+++ b/src/slave/containerizer/mesos/isolators/cgroups/subsystem.cpp
@@ -15,9 +15,13 @@
// limitations under the License.
#include <stout/error.hpp>
+#include <stout/hashmap.hpp>
+#include "slave/containerizer/mesos/isolators/cgroups/constants.hpp"
#include "slave/containerizer/mesos/isolators/cgroups/subsystem.hpp"
+#include "slave/containerizer/mesos/isolators/cgroups/subsystems/cpu.hpp"
+
using process::Future;
using process::Owned;
@@ -28,11 +32,27 @@ namespace internal {
namespace slave {
Try<Owned<Subsystem>> Subsystem::create(
- const Flags& _flags,
- const string& _name,
- const string& _hierarchy)
+ const Flags& flags,
+ const string& name,
+ const string& hierarchy)
{
- return Error("Unknown subsystem '" + _name + "'");
+ hashmap<string, Try<Owned<Subsystem>>(*)(const Flags&, const string&)>
+ creators = {
+ {CGROUP_SUBSYSTEM_CPU_NAME, &CpuSubsystem::create},
+ };
+
+ if (!creators.contains(name)) {
+ return Error("Unknown subsystem '" + name + "'");
+ }
+
+ Try<Owned<Subsystem>> subsystem = creators[name](flags, hierarchy);
+ if (subsystem.isError()) {
+ return Error(
+ "Failed to create subsystem '" + name + "': " +
+ subsystem.error());
+ }
+
+ return subsystem.get();
}
http://git-wip-us.apache.org/repos/asf/mesos/blob/6698cf86/src/slave/containerizer/mesos/isolators/cgroups/subsystem.hpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos/isolators/cgroups/subsystem.hpp b/src/slave/containerizer/mesos/isolators/cgroups/subsystem.hpp
index f8a7a45..06f4400 100644
--- a/src/slave/containerizer/mesos/isolators/cgroups/subsystem.hpp
+++ b/src/slave/containerizer/mesos/isolators/cgroups/subsystem.hpp
@@ -41,8 +41,8 @@ class Subsystem : public process::Process<Subsystem>
{
public:
/**
- * Attempts to create a specific `Subsystem` object that will contain specific
- * information associated with container.
+ * Attempts to create a specific `Subsystem` object that will
+ * contain specific information associated with container.
*
* @param flags `Flags` used to launch the agent.
* @param name The name of cgroups subsystem.
@@ -50,9 +50,9 @@ public:
* @return A specific `Subsystem` object or an error if `create` fails.
*/
static Try<process::Owned<Subsystem>> create(
- const Flags& _flags,
- const std::string& _name,
- const std::string& _hierarchy);
+ const Flags& flags,
+ const std::string& name,
+ const std::string& hierarchy);
virtual ~Subsystem() {}
@@ -91,8 +91,8 @@ public:
pid_t pid);
/**
- * Update resources allocated to the associated container in this cgroups
- * subsystem.
+ * Update resources allocated to the associated container in this
+ * cgroups subsystem.
*
* @param containerId The target containerId.
* @param resources The resources need to update.
@@ -114,8 +114,8 @@ public:
const ContainerID& containerId);
/**
- * Get the run-time status of cgroups subsystem specific properties associated
- * with the container.
+ * Get the run-time status of cgroups subsystem specific properties
+ * associated with the container.
*
* @param containerId The target containerId.
* @return The container status or an error if get fails.
@@ -124,8 +124,8 @@ public:
const ContainerID& containerId);
/**
- * Clean up the cgroups subsystem for the associated container. It will be
- * called when destruction to ensure everyting be cleanup.
+ * Clean up the cgroups subsystem for the associated container. It
+ * will be called when destruction to ensure everyting be cleanup.
*
* @param containerId The target containerId.
* @return Nothing or an error if `cleanup` fails.
http://git-wip-us.apache.org/repos/asf/mesos/blob/6698cf86/src/slave/containerizer/mesos/isolators/cgroups/subsystems/cpu.cpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos/isolators/cgroups/subsystems/cpu.cpp b/src/slave/containerizer/mesos/isolators/cgroups/subsystems/cpu.cpp
new file mode 100644
index 0000000..5912c65
--- /dev/null
+++ b/src/slave/containerizer/mesos/isolators/cgroups/subsystems/cpu.cpp
@@ -0,0 +1,176 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <process/id.hpp>
+
+#include <stout/error.hpp>
+#include <stout/option.hpp>
+
+#include "linux/cgroups.hpp"
+
+#include "slave/containerizer/mesos/isolators/cgroups/subsystems/cpu.hpp"
+
+using process::Failure;
+using process::Future;
+using process::Owned;
+
+using std::string;
+
+namespace mesos {
+namespace internal {
+namespace slave {
+
+Try<Owned<Subsystem>> CpuSubsystem::create(
+ const Flags& flags,
+ const string& hierarchy)
+{
+ if (flags.cgroups_enable_cfs) {
+ Try<bool> exists = cgroups::exists(
+ hierarchy,
+ flags.cgroups_root,
+ "cpu.cfs_quota_us");
+
+ if (exists.isError()) {
+ return Error(
+ "Failed to check the existence of 'cpu.cfs_quota_us': " +
+ exists.error());
+ } else if (!exists.get()) {
+ return Error(
+ "Failed to find 'cpu.cfs_quota_us'. Your kernel might be "
+ "too old to use the CFS quota feature");
+ }
+ }
+
+ return Owned<Subsystem>(new CpuSubsystem(flags, hierarchy));
+}
+
+
+CpuSubsystem::CpuSubsystem(
+ const Flags& _flags,
+ const string& _hierarchy)
+ : ProcessBase(process::ID::generate("cgroups-cpu-subsystem")),
+ Subsystem(_flags, _hierarchy) {}
+
+
+Future<Nothing> CpuSubsystem::update(
+ const ContainerID& containerId,
+ const Resources& resources)
+{
+ if (resources.cpus().isNone()) {
+ return Failure(
+ "Failed to update subsystem '" + name() + "': "
+ "No cpus resource given");
+ }
+
+ double cpus = resources.cpus().get();
+
+ // Always set cpu.shares.
+ uint64_t shares;
+
+ if (flags.revocable_cpu_low_priority &&
+ resources.revocable().cpus().isSome()) {
+ shares = std::max(
+ (uint64_t) (CPU_SHARES_PER_CPU_REVOCABLE * cpus),
+ MIN_CPU_SHARES);
+ } else {
+ shares = std::max(
+ (uint64_t) (CPU_SHARES_PER_CPU * cpus),
+ MIN_CPU_SHARES);
+ }
+
+ Try<Nothing> write = cgroups::cpu::shares(
+ hierarchy,
+ path::join(flags.cgroups_root, containerId.value()),
+ shares);
+
+ if (write.isError()) {
+ return Failure("Failed to update 'cpu.shares': " + write.error());
+ }
+
+ LOG(INFO) << "Updated 'cpu.shares' to " << shares
+ << " (cpus " << cpus << ")"
+ << " for container " << containerId;
+
+ // Set cfs quota if enabled.
+ if (flags.cgroups_enable_cfs) {
+ write = cgroups::cpu::cfs_period_us(
+ hierarchy,
+ path::join(flags.cgroups_root, containerId.value()),
+ CPU_CFS_PERIOD);
+
+ if (write.isError()) {
+ return Failure("Failed to update 'cpu.cfs_period_us': " + write.error());
+ }
+
+ Duration quota = std::max(CPU_CFS_PERIOD * cpus, MIN_CPU_CFS_QUOTA);
+
+ write = cgroups::cpu::cfs_quota_us(
+ hierarchy,
+ path::join(flags.cgroups_root, containerId.value()),
+ quota);
+
+ if (write.isError()) {
+ return Failure("Failed to update 'cpu.cfs_quota_us': " + write.error());
+ }
+
+ LOG(INFO) << "Updated 'cpu.cfs_period_us' to " << CPU_CFS_PERIOD
+ << " and 'cpu.cfs_quota_us' to " << quota
+ << " (cpus " << cpus << ")"
+ << " for container " << containerId;
+ }
+
+ return Nothing();
+}
+
+
+Future<ResourceStatistics> CpuSubsystem::usage(const ContainerID& containerId)
+{
+ ResourceStatistics result;
+
+ // Add the cpu.stat information only if CFS is enabled.
+ if (flags.cgroups_enable_cfs) {
+ Try<hashmap<string, uint64_t>> stat = cgroups::stat(
+ hierarchy,
+ path::join(flags.cgroups_root, containerId.value()),
+ "cpu.stat");
+
+ if (stat.isError()) {
+ return Failure("Failed to read 'cpu.stat': " + stat.error());
+ }
+
+ Option<uint64_t> nr_periods = stat.get().get("nr_periods");
+ if (nr_periods.isSome()) {
+ result.set_cpus_nr_periods(nr_periods.get());
+ }
+
+ Option<uint64_t> nr_throttled = stat.get().get("nr_throttled");
+ if (nr_throttled.isSome()) {
+ result.set_cpus_nr_throttled(nr_throttled.get());
+ }
+
+ Option<uint64_t> throttled_time = stat.get().get("throttled_time");
+ if (throttled_time.isSome()) {
+ result.set_cpus_throttled_time_secs(
+ Nanoseconds(throttled_time.get()).secs());
+ }
+ }
+
+ return result;
+}
+
+} // namespace slave {
+} // namespace internal {
+} // namespace mesos {
http://git-wip-us.apache.org/repos/asf/mesos/blob/6698cf86/src/slave/containerizer/mesos/isolators/cgroups/subsystems/cpu.hpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos/isolators/cgroups/subsystems/cpu.hpp b/src/slave/containerizer/mesos/isolators/cgroups/subsystems/cpu.hpp
new file mode 100644
index 0000000..c1f1004
--- /dev/null
+++ b/src/slave/containerizer/mesos/isolators/cgroups/subsystems/cpu.hpp
@@ -0,0 +1,67 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef __CGROUPS_ISOLATOR_SUBSYSTEMS_CPU_HPP__
+#define __CGROUPS_ISOLATOR_SUBSYSTEMS_CPU_HPP__
+
+#include <string>
+
+#include <process/owned.hpp>
+
+#include <stout/try.hpp>
+
+#include "slave/flags.hpp"
+
+#include "slave/containerizer/mesos/isolators/cgroups/constants.hpp"
+#include "slave/containerizer/mesos/isolators/cgroups/subsystem.hpp"
+
+namespace mesos {
+namespace internal {
+namespace slave {
+
+/**
+ * Represent cgroups cpu subsystem.
+ */
+class CpuSubsystem : public Subsystem
+{
+public:
+ static Try<process::Owned<Subsystem>> create(
+ const Flags& flags,
+ const std::string& hierarchy);
+
+ virtual ~CpuSubsystem() {}
+
+ virtual std::string name() const
+ {
+ return CGROUP_SUBSYSTEM_CPU_NAME;
+ };
+
+ virtual process::Future<Nothing> update(
+ const ContainerID& containerId,
+ const Resources& resources);
+
+ virtual process::Future<ResourceStatistics> usage(
+ const ContainerID& containerId);
+
+private:
+ CpuSubsystem(const Flags& flags, const std::string& hierarchy);
+};
+
+} // namespace slave {
+} // namespace internal {
+} // namespace mesos {
+
+#endif // __CGROUPS_ISOLATOR_SUBSYSTEMS_CPU_HPP__