summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorK900 <me@0upti.me>2020-08-19 08:44:04 +0300
committerGitHub <noreply@github.com>2020-08-19 15:44:04 +1000
commit8008029a2f0b56e3c9cc47c5d379b20151055d1e (patch)
tree8f79558f7a63f6cb525aff8d9a2c09ba166f4dd0
parente3f918aadbe77033efdf62234aaec26ef401abe1 (diff)
cgroups.plugin: add and document support for reading container names from Podman (#9474)
* cgroups.plugin: support reading container names from podman This is, unfortunately, not functional out of the box due to Podman's security model. * cgroups.plugin: document podman support and required configuration * Apply suggestions from code review Co-authored-by: Joel Hans <joel.g.hans@gmail.com> Co-authored-by: Joel Hans <joel.g.hans@gmail.com>
-rw-r--r--collectors/cgroups.plugin/README.md10
-rwxr-xr-xcollectors/cgroups.plugin/cgroup-name.sh.in69
2 files changed, 58 insertions, 21 deletions
diff --git a/collectors/cgroups.plugin/README.md b/collectors/cgroups.plugin/README.md
index a2dc876490..853c0f5946 100644
--- a/collectors/cgroups.plugin/README.md
+++ b/collectors/cgroups.plugin/README.md
@@ -105,7 +105,15 @@ For this mapping Netdata provides 2 configuration options:
The whole point for the additional pattern list, is to limit the number of times the script will be called. Without this pattern list, the script might be called thousands of times, depending on the number of cgroups available in the system.
-The above pattern list is matched against the path of the cgroup. For matched cgroups, Netdata calls the script [cgroup-name.sh](https://raw.githubusercontent.com/netdata/netdata/master/collectors/cgroups.plugin/cgroup-name.sh.in) to get its name. This script queries `docker`, or applies heuristics to find give a name for the cgroup.
+The above pattern list is matched against the path of the cgroup. For matched cgroups, Netdata calls the script [cgroup-name.sh](https://raw.githubusercontent.com/netdata/netdata/master/collectors/cgroups.plugin/cgroup-name.sh.in) to get its name. This script queries `docker`, `kubectl`, `podman`, or applies heuristics to find give a name for the cgroup.
+
+#### Note on Podman container names
+
+Podman's security model is a lot more restrictive than Docker's, so Netdata will not be able to detect container names out of the box unless they were started by the same user as Netdata itself.
+
+If Podman is used in "rootful" mode, it's also possible to use `podman system service` to grant Netdata access to container names. To do this, ensure `podman system service` is running and Netdata has access to `/run/podman/podman.sock` (the default permissions as specified by upstream are `0600`, with owner `root`, so you will have to adjust the configuration).
+
+[docker-socket-proxy](https://github.com/Tecnativa/docker-socket-proxy) can also be used to give Netdata restricted access to the socket. Note that `PODMAN_HOST` in Netdata's environment should be set to the proxy's URL in this case.
### charts with zero metrics
diff --git a/collectors/cgroups.plugin/cgroup-name.sh.in b/collectors/cgroups.plugin/cgroup-name.sh.in
index 5d19014f41..12022f4659 100755
--- a/collectors/cgroups.plugin/cgroup-name.sh.in
+++ b/collectors/cgroups.plugin/cgroup-name.sh.in
@@ -45,34 +45,34 @@ fatal() {
exit 1
}
-function docker_get_name_classic() {
- local id="${1}"
- info "Running command: docker ps --filter=id=\"${id}\" --format=\"{{.Names}}\""
- NAME="$(docker ps --filter=id="${id}" --format="{{.Names}}")"
+function docker_like_get_name_command() {
+ local command="${1}"
+ local id="${2}"
+ info "Running command: ${command} ps --filter=id=\"${id}\" --format=\"{{.Names}}\""
+ NAME="$(${command} ps --filter=id="${id}" --format="{{.Names}}")"
return 0
}
-function docker_get_name_api() {
- local path="/containers/${1}/json"
- if [ -z "${DOCKER_HOST}" ]; then
- warning "No DOCKER_HOST is set"
+function docker_like_get_name_api() {
+ local host_var="${1}"
+ local host="${!host_var}"
+ local path="/containers/${2}/json"
+ if [ -z "${host}" ]; then
+ warning "No ${host_var} is set"
return 1
fi
if ! command -v jq >/dev/null 2>&1; then
- warning "Can't find jq command line tool. jq is required for netdata to retrieve docker container name using ${DOCKER_HOST} API, falling back to docker ps"
+ warning "Can't find jq command line tool. jq is required for netdata to retrieve container name using ${host} API, falling back to docker ps"
return 1
fi
- if [ -S "${DOCKER_HOST}" ]; then
- info "Running API command: curl --unix-socket ${DOCKER_HOST} http://localhost${path}"
- JSON=$(curl -sS --unix-socket "${DOCKER_HOST}" "http://localhost${path}")
- elif [ "${DOCKER_HOST}" == "/var/run/docker.sock" ]; then
- warning "Docker socket was not found at ${DOCKER_HOST}"
- return 1
+ if [ -S "${host}" ]; then
+ info "Running API command: curl --unix-socket \"${host}\" http://localhost${path}"
+ JSON=$(curl -sS --unix-socket "${host}" "http://localhost${path}")
else
- info "Running API command: curl ${DOCKER_HOST}${path}"
- JSON=$(curl -sS "${DOCKER_HOST}${path}")
+ info "Running API command: curl \"${host}${path}\""
+ JSON=$(curl -sS "${host}${path}")
fi
- NAME=$(echo "$JSON" | jq -r .Name,.Config.Hostname | grep -v null | head -n1 | sed 's|^/||')
+ NAME=$(echo "${JSON}" | jq -r .Name,.Config.Hostname | grep -v null | head -n1 | sed 's|^/||')
return 0
}
@@ -126,9 +126,9 @@ function k8s_get_name() {
function docker_get_name() {
local id="${1}"
if hash docker 2>/dev/null; then
- docker_get_name_classic "${id}"
+ docker_like_get_name_command docker "${id}"
else
- docker_get_name_api "${id}" || docker_get_name_classic "${id}"
+ docker_like_get_name_api DOCKER_HOST "${id}" || docker_like_get_name_command podman "${id}"
fi
if [ -z "${NAME}" ]; then
warning "cannot find the name of docker container '${id}'"
@@ -148,6 +148,30 @@ function docker_validate_id() {
fi
}
+function podman_get_name() {
+ local id="${1}"
+
+ # for Podman, prefer using the API if we can, as netdata will not normally have access
+ # to other users' containers, so they will not be visible when running `podman ps`
+ docker_like_get_name_api PODMAN_HOST "${id}" || docker_like_get_name_command podman "${id}"
+
+ if [ -z "${NAME}" ]; then
+ warning "cannot find the name of podman container '${id}'"
+ NAME_NOT_FOUND=2
+ NAME="${id:0:12}"
+ else
+ info "podman container '${id}' is named '${NAME}'"
+ fi
+}
+
+function podman_validate_id() {
+ local id="${1}"
+ if [ -n "${id}" ] && [ ${#id} -eq 64 ]; then
+ podman_get_name "${id}"
+ else
+ error "a podman id cannot be extracted from docker cgroup '${CGROUP}'."
+ fi
+}
# -----------------------------------------------------------------------------
@@ -155,6 +179,7 @@ function docker_validate_id() {
[ -z "${NETDATA_STOCK_CONFIG_DIR}" ] && NETDATA_STOCK_CONFIG_DIR="@libconfigdir_POST@"
DOCKER_HOST="${DOCKER_HOST:=/var/run/docker.sock}"
+PODMAN_HOST="${PODMAN_HOST:=/run/podman/podman.sock}"
CGROUP="${1}"
NAME_NOT_FOUND=0
NAME=
@@ -195,6 +220,10 @@ if [ -z "${NAME}" ]; then
#shellcheck disable=SC1117
DOCKERID="$(echo "${CGROUP}" | sed "s|^.*ecs[-_/].*[-_/]\([a-fA-F0-9]\+\)[-_\.]\?.*$|\1|")"
docker_validate_id "${DOCKERID}"
+ elif [[ ${CGROUP} =~ ^.*libpod-[a-fA-F0-9]+.*$ ]]; then
+ # Podman
+ PODMANID="$(echo "${CGROUP}" | sed "s|^.*libpod-\([a-fA-F0-9]\+\).*$|\1|")"
+ podman_validate_id "${PODMANID}"
elif [[ ${CGROUP} =~ machine.slice[_/].*\.service ]]; then
# systemd-nspawn