Skip to content

Commit

Permalink
Fetch missing CRIO metadata from additional API queries
Browse files Browse the repository at this point in the history
While containerd returns everything in the `info` dictionary,
it's empty for CRIO, which means we need to get the IP address
and the image ID from extra API calls.

Unfortunately, it seems there's no way to get:
* environment variables
* privileged status
* resource limits
in any way from CRIO.
  • Loading branch information
gnosek committed Feb 20, 2019
1 parent 52c61bb commit 3c330d9
Show file tree
Hide file tree
Showing 3 changed files with 119 additions and 22 deletions.
59 changes: 37 additions & 22 deletions userspace/libsinsp/container_engine/cri.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,35 @@ using namespace libsinsp::container_engine;
using namespace libsinsp::runc;

namespace {
bool parse_containerd(const runtime::v1alpha2::ContainerStatusResponse& status, sinsp_container_info *container, sinsp_threadinfo *tinfo)
{
const auto &info_it = status.info().find("info");
if(info_it == status.info().end())
{
return false;
}

Json::Value root;
Json::Reader reader;
if(!reader.parse(info_it->second, root))
{
ASSERT(false);
return false;
}

parse_cri_env(root, container);
parse_cri_json_image(root, container);
parse_cri_runtime_spec(root, container);

if(root.isMember("sandboxID") && root["sandboxID"].isString())
{
const auto pod_sandbox_id = root["sandboxID"].asString();
container->m_container_ip = ntohl(get_pod_sandbox_ip(pod_sandbox_id));
}

return true;
}

bool parse_cri(sinsp_container_manager *manager, sinsp_container_info *container, sinsp_threadinfo *tinfo)
{
if(!s_cri)
Expand Down Expand Up @@ -80,29 +109,13 @@ bool parse_cri(sinsp_container_manager *manager, sinsp_container_info *container
parse_cri_image(resp_container, container);
parse_cri_mounts(resp_container, container);

const auto &info_it = resp.info().find("info");
if(info_it == resp.info().end())
{
ASSERT(false);
return false;
}
Json::Value root;
Json::Reader reader;
if(!reader.parse(info_it->second, root))
if(parse_containerd(resp, container, tinfo))
{
ASSERT(false);
return false;
return true;
}

parse_cri_env(root, container);
parse_cri_json_image(root, container);
parse_cri_runtime_spec(root, container);

if(root.isMember("sandboxID") && root["sandboxID"].isString())
{
const auto pod_sandbox_id = root["sandboxID"].asString();
container->m_container_ip = ntohl(get_pod_sandbox_ip(pod_sandbox_id));
}
container->m_container_ip = get_container_ip(container->m_id);
container->m_imageid = get_container_image_id(resp_container.image_ref());

return true;
}
Expand All @@ -128,8 +141,9 @@ cri::cri()
return;
}

s_cri = runtime::v1alpha2::RuntimeService::NewStub(
grpc::CreateChannel("unix://" + cri_path, grpc::InsecureChannelCredentials()));
auto channel = grpc::CreateChannel("unix://" + cri_path, grpc::InsecureChannelCredentials());
s_cri = runtime::v1alpha2::RuntimeService::NewStub(channel);
s_cri_image = runtime::v1alpha2::ImageService::NewStub(channel);

runtime::v1alpha2::VersionRequest vreq;
runtime::v1alpha2::VersionResponse vresp;
Expand All @@ -156,6 +170,7 @@ cri::cri()
void cri::cleanup()
{
s_cri.reset(nullptr);
s_cri_image.reset(nullptr);
}

void cri::set_cri_socket_path(const std::string& path)
Expand Down
77 changes: 77 additions & 0 deletions userspace/libsinsp/cri.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,25 @@ limitations under the License.

#include "cri.h"

#include <chrono>
#include <grpc++/grpc++.h>

#include "sinsp.h"
#include "sinsp_int.h"

namespace {
bool pod_uses_host_netns(const runtime::v1alpha2::PodSandboxStatusResponse& resp)
{
const auto netns = resp.status().linux().namespaces().options().network();
return netns == runtime::v1alpha2::NODE;
}
}

namespace libsinsp {
namespace cri {
std::string s_cri_unix_socket_path = "/run/containerd/containerd.sock";
std::unique_ptr <runtime::v1alpha2::RuntimeService::Stub> s_cri = nullptr;
std::unique_ptr <runtime::v1alpha2::ImageService::Stub> s_cri_image = nullptr;
int64_t s_cri_timeout = 1000;
sinsp_container_type s_cri_runtime_type = CT_CRI;

Expand Down Expand Up @@ -259,6 +271,11 @@ uint32_t get_pod_sandbox_ip(const std::string &pod_sandbox_id)
return 0;
}

if(pod_uses_host_netns(resp))
{
return 0;
}

const auto &pod_ip = resp.status().network().ip();
if(pod_ip.empty())
{
Expand All @@ -275,5 +292,65 @@ uint32_t get_pod_sandbox_ip(const std::string &pod_sandbox_id)
return ip;
}
}

uint32_t get_container_ip(const std::string &container_id)
{
runtime::v1alpha2::ListContainersRequest req;
runtime::v1alpha2::ListContainersResponse resp;
auto filter = req.mutable_filter();
filter->set_id(container_id);
grpc::ClientContext context;
auto deadline = std::chrono::system_clock::now() + std::chrono::milliseconds(s_cri_timeout);
context.set_deadline(deadline);
grpc::Status lstatus = s_cri->ListContainers(&context, req, &resp);

switch(resp.containers_size())
{
case 0:
g_logger.format(sinsp_logger::SEV_WARNING, "Container id %s not in list from CRI", container_id.c_str());
ASSERT(false);
break;
case 1: {
const auto& cri_container = resp.containers(0);
return ntohl(get_pod_sandbox_ip(cri_container.pod_sandbox_id()));
}
default:
g_logger.format(sinsp_logger::SEV_WARNING, "Container id %s matches more than once in list from CRI", container_id.c_str());
ASSERT(false);
break;
}
return 0;
}

std::string get_container_image_id(const std::string &image_ref)
{
runtime::v1alpha2::ListImagesRequest req;
runtime::v1alpha2::ListImagesResponse resp;
auto filter = req.mutable_filter();
auto spec = filter->mutable_image();
spec->set_image(image_ref);
grpc::ClientContext context;
auto deadline = std::chrono::system_clock::now() + std::chrono::milliseconds(s_cri_timeout);
context.set_deadline(deadline);
grpc::Status status = s_cri_image->ListImages(&context, req, &resp);

switch(resp.images_size())
{
case 0:
g_logger.format(sinsp_logger::SEV_WARNING, "Image ref %s not in list from CRI", image_ref.c_str());
ASSERT(false);
break;
case 1: {
const auto& image = resp.images(0);
return image.id();
}
default:
g_logger.format(sinsp_logger::SEV_WARNING, "Image ref %s matches more than once in list from CRI", image_ref.c_str());
ASSERT(false);
break;
}

return "";
}
}
}
5 changes: 5 additions & 0 deletions userspace/libsinsp/cri.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ namespace libsinsp {
namespace cri {
extern std::string s_cri_unix_socket_path;
extern std::unique_ptr<runtime::v1alpha2::RuntimeService::Stub> s_cri;
extern std::unique_ptr<runtime::v1alpha2::ImageService::Stub> s_cri_image;
extern int64_t s_cri_timeout;
extern sinsp_container_type s_cri_runtime_type;

Expand All @@ -49,5 +50,9 @@ bool parse_cri_runtime_spec(const Json::Value &info, sinsp_container_info *conta
bool is_pod_sandbox(const std::string &container_id);

uint32_t get_pod_sandbox_ip(const std::string &pod_sandbox_id);

uint32_t get_container_ip(const std::string &container_id);

std::string get_container_image_id(const std::string &image_ref);
}
}

0 comments on commit 3c330d9

Please sign in to comment.