ooooo        ooooo ooooo      ooo ooooo     ooo ooooooo  ooooo   .oooooo.   ooooooooo.   
     `888'        `888' `888b.     `8' `888'     `8'  `8888    d8'   d8P'  `Y8b  `888   `Y88. 
      888          888   8 `88b.    8   888       8     Y888..8P    888      888  888   .d88' 
      888          888   8   `88b.  8   888       8      `8888'     888      888  888ooo88P'  
      888          888   8     `88b.8   888       8     .8PY888.    888      888  888`88b.    
      888       o  888   8       `888   `88.    .8'    d8'  `888b   `88b    d88'  888  `88b.  
     o888ooooood8 o888o o8o        `8     `YbodP'    o888o  o88888o  `Y8bood8P'  o888o  o888o 

Úvod do menných priestorov v OS Linux

FILE: 2016-linux-namespaces-intro.md
DATE: 11/2016
UPDATED:
AUTHOR: Ladislav Hajzer -> lala (at) linuxor (dot) sk
VERSION: 1

1 Základné pojmy menných priestorov v OS Linux (Linux namespaces)

Menné priestory (namespaces) v operačnom systemé Linux slúžia na oddelenie/izoláciu prevádzkovaných programov/procesov. Oddelenie/izolácia umožnuje programu/procesu mať iný/rozdielny pohľad na systém resp. systemové prostriedky ako ostatné programy/procesy. Menné priestory môžu byť použité na rôzne účely, ale hlavne použitie našli v implementácií kontajnerizačných technológií. Prvé menné priestory (MNT namespace) boli do jadra pridané už v roku 2002. Najnovším prírastkom (2016) v Linux-ovom jadre sú menné priestory pre riadiace skupiny (CGROUP namespace). Aktuálne je v Linux-ovom jadre implementovaných nasledovných 7 menných priestorov.

+-----------+------------------+---------+-------+-----------------------+-------------------------------------+
| Namespace | Clone Flag       | Kernel  | Rok   | Vyzadovane schopnosti | Izoluje                             |
|           |                  |         |       | capabilities          |                                     |
+-----------+------------------+---------+-------+-----------------------+-------------------------------------+
| MNT       | CLONE_NEWNS      | 2.4.19  | 2002  | CAP_SYS_ADMIN         | Mount points                        |
| UTS       | CLONE_NEWUTS     | 2.6.19  | 2006  | CAP_SYS_ADMIN         | Hostname and NIS domain name        |
| PID       | CLONE_NEWPID     | 2.6.24  | 2008  | CAP_SYS_ADMIN         | Process IDs                         |
| NET       | CLONE_NEWNET     | 2.6.29  | 2009  | CAP_SYS_ADMIN         | Network devices, stacks, ports, ... |
| IPC       | CLONE_NEWIPC     | 2.6.30  | 2009  | CAP_SYS_ADMIN         | System V IPC, POSIX message queues  |
| USER      | CLONE_NEWUSER    | 3.8     | 2013  | Nie su vyzadovane     | User and group IDs                  |
| CGROUP    | CLONE_NEWCGROUP  | 4.6     | 2016  | CAP_SYS_ADMIN         | Cgroup root directory               |
+-----------+------------------+---------+-------+-----------------------+-------------------------------------+

Uvažované, ale zatiaľ neimplementované menné priestory sú nasledovné:
- Security namespace
- Security keys namespace
- Device namespace
- Time namespace

REF: 2006 - Multiple Instances of the Global Linux Namespaces

1.1 Základný popis a účel jednotlivých menných priestorov

  • Menný priestor MNT (Mount points and filesystems namespace)
    Slúži na izoláciu prípojných bodov, ktoré vidí proces alebo skupina procesov takže programy/procesy v rozdielnych MNT menných priestoroch môžu mať rozdielny pohľad na hierarchiu súborového systému. Táto izolácia je podobná izolácii, ktorú umožnuje systemové volanie "chroot()" s tým rozdielom, že MNT menný priestor by mal byť na tieto účely bezpečnejšou a flexibilnejšou voľbou.

  • Menný priestor UTS (UNIX Time-sharing System namespace)
    Slúži na izoláciu dvoch systémových identifikátorov a to názov servera (nodename/hostname) a názov domény (domainname), ktoré vracia systemové volanie "uname()".

  • Menné priestor PID (Process identifier namespace)
    Slúži na izoláciu identifikačných čísiel procesov (PID=Proces IDentifier). Programy/procesy, ktoré sa nachádzajú v rozdielnych PID menných priestoroch môžu mať rovnaký identifikátor procesu (rovnaké PID číslo).

  • Menné priestor NET (Network stack namespace)
    Slúži na izoláciu sieťových systémových prostriedkov. Každý sieťový menný priestor má svoje sieťové zariadenia/adaptéry, IP adresy, smerovacie tabuľky, čísla portov a vlastný adresár "/proc/net".

  • Menné priestor IPC (Interprocess communication namespace)
    Slúži na izoláciu IPC zdrojov, konkrétne System V IPC objekty a POSIX fronty sprav (POSIX message queues). Každý IPC menný priestor disponuje vlastnou sadou System V IPC identifikátorov a vlastnou sadou POSIX front správ.

  • Menný priestor USER (Users and groups namespace)
    Slúži na izoláciu užívateľských (UID) a skupinových (GID) identifikátorov. Umožnuje, aby UID a GID identifikátory boli rozdielne vo vnútri menného priestoru a mimo neho. Čiže vo vnútri menného priestoru sa može pouzívať jedna sada UID a GID identifikátorov a mimo menného priestoru sa používa druhá/iná sada UID a GID identifikátorov.

  • Menný priestor CGROUP (Cgroup root directory)
    Slúži na izoláciu riadiacich skupín (control groups) pre program/proces. Každý CGROUP menné priestor disponuje vlastným koreňovým cgroup adresárom (cgroup root directory).

