一文搞懂 Linux network namespace

本文首發於個人公衆號 Linux雲計算網絡(id: cloud_dev),專一於乾貨分享,號內有 10T 書籍和視頻資源,後臺回覆「1024」便可領取,歡迎你們關注,二維碼文末能夠掃。docker

本文經過 IP 命令操做來簡單介紹 network namespace 的基本概念和用法。深刻了解能夠看看我以前寫的兩篇文章 Docker 基礎技術之 Linux namespace 詳解 和 Docker 基礎技術之 Linux namespace 源碼分析。shell

和 network namespace 相關的操做的子命令是 ip netns編程

1. ip netns add xx 建立一個 namespace

# ip netns add net1
# ip netns ls
net1

2. ip netns exec xx yy 在新 namespace xx 中執行 yy 命令

# ip netns exec net1 ip addr 
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
# ip netns exec net1 bash // 在 net1 中打開一個shell終端
# ip addr // 在net1中的shell終端
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
# exit // 退出net1

上面 bash 很差區分是當前是在哪一個 shell,能夠採用下面的方法解決:segmentfault

# ip netns exec net1 /bin/bash --rcfile <(echo "PS1=\"namespace net1> \"")
namespace net1> ping www.baidu.com

每一個 namespace 在建立的時候會自動建立一個迴環接口 lo ,默認不啓用,能夠經過 ip link set lo up 啓用。安全

3. network namespace 之間的通訊

新建立的 namespace 默認不能和主機網絡,以及其餘 namespace 通訊。bash

可使用 Linux 提供的 veth pair 來完成通訊。下面顯示兩個 namespace 之間通訊的網絡拓撲:網絡

# ip link add type veth
# ip link
3: veth0@veth1: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/ether 1a:53:39:5a:26:12 brd ff:ff:ff:ff:ff:ff
4: veth1@veth0: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/ether 46:df:46:1f:bf:d6 brd ff:ff:ff:ff:ff:ff

使用命令 ip link add xxx type veth peer name yyy 指定 veth pair 的名字。工具

# ip link set veth0 netns net0
# ip link set veth1 netns net1
#
# ip netns exec net0 ip addr
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
10: veth0@if11: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
    link/ether 1a:53:39:5a:26:12 brd ff:ff:ff:ff:ff:ff link-netnsid 1

3.3 給 veth pair 配上 ip 地址

# ip netns exec net0 ip link set veth0 up
# ip netns exec net0 ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
10: veth0@if11: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state LOWERLAYERDOWN group default qlen 1000
    link/ether 1a:53:39:5a:26:12 brd ff:ff:ff:ff:ff:ff link-netnsid 1
# ip netns exec net0 ip addr add 10.1.1.1/24 dev veth0
# ip netns exec net0 ip route
10.1.1.0/24 dev veth0  proto kernel  scope link  src 10.1.1.1 linkdown
#
# ip netns exec net1 ip link set veth1 up
# ip netns exec net1 ip addr add 10.1.1.2/24 dev veth1

能夠看到,在配完 ip 以後,還自動生成了對應的路由表信息。oop

3.4. ping 測試兩個 namespace 的連通性

# ip netns exec net0 ping 10.1.1.2
PING 10.1.1.2 (10.1.1.2) 56(84) bytes of data.
64 bytes from 10.1.1.2: icmp_seq=1 ttl=64 time=0.069 ms
64 bytes from 10.1.1.2: icmp_seq=2 ttl=64 time=0.054 ms
64 bytes from 10.1.1.2: icmp_seq=3 ttl=64 time=0.053 ms
64 bytes from 10.1.1.2: icmp_seq=4 ttl=64 time=0.053 ms

Done!源碼分析

4. 多個不一樣 namespace 之間的通訊

2 個 namespace 之間通訊能夠藉助 veth pair ,多個 namespace 之間的通訊則可使用 bridge 來轉接,否則每兩個 namespace 都去配 veth pair 將會是一件麻煩的事。下面就看看如何使用 bridge 來轉接。

拓撲圖以下:

