Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Контейнерные змеи.

Контейнерные змеи.

Николай Марков (Principal Architect в Aligned Research Group). @Moscow Python Meetup №81
Кажется, мы уже все привыкли работать с контейнерами, но до сих пор у текущих имплементаций контейнерных рантаймов был фатальный недостаток — они написаны не на Python. Попробуем это исправить?

Видео: https://moscowpython.ru/meetup/81/container-snakes/

MoscowPython: http://moscowpython.ru
Курсы Learn Python: http://learn.python.ru
Moscow Python Podcast: http://podcast.python.ru
Заявки на доклады: https://bit.ly/mp-speaker

Moscow Python Meetup
PRO

March 23, 2023
Tweet

More Decks by Moscow Python Meetup

Other Decks in Programming

Transcript

  1. Контейнерные змеи
    что делать, если хочется иметь
    свой Docker
    Николай Марков, 2023

    View Slide

  2. • Занимаюсь профессиональной разработкой
    и проектированием уже больше 11 лет
    • Начинал программистом на Python, сейчас Principal
    Architect в компании Aligned Research Group, а также
    ментор в компании DryLabs
    • В разное время работал с сетями, протоколами
    и различными облаками (AWS, GCP, Azure, OpenStack)
    • Писал проекты на Python, а также Golang, C/C++, Scala
    и Rust
    • Сейчас выстраиваю архитектуры работы
    с данными в разных компаниях

    View Slide

  3. Containers from Scratch
    Liz Rice - Chief Open Source Officer at
    Isovalent | Emeritus chair, Technical
    Oversight Committee at CNCF

    View Slide

  4. А внутре у ней неонка
    Про runc
    Про containerd
    ~$ runc

    View Slide

  5. Докер не нужен

    View Slide

  6. Рантаймы
    https://github.com/opencontainers/runtime-spec
    https://github.com/opencontainers/runtime-spec/blob/main/implementations.md
    На самом деле “образы контейнеров Docker” не имеют отношения к
    Docker, это образы в формате OCI

    View Slide

  7. Namespaces
    Chroot
    Cgroups
    Кишки контейнера

    View Slide

  8. Hostname, PID, filesystem

    View Slide

  9. 1. import argparse
    2. import subprocess
    3.
    4.
    5. def run(*args):
    6. subprocess.run(*args)
    7.
    8.
    9. if __name__ == "__main__":
    10. parser = argparse.ArgumentParser()
    11. parser.add_argument('action', type=str, help="action to
    perform")
    12. args, other = parser.parse_known_args()
    13. if args.action == "run":
    14. run(*other)
    15. else:
    16. parser.print_help()

    View Slide

  10. clone()
    unshare()
    unshare
    (program)
    Клонируем

    View Slide

  11. 1. import os
    2. import ctypes
    3. import ctypes.util
    4.
    5.
    6. libc = ctypes.CDLL(ctypes.util.find_library("c"), use_errno=True)
    7.
    8.
    9. def unshare(flags):
    10. _unshare = libc.unshare
    11. _unshare.restype = ctypes.c_int
    12. _unshare.argtypes = (ctypes.c_int, )
    13.
    14. if _unshare(flags) == -1:
    15. print("Error in unshare:" , os.strerror(ctypes.get_errno()))
    16. return False
    17. return True

    View Slide

  12. 1. CLONE_NEWUTS = 0x04000000
    2.
    3.
    4. def run(*args):
    5. unshare(CLONE_NEWUTS)
    6. subprocess.run(args)
    Мам, гляди, у меня свой хостнейм!

    View Slide

  13. 1. CLONE_NEWUTS = 0x04000000
    2.
    3.
    4. def run(*args):
    5. unshare(CLONE_NEWUTS)
    6. socket.sethostname("container")
    7. subprocess.run(args)

    View Slide

  14. Хочу свой PID!
    1. def run(*args):
    2. unshare(CLONE_NEWUTS | CLONE_NEWPID
    )
    3. subprocess.run(["/proc/self/exe"
    , sys.argv[0], "child", *args])
    4.
    5.
    6. def child(*args):
    7. socket.sethostname("container")
    8. print(os.getpid())
    9. subprocess.run(args)
    10.
    11.
    12. if __name__ == "__main__":
    13. parser = argparse.ArgumentParser()
    14. parser.add_argument('action', type=str, help="action to perform"
    )
    15. args, other = parser.parse_known_args()
    16. if args.action == "run":
    17. run(*other)
    18. elif args.action == "child":
    19. child(*other)
    20. else:
    21. parser.print_help()

    View Slide

  15. Почти работает

    View Slide

  16. У меня будет своя файловая система
    ● Нам нужна файловая система /proc
    ● Да и вообще просто нормальная
    файловая система, чоужтам
    ~$ docker export bbbc09817a7f > ubuntu.tar
    chroot()

    View Slide

  17. Хоть чрут в питоне есть!
    1. def child(*args):
    2. socket.sethostname("container")
    3. os.chroot(os.path.join(os.getcwd(), "fakeroot"))
    4. os.chdir("/")
    5. subprocess.run(args)

    View Slide

  18. 1. def mount(source, target, fs, flags, options):
    2. _mount = libc.mount
    3. _mount.argtypes = (
    4. ctypes. c_char_p,
    5. ctypes. c_char_p,
    6. ctypes. c_char_p,
    7. ctypes. c_ulong,
    8. ctypes. c_char_p
    9. )
    10. if _mount(
    11. source. encode(),
    12. target. encode(),
    13. fs. encode(),
    14. flags ,
    15. options. encode()
    16. ) == -1:
    17. print("Error in mount:" , os.strerror(ctypes.get_errno()))
    18. return False
    19. return True
    mount()
    С mount() и umount()!

    View Slide

  19. С mount() и umount()!
    umount2()
    1. def umount(target, flags):
    2. _umount = libc.umount2
    3. _umount.argtypes = (ctypes.c_char_p, ctypes.c_int)
    4. if _umount(target.encode(), flags) == -1:
    5. print("Error in umount:"
    , os.strerror(ctypes.get_errno()))
    6. return False
    7. return True

    View Slide

  20. С mount() и umount()!
    1. def child(*args):
    2. socket.sethostname( "container" )
    3. os.chroot(os.path.join(os.getcwd(), "fakeroot"))
    4. os.chdir("/")
    5. mount("proc", "/proc", "proc", 0, "")
    6. subprocess.run(args)
    7. umount("/proc", 0)
    Кто считает, что теперь ps
    заработает?

    View Slide

  21. С mount() и umount()!
    1. def child(*args):
    2. socket.sethostname( "container" )
    3. os.chroot(os.path.join(os.getcwd(), "fakeroot"))
    4. os.chdir("/")
    5. mount("proc", "/proc", "proc", 0, "")
    6. subprocess.run(args)
    7. umount("/proc", 0)

    View Slide

  22. cgroups v2

    View Slide

  23. А чо там в докере?

    View Slide

  24. Как работают лимиты
    Перезапустим
    Закрываем, трясем, смотрим

    View Slide

  25. Вопросы?

    View Slide