Docker容器間網絡通信

自從Docker容器出現以來,容器網絡通信就一直是被關注的焦點,也是生產環境的迫切需求。容器網絡通信又分為兩大方面:單主機容器上的相互通信,和跨主機的容器相互通信。

一、Docker單主機容器通信
基于對net namespace的控制,docker可以為在容器創建隔離的網絡環境,在隔離的網絡環境下,容器具有完全獨立的網絡棧,與宿主機隔離,也可以使容器共享主機或者其他容器的網絡命名空間,基本可以滿足開發者在各種場景下的需要。

按docker官方的說法,docker容器的網絡有五種模式:
bridge模式,--net=bridge(默認)
這是dokcer網絡的默認設置,為容器創建獨立的網絡命名空間,容器具有獨立的網卡等所有單獨的網絡棧,是最常用的使用方式。在docker run啟動容器的時候,如果不加--net參數,就默認采用這種網絡模式。安裝完docker,系統會自動添加一個供docker使用的網橋docker0,我們創建一個新的容器時,容器通過DHCP獲取一個與docker0同網段的IP地址,并默認連接到docker0網橋,以此實現容器與宿主機的網絡互通。

host模式,--net=host
這個模式下創建出來的容器,直接使用容器宿主機的網絡命名空間。將不擁有自己獨立的Network Namespace,即沒有獨立的網絡環境。它使用宿主機的ip和端口。

none模式,--net=none
為容器創建獨立網絡命名空間,但不為它做任何網絡配置,容器中只有lo,用戶可以在此基礎上,對容器網絡做任意定制。這個模式下,dokcer不為容器進行任何網絡配置。需要我們自己為容器添加網卡,配置IP。因此,若想使用pipework配置docker容器的ip地址,必須要在none模式下才可以。

其他容器模式(即container模式,join模式),--net=container:NAME_or_ID
與host模式類似,只是容器將與指定的容器共享網絡命名空間。這個模式就是指定一個已有的容器,共享該容器的IP和端口。除了網絡方面兩個容器共享,其他的如文件系統,進程等還是隔離開的。

用戶自定義:docker 1.9版本以后新增的特性,允許容器使用第三方的網絡實現或者創建單獨的bridge網絡,提供網絡隔離能力。

這些網絡模式在相互網絡通信方面的對比如下所示:

南北向通信指容器與宿主機外界的訪問機制,東西向流量指同一宿主機上,與其他容器相互訪問的機制。

1)host模式
由于容器和宿主機共享同一個網絡命名空間,換言之,容器的IP地址即為宿主機的IP地址。所以容器可以和宿主機一樣,使用宿主機的任意網卡,實現和外界的通信。其網絡模型可以參照下圖:

采用host模式的容器,可以直接使用宿主機的IP地址與外界進行通信,若宿主機具有公有IP,那么容器也擁有這個公有IP。同時容器內服務的端口也可以使用宿主機的端口,無需額外進行NAT轉換,而且由于容器通信時,不再需要通過linuxbridge等方式轉發或數據包的拆封,性能上有很大優勢。當然,這種模式有優勢,也就有劣勢,主要包括以下幾個方面:
1)最明顯的就是容器不再擁有隔離、獨立的網絡棧。容器會與宿主機競爭網絡棧的使用,并且容器的崩潰就可能導致宿主機崩潰,在生產環境中,這種問題可能是不被允許的。
2)容器內部將不再擁有所有的端口資源,因為一些端口已經被宿主機服務、bridge模式的容器端口綁定等其他服務占用掉了。

2)bridge模式
bridge模式是docker默認的,也是開發者最常使用的網絡模式。在這種模式下,docker為容器創建獨立的網絡棧,保證容器內的進程使用獨立的網絡環境,實現容器之間、容器與宿主機之間的網絡棧隔離。同時,通過宿主機上的docker0網橋,容器可以與宿主機乃至外界進行網絡通信。其網絡模型可以參考下圖:

從上面的網絡模型可以看出,容器從原理上是可以與宿主機乃至外界的其他機器通信的。同一宿主機上,容器之間都是連接掉docker0這個網橋上的,它可以作為虛擬交換機使容器可以相互通信。然而,由于宿主機的IP地址與容器veth pair的 IP地址均不在同一個網段,故僅僅依靠veth pair和namespace的技術,還不足以使宿主機以外的網絡主動發現容器的存在。為了使外界可以方位容器中的進程,docker采用了端口綁定的方式,也就是通過iptables的NAT,將宿主機上的端口端口流量轉發到容器內的端口上。舉一個簡單的例子,使用下面的命令創建容器,并將宿主機的3306端口綁定到容器的3306端口:?

1

# docker run -tid --name db -p 3306:3306 MySQL

在宿主機上,可以通過iptables -t nat -L -n,查到一條DNAT規則:

1

# DNAT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:3306 to:172.17.0.5:3306

上面的172.17.0.5即為bridge模式下,創建的容器IP。

很明顯,bridge模式的容器與外界通信時,必定會占用宿主機上的端口,從而與宿主機競爭端口資源,對宿主機端口的管理會是一個比較大的問題。同時,由于容器與外界通信是基于三層上iptables NAT,性能和效率上的損耗是可以預見的。

