天天看點

kubernetes Spring Cloud 微服務架構—(9)Kubernetes spring cloud 微服務-Docker 進階網絡操作

9.1 網絡通信基礎

在網絡通信中,兩台主機的唯一辨別為IP 位址(V4/V6), (類似身份證号碼) 基于 IP 位址實作全世界的網絡互聯。

計算機通信 初發展,并未實作系統化與标準化,不同廠商産出各自的網絡來實作通信, 這樣導緻了計算機缺乏靈活性和可擴充性, 為了解決該問題,ISO(國際标準化組織)制定了一個國際标準 OSI(開放式通信系統互聯參考模型), (IETF(國際網際網路工程任務組)TCP/IP 模型)

OSI 模型

9.2 區域網路互聯技術

9.2.1 以太網發展

1973 年, 美國加利福尼亞州的 Xerox 公司實作了 初的以太網(3Mbps)

1980 年, Xerox 與 DEC、Intel 實作了10Mbps 以太網

1983 年, IEEE 标準委員會通過第一個 802.3 标準

1990 年, IEEE 通過了使用雙絞線媒體的以太網标準傳輸 10Mbps

9.2.2 區域網路通信裝置

集線器(HUB),實體層的裝置

 網橋又稱橋接器,(Network Bridge),資料鍊路層裝置  

交換機 Switch,資料鍊路層裝置(網管 snmp/telnet 與非網管)

9.2.3 區域網路(二層)資料轉發原理

192.168.1.10 向 192.168.1.11 發送郵件, 根據 OSI 七層模型, 資料轉發是需要封裝資料包(1500 位元組/分片重組 MTU)

1.  192.168.1.10 查詢本機的位址緩存表(arp -a), 是否有 IP 位址對應的 mac 位址, 如果有直接發送資料包,如果沒有則發送ARP 廣播

2. 192.168.1.10 向網絡發送 ARP 廣播, 詢問 192.168.1.11的 MAC 位址是多少?

3. 在未隔離廣播域的交換機上的端口都會接收到這個廣播.

4. 192.168.1.11 接收到請求以後,比對目标網絡位址, 是否是位址, 然後再回應給192.168.1.10

5. 192.168.1.10 收到 mac 位址以後, 封裝資料包,發送到交換機, 交換機根據目标 mac 轉發資料到

192.168.1.11

9.3 容器通信基礎

在Linux系統中Namespace (> 2.6.x 核心版本) 主要用于資源的隔離。在有了Namespace功能之後,在Linux系統中就可以抽象出多個網絡子系統,并且各子系統間都有自己的網絡裝置,協定棧等,彼此之間互不影響。

如果互相隔離的Namespace之間需要通信時,則用veth-pair來做連接配接作為連接配接橋梁,使原

本互不相幹的容器之間能夠互相通信。

根據網絡連接配接的方式與規模,可分為“直接相連”、“Bridge 相連” 和 “OVS 相連”。下面會詳細講解幾種模式的實作方式。

9.3.1 直接連接配接

直接相連是 簡單的方式,如下圖,一對veth-pair 直接将兩個 namespace 連接配接在一起。

#同一主控端

9.3.1.1配置不同NS, 相同網段的直接連接配接互通

9.3.1.2 建立不同的Namespace

# 建立 namespace 
[root@docker01 ~]# ip netns a ns1 
[root@docker01 ~]# ip netns a ns2      

9.3.1.3 建立veth-pair(veth0/veth1)

#建立一對 veth-pair veth0 veth1 
#建立 veth0 類型為 veth, 對端的位址為 veth1 
[root@docker01 ~]# ip l a veth0 type veth peer name veth1      

9.3.1.4 添加veth0/veth1至兩個不同的NS

/

[root@docker01 ~]# ip l s veth0 netns ns1 
[root@docker01 ~]# ip l s veth1 netns ns2      

9.3.1.5 配置veth IP 位址

