Tìm hiểu chi tiết về mạng trong Docker

  1. Khái niệm mạng trong Docker ==================

Mô hình mạng của container Docker bao gồm ba thành phần chính:

  • network (mạng): Là một driver mạng, tức là một hệ thống mạng bên ngoài với nhiều kiểu cấu hình khác nhau.

  • Các kiểu mạng trong cùng một máy chủ (none, host, bridge)

  • Các kiểu mạng đa máy chủ (overlay, macvlan, flannel)

  • sandbox: Là môi trường cách ly, định nghĩa card mạng ảo, DNS và bảng định tuyến bên trong container. Sandbox là một dạng thực hiện của network namespace, tạo nên ngăn xếp mạng nội bộ của container.

  • endpoint: Là điểm kết nối giữa sandbox và network.

Có thể so sánh network với switch, sandbox với card mạng và endpoint với cổng kết nối và cáp mạng.

  1. Các chế độ mạng trong Docker =================

Các chế độ mạng bao gồm:

  • Chế độ host
  • Chế độ none
  • Chế độ bridge
  • Chế độ container

2.1 Chế độ host

Tương tự như chế độ bridge trong VMware, container sẽ nằm cùng mạng với máy chủ nhưng không có địa chỉ IP độc lập. Docker sẽ không tạo namespace mạng riêng cho container mà dùng namespace mạng mặc định của máy chủ, chia sẻ cùng một ngăn xếp mạng. Điều này khiến IP trong container trùng với IP của máy chủ. Chế độ này phù hợp với các ứng dụng yêu cầu hiệu năng mạng cao nhưng không đảm bảo được tính cách ly mạng tốt.

2.2 Chế độ bridge

Chế độ này tương tự như chế độ NAT trong VMware. Khi Docker khởi động, nó sẽ tạo ra một bridge tên docker0. Mỗi container sẽ nhận một namespace mạng riêng và được cấu hình các thành phần như card mạng ảo, bảng định tuyến, DNS, địa chỉ IP và quy tắc iptables (tức là nội dung của sandbox).

2.2.1 Quy trình cấu hình mạng Bridge trong Docker

  1. Tạo các thiết bị ảo veth pair trên máy chủ. Thiết bị veth luôn xuất hiện theo cặp, tạo kênh truyền dữ liệu từ thiết bị này sang thiết bị kia. Chúng thường được dùng để kết nối hai thiết bị mạng.
  2. Một đầu của veth pair được đặt vào container mới tạo và đặt tên là eth0, đầu còn lại được đặt vào máy chủ với tên như veth45h6 và thêm vào bridge docker0. Có thể kiểm tra bằng lệnh brctl show.
[root@harbor ~]# brctl show 
bridge name		bridge id		STP enabled	interfaces
br-2ba1d6a2e994		8000.02426cb4a81a	no		veth6a79ace
br-8d4b6181687f		8000.0242d8d0780d	no		
docker0			8000.02424dbb4b07	no

  1. Gán một địa chỉ IP từ dải mạng của docker0 cho container và đặt IP của docker0 làm gateway mặc định cho container.
