Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Start tracking k8s liveness probes #1320

Merged
merged 2 commits into from
Jun 14, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
104 changes: 80 additions & 24 deletions userspace/libsinsp/container.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ limitations under the License.

*/

#include <algorithm>

#include "container_engine/cri.h"
#include "container_engine/docker.h"
#include "container_engine/rkt.h"
Expand Down Expand Up @@ -131,8 +133,8 @@ bool sinsp_container_manager::resolve_container(sinsp_threadinfo* tinfo, bool qu
}
}

// Also identify if this thread is part of a container healthcheck
identify_healthcheck(tinfo);
// Also possibly set the category for the threadinfo
identify_category(tinfo);

return matches;
}
Expand Down Expand Up @@ -169,10 +171,7 @@ string sinsp_container_manager::container_to_json(const sinsp_container_info& co

container["Mounts"] = mounts;

if(!container_info.m_healthcheck_obj.isNull())
{
container["Healthcheck"] = container_info.m_healthcheck_obj;
}
sinsp_container_info::container_health_probe::add_health_probes(container_info.m_health_probes, container);

char addrbuff[100];
uint32_t iph = htonl(container_info.m_container_ip);
Expand Down Expand Up @@ -356,15 +355,10 @@ string sinsp_container_manager::get_container_name(sinsp_threadinfo* tinfo)
return res;
}

void sinsp_container_manager::identify_healthcheck(sinsp_threadinfo *tinfo)
void sinsp_container_manager::identify_category(sinsp_threadinfo *tinfo)
{
// This thread is a part of a container healthcheck if its
// parent thread is part of a health check.
sinsp_threadinfo* ptinfo = tinfo->get_parent_thread();

if(ptinfo && ptinfo->m_is_container_healthcheck)
if(tinfo->m_container_id.empty())
{
tinfo->m_is_container_healthcheck = true;
return;
}

Expand All @@ -375,23 +369,65 @@ void sinsp_container_manager::identify_healthcheck(sinsp_threadinfo *tinfo)
return;
}

// Otherwise, the thread is a part of a container healthcheck if:
if(tinfo->m_vpid == 1)
{
if(g_logger.get_severity() >= sinsp_logger::SEV_DEBUG)
{
g_logger.format(sinsp_logger::SEV_DEBUG,
"identify_category (%ld) (%s): initial process for container, assigning CAT_CONTAINER",
tinfo->m_tid, tinfo->m_comm.c_str());
}

tinfo->m_category = sinsp_threadinfo::CAT_CONTAINER;

return;
}

// Categories are passed from parent to child threads
sinsp_threadinfo* ptinfo = tinfo->get_parent_thread();

if(ptinfo && ptinfo->m_category != sinsp_threadinfo::CAT_NONE)
{
if(g_logger.get_severity() >= sinsp_logger::SEV_DEBUG)
{
g_logger.format(sinsp_logger::SEV_DEBUG,
"identify_category (%ld) (%s): taking parent category %d",
tinfo->m_tid, tinfo->m_comm.c_str(), ptinfo->m_category);
}

tinfo->m_category = ptinfo->m_category;
return;
}

if(!cinfo->m_metadata_complete)
{
if(g_logger.get_severity() >= sinsp_logger::SEV_DEBUG)
{
g_logger.format(sinsp_logger::SEV_DEBUG,
"identify_category (%ld) (%s): container metadata incomplete",
tinfo->m_tid, tinfo->m_comm.c_str());
}
mstemm marked this conversation as resolved.
Show resolved Hide resolved

return;
}

// Otherwise, the thread is a part of a container health probe if:
//
// 1. the comm and args match the container's healthcheck
// 1. the comm and args match one of the container's health probes
// 2. we traverse the parent state and do *not* find vpid=1,
// or find a process not in a container
//
// This indicates the initial process of the healthcheck.
// This indicates the initial process of the health probe.

if(!cinfo->m_has_healthcheck ||
cinfo->m_healthcheck_exe != tinfo->m_exe ||
cinfo->m_healthcheck_args != tinfo->m_args)
{
return;
}
sinsp_container_info::container_health_probe::probe_type ptype =
cinfo->match_health_probe(tinfo);