3)none模式
在這種模式下,容器有獨立的網絡棧,但不包含任何網絡配置,只具有lo這個loopback網卡用于進程通信。也就是說,none模式為容器做了最少的網絡設置,但是俗話說得好“少即是多”,在沒有網絡配置的情況下,通過第三方工具或者手工的方式,開發這任意定制容器的網絡,提供了最高的靈活性。

4)其他容器(container)模式
其他網絡模式是docker中一種較為特別的網絡的模式。在這個模式下的容器,會使用其他容器的網絡命名空間,其網絡隔離性會處于bridge橋接模式與host模式之間。當容器共享其他容器的網絡命名空間,則在這兩個容器之間不存在網絡隔離,而她們又與宿主機以及除此之外其他的容器存在網絡隔離。其網絡模型可以參考下圖:

在這種模式下的容器可以通過localhost來同一網絡命名空間下的其他容器,傳輸效率較高。而且這種模式還節約了一定數量的網絡資源,但它并沒有改變容器與外界通信的方式。在一些特殊的場景中非常有用,例如,kubernetes的pod,kubernetes為pod創建一個基礎設施容器,同一pod下的其他容器都以其他容器模式共享這個基礎設施容器的網絡命名空間,相互之間以localhost訪問,構成一個統一的整體。

5)用戶定義網絡模式
在用戶定義網絡模式下,開發者可以使用任何docker支持的第三方網絡driver來定制容器的網絡。并且,docker 1.9以上的版本默認自帶了bridge和overlay兩種類型的自定義網絡driver。可以用于集成calico、weave、openvswitch等第三方廠商的網絡實現。 除了docker自帶的bridge driver,其他的幾種driver都可以實現容器的跨主機通信。而基于bdrige driver的網絡,docker會自動為其創建iptables規則,保證與其他網絡之間、與docker0之間的網絡隔離。 例如,使用下面的命令創建一個基于bridge driver的自定義網絡:

1

# docker network create bri1

則docker會自動生成如下的iptables規則,保證不同網絡上的容器無法互相通信。

1

2

# -A DOCKER-ISOLATION -i br-8dba6df70456 -o docker0 -j DROP

# -A DOCKER-ISOLATION -i docker0 -o br-8dba6df70456 -j DROP

除此之外,bridge driver的所有行為都和默認的bridge模式完全一致。而overlay及其他driver,則可以實現容器的跨主機通信。

二、Docker跨主機容器通信

早期大家的跨主機通信方案主要有以下幾種:
1)容器使用host模式:容器直接使用宿主機的網絡,這樣天生就可以支持跨主機通信。雖然可以解決跨主機通信問題,但這種方式應用場景很有限,容易出現端口沖突,也無法做到隔離網絡環境,一個容器崩潰很可能引起整個宿主機的崩潰。

2)端口綁定:通過綁定容器端口到宿主機端口,跨主機通信時,使用主機IP+端口的方式訪問容器中的服務。顯而易見,這種方式僅能支持網絡棧的四層及以上的應用,并且容器與宿主機緊耦合,很難靈活的處理,可擴展性不佳。

3)docker外定制容器網絡:在容器通過docker創建完成后,然后再通過修改容器的網絡命名空間來定義容器網絡。典型的就是很久以前的pipework,容器以none模式創建,pipework通過進入容器的網絡命名空間為容器重新配置網絡,這樣容器網絡可以是靜態IP、vxlan網絡等各種方式,非常靈活,容器啟動的一段時間內會沒有IP,明顯無法在大規模場景下使用,只能在實驗室中測試使用。

4)第三方SDN定義容器網絡:使用Open vSwitch或Flannel等第三方SDN工具,為容器構建可以跨主機通信的網絡環境。這些方案一般要求各個主機上的docker0網橋的cidr不同,以避免出現IP沖突的問題,限制了容器在宿主機上的可獲取IP范圍。并且在容器需要對集群外提供服務時,需要比較復雜的配置,對部署實施人員的網絡技能要求比較高。

上面這些方案有各種各樣的缺陷,同時也因為跨主機通信的迫切需求,docker 1.9版本時,官方提出了基于vxlan的overlay網絡實現,原生支持容器的跨主機通信。同時,還支持通過libnetwork的plugin機制擴展各種第三方實現,從而以不同的方式實現跨主機通信。就目前社區比較流行的方案來說,跨主機通信的基本實現方案有以下幾種:

1)基于隧道的overlay網絡:按隧道類型來說,不同的公司或者組織有不同的實現方案。docker原生的overlay網絡就是基于vxlan隧道實現的。ovn則需要通過geneve或者stt隧道來實現的。flannel最新版本也開始默認基于vxlan實現overlay網絡。
2)基于包封裝的overlay網絡:基于UDP封裝等數據包包裝方式,在docker集群上實現跨主機網絡。典型實現方案有Weave、Flannel的早期版本。
3)基于三層實現SDN網絡:基于三層協議和路由,直接在三層上實現跨主機網絡,并且通過iptables實現網絡的安全隔離。典型的方案為?Calico。同時對不支持三層路由的環境,Calico還提供了基于IPIP封裝的跨主機網絡實現

