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

March 23, 2023
Tweet

More Decks by Moscow Python Meetup

Other Decks in Programming

Transcript

  1. • Занимаюсь профессиональной разработкой и проектированием уже больше 11 лет

    • Начинал программистом на Python, сейчас Principal Architect в компании Aligned Research Group, а также ментор в компании DryLabs • В разное время работал с сетями, протоколами и различными облаками (AWS, GCP, Azure, OpenStack) • Писал проекты на Python, а также Golang, C/C++, Scala и Rust • Сейчас выстраиваю архитектуры работы с данными в разных компаниях
  2. Containers from Scratch Liz Rice - Chief Open Source Officer

    at Isovalent | Emeritus chair, Technical Oversight Committee at CNCF
  3. 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()
  4. 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
  5. 1. CLONE_NEWUTS = 0x04000000 2. 3. 4. def run(*args): 5.

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

    unshare(CLONE_NEWUTS) 6. socket.sethostname("container") 7. subprocess.run(args)
  7. Хочу свой 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()
  8. У меня будет своя файловая система • Нам нужна файловая

    система /proc • Да и вообще просто нормальная файловая система, чоужтам ~$ docker export bbbc09817a7f > ubuntu.tar chroot()
  9. Хоть чрут в питоне есть! 1. def child(*args): 2. socket.sethostname("container")

    3. os.chroot(os.path.join(os.getcwd(), "fakeroot")) 4. os.chdir("/") 5. subprocess.run(args)
  10. 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()!
  11. С 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
  12. С 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 заработает?
  13. С 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)