容器核心技术之Namespace

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.csdn.net/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
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值