Hello, {{username}}
Я DevOps и очень люблю Linux. Понятное дело, что с такой связкой я просто не мог не полюбить LinuX Containers (тем более, что BSD и Solaris давно радуют аналогичными возможностями своих пользователей).
Естественно, бизнес тоже увидел привлекательную возможность и программы для управления контейнерами стали расти и множиться: docker , rocket, vagga, lxc, systemd-nspawn, etc…
Docker стал стандартом де-факто в первую очередь благодаря системе создания и доставки контента. Но главный демон докера запускается от root, и, на мой взгляд, это минус этого проекта (Пруф).
Rocket и vagga пошли другим путем, и путь этот носит название unprivileged containers. Вам больше не нужны root привилегии, чтобы запустить процесс в новых namespaces, и это открывает интересные перспективы для построения тестовых площадок и безопасного окружения.
Но во всех этих проектах есть один фатальный недостаток: они все написаны с использованием c, go и rust, а я люблю python и не могу поучаствовать в их разработке. Согласитесь, довольно обидно пропускать все веселье.
Так что под катом вас ждет библиотека для запуска процессов в новых linux user namespaces:
Pyspaces
Детка, Ты просто космос
Goals
Сейчас нет удобного способа работать с linux namespaces из python:
- можно использовать asylum — проект выглядит мертвым и хостится непонятно где
- или можно попробовать python-libvirt биндинги с большим уровнем абстракции
- использовать код на c, как это делают vagga и lxc
- или дергать glibc вызовы с помощью ctypes
- в противном случае остается subprocess.Popen
Я хочу изменить это: я хочу создать native python bindings к билбиотеке glibc с интерфейсом как в multiprocessing.Process. И еще немножко целей:
- популяризировать linux
- популяризировать python
- поучаствовать в создании популярного open source проекта
- прославиться
- популярность и девушки будут приятным бонусом
ЗЫ: так же посмотрите на python-nsenter — выглядит здорово!
Example
import os
from pyspaces import Container
def execute(argv):
os.execvp(argv[0], argv)
cmd = "mount -t proc proc /proc; ps ax"
c = Container(target=execute, args=(('bash', '-c', cmd),),
uid_map='0 1000 1',
newpid=True, newuser=True, newns=True
)
c.start()
print("PID of child created by clone() is %ld\n" % c.pid)
c.join()
print("Child returned: pid %s, status %s" % (c.pid, c.exitcode))
PID of child created by clone() is 15978
PID TTY STAT TIME COMMAND
1 pts/19 S+ 0:00 bash -c mount -t proc proc /proc; ps ax
3 pts/19 R+ 0:00 ps ax
Child returned: pid 15978, status 0
CLI
space -v execute --pid --fs --user --uid '0 1000 1' bash -c 'mount -t proc /proc; ps ax'
space chroot --pid --uid '0 1000 1' ~/.local/share/lxc/ubuntu/rootfs/ /bin/ls /home/
TODO
- [x] clone & Container
- [x] CLI
- [x] Chroot
- [ ] process list
- [ ] inject
- [ ] move CLI to separate package
- [ ] addons
- [ ] support for lxc, vagga, rocket, docker, etc...
- [ ] ...
- [ ] one tool for rule them all!!1
Links
Лицензия — MIT, но так же собираюсь добавить BSD и Apache 2.0
It's not the end
Работы предстоит очень много: нужны нормальные тесты, документация, новые фичи и приятное cli. Откладывание анонса в долгий ящик прервали ребята из Minsk Python Meetup, за что им большое спасибо. Теперь я надеюсь на поддержку и интерес у сообщества ;)
И в завершение хотелось бы привести цитату создателя scipy & numpy:
Keys to success: Hard work — specially up front
Often lonely — initially nobody believes in your idea more than you do. Others need some 'proof' before they join you.
The more complicated what you are doing is the lonelier it will be initially.
I spent 18 months not publishing papers to write NumPy
(despite many people telling me it was foolish)
Travis Oliphant
ЗЫ: в живую со мной можно пообщаться по теме и не только на очередном Minsk Python Meetup
Комментарии (7)
estum
27.04.2015 03:37-5Реализация на интерпретируемом языке в любом случае проиграет скомпилированной в производительности, что, как мне кажется, довольно критично для контейнеров.
Klukonin
27.04.2015 08:08+5Производительность самого контейнера весьма слабо зависит от обертки. Будь она на питоне, на си или другом языке.
amarao
27.04.2015 13:39+3Если бы вы знали, как медленно современные ядра работают на большом числе интерфейсов/адресов в системе… Любой питон по сравнению со скоростью соответствующего кода на Си, работающего с правами ядра, будет просто летать.
Не верите?
for a in {{1..255}};do for b in {{1..255}}; do time ip a a 172.16.$b.$a/32 dev eth0;done;done
и любуйтесь цифрами через пол-часика. Одинокое «повесить IP на интерфейс» до 30 с доходить будет.
amarao
А я namespaces юзаю «as is», из баша. Для локальных нужд хватает за глаза и за уши. Тем паче, что чаще всего нужно всего лишь mount namespace и network namespace, а всякие изоляции pid'ов и пользователей — постольку-поскольку.
MrFrizzy Автор
А что именно дергаете, если не секрет?
amarao
Чаще всего нужно изолировать приложение по сети.
ip net create foo
ip link set netns foo dev eth3
ip net exec foo ip link set up dev eth3
ip net exec foo ip a a 192.168.2.2/24
ip net exec foo ip route add default via 192.168.2.1
Ну и вариации по вкусу.
Mount/user/pid namespaces нужны много реже, потому что большинство приложений отлично вкурсе, что не их собачье дело, под каким пользователем их запустили и какие mountpoint'ы в системе.
Так что следующее:
ip net exec foo sudo -u APP_USER /usr/bin/app
и приложение работает.
Если надо залогиниться:
ip net exec foo login -f APP_USER
ValdikSS
А если нужна изоляция не только сети, то:
И просто мой любимый firejail