>  기사  >  운영 및 유지보수  >  Linux 네임스페이스에 대해 알아야 할 사항

Linux 네임스페이스에 대해 알아야 할 사항

WBOY
WBOY앞으로
2022-01-25 17:37:453900검색

이 기사는 Linux 네임스페이스에 대한 관련 지식을 제공합니다. 네임스페이스는 가벼운 형태의 가상화를 제공하여 다양한 측면에서 실행 중인 시스템의 전역 속성을 볼 수 있도록 해줍니다.

Linux 네임스페이스에 대해 알아야 할 사항

1. 기본 개념

- 네임스페이스(Linux 네임스페이스)는 컨테이너 가상화 구현을 위한 리눅스 커널의 기능입니다. 우리가 만드는 각 컨테이너에는 고유한 네임스페이스가 있으며, 그 안에서 실행되는 애플리케이션은 마치 독립적인 운영 체제에서 실행되는 것처럼 보입니다. 네임스페이스는 컨테이너가 서로 영향을 미치지 않도록 합니다.

 Linux의 네임스페이스 메커니즘은 리소스 격리를 위한 솔루션을 제공합니다. PID, IPC 및 네트워크와 같은 시스템 리소스는 더 이상 전역이 아니며 특정 네임스페이스에 속합니다. 네임스페이스는 전역 시스템 리소스의 일종의 캡슐화 및 격리이므로 서로 다른 네임스페이스의 프로세스는 독립적인 전역 시스템 리소스를 갖습니다. 네임스페이스의 시스템 리소스를 변경하면 현재 네임스페이스의 프로세스에만 영향을 미치고 다른 네임스페이스의 프로세스에는 영향을 미치지 않습니다.

  전통적으로 Linux 및 기타 UNIX 파생 제품에서는 많은 리소스가 전역적으로 관리됩니다. 예를 들어, 시스템의 모든 프로세스는 일반적으로 PID로 식별됩니다. 이는 커널이 PID의 전체 목록을 관리해야 함을 의미합니다. 또한 uname 시스템 호출을 통해 모든 호출자가 반환하는 시스템 관련 정보(시스템 이름 및 커널에 대한 일부 정보 포함)는 동일합니다. 사용자 ID는 유사한 방식으로 관리됩니다. 즉, 각 사용자는 전역적으로 고유한 UID 번호로 식별됩니다.

  전역 ID를 사용하면 커널이 특정 권한을 선택적으로 허용하거나 거부할 수 있습니다. UID 0을 가진 루트 사용자는 기본적으로 모든 작업을 수행할 수 있지만 다른 사용자 ID는 제한됩니다. 예를 들어, UID n을 가진 사용자는 사용자 m(m≠ n)에 속한 프로세스를 종료할 수 없습니다. 그러나 이것이 사용자가 서로를 보는 것을 막지는 못합니다. 즉, 사용자 n은 다른 사용자 m이 컴퓨터에서 활성 상태라는 것을 볼 수 있습니다. 사용자가 자신의 프로세스만 조작할 수 있는 한 이는 괜찮습니다. 사용자가 다른 사용자의 프로세스를 보도록 허용해서는 안 될 이유가 없기 때문입니다.

  하지만 이 효과가 바람직하지 않은 상황이 있습니다. 웹 호스팅 제공업체가 사용자에게 루트 권한을 포함하여 Linux 컴퓨터에 대한 전체 액세스 권한을 제공하려는 경우. 전통적으로 이를 위해서는 각 사용자마다 컴퓨터가 필요했는데, 이는 엄청나게 비용이 많이 들었습니다. KVM이나 VMWare에서 제공하는 가상화 환경을 이용하는 것도 문제를 해결하는 방법 중 하나이지만 리소스 할당이 별로 좋지 않습니다. 컴퓨터의 각 사용자에게는 별도의 커널과 완전히 설치된 사용자 수준 응용 프로그램 지원 세트가 필요합니다.

 네임스페이스는 더 적은 리소스가 필요한 다른 솔루션을 제공합니다. 가상화된 시스템에서 물리적 컴퓨터는 여러 코어, 가능하면 여러 운영 체제를 병렬로 실행할 수 있습니다. 네임스페이스는 하나의 커널만 사용하여 하나의 물리적 컴퓨터에서 작동하며 앞서 언급한 모든 전역 리소스는 네임스페이스를 통해 추상화됩니다. 이를 통해 일련의 프로세스를 서로 격리된 컨테이너에 배치할 수 있습니다. 격리를 통해 컨테이너의 구성원은 다른 컨테이너와 관계가 없습니다. 그러나 컨테이너가 특정 양의 정보를 공유하도록 허용하여 컨테이너 간의 분리를 줄일 수도 있습니다. 예를 들어, 자체 PID 세트를 사용하도록 컨테이너를 설정하면서도 파일 시스템의 일부를 다른 컨테이너와 공유할 수 있습니다.