#給兩個 veth0 veth1 配上 IP 并啟用, 必須為一個網段 
[root@docker01 ~]# ip netns exec ns1 ip a a 10.1.1.2/24 dev veth0 
[root@docker01 ~]# ip netns exec ns1 ip l s veth0 up 
[root@docker01 ~]# ip netns exec ns2 ip a a 10.1.1.3/24 dev veth1 
[root@docker01 ~]# ip netns exec ns2 ip l s veth1 up      

9.3.1.6 測試veth 連通性

#給兩個 veth0 veth1 配上 IP 并啟用, 必須為一個網段 
[root@docker01 ~]# ip netns exec ns1 ip a a 10.1.1.2/24 dev veth0 
[root@docker01 ~]# ip netns exec ns1 ip l s veth0 up 
[root@docker01 ~]# ip netns exec ns2 ip a a 10.1.1.3/24 dev veth1 
[root@docker01 ~]# ip netns exec ns2 ip l s veth1 up
rtt min/avg/max/mdev = 0.068/0.084/0.201/0.032 ms      

9.3.2 Linux Bridge連接配接

Linux Bridge 相當于一個網橋,可以中轉兩個namespace的流量。如下圖,兩對 veth-pair 分别将兩個 namespace 連到 Bridge 上。

9.3.2.1 配置不同NS, 相同網絡通過網橋的互通

# 建立 namespace 
[root@docker01 ~]# ip netns a ns1 
[root@docker01 ~]# ip netns a ns2      

9.3.2.2 建立網橋br0

[root@docker01 ~]# ip l a br0 type bridge 
[root@docker01 ~]# ip l s br0 up 
 
建立兩對 veth-pair 
[root@docker01 ~]# ip l a veth01 type veth peer name br-veth0 
[root@docker01 ~]# ip l a veth11 type veth peer name br-veth1      

9.3.2.3 配置veth pair, 并且加入到獨立的NS與相同的br0

9.3.2.3.1 #配置veth01的namespace為ns1, 設定br-veth0的橋接器為br0

[root@docker01 ~]# ip l s veth01 netns ns1 
[root@docker01 ~]# ip l s br-veth0 master br0 
[root@docker01 ~]# ip l s br-veth0 up      

9.3.2.3.2 配置veth11的namespace為ns2, 設定br-veth1的橋接器為br0

[root@docker01 ~]# ip l s veth11 netns ns2

[root@docker01 ~]# ip l s br-veth1 master br0

[root@docker01 ~]# ip l s br-veth1 up

9.3.2.4 配置veth01與veth11 IP 位址

# 給兩個 ns 中的 veth 配置 IP 并啟用 
[root@docker01 ~]# ip netns exec ns1 ip a a 11.1.1.2/24 dev veth01 
[root@docker01 ~]# ip netns exec ns1 ip l s veth01 up 
 
[root@docker01 ~]# ip netns exec ns2 ip a a 11.1.1.3/24 dev veth11 
[root@docker01 ~]# ip netns exec ns2 ip l s veth11 up      

9.3.2.5 測試連通性

#veth01 ping veth11 
[root@localhost ~]# ip netns exec ns1 ping 11.1.1.3 PING 11.1.1.3 (11.1.1.3) 56(84) bytes of data. 
64 bytes from 11.1.1.3: icmp_seq=1 ttl=64 time=0.060 ms 
64 bytes from 11.1.1.3: icmp_seq=2 ttl=64 time=0.105 ms 
--- 11.1.1.3 ping statistics --- 
2 packets transmitted, 2 received, 0% packet loss, time 999ms rtt min/avg/max/mdev = 0.060/0.082/0.105/0.024 ms      

9.3.3 通過OVS 連接配接

OVS 是第三方開源的 Bridge,功能比 Linux Bridge 要更強大

9.3.3.1 安裝OVS