Dokcer通過使用Linux橋接提供容器之間的通信,docker0橋接接口的目的就是方便Docker管理。當Docker daemon啟動時需要做以下操作:
->? 如果docker0不存在則創建
->? 搜索一個與當前路由不沖突的ip段
->? 在確定的范圍中選擇 ip
->? 綁定ip到 docker0

列出當前主機網橋

1

2

3

[root@localhost ~]# brctl show

bridge name??? bridgeid???????????STP enabled?? interfaces

docker0??????? 8000.02426f15541e?? no??????????? vethe833b02

查看當前 docker0 ip

1

2

3

4

5

6

7

8

9

10

[root@localhost ~]# ifconfig

docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>? mtu 1500

????????inet 172.17.0.1? netmask 255.255.0.0? broadcast 0.0.0.0

????????inet6 fe80::42:6fff:fe15:541e? prefixlen 64? scopeid 0x20<link>

????????ether 02:42:6f:15:54:1e? txqueuelen 0? (Ethernet)

????????RX packets 120315? bytes 828868638 (790.4 MiB)

????????RX errors 0? dropped 0? overruns 0? frame 0

????????TX packets 132565? bytes 100884398 (96.2 MiB)

????????TX errors 0? dropped 0 overruns 0? carrier 0? collisions 0

................

在容器運行時,每個容器都會分配一個特定的虛擬機口并橋接到docker0。每個容器都會配置同docker0 ip相同網段的專用ip 地址,docker0的IP地址被用于所有容器的默認網關。
一般啟動的容器中ip默認是172.17.0.1/24網段的。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

[root@linux-node2 ~]# docker images

REPOSITORY?????????????????? TAG???????????????? IMAGE ID??????????? CREATED???????????? SIZE

centos?????????????????????? latest????????????? 67591570dd29??????? 3 months ago??????? 191.8 MB

[root@linux-node2 ~]# docker run -t -i --name my-test centos /bin/bash

[root@c5217f7bd44c /]#

[root@linux-node2 ~]# docker ps

CONTAINER ID??????? IMAGE?????????????? COMMAND???????????? CREATED???????????? STATUS????????????? PORTS??????????????????? NAMES

c5217f7bd44c??????? centos?????????????"/bin/bash"?????????10 seconds ago????? Up 10 seconds??????????????????????????????? my-test

[root@linux-node2 ~]# docker inspect c5217f7bd44c|grep IPAddress

????????????"SecondaryIPAddresses": null,

????????????"IPAddress":"172.17.0.2",

????????????????????"IPAddress":"172.17.0.2",

那么能不能在創建容器的時候指定特定的ip呢?這是當然可以實現的!

注意:宿主機的ip路由轉發功能一定要打開,否則所創建的容器無法聯網!

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

[root@localhost ~]# cat /proc/sys/net/ipv4/ip_forward

1

[root@localhost ~]#

[root@localhost ~]# docker ps

CONTAINER ID??????? IMAGE?????????????? COMMAND???????????? CREATED???????????? STATUS????????????? PORTS?????????????? NAMES

6e64eade06d1??????? docker.io/centos????"/bin/bash"?????????10 seconds ago????? Up 9 seconds??????????????????????????? my-centos

[root@localhost ~]# docker run -itd --net=none --name=container1 docker.io/centos

5e5bdbc4d9977e6bcfa40e0a9c3be10806323c9bf5a60569775903d345869b09

[root@localhost ~]# docker attach container1

[root@5e5bdbc4d997 /]# ping www.baidu.com

PING www.a.shifen.com (61.135.169.121) 56(84) bytes of data.

64 bytes from 61.135.169.121 (61.135.169.121): icmp_seq=1 ttl=53time=2.09 ms

64 bytes from 61.135.169.121 (61.135.169.121): icmp_seq=2 ttl=53time=2.09 ms

關閉ip路由轉發功能,容器即不能聯網

[root@localhost ~]# echo 0 > /proc/sys/net/ipv4/ip_forward

[root@localhost ~]# cat /proc/sys/net/ipv4/ip_forward

0

[root@5e5bdbc4d997 /]# ping www.baidu.com??????? //ping不通~

2.1、創建容器使用特定范圍的IP

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

Docker 會嘗試尋找沒有被主機使用的ip段,盡管它適用于大多數情況下,但是它不是萬能的,有時候我們還是需要對ip進一步規劃。

Docker允許你管理docker0橋接或者通過-b選項自定義橋接網卡,需要安裝bridge-utils軟件包。操作流程如下:

a)確保docker的進程是停止的

b)創建自定義網橋

c)給網橋分配特定的ip

d)以-b的方式指定網橋

??

具體操作過程如下(比如創建容器的時候,指定ip為192.168.5.1/24網段的):

[root@localhost ~]# service docker stop

[root@localhost ~]# ip link set dev docker0 down

[root@localhost ~]# brctl delbr docker0

[root@localhost ~]# brctl addbr bridge0

[root@localhost ~]# ip addr add 192.168.5.1/24 dev bridge0????? //注意,這個192.168.5.1就是所建容器的網關地址。通過docker inspect container_id能查看到

[root@localhost ~]# ip link set dev bridge0 up

[root@localhost ~]# ip addr show bridge0

[root@localhost ~]# vim /etc/sysconfig/docker????? //即將虛擬的橋接口由默認的docker0改為bridge0

OPTIONS='--selinux-enabled --log-driver=journald'

