dockerコンテナネットワーク構成

8303 ワード

文書ディレクトリ

  • Linuxカーネル実装ネームスペースの作成
  • Network Namespace
  • の作成
  • Network Namespace
  • の操作
  • 転送装置
  • veth pair
  • を作成
  • Network Namespace間通信を実現
  • vethデバイス名変更
  • 容器の常用操作
  • コンテナホスト名を表示
  • コンテナ起動時にホスト名
  • を注入する.
  • コンテナで使用するDNS
  • を手動で指定する.
  • 手動で/etc/hostsファイルにホスト名をIPアドレスへ注入するマッピング
  • オープンコンテナポート
  • Linuxカーネルによるネームスペースの作成


    Network Namespaceの作成


    コマンドを使用してns 0という名前のネーミングスペースを作成します.
    [root@docker ~]# ip netns list
    [root@docker ~]# ip netns add ns0
    [root@docker ~]# ip netns list
    ns0
    

    新しく作成したNetwork Namespaceが/var/run/netns/ディレクトリに表示されます.同じ名前のnamespaceが既に存在する場合、コマンドはCannot create namespace file'/var/run/netns/ns 0::File existsのエラーを報告します.
    [root@docker ~]# ls /var/run/netns/
    ns0
    [root@docker ~]# ip netns add ns0
    Cannot create namespace file "/var/run/netns/ns0": File exists
    

    各Network Namespaceには、独自のNIC、ルーティングテーブル、ARPテーブル、iptablesなど、ネットワーク関連のリソースがあります.

    Network Namespaceの操作


    ipコマンドは、ip netns execサブコマンドを提供し、対応するNetwork Namespaceでコマンドを実行できます.
    Network Namespaceを新しく作成したNIC情報の表示
    root@docker ~]# ip netns exec ns0 ip addr
    1: lo:  mtu 65536 qdisc noop state DOWN qlen 1
        link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    

    新しく作成したNetwork Namespaceでは、デフォルトでloループNICが作成され、NICがオフになっていることがわかります.このとき、このloループNICをpingしてみると、Network is unreachableにプロンプトが表示されます.
    [root@docker ~]# ip netns exec ns0 ping 127.0.0.1
    connect: Network is unreachable
    

    次のコマンドでloループNICを有効にします.
    [root@docker ~]# ip netns exec ns0 ip link set lo up
    [root@docker ~]# ip netns exec ns0 ping 127.0.0.1
    PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
    64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.099 ms
    64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.077 ms
    64 bytes from 127.0.0.1: icmp_seq=3 ttl=64 time=0.078 ms
    

    トランスファデバイス


    異なるNetwork Namespace間でデバイス(vethなど)を転送できます.1つのデバイスが1つのNetwork Namespaceにしか属していないため、移行後、このNetwork Namespace内ではこのデバイスが見えなくなります.
    ここでvethデバイスは転送可能デバイスに属し、lo、vxlan、ppp、bridgeなどの多くの他のデバイスは転送できない.

    veth pairの作成

    [root@docker ~]# ip link add type veth
    [root@docker ~]# ip a
    36: veth0@veth1:  mtu 1500 qdisc noop state DOWN qlen 1000
        link/ether 42:a8:5e:58:b7:1d brd ff:ff:ff:ff:ff:ff
    37: veth1@veth0:  mtu 1500 qdisc noop state DOWN qlen 1000
        link/ether 8e:4e:f5:7e:7e:b8 brd ff:ff:ff:ff:ff:ff
    

    Network Namespace間通信の実装


    次に、veth pairを使用して、2つの異なるNetwork Namespace間の通信を実現します.先ほどns 0という名前のNetwork Namespaceを作成しましたが、次にns 1という名前の情報Network Namespaceを作成します.
    [root@docker ~]# ip netns add ns1
    [root@docker ~]# ip netns list
    ns1
    ns0
    

    次にveth 0をns 0に加えveth 1をns 1に加えます
    [root@docker ~]# ip link set veth0 netns ns0
    [root@docker ~]# ip link set veth1 netns ns1
    

    次にveth pairのipアドレスをそれぞれ構成し、有効にします.
    [root@docker ~]# ip netns exec ns0 ip link set veth0 up
    [root@docker ~]# ip netns exec ns0 ip addr add 10.0.0.1/24 dev veth0
    [root@docker ~]# ip netns exec ns1 ip link set veth1 up
    [root@docker ~]# ip netns exec ns1 ip addr add 10.0.0.1/24 dev veth1
    [root@docker ~]# ip netns exec ns1 ip link set lo up
    

    このveth pairのステータスを表示
    [root@docker ~]# ip netns exec ns0 ip a
    1: lo:  mtu 65536 qdisc noqueue state UNKNOWN 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
    36: veth0@if37:  mtu 1500 qdisc noqueue state UP qlen 1000
        link/ether 42:a8:5e:58:b7:1d brd ff:ff:ff:ff:ff:ff link-netnsid 1
        inet 10.0.0.1/24 scope global veth0
           valid_lft forever preferred_lft forever
        inet6 fe80::40a8:5eff:fe58:b71d/64 scope link 
           valid_lft forever preferred_lft forever
    
    [root@docker ~]# ip netns exec ns1 ip a
    1: lo:  mtu 65536 qdisc noqueue state UNKNOWN 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
    37: veth1@if36:  mtu 1500 qdisc noqueue state UP qlen 1000
        link/ether 8e:4e:f5:7e:7e:b8 brd ff:ff:ff:ff:ff:ff link-netnsid 0
        inet 10.0.0.1/24 scope global veth1
           valid_lft forever preferred_lft forever
        inet6 fe80::8c4e:f5ff:fe7e:7eb8/64 scope link 
           valid_lft forever preferred_lft forever
    

    以上から,このveth pairを有効にし,各vethデバイスに対応するipアドレスを割り当てることに成功したことが分かる.ns 1でns 0のipアドレスにアクセスしてみます.
    [root@docker ~]# ip netns exec ns1 ping 10.0.0.1
    PING 10.0.0.1 (10.0.0.1) 56(84) bytes of data.
    64 bytes from 10.0.0.1: icmp_seq=1 ttl=64 time=0.095 ms
    64 bytes from 10.0.0.1: icmp_seq=2 ttl=64 time=0.086 ms
    64 bytes from 10.0.0.1: icmp_seq=3 ttl=64 time=0.060 ms
    

    vethデバイス名の変更

    [root@docker ~]# ip netns exec ns0 ifconfig -a
    eth0: flags=4098  mtu 1500
            inet 10.0.0.1  netmask 255.255.255.0  broadcast 0.0.0.0
            ether 42:a8:5e:58:b7:1d  txqueuelen 1000  (Ethernet)
            RX packets 8  bytes 648 (648.0 B)
            RX errors 0  dropped 0  overruns 0  frame 0
            TX packets 8  bytes 648 (648.0 B)
            TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
    
    lo: flags=73  mtu 65536
            inet 127.0.0.1  netmask 255.0.0.0
            inet6 ::1  prefixlen 128  scopeid 0x10
            loop  txqueuelen 1  (Local Loopback)
            RX packets 10  bytes 840 (840.0 B)
            RX errors 0  dropped 0  overruns 0  frame 0
            TX packets 10  bytes 840 (840.0 B)
            TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
    [root@docker ~]# ip netns exec ns0 ip link set eth0 up
    

    コンテナの一般的な操作


    コンテナホスト名の表示

    [root@salt1 ~]# docker run -it --name t1 --network bridge --rm busybox
    / # hostname
    2caa42691e68
    

    コンテナ起動時にホスト名を入力

    [root@salt1 ~]# docker run -it --name t1 --network bridge --hostname hello --rm busybox
    / # hostname
    hello
    / # cat /etc/hosts 
    127.0.0.1	localhost
    ::1	localhost ip6-localhost ip6-loopback
    fe00::0	ip6-localnet
    ff00::0	ip6-mcastprefix
    ff02::1	ip6-allnodes
    ff02::2	ip6-allrouters
    172.17.0.2	hello       // IP 
    / # cat /etc/resolv.conf 
    # Generated by NetworkManager
    nameserver 114.114.114.114    //DNS DNS
    / # ping www.baidu.com
    PING www.baidu.com (39.156.66.18): 56 data bytes
    64 bytes from 39.156.66.18: seq=0 ttl=127 time=63.355 ms
    64 bytes from 39.156.66.18: seq=1 ttl=127 time=54.062 ms
    64 bytes from 39.156.66.18: seq=2 ttl=127 time=52.691 ms
    

    コンテナで使用するDNSを手動で指定

    [root@salt1 ~]# docker run -it --name t1 --network bridge --hostname hello --dns 192.168.174.2  --rm busybox
    / # cat /etc/resolv.conf 
    nameserver 192.168.174.2
    / # nslookup -type=a www.baidu.com
    Server:		192.168.174.2
    Address:	192.168.174.2:53
    
    Non-authoritative answer:
    www.baidu.com	canonical name = www.a.shifen.com
    Name:	www.a.shifen.com
    Address: 39.156.66.14
    Name:	www.a.shifen.com
    Address: 39.156.66.18
    

    IPアドレスへのホスト名のマッピングを/etc/hostsファイルに手動で注入

    [root@salt1 ~]# docker run -it --name t1 --network bridge --hostname hello --add-host www.a.com:1.1.1.1  --rm busybox
    / # cat /etc/hosts
    127.0.0.1	localhost
    ::1	localhost ip6-localhost ip6-loopback
    fe00::0	ip6-localnet
    ff00::0	ip6-mcastprefix
    ff02::1	ip6-allnodes
    ff02::2	ip6-allrouters
    1.1.1.1	www.a.com
    172.17.0.2	hello
    

    オープンコンテナポート


    docker runを実行するときに-pオプションがあり、コンテナ内のアプリケーションポートをシンクホストにマッピングし、外部ホストがシンクホストのポートにアクセスすることでコンテナ内のアプリケーションにアクセスできるようにする目的を実現します.
    -pオプションは複数回使用できます.露出可能なポートは、コンテナが実際に傍受しているポートである必要があります.
    -pオプションの使用形式:
  • -pは、指定するコンテナポートをホストのすべてのアドレスの動的ポート
  • にマッピングする.
  • -p:コンテナポートを指定したホストポート
  • にマッピングします.
  • -p::指定されたコンテナポートをホスト指定のダイナミックポート
  • にマッピングします.
  • -p::指定コンテナポートをホスト指定ポート
  • にマッピングする.
    ダイナミックポートとはランダムポートを指し、具体的なマッピング結果はdocker portコマンドで表示できます.