1.2 API menných priestorov

API menných priestorov pozostáva z troch systémových volaní:

  • clone()
    Slúži na vytváranie nového procesu v novom mennom priestore. Jedná sa o všeobecnejšiu verziu systémového volania "fork()", pričom funkcionalita je riadená pomocou argumentu "flags".

  • "unshare()"
    Slúži na vytváranie nového menného priestoru, ale nevytvára nový proces. Existujúci program/proces priradí do nového menného priestoru. Hlavným účelom tohoto systémového volania je umožniť programu/procesu riadiť kontext zdieľania bez vytvárania nového procesu.

  • "setns()"
    Slúži na zmenu menného priestoru pre program/proces. Inými slovami toto systémove volanie umožnuje deasociovat program/proces z jednej inštancie konkrétneho typu menného priestoru (napr. z MNT menného priestoru) a reasociovať ho s inou inštanciou toho istého typu menného priestoru, čiže "presun" programu/procesu z MNT menného priestoru X do MNT menného priestoru Y.

2 Práca s mennými priestormi v OS Linux (Linux namespaces) - default namespaces

Preveríme aké menné priestory sú priradené Linux INIT procesu (init alebo systemd proces). Tieto menné priestory sú predvolené/default. Využívajú ich všetky procesy, viď. príklad SSHD servera nižšie, ktorým nie sú priradené špecifické priestory.

# ls -lh /proc/1/ns/
----------------------------------------------------------------------------------------------------------------
lrwxrwxrwx. 1 root root 0 Nov  8 09:54 ipc -> ipc:[4026531839]
lrwxrwxrwx. 1 root root 0 Nov  8 09:54 mnt -> mnt:[4026531840]
lrwxrwxrwx. 1 root root 0 Nov  8 09:54 net -> net:[4026531956]
lrwxrwxrwx. 1 root root 0 Nov  8 09:54 pid -> pid:[4026531836]
lrwxrwxrwx. 1 root root 0 Nov  8 09:54 user -> user:[4026531837]
lrwxrwxrwx. 1 root root 0 Nov  8 09:54 uts -> uts:[4026531838]

Preveríme aké menné priestory sú priradené Linux SSHD procesu ($SSHD_PID). Zistíme si PID sshd procesu a vypíšeme zoznam priradených menných priestorov pre tento proces/PID.

# SSHD_PID=`ps xa | grep -m 1 /usr/sbin/sshd | awk '{print $1}'`; ls -lh /proc/$SSHD_PID/ns/
----------------------------------------------------------------------------------------------------------------
lrwxrwxrwx. 1 root root 0 Nov  8 10:04 ipc -> ipc:[4026531839]
lrwxrwxrwx. 1 root root 0 Nov  8 10:04 mnt -> mnt:[4026531840]
lrwxrwxrwx. 1 root root 0 Nov  8 10:04 net -> net:[4026531956]
lrwxrwxrwx. 1 root root 0 Nov  8 10:04 pid -> pid:[4026531836]
lrwxrwxrwx. 1 root root 0 Nov  8 10:04 user -> user:[4026531837]
lrwxrwxrwx. 1 root root 0 Nov  8 10:04 uts -> uts:[4026531838]

3 Predstavenie nástroja "namespaces-info.sh"

Počas štúdia menných priestorov som vytvoril jednoduchý nástroj/skript pre príkazový interpreter BASH s názvom "namespaces-info.sh". Umožnuje vypísať základné informácie o menných priestoroch. Samotný skrip je umiestnený na GitHub portále -> github - bash-namespaces-info

Syntax skriptu "bash-namespaces-info.sh" je nasledovná:

