1. Namespace简介

Namespace是内核的一个功能,用来给进程隔离一系列系统资源(视图隔离)。

2. 类别

namespace类别 隔离资源 系统调用参数 内核版本 Docker中的例子
Mount namespace 挂载点 CLONE_NEWNS 2.4.19 独立的挂载点
UTS Namespace hostname和domainname CLONE_NEWUTS 2.6.19 独立的hostname
IPC Namespace System V IPC, POSIX message queues CLONE_NEWIPC 2.6.19
PID Namespace 进程ID CLONE_NEWPID 2.6.24 容器进程PID为1
Network Namespace 网络设备,端口,网络栈 CLONE_NEWNET 2.6.24 独立的网络和端口
User Namespace 用户ID,group ID CLONE_NEWUSER 3.8 独立的用户ID

3. Namespace API

API 说明
clone() 基于某namespace创建新进程,他们的子进程也包含在该namespace中
unshare() 将进程移出某个namespace
setns() 将进程加入某个namespace

4. namespace细分

4.1. Mount Namespace

Mount Namespace可以用了隔离各个进程的挂载点视图。不同的namespace中文件系统层次不一样,在其中调用mount和umount仅影响当前namespace。

4.2. Network Namespace

Network Namespace用来隔离网络设备,IP地址端口等网络栈。容器内可以绑定自己的端口,在宿主机建立网桥,就可以实现容器之间的通信。

ip netns 命令用来管理 network namespace。

# ip netns help
Usage: ip netns list
       ip netns add NAME
       ip netns set NAME NETNSID
       ip [-all] netns delete [NAME]
       ip netns identify [PID]
       ip netns pids NAME
       ip [-all] netns exec [NAME] cmd ...
       ip netns monitor
       ip netns list-id

示例:

模拟创建docker0及docker网络

1、创建lxcbr0,相当于docker0

# 添加一个网桥lxcbr0,相当于docker0
brctl addbr lxcbr0
brctl stp lxcbr0 off
ifconfig lxcbr0 192.168.10.1/24 up  # 配置网桥IP地址

# 查看网桥
# ifconfig
lxcbr0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.10.1  netmask 255.255.255.0  broadcast 192.168.10.255
        inet6 fe80::94cb:eaff:fe48:cdd5  prefixlen 64  scopeid 0x20<link>
        ether 96:cb:ea:48:cd:d5  txqueuelen 1000  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 5  bytes 426 (426.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

添加网络命名空间

# 添加网络命名空间ns1
ip netns add ns1
# 激活namespace中的loopback,即127.0.0.1
ip netns exec ns1   ip link set dev lo up

3、添加虚拟网卡

# 增加一个pair虚拟网卡,注意其中的veth类型,其中一个网卡要按进容器中
ip link add veth-ns1 type veth peer name lxcbr0.1
# 把 veth-ns1 按到namespace ns1中,这样容器中就会有一个新的网卡了
ip link set veth-ns1 netns ns1

4、修改容器内网卡为eth0,并分配IP

# 把容器里的 veth-ns1改名为 eth0 (容器外会冲突,容器内就不会了)
ip netns exec ns1  ip link set dev veth-ns1 name eth0 
# 为容器中的网卡分配一个IP地址,并激活它
ip netns exec ns1 ifconfig eth0 192.168.10.11/24 up

5、将lxcbr0.1添加上网桥

# 上面我们把veth-ns1这个网卡按到了容器中,然后我们要把lxcbr0.1添加上网桥上
brctl addif lxcbr0 lxcbr0.1

6、添加路由

# 为容器增加一个路由规则,让容器可以访问外面的网络
ip netns exec ns1     ip route add default via 192.168.10.1

7、添加nameserver

# 在/etc/netns下创建network namespce名称为ns1的目录,
# 然后为这个namespace设置resolv.conf,这样,容器内就可以访问域名了
mkdir -p /etc/netns/ns1
echo "nameserver 8.8.8.8" > /etc/netns/ns1/resolv.conf

8、查看网络空间内的网络配置

# 进入网络命名空间
ip netns exec ns1 bash
# 查看网络配置
ifconfig
eth0: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        inet 192.168.10.11  netmask 255.255.255.0  broadcast 192.168.10.255
        ether 2a:0c:a8:b7:bc:32  txqueuelen 1000  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 4  bytes 240 (240.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 4  bytes 240 (240.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

9、进入现有docker容器的网络命名空间

由于docker默认隐藏了/var/run/netns下的命名空间,因此需要做软链接,容器的1号进程的pid下的ns软链到/var/run/netns

ln -sf /proc/<container-pid>/ns/net "/var/run/netns/<container-id>"
ip netns exec <container-id> bash

参考:

Copyright © www.huweihuang.com 2017-2018 all right reserved,powered by GitbookUpdated at 2023-03-05 22:26:01

results matching ""

    No results matching ""