2. 구현

  네임스페이스 구현에는 두 부분이 필요합니다. 즉, 모든 이전 전역 구성 요소를 네임스페이스로 래핑하는 각 하위 시스템의 네임스페이스 구조와 지정된 프로세스를 해당 프로세스가 속한 각 네임스페이스에 연결하는 메커니즘입니다.

  하위 시스템의 이전 전역 속성은 이제 네임스페이스로 캡슐화되며 각 프로세스는 선택한 네임스페이스와 연결됩니다. 모든 네임스페이스 인식 커널 하위 시스템은 네임스페이스로 제공된 모든 개체를 수집하는 데이터 구조를 제공해야 합니다. struct nsproxy는 하위 시스템별 네임스페이스 래퍼에 대한 포인터를 어셈블하는 데 사용됩니다. nsproxy.h 파일에는 다음이 있습니다.

/*
 * A structure to contain pointers to all per-process
 * namespaces - fs (mount), uts, network, sysvipc, etc.
 *
 * The pid namespace is an exception -- it's accessed using
 * task_active_pid_ns.  The pid namespace here is the
 * namespace that children will use.
 *
 * 'count' is the number of tasks holding a reference.
 * The count for each namespace, then, will be the number
 * of nsproxies pointing to it, not the number of tasks.
 *
 * The nsproxy is shared by tasks which share all namespaces.
 * As soon as a single namespace is cloned or unshared, the
 * nsproxy is copied.
 */struct nsproxy {
	atomic_t count;
	struct uts_namespace *uts_ns;
	struct ipc_namespace *ipc_ns;
	struct mnt_namespace *mnt_ns;
	struct pid_namespace *pid_ns_for_children;
	struct net 	     *net_ns;
	struct time_namespace *time_ns;
	struct time_namespace *time_ns_for_children;
	struct cgroup_namespace *cgroup_ns;};

   현재 커널의 다음 범위는 네임스페이스를 감지할 수 있습니다.

   1. UTS 네임스페이스에는 실행 중인 커널의 이름, 버전, 기본 아키텍처 유형 및 기타 정보가 포함됩니다. UTS는 UNIX Timesharing System의 약자입니다.

   2. IPC(프로세스 간 통신)와 관련된 모든 정보는 struct ipc_namespace에 저장됩니다.

  3. 마운트된 파일 시스템의 보기는 mnt_namespace 구조체에 제공됩니다.

  4. 프로세스 ID에 대한 정보는 struct pid_namespace에서 제공됩니다.

  5. struct user_namespace에 저장된 정보는 각 사용자의 리소스 사용량을 제한하는 데 사용됩니다.

  6. struct net_ns에는 모든 네트워크 관련 네임스페이스 매개변수가 포함되어 있습니다.

  해당 하위 시스템에 대해 논의할 때 각 네임스페이스 컨테이너의 내용을 소개하겠습니다. 새 프로세스를 생성할 때 포크를 사용하여 새 네임스페이스를 설정할 수 있으므로 이 동작을 제어하려면 적절한 플래그를 제공해야 합니다. 각 네임스페이스에는 sched.h 파일에 있는 해당 플래그가 있습니다.

