containerPort в манифесте — это документация, а не контроль. Kubernetes его не проверяет: контейнер может слушать порты, которых в YAML нет, и наоборот. Ровно на этом разрыве между декларацией и реальностью построена работа «
Inside Job: Defending Kubernetes Clusters Against Network Misconfigurations».
Они прогнали 287 публичных Helm-чартов от Bitnami, Banzai Cloud, CNCF, Prometheus Community через связку статического анализа YAML и рантайм-наблюдения в живом кластере. Нашли 634 проблемы у 90% приложений:
- 241 — нет никаких NetworkPolicy
- 188 — порт открыт, но не задекларирован (привет, админские и debug-интерфейсы)
- 67 — порт задекларирован, но не открыт: приходит кто-то другой и занимает его
- 35 — контейнер слушает эфемерный порт, который меняется при каждом старте (и никакая политика по портам его не покроет)
- 52 — коллизии лейблов, когда чужой Pod попадает под селектор вашего Service, а трафик уезжает не туда
Список самых грязных чартов бьет по узнаваемости: kube-prometheus-stack, kube-prometheus, clickhouse, istio-operator, grafana-tempo, zookeeper, jaeger, metallb, node-exporter. То есть ровно то, что стоит у половины читателей канала, причем зачастую в системных неймспейсах. У всей десятки лидеров нет NetworkPolicy и есть незадекларированные порты, 9 из 10 сидят в hostNetwork (а на него, напомним, NetworkPolicy и не действует), 4 из 10 слушают эфемерные порты.
Отдельно они сравнили себя с 11 инструментами — Checkov, KubeLinter, kube-score, kubesec, kubeaudit, Kubescape, Trivy, NeuVector, StackRox и т.д. Статические не видят рассинхрон декларации и реальности
в принципе, потому что смотрят только в YAML, а рантайм- и платформенные решения его просто не ищут. И самое неприятное: коллизии лейблов сами разработчики оценили как наиболее критичную находку — это готовый MITM внутри кластера.