@cryptotaxi247 / netdata-1 / commits / 8008029a2

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>

K900 committed Aug 19, 2020 at 08:44 UTC 8008029a2f0b56e3c9cc47c5d379b20151055d1e
2 files changed +58 -21
collectors/cgroups.plugin/README.md
+9 -1
@@ -105,7 +105,15 @@ For this mapping Netdata provides 2 configuration options:
105
106 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.
107
108 -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.
108 +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.
109 +
110 +#### Note on Podman container names
111 +
112 +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.
113 +
114 +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).
115 +
116 +[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.
117
118 ### charts with zero metrics
119
collectors/cgroups.plugin/cgroup-name.sh.in
+49 -20
@@ -45,34 +45,34 @@ fatal() {
45 exit 1
46 }
47
48 -function docker_get_name_classic() {
49 - local id="${1}"
50 - info "Running command: docker ps --filter=id=\"${id}\" --format=\"{{.Names}}\""
51 - NAME="$(docker ps --filter=id="${id}" --format="{{.Names}}")"
48 +function docker_like_get_name_command() {
49 + local command="${1}"
50 + local id="${2}"
51 + info "Running command: ${command} ps --filter=id=\"${id}\" --format=\"{{.Names}}\""
52 + NAME="$(${command} ps --filter=id="${id}" --format="{{.Names}}")"
53 return 0
54 }
55
55 -function docker_get_name_api() {
56 - local path="/containers/${1}/json"
57 - if [ -z "${DOCKER_HOST}" ]; then
58 - warning "No DOCKER_HOST is set"
56 +function docker_like_get_name_api() {
57 + local host_var="${1}"
58 + local host="${!host_var}"
59 + local path="/containers/${2}/json"
60 + if [ -z "${host}" ]; then
61 + warning "No ${host_var} is set"
62 return 1
63 fi
64 if ! command -v jq >/dev/null 2>&1; then
62 - 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"
65 + 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"
66 return 1
67 fi
65 - if [ -S "${DOCKER_HOST}" ]; then
66 - info "Running API command: curl --unix-socket ${DOCKER_HOST} http://localhost${path}"
67 - JSON=$(curl -sS --unix-socket "${DOCKER_HOST}" "http://localhost${path}")
68 - elif [ "${DOCKER_HOST}" == "/var/run/docker.sock" ]; then
69 - warning "Docker socket was not found at ${DOCKER_HOST}"
70 - return 1
68 + if [ -S "${host}" ]; then
69 + info "Running API command: curl --unix-socket \"${host}\" http://localhost${path}"
70 + JSON=$(curl -sS --unix-socket "${host}" "http://localhost${path}")
71 else
72 - info "Running API command: curl ${DOCKER_HOST}${path}"
73 - JSON=$(curl -sS "${DOCKER_HOST}${path}")
72 + info "Running API command: curl \"${host}${path}\""
73 + JSON=$(curl -sS "${host}${path}")
74 fi
75 - NAME=$(echo "$JSON" | jq -r .Name,.Config.Hostname | grep -v null | head -n1 | sed 's|^/||')
75 + NAME=$(echo "${JSON}" | jq -r .Name,.Config.Hostname | grep -v null | head -n1 | sed 's|^/||')
76 return 0
77 }
78
@@ -126,9 +126,9 @@ function k8s_get_name() {
126 function docker_get_name() {
127 local id="${1}"
128 if hash docker 2>/dev/null; then
129 - docker_get_name_classic "${id}"
129 + docker_like_get_name_command docker "${id}"
130 else
131 - docker_get_name_api "${id}" || docker_get_name_classic "${id}"
131 + docker_like_get_name_api DOCKER_HOST "${id}" || docker_like_get_name_command podman "${id}"
132 fi
133 if [ -z "${NAME}" ]; then
134 warning "cannot find the name of docker container '${id}'"
@@ -148,6 +148,30 @@ function docker_validate_id() {
148 fi
149 }
150
151 +function podman_get_name() {
152 + local id="${1}"
153 +
154 + # for Podman, prefer using the API if we can, as netdata will not normally have access
155 + # to other users' containers, so they will not be visible when running `podman ps`
156 + docker_like_get_name_api PODMAN_HOST "${id}" || docker_like_get_name_command podman "${id}"
157 +
158 + if [ -z "${NAME}" ]; then
159 + warning "cannot find the name of podman container '${id}'"
160 + NAME_NOT_FOUND=2
161 + NAME="${id:0:12}"
162 + else
163 + info "podman container '${id}' is named '${NAME}'"
164 + fi
165 +}
166 +
167 +function podman_validate_id() {
168 + local id="${1}"
169 + if [ -n "${id}" ] && [ ${#id} -eq 64 ]; then
170 + podman_get_name "${id}"
171 + else
172 + error "a podman id cannot be extracted from docker cgroup '${CGROUP}'."
173 + fi
174 +}
175
176 # -----------------------------------------------------------------------------
177
@@ -155,6 +179,7 @@ function docker_validate_id() {
179 [ -z "${NETDATA_STOCK_CONFIG_DIR}" ] && NETDATA_STOCK_CONFIG_DIR="@libconfigdir_POST@"
180
181 DOCKER_HOST="${DOCKER_HOST:=/var/run/docker.sock}"
182 +PODMAN_HOST="${PODMAN_HOST:=/run/podman/podman.sock}"
183 CGROUP="${1}"
184 NAME_NOT_FOUND=0
185 NAME=
@@ -195,6 +220,10 @@ if [ -z "${NAME}" ]; then
220 #shellcheck disable=SC1117
221 DOCKERID="$(echo "${CGROUP}" | sed "s|^.*ecs[-_/].*[-_/]\([a-fA-F0-9]\+\)[-_\.]\?.*$|\1|")"
222 docker_validate_id "${DOCKERID}"
223 + elif [[ ${CGROUP} =~ ^.*libpod-[a-fA-F0-9]+.*$ ]]; then
224 + # Podman
225 + PODMANID="$(echo "${CGROUP}" | sed "s|^.*libpod-\([a-fA-F0-9]\+\).*$|\1|")"
226 + podman_validate_id "${PODMANID}"
227
228 elif [[ ${CGROUP} =~ machine.slice[_/].*\.service ]]; then
229 # systemd-nspawn