if(tinfo->m_vpid == 1)
if(ptype == sinsp_container_info::container_health_probe::PT_NONE)
{
g_logger.format(sinsp_logger::SEV_DEBUG,
"identify_category (%ld) (%s): container health probe PT_NONE",
tinfo->m_tid, tinfo->m_comm.c_str());

return;
}

Expand All @@ -413,7 +449,27 @@ void sinsp_container_manager::identify_healthcheck(sinsp_threadinfo *tinfo)

if(!found_container_init)
{
tinfo->m_is_container_healthcheck = true;
g_logger.format(sinsp_logger::SEV_DEBUG,
"identify_category (%ld) (%s): not under container init, assigning category %s",
tinfo->m_tid, tinfo->m_comm.c_str(),
sinsp_container_info::container_health_probe::probe_type_names[ptype].c_str());

// Each health probe type maps to a command category
switch(ptype)
{
case sinsp_container_info::container_health_probe::PT_NONE:
case sinsp_container_info::container_health_probe::PT_END:
break;
case sinsp_container_info::container_health_probe::PT_HEALTHCHECK:
tinfo->m_category = sinsp_threadinfo::CAT_HEALTHCHECK;
break;
case sinsp_container_info::container_health_probe::PT_LIVENESS_PROBE:
tinfo->m_category = sinsp_threadinfo::CAT_LIVENESS_PROBE;
break;
case sinsp_container_info::container_health_probe::PT_READINESS_PROBE:
tinfo->m_category = sinsp_threadinfo::CAT_READINESS_PROBE;
break;
}
}
}

Expand Down
9 changes: 4 additions & 5 deletions userspace/libsinsp/container.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,11 @@ class sinsp_container_manager
void dump_containers(scap_dumper_t* dumper);
string get_container_name(sinsp_threadinfo* tinfo);

// Set tinfo's is_container_healthcheck attribute to true if
// it is identified as a container healthcheck. It will *not*
// set it to false by default, so a threadinfo that is
// initially identified as a health check will remain one
// Set tinfo's m_category based on the container context. It
// will *not* change any category to NONE, so a threadinfo
// that initially has a category will retain its category
// across execs e.g. "sh -c /bin/true" execing /bin/true.
void identify_healthcheck(sinsp_threadinfo *tinfo);
void identify_category(sinsp_threadinfo *tinfo);

bool container_exists(const string& container_id) const {
return m_containers.find(container_id) != m_containers.end();
Expand Down
1 change: 0 additions & 1 deletion userspace/libsinsp/container_engine/cri.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ limitations under the License.
#include <stdint.h>

class sinsp_container_manager;
class sinsp_container_info;
class sinsp_threadinfo;

#include "container_engine/container_engine.h"
Expand Down
24 changes: 24 additions & 0 deletions userspace/libsinsp/container_engine/docker.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,30 @@ class docker_async_source : public sysdig::async_key_value_source<std::string, c

bool parse_docker(std::string &container_id, sinsp_container_info *container);

// Look for a pod specification in this container's labels and
// if found set spec to the pod spec.
bool get_k8s_pod_spec(const Json::Value &config_obj,
Json::Value &spec);

std::string normalize_arg(const std::string &arg);

// Parse a healthcheck out of the provided healthcheck object,
// updating the container info with any healthcheck found.
void parse_healthcheck(const Json::Value &healthcheck_obj,
sinsp_container_info *container);

// Parse either a readiness or liveness probe out of the
// provided object, updating the container info with any probe
// found.
bool parse_liveness_readiness_probe(const Json::Value &probe_obj,
sinsp_container_info::container_health_probe::probe_type ptype,
sinsp_container_info *container);

// Parse all healthchecks/liveness probes/readiness probes out
// of the provided object, updating the container info as required.
void parse_health_probes(const Json::Value &config_obj,
sinsp_container_info *container);

sinsp *m_inspector;

std::string m_docker_unix_socket_path;
Expand Down
Loading