文章目录
Namespace概述
Linux Namespace 是一种 Linux Kernel 提供的资源隔离方案:
• 系统可以为进程分配不同的 Namespace;
• 并保证不同的 Namespace 资源独立分配、进程彼此隔离,即 不同的 Namespace 下的进程互不干扰
最新的 Linux 5.6 内核中提供了 8 种类型的 Namespace:
Linux内核代码Namespace实现
进程数据结构
struct task_struct {
...
/* namespaces */
struct nsproxy *nsproxy;
...
}
Namespace数据结构
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;
};
源码分析参考: Linux kernel Namespace源码分析
Linux提供的操作Namespace的API
参考: https://blog.youkuaiyun.com/shuningzhang/article/details/89914371
clone() 函数
我们可以通过 clone() 在创建新进程的同时创建 namespace。clone() 在 C 语言库中的声明如下:
/* Prototype for the glibc wrapper function */
#define _GNU_SOURCE
#include <sched.h>
int clone(int (*fn)(void *), void *child_stack, int flags, void *arg);
- fn:指定一个由新进程执行的函数。当这个函数返回时,子进程终止。该函数返回一个整数,表示子进程的退出代码。
- child_stack:传入子进程使用的栈空间,也就是把用户态堆栈指针赋给子进程的 esp 寄存器。调用进程(指调用 clone() 的进程)应该总是为子进程分配新的堆栈。
- flags:表示使用哪些 CLONE_ 开头的标志位,与 namespace 相关的有CLONE_NEWIPC、CLONE_NEWNET、CLONE_NEWNS、CLONE_NEWPID、CLONE_NEWUSER、CLONE_NEWUTS 和 CLONE_NEWCGROUP。
- arg:指向传递给 fn() 函数的参数。
setns() 函数
通过 setns() 函数可以将当前进程加入到已有的 namespace 中。setns() 在 C 语言库中的声明如下:
#define _GNU_SOURCE
#include <sched.h>
int setns(int fd, int nstype);
- fd:表示要加入 namespace 的文件描述符。它是一个指向 /proc/[pid]/ns 目录中文件的文件描述符,可以通过直接打开该目录下的链接文件或者打开一个挂载了该目录下链接文件的文件得到。
- nstype:参数 nstype 让调用者可以检查 fd 指向的 namespace 类型是否符合实际要求。若把该参数设置为 0 表示不检查。
unshare() 函数 和 unshare 命令
通过 unshare 函数可以在原进程上进行 namespace 隔离。也就是将调用进程移动到新的 Namespace 下: unshare() 在 C 语言库中的声明如下:
#define _GNU_SOURCE
#include <sched.h>
int unshare(int flags);
Namespace常用操作命令
查看当前系统的namespace
lsns -t <type>
- -t : 表示要查看的ns的类型如
lsns -t pid
查看pid namespace
查看某进程的namespace
ls -la /proc/<pid>/ns/
- 示例-查看当前进程的ns
ls -la /proc/$$/ns/
进入某namespace运行命令
nsenter -t <pid> -n ip addr # 进入进程<pid>的network命名空间执行ip addr命令
- 说明:nsenter命令可以用来在容器中没有命令时,查看容器的信息
Namespace 练习
1、 在新 network namespace 执行 sleep 指令:
unshare -fn sleep 120
2、 查看进程信息
ps -ef|grep sleep
root 4049 3935 0 10:34 pts/0 00:00:00 unshare -fn sleep 120
root 4050 4049 0 10:34 pts/0 00:00:00 sleep 120
3、 查看网络 Namespace
lsns -t net
4026532264 net 2 4049 root unshare -fn sleep 120
4、进入改进程所在 Namespace 查看网络配置,与主机不一致
nsenter -t 4049 -n ip a
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00