[root@localhost ~]# yum install wget   openssl-devel  \  python-sphinx gcc make python-devel   openssl-devel kernel-devel graphviz kernel-debug-devel \ autoconf automake   rpm-build redhat-rpm-config libtool python-twisted-core python-zope-interface   \ 
PyQt4 desktop-file-utils   libcap-ng-devel groff checkpolicy python-six selinux-policy-devel -y 
[root@localhost ~]# mkdir -p   /root/rpmbuild/SOURCES 
[root@localhost ~]# cd /root/rpmbuild/SOURCES   
[root@localhost ~]# wget   http://openvswitch.org/releases/openvswitch-2.9.2.tar.gz 
[root@localhost ~]# tar xvf   openvswitch-2.9.2.tar.gz 
[root@localhost ~]# rpmbuild -bb   --nocheck openvswitch-2.9.2/rhel/openvswitch-fedora.spec 
[root@localhost ~]# yum localinstall   /root/rpmbuild/RPMS/x86_64/openvswitch-2.9.2-1.el7.centos.x86_64.rpm -y 
[root@demo SOURCES]# systemctl start   openvswitch.service 
[root@demo SOURCES]#   systemctl enable openvswitch.service      

9.3.4 配置veth通過OVS連接配接通信

9.3.4.1 通過OVS指令建立一個bridge

[root@localhost ~]# ovs-vsctl add-br ovs-br      

9.3.4.2 建立兩對veth-pair  

[root@localhost ~]# ip l a veth011 type veth peer name ovs-veth0 
[root@localhost ~]# ip l a veth111 type veth peer name ovs-veth1      

9.3.4.3 配置veth-pair添加到NS與OVS Bridge 中

#操作 veth011 
#添加 veth011 到 ns1 
[root@localhost ~]# ip l s veth011 netns ns1 
#将 ovs-veth0 添加到 ovs-br 橋接器 
[root@localhost ~]# ovs-vsctl add-port ovs-br ovs-veth0 
[root@localhost ~]# ip l s ovs-veth0 up 
#操作 veth1 
#添加 veth1 到 ns2 
[root@localhost ~]# ip l s veth111 netns ns2 
#将 ovs-veth1 添加到 ovs-br 橋接器 
[root@localhost ~]# ovs-vsctl add-port ovs-br ovs-veth1 
[root@localhost ~]# ip l s ovs-veth1 up      

9.3.4.4 配置veth IP 位址

[root@localhost ~]# ip netns exec ns1 ip a a 12.1.1.2/24 dev veth011 
[root@localhost ~]# ip netns exec ns1 ip l s veth011 up 
[root@localhost ~]# ip netns exec ns2 ip a a 12.1.1.3/24 dev veth111 
[root@localhost ~]# ip netns exec ns2 ip l s veth111 up      

9.3.4.5 測試連通性

# veth011 ping veth111

[root@localhost ~]# ip netns exec ns1   ping 12.1.1.3 PING 12.1.1.3 (12.1.1.3) 56(84) bytes of data. 
64 bytes from 12.1.1.3: icmp_seq=1   ttl=64 time=0.311 ms 
64 bytes from 12.1.1.3: icmp_seq=2   ttl=64 time=0.087 ms 
--- 12.1.1.3 ping statistics --- 
2 packets transmitted, 2 received, 0% packet   loss, time 999ms rtt min/avg/max/mdev = 0.087/0.199/0.311/0.112 ms      

9.4 Docker0 網橋詳解

Docker 服務預設會建立一個 docker0 網橋(其上有一個 docker0 内部接口),它在核心層連通了其他的實體或虛拟網卡,這就将所有容器和主控端都在同一個實體網絡。

Docker 預設指定了 docker0 接口 的 IP 位址和子網路遮罩,讓主機和容器之間可以通過網橋互相通信,它還給出了 MTU(接口允許接收的    大傳輸單元),以太網通常是 1500

Bytes,或主控端網絡路由上支援的預設值。這些值都可以在服務啟動的時候進行配置。

--bip=CIDR -- IP 位址加掩碼格式,例如192.168.100.5/24

--mtu=BYTES -- 覆寫預設的 Docker mtu 配置

也可以在配置檔案中配置DOCKER_OPTS,然後重新開機服務。 由于目前 Docker 網橋是 Linux 網橋,使用者可以使用 brctl show 來檢視網橋和端口連接配接資訊。