改為

OPTIONS='--selinux-enabled --log-driver=journald -b=bridge0'????//即添加-b=bridge0

??

[root@localhost ~]# service docker restart

??

--------------------------------------------------------------------------------------

上面是centos7下的操作步驟,下面提供下ubuntu下的操作步驟:

$sudo?service docker stop

$sudo?ip linkset?dev docker0 down

$sudo?brctl delbr docker0

$sudo?brctl addbr bridge0

$sudo?ip addr add 192.168.5.1/24?dev bridge0

$sudo?ip linkset?dev bridge0 up

$ ip addr show bridge0

$echo?'DOCKER_OPTS="-b=bridge0"'?>>/etc/default/docker

$sudo?service docker start

--------------------------------------------------------------------------------------

??

然后創建容器,查看下容器ip是否為設定的192.168.5.1/24網段的

[root@localhost ~]# docker images

REPOSITORY????????? TAG???????????????? IMAGE ID??????????? CREATED???????????? SIZE

docker.io/ubuntu????latest????????????? 0ef2e08ed3fa??????? 2 weeks ago???????? 130 MB

centos7???????????? 7.3.1611??????????? d5ebea14da54??????? 3 weeks ago???????? 311 MB

??

[root@localhost ~]# docker run -t -i --name test2 centos7:7.3.1611 /bin/bash

[root@224facf8e054 /]#

??

[root@localhost ~]# docker run -t -i --name test1 docker.io/ubuntu /bin/bash

root@f5b1bfc2811a:/#

??

[root@localhost ~]# docker ps

CONTAINER ID??????? IMAGE?????????????? COMMAND???????????? CREATED???????????? STATUS????????????? PORTS?????????????? NAMES

224facf8e054??????? centos7:7.3.1611???"/bin/bash"?????????46 minutes ago????? Up 46 minutes?????????????????????????? test2

f5b1bfc2811a??????? docker.io/ubuntu????"/bin/bash"?????????47 minutes ago????? Up 5 minutes??????????????????????????? test1

[root@localhost ~]# docker inspect --format='{{.NetworkSettings.IPAddress}}' f5b1bfc2811a

192.168.5.2

[root@localhost ~]# docker inspect --format='{{.NetworkSettings.IPAddress}}' 224facf8e054

192.168.5.3

[root@localhost ~]# brctl show

bridge name?? bridgeid???????????STP enabled???? interfaces

bridge0?????? 8000.ba141fa20c91?? no????????????? vethe7e227b

??????????????????????????????????????????????????vethf382771

使用pipework給容器設置一個固定的ip

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

可以利用pipework為容器指定一個固定的ip,操作方法非常簡單,如下:

[root@node1 ~]# brctl addbr br0

[root@node1 ~]# ip link set dev br0 up

[root@node1 ~]# ip addr add 192.168.114.1/24 dev br0??????????????????????? //這個ip相當于br0網橋的網關ip,可以隨意設定。

[root@node1 ~]# docker run -ti -d --net=none --name=my-test1 docker.io/nginx /bin/bash

[root@node1 ~]# pipework br0 -i eth0 my-test1 192.168.114.100/24@192.168.114.1

[root@node1 ~]# docker exec -ti my-test1 /bin/bash

root@cf370a090f63:/# ip addr

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default

????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

57: eth0@if58: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000

????link/ether?b2:c1:8d:92:33:e2 brd ff:ff:ff:ff:ff:ff link-netnsid 0

????inet 192.168.114.100/24?brd 192.168.114.255 scope global eth0

???????valid_lft forever preferred_lft forever

????inet6 fe80::b0c1:8dff:fe92:33e2/64?scope link

???????valid_lft forever preferred_lft forever

再啟動一個容器

[root@node1 ~]# docker run -ti -d --net=none --name=my-test2 docker.io/nginx /bin/bash

[root@node1 ~]# pipework br0 -i eth0 my-test12 192.168.114.200/24@192.168.114.1

[root@node1 ~]# pipework br0 -i eth0 my-test2 192.168.114.200/24@192.168.114.1

這樣,my-test1容器和my-test2容器在同一個宿主機上,所以它們固定后的ip是可以相互ping通的,如果是在不同的宿主機上,則就無法ping通!

所以說:

這樣使用pipework指定固定ip的容器,在同一個宿主機下的容器間的ip是可以相互ping通的,但是跨主機的容器通過這種方式固定ip后就不能ping通了。

跨主機的容器間的通信可以看下面的介紹。

2.2、不同主機間的容器通信(pipework ?config docker container ip)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

我的centos7測試機上的docker是yum安裝的,默認自帶pipework工具,所以就不用在另行安裝它了。

-----------------------------------------------------------------------------------------------

如果沒有pipework工具,可以安裝下面步驟進行安裝:

# git clone https://github.com/jpetazzo/pipework.git

# sudo cp -rp pipework/pipework /usr/local/bin/

??????

安裝相應依賴軟件(網橋)

#sudo apt-get install iputils-arping bridge-utils -y

-----------------------------------------------------------------------------------------------

?????

查看Docker宿主機上的橋接網絡

[root@linux-node2 ~]# brctl show

bridge name?? bridgeid???????????STP enabled?? interfaces

docker0?????? 8000.02426f15541e?? no??????????? veth92d132f

