Kubernetes/Architecture

Linux Namespaces

Operation CWAL 2021. 2. 2. 21:28

Namespace는 프로그래밍 언어 외에 다양한 컴퓨팅 분야에 널리 사용되는 개념이다. 하나의 namespace 안에서 이름과 개체(또는 자원)은 1:1로 매칭된다. 일반적인 정의는 다음과 같다.

In computing, a namespace is a set of signs(names) that are used to identify and refer to objects of various kinds. A namespace ensures that all of a given set of objects have unique names so that they can be easily 
identified. - Wikipedia

 

예를 들어, C++, Java와 같은 프로그래밍 언어에서는 동일한 Namespace 안에서 중복된 이름의 변수나 함수를 가질 순 없지만 서로 다른 Namespace 간에는 동일한 이름의 변수나 함수가 존재하며 이들은 메모리상에서 서로 다른 주소를 가르킨다. OS 역시 이와 동일한 개념의 namespace를 사용하며, 우리가 생각하는 것보다 오래된 역사를 가지고 있다. 1980년대 중반부터 2000년대 초반까지 존재했던 Bell 연구소의 Plan-9이라는 분산 OS에서 먼저 시작하였으며, 이 개념은 Linux도 2002년 2.4.19 커널부터 처음 적용되었다.

 

Linux의 Namespace 정의

  • 커널 리소스(네트워크, Filesystem 등)을 별도의 독립된 환경에서 사용할 수 있는 Linux 커널 기능
  • namespace는 하나 이상의 프로세스 그리고 리소스들의 집합으로 구성된다
  • 하나의 리소스는 동시에 여러개의 namespace에 존재할 수 있다

그렇다면 우리가 왜 Linux Namespace를 이해해야 할까? 그것은 Namespace가 Container 기술의 중요한 근간 중 하나이기 때문이다. 예를 들어 우리가 'docker run' 명령어를 통해 container를 생성하고 그 안에 들어가보면, 네트워크 인터페이스, 라우트 테이블, Filesystem 등이 Host와는 전혀 다른 환경으로 이루어진 것을 바로 확인할 수 있다. 그리고 Host에서 이미 사용중인 port를 container 안에서 사용하더라도 충돌하지 않는건, 네트워크와 관련된 Namespace가 다르기 때문에 서로 영향을 주지 않기 때문이다. 이렇듯, Container Runtime은 container를 생성할 때 별도의 namespace들을 할당 후 ENTRYPOINT 또는 CMD로 지정된 명령어를 실행함으로써, 격리된 환경의 프로세스를 제공한다. 

해당 프로세스는 자신에게 배정된 Namespace에 존재하는 리소스(CPU, 메모리, Disk)에 대해서만 접근이 가능할 뿐, 격리되었다는 사실을 알 수 없다.

 

Linux에서 제공하는 Namespace

현재 Kernel 5.6 기준으로 다음과 같은 namespace가 존재한다.

 

IPC Namespace

  • Process의 보안을 위한 Namespace
  • UNIX System V로부터 차용
  • Inter-process communication을 격리하여, 의도치않게 접근하거나 권한이 없는 프로세스에 의해 제거되는 일을 방지하기 위해 사용
  • 개별 IPC는 자신만의 System V 식별자와 POSIX 메시지큐 파일시스템을 가지고 있다

IPC Namespace

Mount Namespace

  • Linux에서 가장 오래된 Namespace
  • Mount Namespace 안에서 mount, unmount 명령어를 통해 자신만의 파일시스템 계층(Filesystem Hierarchy)을 구성할 수 있다
  • chroot jail과 유사한 환경을 제공하기 위해 사용되며, 더욱 안전한 방식

Network Namespace

  • Network Namespace 안에서 자신만의 network 자원(ex: 인터페이스, IP 주소, 라우팅 테이블, 포트 등)로 구성된 스택 제공
  • Container의 Network namespace와 Host의 Network Namespace 사이에 Virtual Network Device(ex: veth pair)를 추가하여 Host to Container, Container to Container 등의 Container Networking을 구성할 수 있다

PID Namespace

  • Process ID 공간을 분리하여, PID Namespace 안에서 PID=1인 프로세스를 만들 수 있다. 또한 PID가 특정되므로, 이 프로세스를 죽이는 시그널(SIG_KILL, SIG_TERM)을 보낼 수도 있다.
  • 원래 Process는 계층 구조로 Parent-Child 관계를 이루고 있고 최상단엔 init process가 존재한다. init은 zombie process를 제거하는 역할을 하지만, PID Namespace를 분리할 경우 PID=1 프로세스가 이 기능을 대신 수행해야 한다. K8s의 pause container를 참고할 것
  • 동일한 프로세스에 대해 Parent와 Child Namespace에서 보이는 PID가 다르다. Child Namespace에서 PID=1인 프로세스는 Parent 입장에서는 PID=1이 될 수 없다.

Time Namespace

  • boot time clock을 분리함으로써, 자신만의 time offset을 제공할 수 있다. 이를 통해 프로세스가 Host와 다른 날짜와 시간을 갖게 된다.
  • 분리된 Time Namespace 안에서 NTP 프로세스를 실행하는 등의 동작이 가능

User Namespace

  • UID(user), GID(group) 공간을 격리하여, Host와는 다른 User와 Group을 가질 수 있다
  • User Namespace는 중첩 가능(outer/internal namespace)

UTS(UNIX Time Sharing) Namespace

  • 별개의 hostname, domainname 사용 가능
  • 이름과 다소 상관없어 보이는 기능때문에 혼동할 수 있으나, syscall 중 uname의 'utsname' 구조체와 관련이 있다.
struct utsname {
               char sysname[];    /* Operating system name (e.g., "Linux") */
               char nodename[];   /* Name within "some implementation-defined
                                     network" */
               char release[];    /* Operating system release
                                     (e.g., "2.6.28") */
               char version[];    /* Operating system version */
               char machine[];    /* Hardware identifier */
           #ifdef _GNU_SOURCE
               char domainname[]; /* NIS or YP domain name */
           #endif
};

 

참고
Introduction to the virtualization solution LXC
What's in a Name? - Linux Namespaces
uname(2) - Linux manual page

 

'Kubernetes > Architecture' 카테고리의 다른 글

Pod Lifecycle  (0) 2021.03.07
Calico Components  (0) 2021.02.11
CNI - Spec  (0) 2021.01.24
Cluster Networking  (0) 2021.01.22
Scheduler  (0) 2021.01.15