You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mesos.apache.org by al...@apache.org on 2016/08/28 15:04:09 UTC
[09/10] mesos git commit: Entered appropriate task's namespaces
during health checking.
Entered appropriate task's namespaces during health checking.
Review: https://reviews.apache.org/r/51379/
Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/bb084fb8
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/bb084fb8
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/bb084fb8
Branch: refs/heads/master
Commit: bb084fb84cb59ed8eb1a554b17141d09ff0ed262
Parents: d2f8bfa
Author: haosdent huang <ha...@gmail.com>
Authored: Fri Aug 26 16:34:41 2016 +0200
Committer: Alexander Rukletsov <al...@apache.org>
Committed: Sun Aug 28 16:42:58 2016 +0200
----------------------------------------------------------------------
src/docker/executor.cpp | 15 ++++++-
src/health-check/health_checker.cpp | 73 ++++++++++++++++++++++++++++----
src/health-check/health_checker.hpp | 25 ++++++++++-
src/launcher/executor.cpp | 16 ++++++-
4 files changed, 117 insertions(+), 12 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/mesos/blob/bb084fb8/src/docker/executor.cpp
----------------------------------------------------------------------
diff --git a/src/docker/executor.cpp b/src/docker/executor.cpp
index 5508819..f5981b0 100644
--- a/src/docker/executor.cpp
+++ b/src/docker/executor.cpp
@@ -181,6 +181,8 @@ public:
inspect = docker->inspect(containerName, DOCKER_INSPECT_DELAY)
.then(defer(self(), [=](const Docker::Container& container) {
if (!killed) {
+ containerPid = container.pid;
+
TaskStatus status;
status.mutable_task_id()->CopyFrom(taskId.get());
status.set_state(TASK_RUNNING);
@@ -510,10 +512,20 @@ private:
strings::join(" ", commandArguments));
}
+ vector<string> namespaces;
+ if (healthCheck.type() == HealthCheck::HTTP ||
+ healthCheck.type() == HealthCheck::TCP) {
+ // Make sure HTTP and TCP health checks are run
+ // from the container's network namespace.
+ namespaces.push_back("net");
+ }
+
Try<Owned<health::HealthChecker>> _checker = health::HealthChecker::create(
healthCheck,
self(),
- task.task_id());
+ task.task_id(),
+ containerPid,
+ namespaces);
if (_checker.isError()) {
// TODO(gilbert): Consider ABORT and return a TASK_FAILED here.
@@ -555,6 +567,7 @@ private:
Option<TaskID> taskId;
Owned<health::HealthChecker> checker;
Option<NetworkInfo> containerNetworkInfo;
+ Option<pid_t> containerPid;
};
http://git-wip-us.apache.org/repos/asf/mesos/blob/bb084fb8/src/health-check/health_checker.cpp
----------------------------------------------------------------------
diff --git a/src/health-check/health_checker.cpp b/src/health-check/health_checker.cpp
index e5e7b94..f373df1 100644
--- a/src/health-check/health_checker.cpp
+++ b/src/health-check/health_checker.cpp
@@ -46,6 +46,10 @@
#include "common/status_utils.hpp"
+#ifdef __linux__
+#include "linux/ns.hpp"
+#endif
+
using process::delay;
using process::Clock;
using process::Failure;
@@ -73,10 +77,40 @@ static const string DEFAULT_HTTP_SCHEME = "http";
static const string DEFAULT_DOMAIN = "127.0.0.1";
+#ifdef __linux__
+pid_t cloneWithSetns(
+ const lambda::function<int()>& func,
+ Option<pid_t> taskPid,
+ const vector<string>& namespaces)
+{
+ return process::defaultClone([=]() -> int {
+ if (taskPid.isSome()) {
+ foreach (const string& ns, namespaces) {
+ Try<Nothing> setns = ns::setns(taskPid.get(), ns);
+ if (setns.isError()) {
+ // This effectively aborts the health check.
+ LOG(FATAL) << "Failed to enter the " << ns << " namespace of "
+ << "task (pid: '" << taskPid.get() << "'): "
+ << setns.error();
+ }
+
+ VLOG(1) << "Entered the " << ns << " namespace of "
+ << "task (pid: '" << taskPid.get() << "') successfully";
+ }
+ }
+
+ return func();
+ });
+}
+#endif
+
+
Try<Owned<HealthChecker>> HealthChecker::create(
const HealthCheck& check,
const UPID& executor,
- const TaskID& taskID)
+ const TaskID& taskID,
+ Option<pid_t> taskPid,
+ const vector<string>& namespaces)
{
// Validate the 'HealthCheck' protobuf.
Option<Error> error = validation::healthCheck(check);
@@ -87,7 +121,9 @@ Try<Owned<HealthChecker>> HealthChecker::create(
Owned<HealthCheckerProcess> process(new HealthCheckerProcess(
check,
executor,
- taskID));
+ taskID,
+ taskPid,
+ namespaces));
return Owned<HealthChecker>(new HealthChecker(process));
}
@@ -117,13 +153,24 @@ Future<Nothing> HealthChecker::healthCheck()
HealthCheckerProcess::HealthCheckerProcess(
const HealthCheck& _check,
const UPID& _executor,
- const TaskID& _taskID)
+ const TaskID& _taskID,
+ Option<pid_t> _taskPid,
+ const vector<string>& _namespaces)
: ProcessBase(process::ID::generate("health-checker")),
check(_check),
initializing(true),
executor(_executor),
taskID(_taskID),
- consecutiveFailures(0) {}
+ taskPid(_taskPid),
+ namespaces(_namespaces),
+ consecutiveFailures(0)
+{
+#ifdef __linux__
+ if (!namespaces.empty()) {
+ clone = lambda::bind(&cloneWithSetns, lambda::_1, taskPid, namespaces);
+ }
+#endif
+}
Future<Nothing> HealthCheckerProcess::healthCheck()
@@ -264,7 +311,8 @@ Future<Nothing> HealthCheckerProcess::_commandHealthCheck()
Subprocess::FD(STDERR_FILENO),
Subprocess::FD(STDERR_FILENO),
NO_SETSID,
- environment);
+ environment,
+ clone);
} else {
// Use the exec variant.
vector<string> argv;
@@ -283,7 +331,8 @@ Future<Nothing> HealthCheckerProcess::_commandHealthCheck()
Subprocess::FD(STDERR_FILENO),
NO_SETSID,
nullptr,
- environment);
+ environment,
+ clone);
}
if (external.isError()) {
@@ -353,7 +402,11 @@ Future<Nothing> HealthCheckerProcess::_httpHealthCheck()
argv,
Subprocess::PATH("/dev/null"),
Subprocess::PIPE(),
- Subprocess::PIPE());
+ Subprocess::PIPE(),
+ NO_SETSID,
+ nullptr,
+ None(),
+ clone);
if (s.isError()) {
return Failure("Failed to create the curl subprocess: " + s.error());
@@ -461,7 +514,11 @@ Future<Nothing> HealthCheckerProcess::_tcpHealthCheck()
argv,
Subprocess::PATH("/dev/null"),
Subprocess::PIPE(),
- Subprocess::PIPE());
+ Subprocess::PIPE(),
+ NO_SETSID,
+ nullptr,
+ None(),
+ clone);
if (s.isError()) {
return Failure("Failed to create the bash subprocess: " + s.error());
http://git-wip-us.apache.org/repos/asf/mesos/blob/bb084fb8/src/health-check/health_checker.hpp
----------------------------------------------------------------------
diff --git a/src/health-check/health_checker.hpp b/src/health-check/health_checker.hpp
index 52acdef..392b4d5 100644
--- a/src/health-check/health_checker.hpp
+++ b/src/health-check/health_checker.hpp
@@ -19,6 +19,7 @@
#include <string>
#include <tuple>
+#include <vector>
#include <mesos/mesos.hpp>
@@ -43,10 +44,25 @@ class HealthCheckerProcess;
class HealthChecker
{
public:
+ /**
+ * Attempts to create a `HealthChecker` object.
+ *
+ * @param check The protobuf message definition of health check.
+ * @param executor The executor UPID to which health check results will be
+ * reported.
+ * @param taskID The TaskID of the target task.
+ * @param taskPid The target task's pid used to enter the specified
+ * namespaces.
+ * @param namespaces The namespaces to enter prior performing a single health
+ * check.
+ * @return A `HealthChecker` object or an error if `create` fails.
+ */
static Try<process::Owned<HealthChecker>> create(
const HealthCheck& check,
const process::UPID& executor,
- const TaskID& taskID);
+ const TaskID& taskID,
+ Option<pid_t> taskPid,
+ const std::vector<std::string>& namespaces);
~HealthChecker();
@@ -65,7 +81,9 @@ public:
HealthCheckerProcess(
const HealthCheck& _check,
const process::UPID& _executor,
- const TaskID& _taskID);
+ const TaskID& _taskID,
+ Option<pid_t> _taskPid,
+ const std::vector<std::string>& _namespaces);
virtual ~HealthCheckerProcess() {}
@@ -104,6 +122,9 @@ private:
bool initializing;
process::UPID executor;
TaskID taskID;
+ Option<pid_t> taskPid;
+ std::vector<std::string> namespaces;
+ Option<lambda::function<pid_t(const lambda::function<int()>&)>> clone;
uint32_t consecutiveFailures;
process::Time startTime;
};
http://git-wip-us.apache.org/repos/asf/mesos/blob/bb084fb8/src/launcher/executor.cpp
----------------------------------------------------------------------
diff --git a/src/launcher/executor.cpp b/src/launcher/executor.cpp
index 71ede1e..5370634 100644
--- a/src/launcher/executor.cpp
+++ b/src/launcher/executor.cpp
@@ -418,11 +418,25 @@ protected:
cout << "Forked command at " << pid << endl;
if (task->has_health_check()) {
+ vector<string> namespaces;
+ if (rootfs.isSome() &&
+ task->health_check().type() == HealthCheck::COMMAND) {
+ // Make sure command health checks are run from the task's mount
+ // namespace. Otherwise if rootfs is specified the command binary
+ // may not be available in the executor.
+ //
+ // NOTE: The command executor shares the network namespace
+ // with its task, hence no need to enter it explicitly.
+ namespaces.push_back("mnt");
+ }
+
Try<Owned<health::HealthChecker>> _checker =
health::HealthChecker::create(
task->health_check(),
self(),
- task->task_id());
+ task->task_id(),
+ pid,
+ namespaces);
if (_checker.isError()) {
// TODO(gilbert): Consider ABORT and return a TASK_FAILED here.