????

有兩種方式做法:

1)可以選擇刪除docker0,直接把docker的橋接指定為br0;

2)也可以選擇保留使用默認docker0的配置,這樣單主機容器之間的通信可以通過docker0;

???跨主機不同容器之間通過pipework將容器的網卡橋接到br0上,這樣跨主機容器之間就可以通信了。

????

如果保留了docker0,則容器啟動時不加--net=none參數,那么本機容器啟動后就是默認的docker0自動分配的ip(默認是172.17.1.0/24網段),它們之間是可以通信的;

跨宿主機的容器創建時要加--net=none參數,待容器啟動后通過pipework給容器指定ip,這樣跨宿主機的容器ip是在同一網段內的同網段地址,因此可以通信。

???

一般來說:最好在創建容器的時候加上--net=none,防止自動分配的IP在局域網中有沖突。若是容器創建后自動獲取ip,下次容器啟動會ip有變化,可能會和物理網段中的ip沖突

??

---------------------------------------------------------------------------------------------------

實例說明如下:

宿主機信息

ip:192.168.1.23????????? (網卡設備為eth0)

gateway:192.168.1.1

netmask:255.255.255.0

1)刪除虛擬橋接卡docker0的配置

[root@localhost ~]# service docker stop

[root@localhost ~]# ip link set dev docker0 down

[root@localhost ~]# brctl delbr docker0

[root@localhost ~]# brctl addbr br0

[root@localhost ~]# ip link set dev br0 up??????

[root@localhost ~]# ip addr del 192.168.1.23/24 dev eth0?????? //刪除宿主機網卡的IP(如果是使用這個地址進行的遠程連接,這一步操作后就會斷掉;如果是使用外網地址連接的話,就不會斷開)

[root@localhost ~]# ip addr add 192.168.1.23/24 dev br0??????? //將宿主主機的ip設置到br0

[root@localhost ~]# brctl addif br0 eth0??????????????????????? //將宿主機網卡掛到br0上

[root@localhost ~]# ip route del default?????????????????????? //刪除默認的原路由,其實就是eth0上使用的原路由192.168.1.1(這步小心,注意刪除后要保證機器能遠程連接上,最好是通過外網ip遠程連的。別刪除路由后,遠程連接不上,中斷了)

[root@localhost ~]# ip route add default via 192.168.1.1 dev br0????? //為br0設置路由

[root@localhost ~]# vim /etc/sysconfig/docker???????????????? //即將虛擬的橋接口由默認的docker0改為bridge0

OPTIONS='--selinux-enabled --log-driver=journald'

改為

OPTIONS='--selinux-enabled --log-driver=journald -b=br0'????//即添加-b=br0

???

[root@localhost ~]# service docker start

??

??

啟動一個手動設置網絡的容器

[root@localhost ~]# docker ps

CONTAINER ID??????? IMAGE?????????????? COMMAND???????????? CREATED???????????? STATUS????????????? PORTS?????????????? NAMES

6e64eade06d1??????? docker.io/centos????"/bin/bash"?????????10 seconds ago????? Up 9 seconds??????????????????????????? my-centos

[root@localhost ~]# docker run -itd --net=none --name=my-test1 docker.io/centos

???

為my-test1容器設置一個與橋接物理網絡同地址段的ip(如下,"ip@gateway"

默認不指定網卡設備名,則默認添加為eth0。可以通過-i參數添加網卡設備名

[root@localhost ~]# pipework br0 -i eth0 my-test1 192.168.1.190/24@192.168.1.1

??

同理,在其他機器上啟動容器,并類似上面用pipework設置一個同網段類的ip,這樣跨主機的容器就可以相互ping通了!

??

--------------------------------------------------------------------------------------------------

2)保留默認虛擬橋接卡docker0的配置

[root@localhost ~]# cd /etc/sysconfig/network-scripts/

[root@localhost network-scripts]# cp ifcfg-eth0 ifcfg-eth0.bak

[root@localhost network-scripts]# cp ifcfg-eth0 ifcfg-br0

[root@localhost network-scripts]# vim ifcfg-eth0??????????? //增加BRIDGE=br0,刪除IPADDR,NETMASK,GATEWAY,DNS的設置

......

BRIDGE=br0

[root@localhost network-scripts]# vim ifcfg-br0??????????? //修改DEVICE為br0,Type為Bridge,把eth0的網絡設置設置到這里來(里面應該有ip,網關,子網掩碼或DNS設置)

......

TYPE=Bridge

DEVICE=br0

?????

[root@localhost network-scripts]# service network restart

?????

[root@localhost network-scripts]# service docker restart

?????

開啟一個容器并指定網絡模式為none(這樣,創建的容器就不會通過docker0自動分配ip了,而是根據pipework工具自定ip指定)

[root@localhost network-scripts]# docker images

REPOSITORY????????? TAG???????????????? IMAGE ID??????????? CREATED???????????? SIZE

docker.io/centos????latest????????????? 67591570dd29??????? 3 months ago??????? 191.8 MB

[root@localhost network-scripts]# docker run -itd --net=none --name=my-centos docker.io/centos /bin/bash

6e64eade06d1eb20be3bd22ece2f79174cd033b59182933f7bbbb502bef9cb0f

