2022. 8. 1. 10:35ㆍ카테고리 없음
docker를 공부하는데 linux namespace 개념이 필요한 이유...
docker는 프로세스 관리자로서 컨테이너라는 개념으로 프로세스를 나누고 독립적으로 운영할 수 있도록한다.
docker는 기본적으로 linux의 namespace기능을 사용하여 resource(컨테이너를 구축하기 위한 모든 자원)를 독립적으로 운영하게 되는데. linux namespace, Cgroup, chroot와 같은 리눅스 기반 기술들의 집합체 임으로 이 세가지의 원리 및 기술을 모르면 docker를 제대로 이해했다고 할 수 없는것 같다.

<namespace>
먼저 namespace에 대해서 설명하면 다음과 같다.
linux namespace는 하나의 독립된 기능이 아니라 6가지 세분화된 기능을 포함하여 linux namespace기능이라 통칭한다.
각 6가지 기능에서 대해서 먼저 간략하게 설명하면 다음과 같다.
linux namespace는 커널에 제공하고 있으며, 하나의 시스템에서 프로세스를 격리(isolation)시킬 수 있는 가상화 기술.
IPC namespace(Inter-process communication) : 프로세스간 통신을 가능하게 해주는 네임스페이스
network namespace : IP, 라우팅 테이블 등, 네트워크 규격을 독자적으로 가질 수 있는 네임스페이스
PID namespace(Process ID) : 독립적인 PID를 가질 수 있는 네임스페이스
NS namespace(Mount) : 새로운 네임스페이스 생성시 부모 네임스페이스와 자식 네임스페이스간 프로세스를 격리시키는 namespace
USER namespace : namespace생성 시 긴밀하게 연관된 user ID, group ID를 분리 시키는 역할
UTS namespace(Unix time sharing) 등 linux namespace의 기능을 사용하여 컨테이너를 구축할 수 있다.
컨테이너를 좀 더 세밀하게 들여다보면 다음과 같은 linux namespace구조를 가지고 있다.

그림을 상세히 살펴보면 각 namespace를 사용하여 로컬PC와의 분리된 환경을 제공하는 것을 알 수 있다.
만약 k8s를 사용하여 container라는 개념과 pod라는 개념을 하나의 그림으로 표시하면 다음과 같은 그림을 그려볼 수 있다.

즉, POD는 컨테이너의 상호 호환성과 분리된 환경을 제공하기 위한 단위임을 알 수 있고, 컨테이너의 확장된 개념임을 알 수 있다.
그렇다면 namespace란 무엇일까
namespace란?
애플리케이션의 실행환경을 위한 docker container라는 독립된 환경을 만들기 위한 linux kunel의 기능
리눅스 namespace의 6가지 기능
<PID namespace>
PID namespace는 프로세스 ID공간을 격리시키는 네임스페이스. 즉, 프로세스 ID를 분할하여 관리하기 위해 필요.
PID namespace를 사용함으로서 systemd 프로세스만 가질 수 있는 PID 1번을 독립적으로 추가할당 해줌으로서 동일한 OS에서 systemd 프로세스 뿐만 아니라 여러 프로세스가 독립적인 PID를 가지게 해준다.
이렇게 되면 PID넘버가 충돌없이 실행가능해 진다.(즉, 컨테이너)
좀 더 자세하게 살펴보면, linux에서 실행되는 모든 process들은 각각 고유한 process ID(PID)가 부여된다. kernel에서는 이 Process들응 tree 형태로 관리한다.
tree형태라는 의미는 모든 process가 부모-자식 관계(parent-child hierachy)를 가지고 있다는 의미.

version : centOS 6기준 현재는 systemd로 바뀐 상황(initd와 systemd 뒤에서 설명)

version : centos 7 기준은 다음과 같다.