一般 Linux 中和 bridge 有關的操做是使用命令 brctl (yum install -y bridge-utils ) 。但爲了先後照應,這裏都用 ip 相關的命令來操做。

// 創建一個 bridge
# ip link add br0 type bridge
# ip link set dev br0 up
9: br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN group default qlen 1000
    link/ether 42:55:ed:eb:a0:07 brd ff:ff:ff:ff:ff:ff
    inet6 fe80::4055:edff:feeb:a007/64 scope link
       valid_lft forever preferred_lft forever

4.2 建立 veth pair

//(1)建立 3 個 veth pair
# ip link add type veth
# ip link add type veth
# ip link add type veth

4.3 將 veth pair 的一頭掛到 namespace 中,一頭掛到 bridge 上,並設 IP 地址

// (1)配置第 1 個 net0
# ip link set dev veth1 netns net0
# ip netns exec net0 ip link set dev veth1 name eth0
# ip netns exec net0 ip addr add 10.0.1.1/24 dev eth0
# ip netns exec net0 ip link set dev eth0 up
#
# ip link set dev veth0 master br0
# ip link set dev veth0 up

// (2)配置第 2 個 net1
# ip link set dev veth3 netns net1
# ip netns exec net1 ip link set dev veth3 name eth0
# ip netns exec net1 ip addr add 10.0.1.2/24 dev eth0
# ip netns exec net1 ip link set dev eth0 up
#
# ip link set dev veth2 master br0
# ip link set dev veth2 up

// (3)配置第 3 個 net2
# ip link set dev veth5 netns net2
# ip netns exec net2 ip link set dev veth5 name eth0
# ip netns exec net2 ip addr add 10.0.1.3/24 dev eth0
# ip netns exec net2 ip link set dev eth0 up
# 
# ip link set dev veth4 master br0
# ip link set dev veth4 up

這樣以後,居然通不了,經查閱 參見 ,是由於

緣由是由於系統爲bridge開啓了iptables功能,致使全部通過br0的數據包都要受iptables裏面規則的限制,而docker爲了安全性(個人系統安裝了 docker),將iptables裏面filter表的FORWARD鏈的默認策略設置成了drop,因而全部不符合docker規則的數據包都不會被forward,致使你這種狀況ping不通。

解決辦法有兩個,二選一:

  1. 關閉系統bridge的iptables功能,這樣數據包轉發就不受iptables影響了:echo 0 > /proc/sys/net/bridge/bridge-nf-call-iptables
  2. 爲br0添加一條iptables規則,讓通過br0的包能被forward:iptables -A FORWARD -i br0 -j ACCEPT

第一種方法不肯定會不會影響docker,建議用第二種方法。

我採用如下方法解決:

iptables -A FORWARD -i br0 -j ACCEPT

結果:

# ip netns exec net0 ping -c 2 10.0.1.2
PING 10.0.1.2 (10.0.1.2) 56(84) bytes of data.
64 bytes from 10.0.1.2: icmp_seq=1 ttl=64 time=0.071 ms
64 bytes from 10.0.1.2: icmp_seq=2 ttl=64 time=0.072 ms

--- 10.0.1.2 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 999ms
rtt min/avg/max/mdev = 0.071/0.071/0.072/0.008 ms

# ip netns exec net0 ping -c 2 10.0.1.3
PING 10.0.1.3 (10.0.1.3) 56(84) bytes of data.
64 bytes from 10.0.1.3: icmp_seq=1 ttl=64 time=0.071 ms
64 bytes from 10.0.1.3: icmp_seq=2 ttl=64 time=0.087 ms

--- 10.0.1.3 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1000ms
rtt min/avg/max/mdev = 0.071/0.079/0.087/0.008 ms

Done!


個人公衆號 「Linux雲計算網絡」(id: cloud_dev) ,號內有 10T 書籍和視頻資源,後臺回覆 「1024」 便可領取,分享的內容包括但不限於 Linux、網絡、雲計算虛擬化、容器Docker、OpenStack、Kubernetes、工具、SDN、OVS、DPDK、Go、Python、C/C++編程技術等內容,歡迎你們關注。

相關文章
相關標籤/搜索