??

接著給容器配置網絡

[root@localhost network-scripts]# pipework br0 -i eth0 my-centos 192.168.1.150/24@192.168.1.1

[root@localhost network-scripts]# docker attach 6e64eade06d1

[root@6e64eade06d1 /]# ifconfig eth0???????????????? //若沒有ifconfig命令,可以yum安裝net-tools工具

eth0????? Link encap:Ethernet? HWaddr 86:b6:6b:e8:2e:4d

??????????inet addr:192.168.1.150? Bcast:0.0.0.0? Mask:255.255.255.0

??????????inet6 addr: fe80::84b6:6bff:fee8:2e4d/64?Scope:Link

??????????UP BROADCAST RUNNING MULTICAST? MTU:1500? Metric:1

??????????RX packets:8 errors:0 dropped:0 overruns:0 frame:0

??????????TX packets:9 errors:0 dropped:0 overruns:0 carrier:0

??????????collisions:0 txqueuelen:1000

??????????RX bytes:648 (648.0 B)? TX bytes:690 (690.0 B)

[root@6e64eade06d1 /]# route -n

Kernel IP routing table

Destination???? Gateway???????? Genmask???????? Flags Metric Ref??? Use Iface

0.0.0.0???????? 192.168.1.1???? 0.0.0.0???????? UG??? 0????? 0??????? 0 eth0

192.168.115.0?? 0.0.0.0???????? 255.255.255.0?? U???? 0????? 0??????? 0 eth0

?????

另外pipework不能添加靜態路由,如果有需求則可以在run的時候加上--privileged=true?權限在容器中手動添加,但這種方法安全性有缺陷。

除此之外,可以通過ip netns(--help參考幫助)添加靜態路由,以避免創建容器使用--privileged=true選項造成一些不必要的安全問題:

?????

如下獲取指定容器的pid

[root@localhost network-scripts]# docker inspect --format="{{ .State.Pid }}" 6e64eade06d1

7852

[root@localhost network-scripts]# ln -s /proc/7852/ns/net /var/run/netns/7852

[root@localhost network-scripts]# ip netns exec 7852 ip route add 192.168.0.0/16 dev eth0 via 192.168.1.1

[root@localhost network-scripts]# ip netns exec 7852 ip route??? //添加成功

192.168.0.0/16?via 192.168.1.1 dev eth0

?????

同理,在其它宿主機進行相應的配置,新建容器并使用pipework添加虛擬網卡橋接到br0,如此創建的容器間就可以相互通信了。

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

1)重啟網卡報錯如下:

# systemctl restart network

......

Nov 23 22:09:08 hdcoe02 systemd[1]: network.service: control process exited, code=exited status=1?

Nov 23 22:09:08 hdcoe02 systemd[1]: Failed to start LSB: Bring up/down?networking.?

Nov 23 22:09:08 hdcoe02 systemd[1]: Unit network.service entered failed state.</span>?

解決辦法:

# systemctl enable NetworkManager-wait-online.service

# systemctl stop NetworkManager

# systemctl? restart network.service

2)創建容器,出現下面告警

WARNING: IPv4 forwarding is disabled. Networking will not work.

解決辦法:

#vim /usr/lib/sysctl.d/00-system.conf

添加如下代碼:

net.ipv4.ip_forward=1

重啟network服務

# systemctl restart network

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
其實除了上面使用的pipework工具還,還可以使用虛擬交換機(Open vSwitch)進行docker容器間的網絡通信,廢話不多說,下面說下Open vSwitch的使用:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

一、在Server1和Server2上分別安裝open?vswitch

[root@Slave1 ~]# # yum -y install wget openssl-devel kernel-devel

[root@Slave1 ~]# yum groupinstall "Development Tools"

[root@Slave1 ~]# adduser ovswitch

[root@Slave1 ~]# su - ovswitch

[ovswitch@Slave1 ~]$ wget http://openvswitch.org/releases/openvswitch-2.3.0.tar.gz

[ovswitch@Slave1 ~]$tar?-zxvpf openvswitch-2.3.0.tar.gz

[ovswitch@Slave1 ~]$mkdir?-p ~/rpmbuild/SOURCES

[ovswitch@Slave1 ~]$sed?'s/openvswitch-kmod, //g'?openvswitch-2.3.0/rhel/openvswitch.spec > openvswitch-2.3.0/rhel/openvswitch_no_kmod.spec

[ovswitch@Slave1 ~]$cp?openvswitch-2.3.0.tar.gz rpmbuild/SOURCES/

[ovswitch@Slave1 ~]$ rpmbuild -bb --without check ~/openvswitch-2.3.0/rhel/openvswitch_no_kmod.spec

[root@Slave1 ~]$exit

????

[root@Slave1 ~]# yum localinstall /home/ovswitch/rpmbuild/RPMS/x86_64/openvswitch-2.3.0-1.x86_64.rpm

[root@Slave1 ~]# mkdir /etc/openvswitch

[root@Slave1 ~]# setenforce 0

[root@Slave1 ~]# systemctl start openvswitch.service

[root@Slave1 ~]# systemctl? status openvswitch.service -l

??

二、在Slave1和Slave2上建立OVS Bridge并配置路由

1)在Slave1宿主機上設置docker容器內網ip網段172.17.1.0/24

