Tìm hiểu bridge network trong Docker
TIL
594
Docker
29
White

manhdung viết ngày 22/07/2016

Bridge network trong Docker

Về native, docker hỗ trợ 3 loại network:

[root@localhost ~]# docker network ls
NETWORK ID          NAME                DRIVER
f163f5a13de0        bridge              bridge              
4cf5b3a8120b        host                host                
d33d2260ad2c        none                null 

Mặc định, docker dùng bridge network. Khi cài đặt docker, bạn sẽ thấy một interface docker0 trên host. Khi khởi chạy một container trong host, một interface mới đại diện cho nó sẽ được sinh ra trên host:

4: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP 
    link/ether 02:42:f1:59:1a:46 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:f1ff:fe59:1a46/64 scope link 
       valid_lft forever preferred_lft forever
92: vethc4c9915@if91: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP 
    link/ether de:bf:41:5b:54:f6 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet6 fe80::dcbf:41ff:fe5b:54f6/64 scope link 
       valid_lft forever preferred_lft forever

trong container:

91: eth0@if92: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP 
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.2/16 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:acff:fe11:2/64 scope link 
       valid_lft forever preferred_lft forever

eth0@if92 có nghĩa nó sẽ map giữa interface 92 vethc4c9915@if91 đến eth0, gắn IP wan của docker host.

Có thể xem ip của docker container qua:

[root@localhost ~]# docker inspect 992f2635e59f | grep IPAddr
            "SecondaryIPAddresses": null,
            "IPAddress": "172.17.0.2",
                    "IPAddress": "172.17.0.2",

Lần lượt mỗi container được tạo ra sẽ dùng ip kế tiếp trong dải 172.17.0.0/16 Với 16 bist dành cho host thì số host có thể có tối đa là 2^16 - 2 container trong một host.
Tất cả các container đều nhận host làm gateway:

[root@992f2635e59f /]# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         172.17.0.1      0.0.0.0         UG    0      0        0 eth0
172.17.0.0      0.0.0.0         255.255.0.0     U     0      0        0 eth0

Do các container đều dùng host làm gateway nên bridge network cho phép:

  • các container trên cùng host giao tiếp với nhau được
  • các container có thể gửi packet ra bên ngoài host được.

Để đảm bảo host forward được IP thì nó cần được cấu hình NAT và cho phép ip forward.

Trên host cấu hình ip forward:
vi /etc/sysctl.conf
net.ipv4.conf.all.forwarding = 1
sysctl -p

Mặc định, khi mới start service docker trên host bạn đã có những rule iptables do docker sinh ra. Những rule này là đủ để container có thể sử dụng host làm gateway để truy cập ra outside world. Những rule này là based, không cần có container run vẫn có.

*nat
:PREROUTING ACCEPT [67:4224]
:INPUT ACCEPT [3:1248]
:OUTPUT ACCEPT [1:160]
:POSTROUTING ACCEPT [1:160]
:DOCKER - [0:0]
-A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER
-A OUTPUT ! -d 127.0.0.0/8 -m addrtype --dst-type LOCAL -j DOCKER
-A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE
-A DOCKER -i docker0 -j RETURN
COMMIT


*filter
:INPUT ACCEPT [121:23360]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [48:6144]
:DOCKER - [0:0]
:DOCKER-ISOLATION - [0:0]
-A FORWARD -j DOCKER-ISOLATION
-A FORWARD -o docker0 -j DOCKER
-A FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -i docker0 ! -o docker0 -j ACCEPT
-A FORWARD -i docker0 -o docker0 -j ACCEPT
-A DOCKER-ISOLATION -j RETURN
COMMIT

Chỉ chú ý vài dòng sau:
Dòng
-A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE
nói cho biết là thêm một rule vào POSTROUTING chain của nat table của iptables, tất cả các packet có source ip là 172.17.0.0/16 không đi đến interface docker0 sẽ được MASQUERADE nghĩa là nếu package này sẽ được sửa đổi source IP sao cho giống out interface của host mà nó đi qua.

MASQUERADE giống SNAT, chỉ khác là MASQUERADE phù hợp cho trường hợp external network, ở đây là network của host dynamically còn SNAT thì phải chỉ định chính xác IP đang được gán trên external network.

-A FORWARD -o docker0 -j DOCKER
-A FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
hai rule này sẽ nằm trong FORWARD chain của filter table, tất cả các packet cứ được forward đến docker0 sẽ được đẩy vào chain DOCKER, do chain DOCKER không khai báo gì nên nó ACCEPT, tiếp sau đó, với tất cả các packet được forward đến docker0 có trạng thái RELATED hoặc ESTABLISHED thì đều được ACCEPT.

Forward hiểu đơn giản là nhận gói tin từ một interface nhưng sau đó đẩy sang interface khác.

Chú ý rule trên chưa có DNAT nên từ ngoài truy cập vào dịch vụ trong container thì chưa được.