[root@harbor ~]# docker ps 
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                  NAMES
4b59058aece1        docker-nexus3:v1    "sh -c ${SONATYPE_DI…"   2 months ago        Up 2 months         0.0.0.0:81->8081/tcp   nexus3
[root@harbor ~]# docker inspect 4b59058aece1
.......
            "Networks": {
                "nexus_default": {
                    "IPAMConfig": null,
                    "Links": null,
                    "Aliases": [
                        "4b59058aece1",
                        "docker_nexus3"
                    ],
                    "NetworkID": "2ba1d6a2e994bb68c9a9ec000867db8fb14e20c6abcaa95f9399b0d9a270b960",
                    "EndpointID": "e191fe5833aff25bbc6f71c215a717c5fa6c9f2b62690d94806768a302272129",
                    "Gateway": "172.18.0.1",
                    "IPAddress": "172.18.0.2",
                    "IPPrefixLen": 16,
                    "IPv6Gateway": "",
                    "GlobalIPv6Address": "",
                    "GlobalIPv6PrefixLen": 0,
                    "MacAddress": "02:42:ac:12:00:02",
                    "DriverOpts": null
                }
            }
        }
    }
]
# Kiểm tra bridge network nexus_default
[root@harbor_reg ~]# docker network inspect nexus_default
[
    {
        "Name": "nexus_default",
        "Id": "2ba1d6a2e994bb68c9a9ec000867db8fb14e20c6abcaa95f9399b0d9a270b960",
        "Created": "2020-08-24T10:20:21.947908808+08:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "172.18.0.0/16",
                    "Gateway": "172.18.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": true,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "4b59058aece184806ecc8d7d2c7c9dd93b24d7d120ea782d5c6909819725fe2d": {
                "Name": "nexus3",
                "EndpointID": "e191fe5833aff25bbc6f71c215a717c5fa6c9f2b62690d94806768a302272129",
                "MacAddress": "02:42:ac:12:00:02",
                "IPv4Address": "172.18.0.2/16",
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {
            "com.docker.compose.network": "default",
            "com.docker.compose.project": "nexus",
            "com.docker.compose.version": "1.23.2"
        }
    }
]

2.3 Chế độ none

Chế độ này là một trường hợp đặc biệt của chế độ bridge. Docker vẫn tạo namespace mạng riêng cho container nhưng không cấu hình card mạng ảo, địa chỉ IP hay bảng định tuyến. Người dùng phải tự cấu hình. Container chỉ có giao diện loopback (lo), không có card mạng nào khác. Có thể chỉ định chế độ này khi tạo container bằng --network=none. Mạng loại này không thể kết nối internet, rất an toàn vì hoàn toàn cô lập.

2.4 Chế độ container

Chế độ chia sẻ container, là sự mở rộng của chế độ host. Nhiều container chia sẻ cùng một namespace mạng. Về mặt mạng, chúng có cùng địa chỉ IP và chia sẻ cùng một ngăn xếp mạng.

  1. Giao tiếp mạng giữa các máy chủ trong Docker ====================

Mặc định, các container trong cùng một máy chủ có thể giao tiếp qua bridge docker0, nhưng giữa các máy chủ chỉ có thể thông qua ánh xạ cổng (port mapping). Để cho phép container giao tiếp trực tiếp với IP của chúng, cần áp dụng các phương pháp sau:

  • Định tuyến trực tiếp
  • Tunnel overlay (ví dụ: flannel, ovs+gre)
  • Cổng bridge (ví dụ: pipework)

3.1 Định tuyến trực tiếp

Thêm tuyến tĩnh vào mỗi máy chủ:

ip route add 172.16.1.0/24 via 192.168.20.1
ip route add 172.16.2.0/24 via 192.168.20.2

Lưu ý: Trên CentOS cần bật forwarding IP:

vim /etc/sysctl.d/99-sysctl.conf
net.ipv4.ip_forward = 1
sysctl -p

Tham khảo bài viết chi tiết về giao tiếp giữa container qua các máy chủ: https://www.cnblogs.com/xiao987334176/p/10049844.html

3.2 Tunnel overlay

Giải thích bằng flannel (flannel+udp hoặc flannel+vxlan):

Quá trình hoạt động của flannel:

  • Mỗi máy chủ cài đặt và chạy etcd và flannel
  • Trong etcd cấu hình dải mạng docker0 cho tất cả các máy chủ
  • flanneld trên mỗi máy chủ đọc cấu hình từ etcd để phân bổ dải mạng cho docker0, đảm bảo không trùng và lưu trữ thông tin vào etcd
  • Khi cần giao tiếp với container ở máy chủ khác, truy vấn etcd để tìm IP của máy chủ đích
  • Gói tin gốc được đóng gói trong gói Vxlan hoặc UDP với IP đích là IP máy chủ
  • Gói tin đến máy chủ đích sẽ được giải nén, trả lại gói tin gốc và chuyển đến container đích

3.3 Cổng bridge

Có thể cấu hình địa chỉ IP của container trùng với mạng của máy chủ. Không đi sâu vào chi tiết, tham khảo các bài viết khác: https://blog.csdn.net/xpt211314/article/details/97375671

Tài liệu tham khảo: https://www.jianshu.com/p/22a7032bb7bd https://zhuanlan.zhihu.com/p/82735394

Thẻ: docker Networking container bridge overlay

Đăng vào ngày 3 tháng 7 lúc 22:26