[root@Slave1 ~]# vim /proc/sys/net/ipv4/ip_forward

1

[root@Slave1 ~]# ovs-vsctl add-br obr0

[root@Slave1 ~]# ovs-vsctl add-port obr0 gre0 -- set Interface gre0 type=gre options:remote_ip=192.168.115.5

????

[root@Slave1 ~]# brctl addbr kbr0

[root@Slave1 ~]# brctl addif kbr0 obr0

[root@Slave1 ~]# ip link set dev docker0 down

[root@Slave1 ~]# ip link del dev docker0

????

[root@Slave1 ~]# vim /etc/sysconfig/network-scripts/ifcfg-kbr0

ONBOOT=yes

BOOTPROTO=static

IPADDR=172.17.1.1

NETMASK=255.255.255.0

GATEWAY=172.17.1.0

USERCTL=no

TYPE=Bridge

IPV6INIT=no

????

[root@Slave1 ~]# vim /etc/sysconfig/network-scripts/route-ens32

172.17.2.0/24?via 192.168.115.6 dev ens32

??

[root@Slave1 ~]# systemctl? restart network.service

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

2)在Slave2宿主機上設置docker容器內網ip網段172.17.2.0/24

[root@Slave2 ~]# vim /proc/sys/net/ipv4/ip_forward

1

[root@Slave2 ~]# ovs-vsctl add-br obr0

[root@Slave2 ~]# ovs-vsctl add-port obr0 gre0 -- set Interface gre0 type=gre options:remote_ip=192.168.115.6

???

[root@Slave2 ~]# brctl addbr kbr0

[root@Slave2 ~]# brctl addif kbr0 obr0

[root@Slave2 ~]# ip link set dev docker0 down

[root@Slave2 ~]# ip link del dev docker0

???

[root@Slave2 ~] vim/etc/sysconfig/network-scripts/ifcfg-kbr0

ONBOOT=yes

BOOTPROTO=static

IPADDR=172.17.2.1

NETMASK=255.255.255.0

GATEWAY=172.17.2.0

USERCTL=no

TYPE=Bridge

IPV6INIT=no

???

[root@Slave2 ~]# vim /etc/sysconfig/network-scripts/route-ens32

172.17.1.0/24?via 192.168.115.5 dev ens32

???

[root@Slave2 ~]# systemctl? restart network.service

三、啟動容器測試
Server1和Server2上修改docker啟動的虛擬網卡綁定為kbr0,重啟docker進程
1)在Server1宿主機上啟動容器,然后登陸容器內查看ip,就會發現ip是上面設定額172.17.1.0/24網段的

1

[root@Slave1 ~]# docker run -idt --name my-server1 daocloud.io/library/centos/bin/bash

2)在Server2宿主機上啟動容器,然后登陸容器內查看ip,就會發現ip是上面設定額172.17.2.0/24網段的

1

[root@Slave2 ~]#docker run -idt --name my-server1 daocloud.io/library/centos /bin/bash

然后在上面啟動的容內互ping對方容器,發現是可以ping通的

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/535313.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/535313.shtml
英文地址,請注明出處:http://en.pswp.cn/news/535313.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Docker容器的重啟策略

1. Docker容器的重啟策略 Docker容器的重啟策略是面向生產環境的一個啟動策略&#xff0c;在開發過程中可以忽略該策略。 Docker容器的重啟都是由Docker守護進程完成的&#xff0c;因此與守護進程息息相關。 Docker容器的重啟策略如下&#xff1a; no&#xff0c;默認策略&…

innobackupex實現導出和導入單張表

默認情況下&#xff0c;InnoDB表不能通過直接復制表文件的方式在mysql服務器之間進行移植&#xff0c;即便使用了innodb_file_per_table選項。而使用Xtrabackup工具可以實現此種功能&#xff0c;不過只能"導出"具有.ibd文件的表&#xff0c;也就是說導出表的mysql服務…

xtrabackup工具

(1).備份過程 和innobackupex備份過程不同的是&#xff0c;xtrabackup的備份路徑是由"--target-dir"選項嚴格指定的&#xff0c;如果指定的目錄不存在&#xff0c;它備份的時候不會在target-dir目錄中再創建時間戳子目錄。 [rootxuexi data]# xtrabackup --backup …

mysql數據庫參數

注意&#xff1a;在配置binlog相關變量的時候&#xff0c;相關變量名總是搞混&#xff0c;因為有的是binlog&#xff0c;有的是log_bin&#xff0c;當他們分開的時候&#xff0c;log在前&#xff0c;當它們一起的時候&#xff0c;bin在前。在配置文件中也同樣如此。 log_bin …

oracle命令行安裝

cd /home/oracle/databases/runInstaller -silent -force -showprogress -responseFile /home/oracle/database/db_install.rsp -ignoreSysPrereqs -ignorePrereqdbca -silent -responseFile pwd/dbca.rspnetca -silent -responseFile /home/oracle/databases/netca.rsp

定期刪除數據腳本

#!/bin/sh backup_dir/data/xtrabackup DATEdate %Y-%m-%d #DATE_NOWdate %Y-%m-%d.%H%M DATE_NOWdate %Y-%m-%d PATH/usr/local/mysql/bin:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin export PATH#binog保留7天 binlog/data/binlogserver binlog_Rtime7#備…

