Pull to refresh

Comments 18

Distroless контенеры - поправьте заголовок пожалуйста

Сложно отлаживать. Нельзя просто зайти в shell на контейнере (на pod) и выполнить команды. Не конфиг посмотреть! Даже ps не сделать.

Достаточно получить PID процесса в контейнере, и в его пространствах имен можно запускать программы с хоста. Например, для Docker:


sudo nsenter -p -t $(docker inspect -f '{{ .State.Pid }}' $container) ps
sudo nsenter -n -t $(docker inspect -f '{{ .State.Pid }}' $container) ss -tnlp

Файлы контейнера доступны через /proc/$PID/root. Не очень актуально для distroless, но в обычных контейнерах так удобно редактировать файлы.

Спасибо! Отличная утилита. Я про нее не знал. Посмотрю поподробнее.

А ещё есть такая штука как Nix, с его помощью можно очень даже компактные контейнеры делать, причем с помощью кросскомпиляции, что довольно удобно, особенно на макоси.

Подéлитесь удачным опытом?


Если делать контейнер на базе NixOS, он получается не меньше и не факт, что безопаснее. Во-первых, пакеты деривации в nixpkgs не принято разбивать. Во-вторых, хотя в PATH не будет шелла, если его не попросить, он может быть подтянут в контейнер ради скрипта-обертки, которые в nixpkgs повсюду. Например, образ с clang и LLVM на базе Debian у меня получался около 900 МБ (и можно было чуть ужать), а с NixOS выходило около 1,5 ГБ. Можно было бы пересобирать зависимости, чтобы уменьшить размер, но это трудозатраты.

А я придумал как хитрить: ты собираешь nix-shell, в нем билдишь бинарь, а потом через nix-build вызываешь сборку образа, где указываешь прямую ссылку на получившийся бинарь и указываешь только самый минимальный набор зависимостей.
Вот у меня есть оверлей с багфиксами кросс-сборки и там есть пример, но немного корявый.
https://github.com/alekseysidorov/nixpkgs-cross-overlay/tree/main/examples/hello_world

Я лично думаю как найду время, оформлю это все красиво и поделюсь в виде статьи и руководства как этим пользоваться.

А еще там во многих деривациях таки есть разделение, ну типа openssl.dev, openssl.bin, openssl.lib.

Спасибо, хороший пример.


Отдельные outputs для dev, bin и lib — это не то же, что разбиение пакетов для минимизации зависимостей. Например, openssl.bin притащит за собой Perl ради скрипта c_rehash, а вот в Alpine скрипт разумно вынесли в другой пакет. Или DPDK, из десятков библиотек которого обычно нужна лишь малая часть, в nixpkgs сделан одной деривацией, а в Debian библиотеки вынесены в свои пакеты. Да, в nix подрихтовать деривации проще, чем пакеты в других дистрибутивах, но все равно надо разбираться в самой деривации и системе сборки, иногда выходит грязь.

Тем не менее, Distroless контейнеры далеко не всегда так безопасны, как кажутся. https://www.form3.tech/engineering/content/exploiting-distroless-images

Вот статья о методиках взлома контейнера от Google. Сам гугл не признает это уязвимостью и исправлять это не будет...

В двух словах, через openssl внутри контейнера можно подгружать любые пользовательские либы, которые будут выполнять код, недоступный вам изначально. В том числе и чтение нужных секретов из контейнера.

Да! Есть довольно много критики distroless именно в области безопасности. Скажем так нельзя считать их безопасными просто по факту.

Ссылка с методиками взлома контейнера для меня выглядит высосанной из пальца. Может я что не понимаю, но для доступа к openssl уже должна быть RCE в приложении или утечка доступа к exec контейнера - как при таких проблемах сможет помочь способ сборки image. На этот момент песенка уже спета, разве нет? Все что можно сделать - усложнить поиск payload, что и делает distroless подход

Сложно отлаживать. Нельзя просто зайти в shell на контейнере (на pod) и выполнить команды. Не конфиг посмотреть! Даже ps не сделать.

В версии кубера 1.25 выкатили - Ephemeral Containers. Как раз для дебага distroless based контейнеров в поде, с монтированием файловой системы etc etc. В ранних версиях куба, (1.23 проверял) можно активировать как future-feature.

Дебаг отдельная тема - достойна еще одной статьи ;).

Знать, что ты Совершенство, знать, что ты Идеал? Может просто обернуться к lxc?