process의 최상단에 위치한 process가 존재하는데 이 첫번쨰 process를 init process라고한다.
시스템에서 생성되는 모든 process들은 init process에 의해 실행되어 지고... init process에게는 유일하게 PID number가 1이라는 숫자를 할당 한다.
PID1 = init ---> 제일 root pid이다.
이 init PID는 어떠한 독립적인 application이 생성되면 독립적으로 PID number가 1인 독립적인 number를 할당해준다.
위 그림에서 보여진봐와 같이 child영역에 6번 process에 PID = 1을 부여하고, init process가 할 수 있는 역할을 대신 수행할 수 있는 기능과 권한을 부여한다.

4번 process를 parent로 하는 6번 process가 PID namespace로 구성되고,
6번 processs는 init process의 역할을 하는 1번 init process ID를 부여 받는다.
그리고 6번 프로세스 밑으로 분기되는 (child namespace 안에서)child process들은 기존 PID 할당순서와 별개로 PID를 부여 받게 된다.
추가적으로 6번 process는 init의 역할과 권한을 부여 받았지만 init process는 아니다.
child namespace에서 PID 1을 할당 받았다고 해서 6번 process가 init process가 될 수 없다.
그렇기 때문에
위 그림에서 8번 process가 죽게 되면, 9번 process는 parent가 없는 고아(orphaned process)가 되는데 , 이때 자동으로 6(1)번 process가 parent가 되는 child reping이 일어난다. 원래는 이러한 기능을 init process가 수행해야 하지만 PID namespace에서는 6번이 이 역할을 대신 수행한다.
<network namespace>
NET namespace는 격리화된 network interface를 제공하는 기술이다. namespace기능은 프로세스를 분기한다고 PID namespace에서 보았다. 각 분기된 프로세스가 네트워크가 되려면 네트워크 인터페이스 또한 분기 처리가 필요하다. 이때 사용하는기능이 network namespace의 기능이다.
직접적으로 눈으로 확인하기 위해 network interface를 통해 확인해보면,
현재 link 연결된 interface는 다음과 같다.

여기서 네트워크 인터페이스를 만들어 link해보자.
PID를 namespace로 구분한 것과 같이 network interface도 namespace로 구분하는 것이 가능하다.
다음과 같이 david_ns라는 이름으로 namespace를 구축하였다.

david_ns namespace 내부 network interface를 확인한 결과 현재 loopback interface의 network interface가 하나 존재하는 것을 확인 할 수 있고. 상태가 DOWN모드 인것을 확인 할 수 있다.( 네트워크 인터페이스 비활성화 라는 뜻)
또한 <LOOPBACK>상태 임으로 가상으로 만들었기 때문에 논리적인 인터페이스로 실제로 존재하지 않는 인터페이스라는 뜻.

interface 활성화를 위해 다음과 같이 시도해보면

결론적으로 <LOOPBACK, UP, LOWER_UP>으로 활성화 된 것을 확힌 할 수 있다.
만든 NET interface가 외부와 통신하려면 packet이 나가는 역할을 할 수 있는 인터페이스와 들어올 수 있는 인터페이스 총 두개 더 필요하다.

veth0 interface가 peer_ifindex 가 3으로 설정되어 있다. 이는 ip link list 로 확인했을때 veth1의 index임을 알 수 있다.
즉, 두 interface가 pair로 설정되어 있다는 의미이다.
veth0와 veth1 interface를 생성하고 두 interface를 pair로 설정.

이렇게 생성된 veth1 interface를 david_ns namespace에 할당하면
veth1 인터페이스가 david_ns에 할당 된 것을 확인 할 수 있다. docker도 이렇게 컨테이너에 네트워크 기능을 할당하는것이 틀림없다...

아직 veth0m veth1을 활성화 시키지 않았음으로 활성화 시켜보자.
==========================================================================================
veth0 활성화

veth1 활성화

==========================================================================================
veth0 ip 할당

할당 후 결과

==========================================================================================
veth1 ip 할당

할당 후 결과

==========================================================================================
veth0과 veth1가 잘 연결 되었는지 확인해보자


위 결과를 그림으로 정리하면 다음과 같다.