定期備份數據庫腳本

#!/bin/bash MasterIp* USERroot PORT3306 PASSWD000000 DATEdate %Y-%m-%d #DATE_NOWdate %Y-%m-%d.%H%M DATE_NOWdate %Y-%m-%d OLDDATEdate %Y-%m-%d -d "30 days ago"  #全表備份 BACKUPDIR/data/mysql_backup/fulltable #單表tb_trcevt備份 datapath/data/mysq…

日志清理腳本

#!/bin/bash#定義日志所在分區當前空間所占比例數(去掉%)。grep -w表示精準匹配&#xff0c;只匹配"/"這個分區 LOG_PARTITION$(which df -h|awk {print $5,$6}|grep -w "/"|cut -d" " -f1|awk -F"%" {print $1}) #定義一周前的日期&a…

k8s二進制安裝

1. 前言 之前文章安裝 kubernetes 集群&#xff0c;都是使用 kubeadm 安裝&#xff0c;然鵝很多公司也采用二進制方式搭建集群。這篇文章主要講解&#xff0c;如何采用二進制包來搭建完整的高可用集群。相比使用 kubeadm 搭建&#xff0c;二進制搭建要繁瑣很多&#xff0c;需要…

Logstash mutate 插件

mutate 插件可以在字段上執行變換&#xff0c;包括重命名、刪除、替換和修改。這個插件相當常用。 比如&#xff1a; 你已經根據 Grok 表達式將 Tomcat 日志的內容放到各個字段中&#xff0c;想把狀態碼、字節大小或是響應時間&#xff0c;轉換成整型&#xff1b;你已經根據正則…

nginx日志分析腳本

#!/usr/bin/env bashecho "" echo " " echo " \ Nginx日志安全分析腳本 V1.0 / " echo " " echo " # 支持Nginx日志分析&#xff0c;攻擊告警分析等 " echo " # auth…

ELK學習筆記之Logstash詳解

0x00 Logstash概述 官方介紹&#xff1a;Logstash is an open source data collection engine with real-time pipelining capabilities。簡單來說logstash就是一根具備實時數據傳輸能力的管道&#xff0c;負責將數據信息從管道的輸入端傳輸到管道的輸出端&#xff1b;與此同時…

nginx-zabbix監控腳本

nginx_status_fun (){#函數內容NGINX_PORT$1#端口&#xff0c;函數的第一個參數是腳本的第二個參數&#xff0c;即腳本的第二個參數是段端口號NGINX_COMMAND$2#命令&#xff0c;函數的第二個參數是腳本的第三個參數&#xff0c;即腳本的第三個參數是命令nginx_active(){ #獲…

percona-xtrabackup備份

#!/bin/bash # 需要安裝 percona-xtrabackup # xtrabackup: https://www.percona.com/downloads/Percona-XtraBackup-2.4/LATEST/ # xtrabackup 版本&#xff1a;2.4.24 (RPM安裝) # MySQL 版本: 5.7.36 (RPM安裝) # version: 22.01.17# 備份服務器 ip DB_BACKUP_SERVER"…

k8---proxy

kube-proxy 通過 Informer知道了Service、endpoints對象的創建&#xff0c;然后把service身上的CLUSTER-IP 和端口已經端點信息拿出來&#xff0c;創建iptable NAT規則做轉發或通過ipvs模塊創建VS服務器&#xff0c;這樣經過CLUSTER-IP的流量都被轉發到后端pod。 iptables模式 …

k8s--configmap

當卷中使用的ConfigMap被更新時&#xff0c;所投射的鍵最終也會被更新。kubelet組件會在每次周期性同步時檢查所掛載的ConfigMap是否為最新。 不過,kubelet使用的是其本地的高速緩存來獲得ConfigMap的當前值。 ConfigMap既可以通過watch操作實現內容傳播&#xff08;默認形式&…

etcd命令

[rootlocalhost calico]# etcdctl get /coreos.com/network/subnets/4.0.32.0-24 {"PublicIP":"10.8.65.53"} 從etcd中查詢出4.0.32.0/24的子網的宿主機host的ip10.8.65.53。

docker搭建ldap

1.下載鏡像 docker pull osixia/openldap docker pull docker.io/osixia/phpldapadmin 2.運行鏡像 docker run -dit --name ldap23 --restartalways -p 389:389 -p 636:636 -e LDAP_ORGANISATION”test” -e LDAP_DOMAIN”test.com” -e LDAP_ADMIN_PASSWORD123456″ osixi…

centos 縮減邏輯卷

在使用期間磁盤空間不足&#xff0c;發現/dev/mapper/centos-home下還有很多空間&#xff0c;如果想要將home下面的磁盤空間分配到root磁盤下面&#xff0c;可以使用以下方法 查看磁盤空間&#xff0c;每個人的磁盤名稱可能不同 df -h 1 備份home文件 tar cvf /tmp/home.tar /…

zabbix自動發現監控腳本

自動發現端口列表腳本 # -*- coding: utf-8 -*- import os import json data{} tcp_list[] port_list[] commandos.popen("ss -4tln | awk -F [ :] NR>2{print $5}") for port in command:port_list.append(port.strip()) for port in port_list:port_dict{}por…