9.4.1 檢視docker0網橋

9.4.2 安裝網絡工具

#如果已經安裝 Docker CE 則無需要再安裝 
[root@node-2 ~]#  yum install -y yum-utils device-mapper-persistent-data lvm2 
[root@node-2 ~]#  yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo [root@node-2 ~]#  yum install docker-ce-19.03.6 docker-ce-cli-19.03.6 containerd.io -y 
#安裝網絡檢視工具 
[root@node-2 ~]#  yum install bridge-utils      

9.4.3 檢視網絡

#檢視系統網絡接口 
[root@node-2 ~]# ip a 
1: lo: <LOOPBACK,UP,LOWER_UP>   mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000     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 
2:   ens32: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast   state UP group default qlen
1000 
      link/ether 00:0c:29:14:38:91 brd ff:ff:ff:ff:ff:ff     inet 192.168.91.136/24 brd 192.168.91.255   scope global noprefixroute ens32          valid_lft forever preferred_lft forever     inet6 fe80::7dfd:e7a3:7683:20e7/64 scope   link noprefixroute         valid_lft   forever preferred_lft forever 
3: docker0:   <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN   group default      link/ether   02:42:2f:4c:4a:2b brd ff:ff:ff:ff:ff:ff       inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0        valid_lft forever preferred_lft forever      

9.4.4 檢視網橋

[root@node-2 ~]# brctl show bridge name     bridge id               STP enabled     interfaces docker0         8000.02422f4c4a2b       no      

9.4.5 啟動nginx demo容器

#運作 nginx demo 
[root@node-2 ~]# docker run --name nginx-demo -p 8081:80 -d nginx      

9.4.6 擷取容器程序id

#系統所支援的網絡命名空間(在核心中根據程序号隔離) 
[root@node-2 ~]# ll /proc/1370/ns/ total 0 lrwxrwxrwx 1 root root 0 Nov  6 11:51 ipc -> ipc:[4026532449] lrwxrwxrwx 1 root root 0 Nov  6 11:51 mnt -> mnt:[4026532447] lrwxrwxrwx 1 root root 0 Nov  6 11:50 net -> net:[4026532443] lrwxrwxrwx 1 root root 0 Nov  6 11:51 pid -> pid:[4026532450] lrwxrwxrwx 1 root root 0 Nov  6 11:51 user -> user:[4026531837] lrwxrwxrwx 1 root root 0 Nov  6 11:51 uts -> uts:[4026532448]      

9.4.7 檢視命名空間

#系統所支援的網絡命名空間(在核心中根據程序号隔離) 
[root@node-2 ~]# ll /proc/1370/ns/ total 0 lrwxrwxrwx 1 root root 0 Nov  6 11:51 ipc -> ipc:[4026532449] lrwxrwxrwx 1 root root 0 Nov  6 11:51 mnt -> mnt:[4026532447] lrwxrwxrwx 1 root root 0 Nov  6 11:50 net -> net:[4026532443] lrwxrwxrwx 1 root root 0 Nov  6 11:51 pid -> pid:[4026532450] lrwxrwxrwx 1 root root 0 Nov  6 11:51 user -> user:[4026531837] lrwxrwxrwx 1 root root 0 Nov  6 11:51 uts -> uts:[4026532448]      

9.4.8 通過程序id 擷取到網絡命名空間

[root@demo ~]# ll /proc/1370/ns/net 
lrwxrwxrwx 1 root root 0 Mar 23 23:35 /proc/1370/ns/net -> net:[4026532443]      

9.4.9 檢視系統網絡接口

#檢視網絡結構, 多了一塊網卡 
[root@node-2 ~]# ip a 
1: lo: <LOOPBACK,UP,LOWER_UP>   mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000     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 
2:   ens32:   <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP   group default qlen
1000 
      link/ether 00:0c:29:14:38:91 brd ff:ff:ff:ff:ff:ff     inet 192.168.91.136/24 brd   192.168.91.255 scope global noprefixroute ens32        valid_lft forever preferred_lft   forever     inet6   fe80::7dfd:e7a3:7683:20e7/64 scope link noprefixroute         valid_lft forever preferred_lft   forever 
