Jeder der sich mit sicheren Containern beschäftigt ist vermutlich schon über den einen oder anderen Artikel gestolpert der berechtigterweise empfiehlt eine der folgenden minimalen Baseimages zu verwenden
Nach einigen Versuchen hast Du es sicher geschafft Deine Anwendung mit einem der Baseimages zum Laufen zu bringen und die neue Anwendung in Produktion zu deployen.
Irgendwann geht aber was schief. Deine Anwendung funktioniert nicht mehr und Du befindest Dich im Blindflug. Die Story die Anwendung mit OpenTelementry zu instrumentieren hast Du noch nicht begonnen. Um die Anwendung zu debuggen oder weitere Informationen zu entlocken benötigst Du eine Shell in den Container. Jedoch grüßt dich eine Fehlermeldung und keine Shell.
docker exec -it proxy /bin/sh
OCI runtime exec failed: exec failed: unable to start container process: exec: "/bin/sh": stat /bin/sh: no such file or directory: unknown
Als Beispiel starten wir einen nginx basierend auf einem minimalen Image das keine Shell enthält
docker run --rm --name secure-web -d abdennour/nginx-distroless-unprivileged
Wenn wir nun versuchen eine Shell in diesen Conainer zu erhalten bekommen wir eine Fehlermeldung
docker exec -it secure-web /bin/sh
OCI runtime exec failed: exec failed: unable to start container process: exec: "/bin/sh": stat /bin/sh: no such file or directory: unknown
Bestens. Jetzt können wir eine Lösung dafür bauen
Auch wenn wir keine Shell in den Container bekommen können wir diesen mit einem Sidecar Container debuggen. Eine Sidecar Container ist nichts anderes als ein Container der seine Resourcen mit einem anderen Container teilt. Du frägst dich jetzt bestimmt welche Resourcen das sind? Prozess-ID (PID) und Netzwerk hautptsächlich.
In Kubernetes läuft ein Sidecar Container im gleichen Pod wie ein anderer Container. In diesem Beispiel verwenden wir keine Kubernetes aber wir können trotzdem einen Sidecar Container erstellen und diesen an die Resourcen des Applikaktionscontainer binden.
Dafür nehmen wir eine Ubuntu Container und binden diesen an die gleiche Prozess-ID und das gleiche Netzwerk wie unser Nginx Container.
docker run --rm -it --pid container:secure-web \
--network container:secure-web \
--cap-add=SYS_PTRACE \
--security-opt seccomp=unconfined ubuntu:latest
Die Option --pid
gibt den PID Namespace an der benutzt werden soll.
Die Optionen --cap-add
und --security-opt
sind notwendig damit das Kommando strace
funktioniert. Dieses Kommando gibt alle Systemcalls aus. Das kann bei der Fehlersuche hilfreich sein.
Danach installieren wir noch ein paar Debuggingtools
apt update && apt install -y iproute2 file strace
Diese können wir nun benutzen.
Wir können uns die Liste aller Prozesse anzeigen
root@49a834bc2851:/# ps -ef
UID PID PPID C STIME TTY TIME CMD
1001 1 0 0 19:59 ? 00:00:00 nginx: master process nginx -g daemon off;
1001 6 1 0 19:59 ? 00:00:00 nginx: worker process
root 13 0 0 20:08 pts/0 00:00:00 /bin/bash
root 388 13 0 20:10 pts/0 00:00:00 ps -ef
Mit strace können wir uns nun auch auf einen der laufenden Prozesse aus dem anderen Container connecten
root@49a834bc2851:/# strace -p 6
strace: Process 6 attached
epoll_pwait(8,
Auch das Dateisystem des anderen Container können wir untersuchen
root@49a834bc2851:/# cat /proc/1/root/usr/share/nginx/html/index.html
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
Dies ist eine elegante Möglichkeit um mit einer Shell auf einen bestehenden Container zuzugreifen, bei dem das eigentlich nicht vorgesehen wurde. Das Beste an dieser Vorgehensweise ist das wir keine Änderungen an dem bestehenden Image vornehmen müssen. Sobald wir mit der Fehlersuche fertig sind, können wir den Sidecar Container entfernen und hinterlassen keine Spuren oder Nebeneffekte.