一、docker網絡
1、docker網絡原理
Docker本地網絡創建是利用了linux系統上的網絡命名空間和虛擬網絡設備,在本地主機和容器你分別創建一個虛擬接口,並讓他們彼此連通。
2、docker網絡創建過程
(1)創建一對虛擬接口,分別放到本地主機和新容器的命名空間中
(2)本地主機的一段連接到默認的docker0橋上,並修改爲以veth開頭的名字,容器一端的放到容器中並修改名稱爲eth0
(3)從網橋可用地址段中獲取一個空閒地址分配給容器的eth0,並配置默認的網關爲docker0網卡的內部接口docker0的IP地址。
# 創建一個不帶網絡的容器
]# docker run --name n1 --net=none -it -d busybox
]# docker exec -it n1 ifconfig
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
# 在本地查找容器的進程ip,併爲容器創建網絡命名空間
]# docker inspect -f '{{.State.Pid}}' n1
7381
]# pid=7381
]# mkdir -p /var/run/netns
]# ln -s /proc/$pid/ns/net /var/run/netns/$pid
# 檢查橋接網卡的信息
]# ip addr show docker0
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
link/ether 02:42:97:3e:f3:ad brd ff:ff:ff:ff:ff:ff
inet 10.0.0.1/16 brd 10.0.255.255 scope global docker0
valid_lft forever preferred_lft forever
# 創建一對“veth pair”接口A和接口B綁定A接口到網橋docker0並啓用
]# ip link add A type veth peer name B
]# brctl addif docker0 A
]# ip link set A up
# 將接口B放到容器的網絡命名空間,命名爲eth0啓用並配置IP地址
]# ip link set B netns $pid
]# ip netns exec $pid ip link set dev B name eth0
]# ip netns exec $pid ip link set eth0 up
]# ip netns exec $pid ip addr add 10.0.0.100/16 dev eth0
]# ip netns exec $pid ip route add default via 10.0.0.1
# 查看容器內的網絡
]# docker exec -it n1 ifconfig eth0
eth0 Link encap:Ethernet HWaddr 32:B3:BF:24:BD:81
inet addr:10.0.0.100 Bcast:0.0.0.0 Mask:255.255.0.0
3、創建容器時指定容器網絡配置
在使用”docker run”命令創建容器的過程中,可以通過”--net”參數來指定容器的網絡配置:
(1)--net-bridge:默認值,在docker網橋docker0爲容器創建新的網絡棧
(2)--net-none:創建容器時,不創建網絡,之後,用戶可以自行進行配置。
(3)--net-container:NAME_or_ID:將新建容器的進程放到一個已存在的網絡容器棧中
(4)--net=host:讓創建的容器使用本地主機的網絡
(5)--net=user_defined_network:使用用戶自定義網絡
# 創建容器時使用本地網絡
]# docker run --name n2 --net=host -it -d busybox
]# docker exec -it n2 ifconfig ens33
ens33 Link encap:Ethernet HWaddr 00:0C:29:1D:3E:4D
inet addr:192.168.16.160 Bcast:192.168.16.255 Mask:255.255.255.0
4、創建容器時的更多網絡配置
(1)以下選項只有在docker服務啓動時指定
-b BRIDGE或—bridge=BRIDGE:指定容器掛載的網橋
--bip=CIDR:指定docker0的掩碼
-H SOCKET或—host=SOCKET:docker服務端接收命令的通道
--icc=true|false:是否支持容器之間進行通信
--ip-forward=true|false:啓用net.ipv4.ip_forward,打開轉發功能
--iptables=true|false:禁止docker添加iptables規則
網絡的一些相關配置也可以配置在配置文件/etc/docker/daemon.json中,配置如下
{
"bip": "192.168.1.5/24",
"fixed-cidr": "192.168.1.5/25",
"fixed-cidr-v6": "2001:db8::/64",
"mtu": 1500,
"default-gateway": "10.20.1.1",
"default-gateway-v6": "2001:db8:abcd::89",
"dns": ["10.20.1.2","10.20.1.3"]
}
(2)dns的配置也可在創建容器及啓動容器時配置
1)--dns=IPADDRESS:使用指定的dns服務器
2)--dns-search=DOMAIN:指定dns搜索域
容器中的DNS和主機名配置都是通過宿主機的三個系統配置文件/etc/resolv.conf,/etc/hostname,/etc/hosts來維護,在啓動容器時,這三個文件都會被掛在到容器中的對應位置,/etc/resolv.conf中的內容回和宿主機該文件內容保持一致,而/etc/hosts文件中默認只記錄了容器自身的一些地址和名稱。Docker1.2開始可以直接編輯這三個文件,但修改只是臨時的。
(3)在啓動容器時可以使用的選項:
-h HOSTNAME(--hostname=HOSTNAME):配置容器的主機名
--link=CONTAINER_NAME:ALIAS:添加到另一個容器的連接
-p SPEC(--publish=SPEC):映射容器端口到宿主主機
-P (--publish-all=true|false):映射容器所有端口到宿主主機
二、容器訪問控制
1、容器訪問外部網絡的實現
容器訪問外部網絡時需要打開宿主機的網絡轉發功能。在沒有打開時,需要打開,否則容器無法訪問外部網絡。
# 查看網絡轉發功能是否打開,值等於0時表示沒有打開
]# sysctl net.ipv4.ip_forward
net.ipv4.ip_forward = 0
# 打開網絡轉發功能
]# sysctl -w net.ipv4.ip_forward=1
net.ipv4.ip_forward = 1
容器訪問外部網絡時則會進行源地址轉化(在創建容器時,默認會在iptables中添加規則),以實現容器訪問外部網絡。
# IPTABLES的轉發規則
]# iptables -t nat -vnL POSTROUTING
Chain POSTROUTING (policy ACCEPT 449 packets, 33898 bytes)
pkts bytes target prot opt in out source destination
5 345 MASQUERADE all -- * !docker0 10.0.0.0/16 0.0.0.0/0
2、容器之間的互相訪問
容器之間的訪問需要容器之間的網絡拓撲連通的情況下本地系統的iptables允許訪問時,各容器之間才能互相訪問。
3、外部網絡訪問容器的實現
讓外部網絡訪問容器,在啓動容器時通過”-P”或者”-p”參數將容器內的端口映射到宿主機上,再通過宿主機的IP加端口去訪問;其實也是對訪問的外部的IP地址進行了目的地址轉化。
]# docker run --name web1 -p 80:80 -d busybox /bin/httpd -f
]# iptables -t nat -vnL
Chain POSTROUTING (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
5 345 MASQUERADE all -- * !docker0 10.0.0.0/16 0.0.0.0/0
0 0 MASQUERADE tcp -- * * 10.0.0.2 10.0.0.2 tcp dpt:80
Chain DOCKER (2 references)
pkts bytes target prot opt in out source destination
0 0 RETURN all -- docker0 * 0.0.0.0/0 0.0.0.0/0
0 0 DNAT tcp -- !docker0 * 0.0.0.0/0 0.0.0.0/0 tcp dpt:80 to:10.0.0.2:80
三、docker網絡應用
1、使用自定義的網橋
創建容器時在不指定網絡的情況下默認通過docker0網橋來橋接的,如果不想使用docker0網橋橋接也可通過自己創建的網橋來橋接。
# 創建一個網橋
]# docker network create --driver bridge test-net
b66df5a40b4984ccb41efcb389c8772ae5e1abe5b2be8a48461b38298d6823e1
# 查看創建的網橋的配置信息
]# docker inspect network test-net
[
{
"Name": "test-net",
"Id": "b66df5a40b4984ccb41efcb389c8772ae5e1abe5b2be8a48461b38298d6823e1",
"Created": "2018-12-18T22:41:42.30515433-05:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "172.17.0.0/16",
"Gateway": "172.17.0.1"
}
]
},
……
# 創建一個容器指定網絡爲test-net
]# docker run -it --name t1 --network test-net busybox /bin/sh
/ # ifconfig eth0
eth0 Link encap:Ethernet HWaddr 02:42:AC:11:00:02
inet addr:172.17.0.2 Bcast:172.17.255.255 Mask:255.255.0.0
2、使用OpenvSwitch網橋
Docker默認使用的是linux自帶的網橋,同時,docker也可以使用openvswitch實現網絡功能
(1)安裝openvswitch
# 安裝openvswitch
]# yum install openvswitch
# 添加網橋
]# ovs-vsctl add-br br0
]# ovs-vsctl show
04ab1358-e6d4-4712-a89e-e49d175362f3
Bridge "br0"
Port "br0"
Interface "br0"
type: internal
ovs_version: "2.0.0"
(2)配置容器連接到openvswitch網橋
# 創建不帶網絡功能的容器
]# docker run -it -exec -d --name o1 --net=none busybox
743a5cc99fc20b00cf719aee81ea18f3ae5583124e586a2f8d7c9d14e44659d6
# 下載openvswitch提供的輔助腳本,並賦予執行權限(腳本地址爲https://github.com/openvswitch/ovs/blob/master/utilities/ovs-docker)
]# chmod a+x ovs-docker
# 爲容器添加網卡,並掛在到br0上
]# ./ovs-docker add-port br0 eht0 o1 --ipaddress=192.168.0.2/16
]# docker exec -it o1 ifconfig
eht0 Link encap:Ethernet HWaddr 3E:E4:8F:74:7B:38
inet addr:192.168.0.2 Bcast:0.0.0.0 Mask:255.255.0.0
# 爲網橋br0添加IP地址
]# ifconfig br0 192.168.0.1/16
3、實現兩個容器之間點到點的連接
有時需要兩個容器之間可以直接連接通信,不需要通過主機網橋進行橋接,此時可以創建一對peer接口,分別放到兩個容器接口中,配置成點到點鏈路即可。
# 創建兩個沒有網絡的容器
]# docker run -it --name p1 -d --net=none busybox
0d8d5dcdf28cfeddc97a9c13a8d3609f18aad9527927007a5cb00447b96e3117
]# docker run -it --name p2 -d --net=none busybox
a035e11b33a45dffa3ebd922ea24777c51713412fe7816cfd0d0aacb65e5bc94
# 找到進程號,創建網絡名稱空間的的追蹤文件
]# docker inspect -f {{.State.Pid}} 0d8d5dcdf28c
12823
]# docker inspect -f {{.State.Pid}} a035e11b33a4
12897
]# mkdir /var/run/netns
]# ln -s /proc/12823/ns/net /var/run/netns/12823
]# ln -s /proc/12897/ns/net /var/run/netns/12897
# 創建一對peer接口C和D
]# ip link add C type veth peer name D
# 爲兩個接口分別添加IP地址及路由信息
]# ip link set C netns 12823
]# ip netns exec 12823 ip addr add 1.1.1.1/32 dev C
]# ip netns exec 12823 ip link set C up
]# ip netns exec 12823 ip route add 1.1.1.2/32 dev C
]# ip link set D netns 12897
]# ip netns exec 12897 ip addr add 1.1.1.2/32 dev D
]# ip netns exec 12897 ip link set D up
]# ip netns exec 12897 ip route add 1.1.1.1/32 dev D
四、docker網絡命令的使用
1、插件化網絡
Docker從1.7.0版本開始把網絡和存儲的功能實現都已插化形式剝離出來,允許用戶通過指令來選擇不同的後端實現;剝離出來的獨立容器的網絡項目叫做libnetwork。
2、容器的網絡模型
Libnetwork中容器網絡模型(CNM)十分簡潔,可以讓上層使用網絡的應用容器最大程度上不去關心底層實現。網絡模型的結構如下所示:
(1)模型中的三種元素
1)Sandbox(沙盒):代表一個容器(容器的網絡命名空間)
2)Endpint:代表網絡上可以掛在容器的網絡接口,會分配IP地址
3)Network:可以連通多個接入點的一個子網
(2)網絡模型CNM支持的驅動的類型
1)Null:不提供網絡服務,容器啓動後無網絡接入
2)Bridge:Docker傳統上默認用linux網橋和iptables實現的單機網絡
3)Overlay:用vxlan隧道實現的跨主機容器網絡
4)Remote:擴展類型,預留給其他外部實現的方案
3、docker網絡相關命令
(1)常用的網絡命令
使用”docker network --help”查看有如下的網絡命令:
]# docker network --help
Usage: docker network COMMAND
Manage networks
Commands:
connect Connect a container to a network
create Create a network
disconnect Disconnect a container from a network
inspect Display detailed information on one or more networks
ls List networks
prune Remove all unused networks
rm Remove one or more networks
(2)創建網絡
命令:docker network create [OPTIONS] NETWORK
支持的選項(可通過docker network create –help查看):
--aux-address:輔助IP地址
--driver string(-d):網絡驅動類型
--gateway:網關地址
--internal:禁止外部對創建網絡的訪問
--ip-range:分配IP地址範圍
--ipam-driver:IP地址管理的插件類型
--ipam-opt:ip地址管理插件的選項
--label:爲網絡添加元標籤信息
--opt:網絡驅動支持的選項
--subnet:網絡地址段
(3)刪除網絡
命令:docker network rm NETWORK [NETWORK…]
刪除指定的網絡時,只有當網絡上不存在接入點時才能刪除成功。
(4)接入容器
接入容器是將容器連接到一個已存在的網絡上
命令:docker network connect [OPTIONS] NETWORK CONTAINER
主要選項(可”docker network connect –help”命令查看):
--alias strings:爲容器添加一個別名,此別名僅在所添加網絡上可見
--ip string:指定IP地址
--ip6 string:指定ipv6地址
--link list:添加連接到另外一個容器
--link-local-ip strings:爲容器添加一個連接地址
(5)刪除容器網絡
將一個連接到網絡上的容器從網絡上刪除
命令:docker network disconnect [OPTIONS] NETWORK CONTAINER
(6)查看網絡信息
命令:docker network inspect [OPTIONS] NETWORK [NETWORK…]