3: docker0:   <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group   default      link/ether 02:42:2f:4c:4a:2b   brd ff:ff:ff:ff:ff:ff     inet 172.17.0.1/16   brd 172.17.255.255 scope global docker0        valid_lft forever preferred_lft   forever     inet6   fe80::42:2fff:fe4c:4a2b/64 scope link           valid_lft forever preferred_lft forever 
5:   veth7ebd9ef@if4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue   master docker0 state   UP group default      link/ether b2:12:dc:e7:a5:17 brd   ff:ff:ff:ff:ff:ff link-netnsid 0       inet6 fe80::b012:dcff:fee7:a517/64 scope link         valid_lft forever preferred_lft forever      

9.4.9.1 檢視網卡橋接

[root@demo ~]# brctl show bridge name     bridge id               STP enabled     interfaces docker0         8000.0242c736b32f       no              veth7ebd9ef

9.4.9.2 檢視Iptables

#iptables 存在有位址轉換

[root@node-2 ~]# iptables -L -n -t nat   Chain DOCKER (2 references) 
target     prot opt source               destination          
RETURN     all    --  0.0.0.0/0            0.0.0.0/0            
DNAT       tcp    --  0.0.0.0/0            0.0.0.0/0            tcp dpt:8081 to:172.17.0.2:80      

9.5 建立 Docker 自定義網橋

Docker 自定義網橋除了預設的 docker0 網橋,使用者也可以指定網橋來連接配接各個容器。在啟動 Docker 服務的時候,使用 -b BRIDGE或--bridge=BRIDGE 來指定使用的網橋。如果Docker服務已經運作,那需要先停止服務。

9.5.1 自定義網橋邏輯架構圖容器通過自定義的網橋bridge0通路外網

9.5.2 停止docker 服務

[root@node-2 ~]# service docker stop

9.5.3 建立自定義網橋bridge0

#設定bridge0網段為192.168.6.0/24 
#添加網橋 
[root@node-2 ~]# brctl addbr bridge0 
#設定網橋 IP 位址段 
[root@node-2 ~]# ip addr add 192.168.6.1/24 dev bridge0 
#設定網橋狀态 UP 
[root@node-2 ~]# ip link set dev bridge0 up      

9.5.4 檢視網絡

#檢視系統增加橋接器bridge0

[root@node-2 ~]# ip a 
1: lo: <LOOPBACK,UP,LOWER_UP>   mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000     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 
2:   ens32: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast   state UP group default qlen
1000 
      link/ether 00:0c:29:14:38:91 brd ff:ff:ff:ff:ff:ff     inet 192.168.91.136/24 brd   192.168.91.255 scope global noprefixroute ens32        valid_lft forever preferred_lft   forever     inet6   fe80::7dfd:e7a3:7683:20e7/64 scope link noprefixroute         valid_lft forever preferred_lft   forever 
3: docker0:   <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN   group default      link/ether   02:42:2f:4c:4a:2b brd ff:ff:ff:ff:ff:ff       inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0        valid_lft forever preferred_lft   forever     inet6   fe80::42:2fff:fe4c:4a2b/64 scope link           valid_lft forever preferred_lft forever 
6:   bridge0:   <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN   group default qlen 1000     link/ether   12:e7:be:6c:aa:1c brd ff:ff:ff:ff:ff:ff       inet 192.168.6.1/24 scope global bridge0        valid_lft forever preferred_lft   forever     inet6   fe80::10e7:beff:fe6c:aa1c/64 scope link tentative         valid_lft forever preferred_lft   forever      

9.5.5 檢視系統所有橋接器

[root@node-2 ~]# brctl show bridge name     bridge id               STP enabled     interfaces bridge0         8000.000000000000       no docker0         8000.02422f4c4a2b       no      

9.5.6 檢視網橋狀态

