Tổng quan về các Native Docker Network Driver [phần 1]: Host và Bridge

Tại bài viết Tổng quan về Docker Container Network Model đã trình bày về tổng quan mô hình mạng container của Docker. Trong đó đã sơ lược các nhóm trình điều khiển container network, bao gồm Docker Netword DriverIPAM Driver, mỗi loại lại bao gồm native driverremote driver.

Native driver là các trình điều khiển được cung cấp sẵn bởi Docker và có thể sử dụng mà không cần bổ sung bất cứ module nào khác.

Chuỗi bài viết này trình bày về các native Docker network driver – các trình điều khiển hoạt động tại tầng Network trong mô hình mạng container của Docker.

Docker Host Network Driver

Đối với người mới làm quen với Docker, host là driver dễ làm quen nhất, bởi nó mang cùng cấu hình mạng giống như trong trường hợp không có Docker. Cờ --net-host tắt các hiệu ứng của Docker network và sử dụng ngăn xếp mạng của hệ điều hành máy host.

Thông thường, với các driver khác, mỗi container sẽ được đặt trong network namespace (hoặc sandbox) của riêng chúng, để tạo nên sự cô lập. Với driver host, các container được đặt trong cùng network namespace với máy host và sử dụng chung interface và ngăn xếp IP của máy host. Nhìn từ phía mạng, điều này tương đương với có thêm tiến trình chạy trên máy chủ không có container. Bởi các container sủ dụng chung interface mạng với máy chủ, không thể có hai container nào có thể mapping vào cùng một TCP port. Điều này có thể gây ra tranh chấp cổng nếu có nhiều container trên cùng một host.

Ví dụ dưới đây tạo ra hai container là C1nginx trên cùng một máy host. Chúng chia sẻ với nhau interface eth0. Điều này khiến host không phù hợp cho các ứng dụng cần mức bảo mật cao hoặc có nhiều người thuê. Máy host có khả năng truy cập tới bất kỳ container nào. Điều đó cũng đúng với các container. Để ý câu lệnh curl được thực thi từ container C1 và nó thực sự giao tiếp với nginx, thông qua localhost.

#Create containers on the host network
host $ docker run --rm -itd --net host --name C1 alpine sh
host $ docker run --rm -itd --net host --name nginx nginx

#Show host eth0
host $ ip -o -4 address show dev eth0 |cut -d’ ‘ -f1-7
2: eth0    inet 172.31.21.213/20

#Show eth0 from C1
host $ docker exec -it C1 sh
C1 # ip -o -4 address show dev eth0 |cut -d' ' -f1-7
2: eth0    inet 172.31.21.213/20

#Contact the nginx container through localhost on c1
C1 $ curl localhost
!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
...

Với driver host, Docker không quản lý bất kỳ bộ phận nào trong ngăn xếp mạng giữa các container như port mapping hay routing. Điều này có nghĩa là các cờ mạng phổ biến như -p hay --icc không có ý nghĩa với driver host, chúng bị bỏ qua. Điều này khiến cho host là driver đơn giản nhất và có độ trễ thấp nhất trong số các network driver. Dòng tin chảy trực tiếp từ tiến trình trong container tới interface của máy host, cung cấp trần hiệu năng tương đương với tiến trình nằm trực tiếp trên máy host.

Khả năng tuy cập máy host không giới hạn và không có policy quản lý có thể khiến driver host khó mà đóng vai trò một driver mạng một cách toàn diện. Tuy vậy, host có thể ứng dụng trong một vài trường hợp, chẳng hạn cho các ứng dụng yêu cầu hiệu năng cao, hay các ứng dụng chẩn đoán sự cố.

Driver host chỉ hoạt động trên máy chủ Linux và không được hỗ trợ trên Docker của macOS, Windows hay Windows Server.

Docker Bridge Network Driver

Về driver bridge có hai khái niệm để đi vào chi tiết, là mạng Docker bridge mặc định, và mạng Docker bridge do người dùng tự định nghĩa.

Mạng Docker-bridge mặc định

Trên bất kỳ máy host Linux nào đang chạy Docker Engine, luôn tồn tại mặc định một Docker network tên là bridge. Network này được tạo bởi bridge driver, thông qua một Linux bridge tên là docker0. Rất rắc rối.

  • bridge là tên của Docker network
  • bridge là Docker network driver mà tạo ra network trên
  • docker0 là tên của Linux bridge mà kernel sử dụng để triển khai network trên

Trên một Linux host độc lập, bridge là network mặc định mà các container kết nối vào trong trường hợp không có network nào được chỉ định. Trong ví dụ dưới đây một container được tạo ra mà không có tham số network. Docker Engine kết nối nó với network bridge một cách mặc định. Trong container, để ý sự hiện diện của eth0 – interface được tạo ra bởi bridge driver và được gán IP bởi native IPAM driver.