Если говорить о .net, какие преимущества от контейнера можно получить в сравнении с обычным приложением опубликованным как self-hosted? В ряде случаев я могу понять удобство контейнеров (приложения на python или чем то подобном где так и не смогли победить проблему dll hell, а точнее package hell, или предподготовленные сборки со сложной конфигурацией). Но в случае .net, где нет проблем с версионностью библиотек, пока не могу найти ни одного плюса от них. По тестам, контейнеры еще и дают 2-5% падение производительности.

Чтобы четче обозначить, я сравниваю подход когда какой то инструмент публикует .net приложение просто в каталог и устанавливает в качестве службы, и подход когда это же приложение будет развернуто в контейнере. Интересует реальный профит который можно от этого получить.

Я думаю основной плюс контейнеризации это их оркестрация, разве нет? Сварм Кубер etc всё это очень удобно. CI/CD опять же проще. Сервис же он не один .net приложение, с ним может поставляться куча инфраструктуры

Достаточно написать FROM scratch в Dockerfile и мы получим абсолютно пустую файловую систему и сможем запустить свою программу без файлов вообще.

Есть у меня большие сомнения, что вы пробовали это сделать ))
А я попробовал - нужен как минимум линкер (без него docker жалуется, что ваш executable файл вообще не найден)
Если уже добавлен линкер, то тогда система будет уже вразумительно ругаться на отсуутсвующие dll-ки.

Вот пример моего минимального образа. Здесь minimal-hello - это c-шный hello-world собранный статически (вроде, судя по настройкам в Eclipse, но... мог здесь и налажать)

FROM scratch

ADD minimal-hello /

# linker
ADD sys_linux_root/lib64/ld-linux-x86-64.so.2 /lib64/

# Standard C lib
ADD sys_linux_root/usr/lib/x86_64-linux-gnu/libc.so.6 /usr/lib/x86_64-linux-gnu/

CMD ["./minimal-hello"]

А вот немножко больший образ

FROM scratch

ADD minimal-hello /

# optional
ADD sys_linux_root/bin/* /bin/

#
# Required for ANY minimal executables
#  * dynamic linker
ADD sys_linux_root/lib64/ld-linux-x86-64.so.2 /lib64/

# Standard C lib
ADD sys_linux_root/usr/lib/x86_64-linux-gnu/libc.so.6 /usr/lib/x86_64-linux-gnu/

# Additional libs fo ls/sh/bash
ADD sys_linux_root/usr/lib/x86_64-linux-gnu/* /usr/lib/x86_64-linux-gnu/

# Some data files
COPY hello.txt /
COPY hello.txt /hello-002.txt

CMD ["./minimal-hello"]

Содержимое моего sys_linux_root.
Здесь bash, cat, sleep, ls, sh просто, чтобы поиграться и дополнительные ddl-ки, нужные им или программам, которые делают хоть что-то полезное. Все эти файлы скопированы просто с моего текущего линукса.

.
├── bin
│   ├── bash
│   ├── cat
│   ├── ls
│   ├── sh
│   └── sleep
├── lib64
│   └── ld-linux-x86-64.so.2
└── usr
    └── lib
        └── x86_64-linux-gnu
            ├── libc.so.6
            ├── libdl.so.2
            ├── libpcre2-8.so.0
            ├── libpthread-2.31.so
            ├── libpthread.so
            ├── libpthread.so.0
            ├── libselinux.so.1
            └── libtinfo.so.6

Если кто-то умудрился сделать образ даже без линкера, то будет интересно послушать.

PS: Жду минусов, как обычно ))

Вы правы и про линкер и про меня! Проблема в том, что надо все библиотеки залинковать статически в бинарь. Примерно вот так:

FROM alpine AS build

WORKDIR /static

RUN apk add build-base

COPY hello.c .

RUN gcc -o hello --static hello.c

FROM scratch

COPY --from=build /static/hello /

CMD [ "/hello" ]

Тогда все заработает. В этом бинаре нет ни одного динамического символа, только syscall в ядро с которыми и работает докер.
Конечно мой пример супер прост как только вы например подключите стандартную библиотеку вам понадобится куча возможностей системы и с ними файлы конфигурации. Например /etc/passwd для определения текущего пользователя, сертификаты для web и тп.
При подготовки статьи я не проверял вся на c я проверил все только на go. Go умеет делать все статическим по этому там такое сильно проще. Чтобы не проверять пример я нашел его в интернете: https://github.com/jeremyhuiskamp/golang-docker-scratch/blob/main/Dockerfile обратите внимание на 14 строку там копируются сертификаты .
Спасибо за вопрос!

Sign up to leave a comment.

Articles