[root@node-2 ~]# ip addr show bridge0 
6: bridge0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN group default qlen 1000     link/ether 12:e7:be:6c:aa:1c brd ff:ff:ff:ff:ff:ff    inet 192.168.6.1/24 scope global bridge0        valid_lft forever preferred_lft forever
    inet6 fe80::10e7:beff:fe6c:aa1c/64 scope link         valid_lft forever preferred_lft forever      

9.5.7 配置Docker使用新網橋bridge0

[root@node-2 ~]# cat /etc/docker/daemon.json     
{ 
  "bridge": "bridge0" 
} 
 
#完整配置 
{ 
   "bridge": "bridge0", 
  "registry-mirrors": ["https://plqjafsr.mirror.aliyuncs.com"], 
   "data-root": "/data/docker", 
    "storage-driver": "overlay2", 
    "storage-opts": [ 
     "overlay2.override_kernel_check=true", 
      "overlay2.size=1G" 
    ] 
}      

9.5.8 重新開機docker 服務

#重載

[root@node-2 ~]# systemctl daemon-reload

[root@node-2 ~]# service docker restart

9.5.8.1 啟動容器

#啟動一個已經退出的容器

[root@demo ~]# docker ps -a 
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                     PORTS               NAMES 
400fb9f1f415 centos              "/bin/bash"              27 hours ago        Exited (1) 26 hours ago                        happy_lumiere 
#啟動容器 
[root@demo ~]# docker start   400fb9f1f415 
#進入終端 
[root@demo ~]# docker exec -it   400fb9f1f415 /bin/bash 
[root@400fb9f1f415 /]# ip a 
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536   qdisc noqueue state UNKNOWN group default qlen 1000     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      

9.5.9 運作容器,是否可以使用新網橋

9.5.9.1 重新運作容器

[root@node-2 ~]#  docker run -it --name centos-d1 centos /bin/bash

9.5.9.2 使用 ping 測試網絡連通性

/ # ping www.baidu.com

PING www.baidu.com (163.177.151.109): 56 data bytes

64 bytes from 163.177.151.109: seq=0 ttl=127 time=9.102 ms

64 bytes from 163.177.151.109: seq=1 ttl=127 time=9.358 ms

64 bytes from 163.177.151.109: seq=2 ttl=127 time=9.284 ms

9.5.9.3 檢視容器ip

#新容器使用bridge0網段192.168.6.0/24, docker0為172.17.0.0/16 網段

[root@node-2 ~]# docker run -ti   centos 
/ # ip a 
1: lo: <LOOPBACK,UP,LOWER_UP>   mtu 65536 qdisc noqueue qlen 1000       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 
30: eth0@if31:   <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue      link/ether 02:42:c0:a8:06:03 brd   ff:ff:ff:ff:ff:ff     inet 192.168.6.3/24 brd 192.168.6.255 scope   global eth0        valid_lft forever   preferred_lft forever      

9.5.9.4 檢視系統Iptables 轉發規則 MASQUERADE:  

通過MASQUERADE自動實作SNAT,把192.168.6.0網段的位址, 轉換發送到外網。  也就是說在自定義添加了網橋以後, docker 會自動添加網橋的網段到iptables SNAT 的規則中,實作容器啟動以後能夠自動的連接配接到外網。

[root@node-2 ~]# iptables -L -n -t nat 
……….省略 
Chain POSTROUTING (policy ACCEPT) 
target     prot opt source               destination          
MASQUERADE  all --  192.168.6.0/24   0.0.0.0/0      

9.6 容器 None 網絡模式添加網卡

Docker 的網絡實作其實就是利用了 Linux 上的網絡名字空間隔離技術和虛拟網絡裝置(veth pair)連接配接技術,實作容器對外部網絡的通路。

9.6.1 建立容器流程回顧(橋接模式)

Docker 建立一個容器的時候,會執行如下操作:

