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 Driver và IPAM Driver, mỗi loại lại bao gồm native driver và remote 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à C1
và nginx
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 networkbridge
là Docker network driver mà tạo ra network trêndocker0
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 MACac:11:00:02
tương ứng với IP172.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 docker0
và eth0
, 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.
Dockerbridge
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 đượcbridge
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 c2
và c3
.
$ 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à host
và bridge
. Bài viết tiếp theo sẽ giải thích về driver overlay
và MACVLAN
.