#Create a busybox container named "c1" and show its IP addresses
host $ docker run --rm -it --name c1 busybox sh
c1 # ip address
4: eth0@if5: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.2/16 scope global eth0
...

Địa chỉ MAC của interface trong container được tạo ra lâm thời và có sự tương đồng nhất định với địa chỉ IP để tránh nhầm lẫn. Trong ví dụ trên MAC ac:11:00:02 tương ứng với IP 172.17.0.2.

Công cụ brctl của máy host có thể liệt kê các Linux bridge đang hiện hữu tại network namespace của host. Và nó hiển thị một bridge tên là docker0. docker0 có một interface, trong trường hợp này là vetha3788c4, veth này cung cấp kết nối từ bridge tới interface eth0 nằm trong container c1.

host $ brctl show
bridge name      bridge id            STP enabled    interfaces
docker0          8000.0242504b5200    no             vethb64e8b8

Trong container c1, container hướng dòng tin tới eth0 và theo đó dòng tin chảy tới cầu docker0.

c1# ip route
default via 172.17.0.1 dev eth0
172.17.0.0/16 dev eth0  src 172.17.0.2

Một container có thể không có hoặc có nhiều interface phụ thuộc vào việc nó kết nối tới bao nhiêu network. Mỗi Docker network chỉ có thể đặt một interface cho mỗi container.

Tại routing table của máy host, danh sách các interface mang IP tại global network namespace giờ chứa cả docker0. Máy host cung cấp kết nối giữa docker0eth0, và hoàn thành đường dẫn từ trong container với mạng bên ngoài.

host $ ip route
default via 172.31.16.1 dev eth0
172.17.0.0/16 dev docker0  proto kernel  scope link  src 172.17.42.1
172.31.16.0/20 dev eth0  proto kernel  scope link  src 172.31.16.102

Mặc định, bridge được gắn subnet trong khoảng 172.[17-31].0.0/16 hoặc 192.168.[0-256].0/20, những khoảng này không trùng lắp với bất kỳ interface nào của host. bridge network mặc định cũng có thể được cấu hình địa chỉ tùy biến. Đồng thời, một Linux bridge có sẵn có thể được sử dụng cho bridge network thay vì sử dụng bridge được tạo bởi Docker.

Docker bridge network mặc định là network duy nhất hỗ trợ cơ chế links. Ngoài ra, service discovery dựa trên tên và IP không được bridge network mặc định hỗ trợ.

Mạng Docker-bridge do người dụng tự định nghĩa

Bên cạnh network mặc định, người dùng có thể tạo network của riêng họ bằng bất kỳ network driver nào. Trong trường hợp của bridge network, một Linux bridge mới sẽ được tạo ra trên máy host. Không giống như bridge network mặc định, network do người dùng định nghĩa hỗ trợ đặt IP và subnet thủ công. Nếu chúng không được gán, IPAM driver mặc định sẽ tìm IP tiếp theo khả dụng trong subnet để đặt.

Trong ví dụ dưới đây, một bridge network được tạo ra với hai container. Một subnet được chỉ định, và network được đặt tên là my_bridge. Một container không được cung cấp tham số về IP, nên IPAM driwer đã gán cho nó IP khả dụng tiếp theo trong subnet. Container còn lại nhận IP được chỉ định.

$ docker network create -d bridge --subnet 10.0.0.0/24 my_bridge
$ docker run --rm -itd --name c2 --net my_bridge busybox sh
$ docker run --rm -itd --name c3 --net my_bridge --ip 10.0.0.254 busybox sh

Lệnh brctl bây giờ sẽ hiễn thị Linux bridge thứ hai trên máy host. Tên của Linux bridge, br-4bcc22f5e5b9 khớp với Network ID của network my_bridge. Network my_bridge cũng có hai veth interface kết nối tới c2c3.

$ brctl show
bridge name      bridge id            STP enabled    interfaces
br-b5db4578d8c9  8000.02428d936bb1    no             vethc9b3282
                                                     vethf3ba8b5
docker0          8000.0242504b5200    no             vethb64e8b8

$ docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
b5db4578d8c9        my_bridge           bridge              local
e1cac9da3116        bridge              bridge              local
...

Liệt kê các interface tại global network namespace sẽ cho thấy mạch mạng Linux được tạo ra bởi Docker.Mỗi veth và Linux bridge interface xuất hiện như một đường nối giữa một Linux bridge và container network namespace.

$ ip link

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500
5: vethb64e8b8@if4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500
6: br-b5db4578d8c9: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500
8: vethc9b3282@if7: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500
10: vethf3ba8b5@if9: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500
...

Tổng kết

Bài viết này đã trình bày tổng quan về hai Docker Network Driver là hostbridge. Bài viết tiếp theo sẽ giải thích về driver overlayMACVLAN.

Loading

Leave a Reply

Your email address will not be published. Required fields are marked *