建立一對虛拟接口(veth pair),分别放到本地主機和新容器中;本地主機一端橋接到預設的 docker0 或指定網橋上,并具有一個唯一的名字,比如 veth65f9;容器一端放到新容器中,并修改名字作為 eth0,這個接口隻在容器的名字空間可見;從網橋可用位址段中擷取一個空閑位址配置設定給容器的 eth0,并配置預設路由到橋接網卡 veth65f9。完成這些之後,容器就可以使用 eth0 虛拟網卡來連接配接其他容器和其他網絡。

9.6.1.1 本案例實作的效果為容器busybox容器添加自定義的網卡,容器可以通過網卡連接配接到外部網絡。

9.6.2 操作過程

9.6.2.1 建立一個容器, 設定網絡模式是none

#啟動一個 /bin/bash 容器,指定--net=none 參數。

[root@demo ~]# docker run -it --name=demo-none  --net=none busybox

9.6.3 檢視容器IP

#此時的容器是沒有任何IP

/ # ip a

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000     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

9.6.4 擷取容器id

#在本地主機查找容器的程序 id

[root@node-2 ~]# docker ps

CONTAINER ID  IMAGE  COMMAND    CREATED       STATUS              PORTS               NAMES

38078e9a638d busybox  "sh" 13 minutes ago Up 13 minutes                          youthful_chandrasekhar

9.6.5 擷取到容器的程序id

[root@node-2 ~]# docker inspect -f '{{.State.Pid}}' demo-none 
13034 
 
9.6.6 建立網絡命名空間挂載點 
[root@node-2 ~]# pid=13034 
 
#建立網絡空間挂載點(本地檔案目錄) 
[root@node-2 ~]# mkdir -p /var/run/netns 
 
#綁定網絡命名空間到挂載點 
[root@node-2 ~]# ln -s /proc/$pid/ns/net  /var/run/netns/$pid      

9.6.7 檢視需要添加的橋接器的網段與橋接器名稱

#檢查橋接網卡的 IP 和子網路遮罩資訊。 
[root@node-2 ~]# ip addr show bridge0   
6: bridge0:   <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN   group default qlen 1000     link/ether   00:00:00:00:00:00 brd ff:ff:ff:ff:ff:ff 
    inet 192.168.6.1/24 scope global bridge0                #容器網關位址        valid_lft forever   preferred_lft forever     inet6   fe80::10e7:beff:fe6c:aa1c/64 scope link         valid_lft forever preferred_lft forever      

9.6.8 建立veth-pair 

namespace之間需要通信,用veth-pair 來做橋梁建立一對 “veth pair” 接口 A 和 B,綁定 A 到網橋 bridge0,并啟用。 
A 為: veth 接口(主控端), B 為容器網卡 
[root@node-2 ~]# ip link add A type veth peer name B 
 
#設定 A veth 橋接到 bridge0 
[root@node-2 ~]# brctl addif bridge0 A 
 
#啟動 veth A 
[root@node-2 ~]# ip link set A up      

9.6.9 設定網絡與ip

#将B放到容器的網絡命名空間,命名為 eth10,啟動它并配置一個可用 IP(橋接網段)和預設網關。 
#添加網卡 B 到網絡命名空間 13034 
[root@node-2 ~]# ip link set B netns $pid 
 
#設定容器網卡的名稱為 eth10 
[root@node-2 ~]# ip netns exec $pid ip link set dev B name eth10 
 
#設定網卡的狀态為 up 
[root@node-2 ~]# ip netns exec $pid ip link set eth10 up 
 
#設定容器網卡的 ip 位址 
[root@node-2 ~]# ip netns exec $pid ip addr add 192.168.6.100/24 dev eth10 
 
#設定預設路由 
[root@node-2 ~]# ip netns exec $pid ip route add default via 192.168.6.1      

9.6.9.1 檢視容器ip

#檢視容器是否有 eth10 
/ # ip a 
1: lo: <LOOPBACK,UP,LOWER_UP>   mtu 65536 qdisc noqueue qlen 1000     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 
20: eth10@if21:   <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue qlen   1000     link/ether 8e:6b:02:17:36:0a   brd ff:ff:ff:ff:ff:ff     inet 192.168.6.100/24 scope global eth10        valid_lft forever preferred_lft   forever      