-d      Vypíše systémove/default (parent) menné priestory
-a      Vypíše zoznam všetkých menných priestorov pre všetky procesy (PIDs)
-n      Vypíše zoznam nesystémových/nondefault menných priestorov pre všetky procesy (PIDs)
-p PID  Vypíše zoznam menných priestorov pre proces (PID)
-v      Vypíše verziu skriptu

Príklad spustenia skriptu "namespaces-info.sh" s prepínačom "-d".

# /root/namespaces-info.sh -d
--------------- + --------------------------
Linux Namespace | System default namespaces
--------------- + --------------------------
IPC  namespace  | ipc:[4026531839]
MNT  namespace  | mnt:[4026531840]
NET  namespace  | net:[4026531956]
PID  namespace  | pid:[4026531836]
USER namespace  | user:[4026531837]
UTS  namespace  | uts:[4026531838]
--------------- + --------------------------

Príklad spustenia skriptu "namespaces-info.sh" s prepínačom "-a".

# /root/namespaces-info.sh -a
---------- + ---------- + -------------------- + -------- + ----------------------------------------
PID        | PPID       | NAMESPACE            | DEFAULT  | COMMAND
---------- + ---------- + -------------------- + -------- + ----------------------------------------
1          |      0     | ipc:[4026531839]     | YES      | /usr/lib/systemd/systemd --switched-root
1          |      0     | mnt:[4026531840]     | YES      | /usr/lib/systemd/systemd --switched-root
1          |      0     | net:[4026531956]     | YES      | /usr/lib/systemd/systemd --switched-root
1          |      0     | pid:[4026531836]     | YES      | /usr/lib/systemd/systemd --switched-root
1          |      0     | user:[4026531837]    | YES      | /usr/lib/systemd/systemd --switched-root
1          |      0     | uts:[4026531838]     | YES      | /usr/lib/systemd/systemd --switched-root
---------- + ---------- + -------------------- + -------- + ----------------------------------------
2          |      0     | ipc:[4026531839]     | YES      | [kthreadd]
2          |      0     | mnt:[4026531840]     | YES      | [kthreadd]
2          |      0     | net:[4026531956]     | YES      | [kthreadd]
2          |      0     | pid:[4026531836]     | YES      | [kthreadd]
2          |      0     | user:[4026531837]    | YES      | [kthreadd]
2          |      0     | uts:[4026531838]     | YES      | [kthreadd]
---------- + ---------- + -------------------- + -------- + ----------------------------------------

Príklad spustenia skriptu "namespaces-info.sh" s prepínačom "-n".

# /root/namespaces-info.sh -n
---------- + ---------- + -------------------- + -------- + ----------------------------------------
PID        | PPID       | NAMESPACE            | DEFAULT  | COMMAND
---------- + ---------- + -------------------- + -------- + ----------------------------------------
18         |      2     | mnt:[4026531856]     | NO       | [kdevtmpfs]
---------- + ---------- + -------------------- + -------- + ----------------------------------------
582        |      1     | mnt:[4026532423]     | NO       | /usr/lib/systemd/systemd-udevd
---------- + ---------- + -------------------- + -------- + ----------------------------------------
718        |      1     | mnt:[4026532450]     | NO       | /usr/bin/vmtoolsd
---------- + ---------- + -------------------- + -------- + ----------------------------------------
750        |      1     | mnt:[4026532451]     | NO       | /usr/sbin/NetworkManager --no-daemon
---------- + ---------- + -------------------- + -------- + ----------------------------------------
9870       |    750     | mnt:[4026532451]     | NO       | /sbin/dhclient -d -q -sf /usr/libexec/nm
---------- + ---------- + -------------------- + -------- + ----------------------------------------
72966      |   9926     | mnt:[4026532578]     | NO       | bash
72966      |   9926     | net:[4026532452]     | NO       | bash
---------- + ---------- + -------------------- + -------- + ----------------------------------------
72975      |   9945     | mnt:[4026532579]     | NO       | bash
72975      |   9945     | net:[4026532510]     | NO       | bash
---------- + ---------- + -------------------- + -------- + ----------------------------------------

Príklad spustenia skriptu "namespaces-info.sh" s prepínačom "-p".

# /root/lh-ns.sh -p 72975
---------- + ---------- + -------------------- + -------- + ----------------------------------------
PID        | PPID       | NAMESPACE            | DEFAULT  | COMMAND
---------- + ---------- + -------------------- + -------- + ----------------------------------------
72975      |   9945     | ipc:[4026531839]     | YES      | bash
72975      |   9945     | mnt:[4026532579]     | NO       | bash
72975      |   9945     | net:[4026532510]     | NO       | bash
72975      |   9945     | pid:[4026531836]     | YES      | bash
72975      |   9945     | user:[4026531837]    | YES      | bash
72975      |   9945     | uts:[4026531838]     | YES      | bash
---------- + ---------- + -------------------- + -------- + ----------------------------------------