1. 程式人生 > 其它 >Docker 與 K8S學習筆記(七)—— 容器的網路

Docker 與 K8S學習筆記(七)—— 容器的網路

本節我們來看看Docker網路,我們這裡主要討論單機docker上的網路。當docker安裝後,會自動在伺服器中建立三種網路:none、host和bridge,接下來我們分別瞭解下這三種網路:

$ sudo docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
528c3d49c302   bridge    bridge    local
464b3d11003c   host      host      local
faa8eb8310b4   none      null      local

一、none網路

none網路就是什麼都沒有的網路,使用此網路的容器除了lo沒有其他任何網絡卡,所以此容器不提供任何網路服務,也無法訪問其它容器,那麼這種封閉網路有什麼用呢?這個一般會用於對網路安全要求較高並且不需要聯網的應用。

$ sudo docker run -it --network=none busybox
/ # 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)

二、host網路

使用host網路的容器將共享docker host的網路棧,容器的網路配置與host一樣。大家可以發現,使用此網路的容器能看到伺服器所有網絡卡,這種網路模式的使用場景是那些對網路傳輸效率要求較高的應用,當然此模式也存在不夠靈活的問題,例如埠衝突問題。

$ sudo docker run -it --network=host busybox
/ # ifconfig
docker0   Link encap:Ethernet  HWaddr 
02:42:6B:5A:FC:54 UP BROADCAST MULTICAST MTU:1500 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:17 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:0 (0.0 B) TX bytes:1526 (1.4 KiB) ens33 Link encap:Ethernet HWaddr 00:0C:29:D5:73:1C inet addr:172.16.194.135 Bcast:172.16.194.255 Mask:255.255.255.0 inet6 addr: fe80::20c:29ff:fed5:731c/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:32097 errors:0 dropped:0 overruns:0 frame:0 TX packets:20666 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:24596169 (23.4 MiB) TX bytes:9708382 (9.2 MiB) lo Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0 inet6 addr: ::1/128 Scope:Host UP LOOPBACK RUNNING MTU:65536 Metric:1 RX packets:270 errors:0 dropped:0 overruns:0 frame:0 TX packets:270 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:24089 (23.5 KiB) TX bytes:24089 (23.5 KiB)

三、bridge網路

Docker安裝時會建立一個名為docker0的網橋(使用brctl工具可以檢視Linux下所有網橋),容器啟動時如果不指定--network則預設都是bridge網路。

$ brctl show
bridge name  bridge id    STP enabled  interfaces
docker0    8000.02426b5afc54  no

此時我們啟動一個Nginx容器看看該網橋的變化:

$ sudo docker run -d nginx
27644bd64114482f58adc47a52d3f768732c0396ca0eda8f13e68b10385ea359
$ brctl show
bridge name  bridge id    STP enabled  interfaces
docker0    8000.0242cef1fc32  no    vethe21ab12

我們可以看到此時一個新的網路介面vethe21ab12掛到docker0上,vethe21ab12就是Nginx容器的虛擬網絡卡。我們接著去Nginx容器中看看網路配置情況:

$ sudo docker exec -it 27644bd64114 bash
root@27644bd64114:/# 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
45: eth0@if46: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever

我們看到容器中有一個網絡卡eth0@if46,為什麼不是vethe21ab12呢?實際上,eth0@if46和vethe21ab12是一對veth-pair,那什麼是veth-pair呢?

veth-pair是一種虛擬裝置介面,它是成對出現的,一端連著協議棧,一端彼此相連著,在本例中大家可以想象成它們是由一根虛擬網線連線起來的一對網絡卡,網絡卡的一頭(eth0@if46)在容器裡,另一頭(vethe21ab12)掛在網橋docker0上,最終的效果就是把eth0@if46也掛在docker0上。

我們還能看到這個容器中eth0@if46配置的ip是172.17.0.2,為什麼是這個網段呢?我們看下網橋的網路配置:

$ sudo docker network inspect bridge
[
    {
        "Name": "bridge",
        "Id": "6f0087fd32cd0e3b4a7ef1133e2f5596a2e74429cf5240e42012af85d1146b9f",
        "Created": "2021-10-17T06:43:11.849460184Z",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "172.17.0.0/16",
                    "Gateway": "172.17.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "27644bd64114482f58adc47a52d3f768732c0396ca0eda8f13e68b10385ea359": {
                "Name": "lucid_moore",
                "EndpointID": "b6c9de5a52e2f0b858a6dbf6c8e51b535aec3500fca7d1f1dcca98613e57dabd",
                "MacAddress": "02:42:ac:11:00:02",
                "IPv4Address": "172.17.0.2/16",
                "IPv6Address": ""
            }
        },
        "Options": {
            "com.docker.network.bridge.default_bridge": "true",
            "com.docker.network.bridge.enable_icc": "true",
            "com.docker.network.bridge.enable_ip_masquerade": "true",
            "com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
            "com.docker.network.bridge.name": "docker0",
            "com.docker.network.driver.mtu": "1500"
        },
        "Labels": {}
    }
]
$ ifconfig docker0
docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.17.0.1  netmask 255.255.0.0  broadcast 172.17.255.255
        inet6 fe80::42:ceff:fef1:fc32  prefixlen 64  scopeid 0x20<link>
        ether 02:42:ce:f1:fc:32  txqueuelen 0  (Ethernet)
        RX packets 2827  bytes 115724 (115.7 KB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 3853  bytes 10144700 (10.1 MB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

原來網橋的網路配置的subnet就是172.17.0.0,閘道器則是172.17.0.1。這個閘道器就在docker0上,所以當前容器網路拓撲圖如下:

四、後記

大家在進行本篇的實驗時,可能會遇到如下問題:

1、進入Nginx容器後,沒有ip命令?

這個命令需要自行在容器中安裝:apt-get install iproute2

2、安裝iproute2時發現容器無法連線網路。

首先我們需要重建docker0網路:

$ sudo pkill docker
$ sudo iptables -t nat -F
$ sudo ifconfig docker0 down
$ sudo btctl delbr docker0
$ sudo systemctl restart docker

接著啟動容器並進入容器,更新軟體源:

root@27644bd64114:/# apt-get update
Get:1 http://security.debian.org/debian-security buster/updates InRelease [65.4 kB]
Get:2 http://deb.debian.org/debian buster InRelease [122 kB]
Get:3 http://security.debian.org/debian-security buster/updates/main amd64 Packages [307 kB]
Get:4 http://deb.debian.org/debian buster-updates InRelease [51.9 kB]
Get:5 http://deb.debian.org/debian buster/main amd64 Packages [7906 kB]
Get:6 http://deb.debian.org/debian buster-updates/main amd64 Packages [15.2 kB]
Fetched 8467 kB in 14s (603 kB/s)
Reading package lists... Done

最後安裝iproute2即可。