9.6.9.2 檢視主控端網橋

[root@node-2 ~]# brctl show bridge name     bridge id               STP enabled     interfaces bridge0         8000.1651b5e3adba       no              A docker0         8000.02422f4c4a2b       no 

9.6.9.3 檢視系統網卡

[root@node-2 ~]# ip a 
1: lo: <LOOPBACK,UP,LOWER_UP>   mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000     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 
2:   ens32: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast   state UP group default qlen
1000 
      link/ether 00:0c:29:14:38:91 brd ff:ff:ff:ff:ff:ff     inet 192.168.91.136/24 brd 192.168.91.255   scope global noprefixroute ens32          valid_lft forever preferred_lft forever     inet6 fe80::7dfd:e7a3:7683:20e7/64 scope   link noprefixroute      
valid_lft forever preferred_lft forever 
3: docker0:   <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN   group default      link/ether   02:42:2f:4c:4a:2b brd ff:ff:ff:ff:ff:ff       inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0        valid_lft forever preferred_lft forever     inet6 fe80::42:2fff:fe4c:4a2b/64 scope   link         valid_lft forever preferred_lft forever 
6:   bridge0:   <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group   default qlen
1000 
      link/ether 16:51:b5:e3:ad:ba brd ff:ff:ff:ff:ff:ff     inet 192.168.6.1/24 scope global bridge0        valid_lft forever preferred_lft   forever     inet6   fe80::10e7:beff:fe6c:aa1c/64 scope link         valid_lft forever preferred_lft   forever 
21: A@if20: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue   master bridge0 state UP group default qlen 1000     link/ether 16:51:b5:e3:ad:ba brd   ff:ff:ff:ff:ff:ff link-netnsid 0       inet6 fe80::1451:b5ff:fee3:adba/64 scope link         valid_lft forever preferred_lft   forever      

9.7 運作容器 IP 添加位址

#拉取鏡像 CentOS 
[root@ demo ~]# docker pull centos 
 

      

9.7.1 運作容器

#前台運作centos

[root@demo ~]# docker run --name=centos-IP1 -it centos /bin/bash

9.7.2 擷取到容器啟動程序号

[root@ demo ~]# docker inspect -f '{{.State.Pid}}' centos-IP1  

13575

9.7.3 容器修改之前的ip 

[root@95d78806950d /]# ip a 
1: lo: <LOOPBACK,UP,LOWER_UP>   mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000     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 
28: eth0@if29:   <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group   default      link/ether   02:42:c0:a8:06:03 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 192.168.6.3/24 brd 192.168.6.255 scope global eth0        valid_lft forever preferred_lft forever      

9.7.4 建立容器網絡命名空間挂載點

[root@ demo ~]# pid=13575 
 
#無法直接操作必須要有網絡空間挂載點 
[root@demo ~]# ip netns exec $pid ip a 
Cannot open network namespace "13575": No such file or directory 
 
[root@ demo ~]# mkdir -p /var/run/netns 
#建立網絡空間挂載點 
[root@ demo ~]# ln -s /proc/$pid/ns/net  /var/run/netns/$pid 
 
#檢視現在容器 IP 
[root@ demo ~]# ip netns exec $pid ip a 
 
9.7.5 設定容器新IP 
#設定容器的ip 位址 
[root@ demo ~]# ip netns exec $pid ip addr add 192.168.6.10/24 dev eth0 
 
9.7.6 容器内部檢驗IP 
#檢驗新的ip 位址是否添加 
[root@ demo ~]# ip netns exec $pid ip a      

9.8 總結 Docker 實作原理

1)   底層硬體支撐, 也可以用虛拟機運作Docker。

2)   在硬體或虛拟機内安裝支援容器運作的作業系統

3) Docker 通過NS、Cgroups與OverlayFs技術實作容器的加載啟動.

4)容器通過利用系統中的Docker0網橋與外部網絡互通。