Sơ qua về iptables flow:

alt text

iptables có hai table:
nat. Có ba chain trong nat

  • PREROUTING
  • POSTROUTING
  • OUTPUT: Ngay sau khi qua POSTROUTING filter. Có ba chain trong filter
  • INPUT
  • OUTPUT
  • FORWARD

Còn có một table nữa, nhưng cái đó không liên quan đến cái đang bàn nên tôi không đưa vào đây.

DNAT được thực hiện ở PREROUTING
còn SNAT và MASQUERADE thực hiện ở POSTROUTING

Local process là quá trình xử lý gói tin của this host, gói tin sẽ đi qua network stack để xử lý sau đó đẩy output đi, output có thể là một response cho input trước đó hoặc output cũng có thể là một request, mà không có input nào trước đó. Do local process network stack nằm sau INPUT chain, PREROUTING chain nên nếu có gì đó bị chặn ở INPUT, PREROUTING thì bạn hoàn toàn không thể nhận thấy qua capture wireshark.

Để từ outside world truy cập dịch vụ bên trong container, bạn phải expose service trong container. Thực chất là một kiểu port forwarding. Trong Dockerfile có hỗ trợ instruction EXPOSE nhưng về bản chất instruction này sẽ không thực hiện map gì cả. Nói chung là instruction này tôi thấy vô nghĩa, có lẽ là một chỉ dẫn cho system admin biết sẽ có dịch vụ nào được expose từ container này khi đọc Dockerfile mà thôi.
Để expose, khi run:
[root@localhost Docker_Centos6]# docker run -it -p 81:80 image_name
ở đây port trong container 80 sẽ được map đến 81 trong host.

Việc map port forwarding này bản chất là một số chỉ dẫn được thêm vào iptables trong host:

*nat
....
-A POSTROUTING -s 172.17.0.2/32 -d 172.17.0.2/32 -p tcp -m tcp --dport 80 -j MASQUERADE
-A DOCKER -i docker0 -j RETURN
-A DOCKER ! -i docker0 -p tcp -m tcp --dport 81 -j DNAT --to-destination 172.17.0.2:80
COMMIT

*filter
....
-A DOCKER -d 172.17.0.2/32 ! -i docker0 -o docker0 -p tcp -m tcp --dport 80 -j ACCEPT
-A DOCKER-ISOLATION -j RETURN

Những dòng bôi đen là được bổ sung khi map port
Port đã được map nhưng dịch vụ trong container phải được start thì mới dùng đươc.

Khi stop container, các rule phục vụ cho map port này cũng tự động được gỡ bỏ.

Trường hợp nếu khi run bạn quên không map port thì chỉ cần tự bổ sung iptables rule cho DNAT là cũng map port được thôi.

Với các rule set manually này thì khi stop container, rule không tự động gỡ bỏ.

manhdung 23-06-2016

Bình luận


White
{{ comment.user.name }}
Bỏ hay Hay
{{comment.like_count}}
Male avatar
{{ comment_error }}
Hủy
   

Hiển thị thử

Chỉnh sửa

White

manhdung

44 bài viết.
263 người follow
Kipalog
{{userFollowed ? 'Following' : 'Follow'}}
Cùng một tác giả
White
76 11
Giới thiệu RabbitMQ là một message broker ( messageoriented middleware) sử dụng giao thức AMQP Advanced Message Queue Protocol (Đây là giao thức ph...
manhdung viết 3 năm trước
76 11
White
48 4
Giả định bạn tiếp nhận một server mới toanh, bạn cần tìm một số thông tin về nó như loại CPU, loại main, loại memory, memory dùng của hãng nào... c...
manhdung viết gần 2 năm trước
48 4
White
41 12
Trong phần 1, tôi đã giới thiệu về sơ lược rabbitmq, vai trò của rabbitmq trong hệ thống phân tán và hướng dẫn cài đặt. Trong phần này, tôi sẽ trìn...
manhdung viết 3 năm trước
41 12
Bài viết liên quan
White
0 2
fCC: Technical Documentation Page note So I have finished the HTML part of this exercise and I want to come here to lament about the lengthy HTML ...
HungHayHo viết 1 tháng trước
0 2
White
8 0
Một trong những trường hợp build docker image là thừa hưởng từ một image mẹ Lấy một ví dụ sau: Dockefile FROM my_repo/my_image ENTRYPOINT ech...
Lơi Rệ viết gần 3 năm trước
8 0
{{like_count}}

kipalog

{{ comment_count }}

bình luận

{{liked ? "Đã kipalog" : "Kipalog"}}


White
{{userFollowed ? 'Following' : 'Follow'}}
44 bài viết.
263 người follow

 Đầu mục bài viết

Vẫn còn nữa! x

Kipalog vẫn còn rất nhiều bài viết hay và chủ đề thú vị chờ bạn khám phá!