Легко захватить сетевой трафик с помощью инструмента захвата (например, tcpdump), если у нас есть доступ к сетевому интерфейсу.
Но в Kubernetes это непросто.
Есть несколько вариантов, например: контейнер sidecar, плагин захвата, контейнер docker, прямой доступ в том же пространстве имен.
Управляемые Kubernetes имеют усиленную конфигурацию безопасности, поэтому в зависимости от наших возможностей доступа и прав на кластер, приведенные ниже примеры могут работать (если есть возможность доступа к ОС ноды, если контейнер разрешен для запуска от имени root и т.д.).
Приведенные ниже примеры протестированы на кластере K8s на базе VM.
Инструменты
В большинстве случаев контейнер, в котором будет перехватываться сетевой трафик, конечно же, не содержит никаких инструментов захвата.
Часть альтернативных вариантов использует новый контейнер, который содержит инструменты захвата сети.
Классный образ Docker – https://github.com/nicolaka/netshoot, который содержит несколько сетевых инструментов, например: tcpdump, tshark, termshark, iptraf-ng.
Параметры будут выполняться как команда, например:
sudo docker run -it --rm --net container:k8s_nginx_my-nginx-b7d7bc74d-zxx28_default_ae4ee834-fb5d-4ec4-86b1-7834e538c666_0 nicolaka/netshoot tcpdump -i eth0 -s 0 -Xvv tcp port 80
Tcpdump может перенаправлять захваченные пакеты в stdout, который можно сохранить или использовать, например, на хосте:
tcpdump -i eth0 -s 0 -w - >/tmp/container.cap tcpdump -i eth0 -s 0 -w - | wireshark -k -i -
Параметр -v /tmp:/tmp/tmp может быть полезен в тех случаях, если перехваченные пакеты записываются в файл внутри контейнера.
Есть несколько инструментов перехвата, для которых нужно больше прав (tshark, termshark), например, в docker запустить CLI : –cap-add=NET_ADMIN –cap-add=CAP_NET_RAW .
И, наконец, целый пример с наличием оболочки для запуска такого рода инструментов:
sudo docker run -it --rm -v /tmp:/tmp/tmp --cap-add=NET_ADMIN --cap-add=CAP_NET_RAW --net container:k8s_nginx_my-nginx-b7d7bc74d-zxx28_default_ae4ee834-fb5d-4ec4-86b1-7834e538c666_0 nicolaka/netshoottermshark
Прямой доступ к ноде K8s
Это самая безобидная ситуация, потому что нам не нужно трогать кластер K8s.
Во-первых, мы должны знать имя контейнера Docker и место, на котором он запущен, например:
kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES my-nginx-b7d7bc74d-zxx28 1/1 Running 0 10m 10.244.2.2 node2 <none> <none>
vagrant ssh node2
sudo docker ps | grep my-nginx-b7d7bc74d-zxx28
f22ab3b7130b nginx "/docker-entrypoint.…" 39 minutes ago Up 39 minutes k8s_nginx_my-nginx-b7d7bc74d-zxx28_default_ae4ee834-fb5d-4ec4-86b1-7834e538c666_0 62c7cacd66c1 k8s.gcr.io/pause:3.2 "/pause" 3 9 minutes ago Up 39 minutes k8s_POD_my-nginx-b7d7bc74d-zxx28_default_ae4ee834-fb5d-4ec4-86b1-7834e538c666_0
Перехват с помощью контейнера nicolaka/netshoot
Контейнер nicolaka/netshoot должен быть запущен в том же сетевом пространстве имен (задается командой –net container: ):
sudo docker run -it --rm --net container:k8s_nginx_my-nginx-b7d7bc74d-zxx28_default_ae4ee835d-4ec4-86b1-7834e538c666_0 nicolaka/netshoot tcpdump -i eth0 -s 0 -Xvv tcp port 80
Захват в сетевом пространстве имен контейнера
Docker использует сетевые пространства имен ядра Linux для изоляции контейнеров.
Имея root-доступ, его можно использовать для перехвата трафика:
sudo docker inspect --format '{{ .State.Pid }}' k8s_nginx_my-nginx-b7d7bc74d-zxx28_default_ae4ee834-fb5d-4ec4-86b1-7834e538c666_0 sudo nsenter -t 17900 -n /bin/bash -xec 'ip a; tcpdump -i eth0 -s 0 -Xvv tcp port 80'
Можно передавать захваченные tcpdump пакеты в Wireshark, см. пример скрипта для удаленного захвата в реальном времени на
https://github.com/pgillich/kubeadm-vagrant/blob/master/Ubuntu/capture_pod.sh.
Пример использования (имя контейнера необязательно):
./capture_pod.sh default my-nginx-596d59c679-9t4vp nginx
Перехват с помощью ksniff
kubectl sniff loki-0 -v -n monitoring -p -r /data/sniff/loki-0.cap | wireshark -k -i -
Захват трафика в контейнере
kubectl cp tcpdump my-nginx-596d59c679-9t4vp:/tmp; kubectl exec -t my-nginx-596d59c679-9t4vp -- /tmp/tcpdump -i eth0 -s 0 -w - | wireshark -k -i -
./capture_in_pod.sh default my-nginx-596d59c679-9t4vp nginx
Дополнительный контейнер в том же поде
kubectl edit deployment my-nginxspec: (...) template: (...) spec: containers: - command: - /bin/sleep - infinity image: nicolaka/netshoot name: netshoot - image: nginx:latest imagePullPolicy: Always name: nginx resources: {} terminationMessagePath: /dev/termination-log terminationMessagePolicy: File
kubectl exec my-nginx-7bc9465bb9-lqnwd -ti -c netshoot -- /bin/bash
- https://speedscale.com/2020/07/16/capturing-network-traffic-during-container-startup/
- https://kubernetes.io/docs/concepts/storage/volumes/#emptydir-configuration-example
Эфемерные отладочные контейнеры
kubectl debug -it my-nginx-b7d7bc74d-7t7nr -c netshoot --target=nginx --image=nicolaka/netshoot --image-pull-policy=IfNotPresent -- /bin/bash
kubectl get --raw /api/v1/namespaces/default/pods/my-nginx-b7d7bc74d-7t7nr/ephemeralcontainers | jq{ "kind": "EphemeralContainers", "apiVersion": "v1", "metadata": { "name": "my-nginx-b7d7bc74d-7t7nr", "namespace": "default", "uid": "5363a259-411a-4658-9384-d136ce9b6519", "resourceVersion": "2893", "creationTimestamp": "2020-12-27T18:56:18Z" }, "ephemeralContainers": [ { "name": "netshoot", "image": "nicolaka/netshoot", "command": [ "/bin/bash" ], "resources": {}, "terminationMessagePath": "/dev/termination-log", "terminationMessagePolicy": "File", "imagePullPolicy": "IfNotPresent", "stdin": true, "tty": true, "targetContainerName": "nginx" } ] }