Sobes.tech
Назад к вопросам
Senior
3

Как реализуется изоляция контейнеров на уровне ядра Linux? Расскажите подробнее про namespaces

Компании, где спрашивали
СБЕРСБЕР

Ответ от нейросети

sobes.tech AI

Изоляция контейнеров в Linux достигается с помощью механизма namespaces — это особенность ядра, которая позволяет создавать отдельные пространства имён для различных системных ресурсов. Каждый namespace изолирует определённый аспект окружения процесса, например:

  • PID namespace — изолирует идентификаторы процессов, так что процессы в одном namespace видят только свои PID.
  • Mount namespace — изолирует точки монтирования файловой системы, позволяя контейнеру иметь собственную файловую структуру.
  • Network namespace — изолирует сетевые интерфейсы и настройки, создавая отдельный сетевой стек.
  • UTS namespace — изолирует hostname и domain name.
  • IPC namespace — изолирует межпроцессное взаимодействие.
  • User namespace — изолирует идентификаторы пользователей и групп, позволяя контейнеру иметь свои UID/GID.

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

Пример создания нового PID namespace в Go с использованием syscall:

package main

import (
    "fmt"
    "syscall"
    "os"
)

func main() {
    cmd := os.Args[0]
    if len(os.Args) > 1 && os.Args[1] == "child" {
        fmt.Printf("[child] PID: %d\n", syscall.Getpid())
        select {} // ждем
    } else {
        fmt.Printf("[parent] PID: %d\n", syscall.Getpid())
        attr := &syscall.ProcAttr{
            Files: []uintptr{0, 1, 2},
            Sys: &syscall.SysProcAttr{
                Cloneflags: syscall.CLONE_NEWPID,
            },
        }
        pid, err := syscall.ForkExec(cmd, []string{cmd, "child"}, attr)
        if err != nil {
            panic(err)
        }
        fmt.Printf("Запущен процесс с новым PID namespace, PID: %d\n", pid)
    }
}

Этот пример демонстрирует создание процесса с новым PID namespace, где у дочернего процесса будет свой набор PID, изолированный от родительского пространства.