#define CLONE_NEWCGROUP		0x02000000	/* New cgroup namespace */
#define CLONE_NEWUTS		0x04000000	/* New utsname namespace */
#define CLONE_NEWIPC		0x08000000	/* New ipc namespace */
#define CLONE_NEWUSER		0x10000000	/* New user namespace */
#define CLONE_NEWPID		0x20000000	/* New pid namespace */
#define CLONE_NEWNET		0x40000000	/* New network namespace */

  다양한 유형의 네임스페이스의 기능:

  IPC:用于隔离进程间通讯所需的资源( System V IPC, POSIX message queues),PID命名空间和IPC命名空间可以组合起来用,同一个IPC名字空间内的进程可以彼此看见,允许进行交互,不同空间进程无法交互

  Network:Network Namespace为进程提供了一个完全独立的网络协议栈的视图。包括网络设备接口,IPv4和IPv6协议栈,IP路由表,防火墙规则,sockets等等。一个Network Namespace提供了一份独立的网络环境,就跟一个独立的系统一样。

  Mount:每个进程都存在于一个mount Namespace里面,  mount Namespace为进程提供了一个文件层次视图。如果不设定这个flag,子进程和父进程将共享一个mount Namespace,其后子进程调用mount或umount将会影响到所有该Namespace内的进程。如果子进程在一个独立的mount Namespace里面,就可以调用mount或umount建立一份新的文件层次视图。

  PID::linux通过命名空间管理进程号,同一个进程,在不同的命名空间进程号不同!进程命名空间是一个父子结构,子空间对于父空间可见。

  User:用于隔离用户

  UTS:用于隔离主机名

  每个进程都关联到自身的命名空间视图,在任务定义的结构体task_struct中有如下定义:

struct task_struct {.../* 命名空间 */struct nsproxy *nsproxy;...}

  因为使用了指针,多个进程可以共享一组子命名空间。这样,修改给定的命名空间,对所有属于该命名空间的进程都是可见的。
  init_nsproxy定义了初始的全局命名空间,其中维护了指向各子系统初始的命名空间对象的指针。在kernel/nsproxy.c文件内有

struct nsproxy init_nsproxy = {
	.count			= ATOMIC_INIT(1),
	.uts_ns			= &init_uts_ns,#if defined(CONFIG_POSIX_MQUEUE) || defined(CONFIG_SYSVIPC)
	.ipc_ns			= &init_ipc_ns,#endif
	.mnt_ns			= NULL,
	.pid_ns_for_children	= &init_pid_ns,#ifdef CONFIG_NET
	.net_ns			= &init_net,#endif#ifdef CONFIG_CGROUPS
	.cgroup_ns		= &init_cgroup_ns,#endif#ifdef CONFIG_TIME_NS
	.time_ns		= &init_time_ns,
	.time_ns_for_children	= &init_time_ns,#endif};

三、UTS命名空间

  UTS命名空间几乎不需要特别的处理,因为它只需要简单量,没有层次组织。所有相关信息都汇集到下列结构的一个实例中。在utsname.h文件内:

struct uts_namespace {
	struct new_utsname name;
	struct user_namespace *user_ns;
	struct ucounts *ucounts;
	struct ns_common ns;} __randomize_layout;

  uts_namespace所提供的属性信息本身包含在struct new_utsname中:

struct oldold_utsname {
	char sysname[9];
	char nodename[9];
	char release[9];
	char version[9];
	char machine[9];};#define __NEW_UTS_LEN 64struct old_utsname {
	char sysname[65];
	char nodename[65];
	char release[65];
	char version[65];
	char machine[65];};struct new_utsname {
	char sysname[__NEW_UTS_LEN + 1];
	char nodename[__NEW_UTS_LEN + 1];
	char release[__NEW_UTS_LEN + 1];
	char version[__NEW_UTS_LEN + 1];
	char machine[__NEW_UTS_LEN + 1];
	char domainname[__NEW_UTS_LEN + 1];}

  各个字符串分别存储了系统的名称( Linux…)、内核发布版本、机器名,等等。使用uname工具可以取得这些属性的当前值,也可以在/proc/sys/kernel/中看到

z@z-virtual-machine:~$ cat /proc/sys/kernel/ostype
Linux
z@z-virtual-machine:~$ cat /proc/sys/kernel/osrelease5.3.0-40-generic

  初始设置保存在init_uts_ns中,在init/version.c文件内:

struct uts_namespace init_uts_ns = {
	.ns.count = REFCOUNT_INIT(2),
	.name = {
		.sysname	= UTS_SYSNAME,
		.nodename	= UTS_NODENAME,
		.release	= UTS_RELEASE,
		.version	= UTS_VERSION,
		.machine	= UTS_MACHINE,
		.domainname	= UTS_DOMAINNAME,
	},
	.user_ns = &init_user_ns,
	.ns.inum = PROC_UTS_INIT_INO,#ifdef CONFIG_UTS_NS
	.ns.ops = &utsns_operations,#endif};

相关推荐:《Linux视频教程

위 내용은 Linux 네임스페이스에 대해 알아야 할 사항의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 csdn.net에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제