Computer >> Máy Tính >  >> Phần mềm >> Máy ảo

Kết nối mạng bộ chứa Docker - Hướng dẫn

Đã đến lúc khám phá thêm những điều kỳ diệu của Docker. Cho đến nay, chúng tôi đã có hai hướng dẫn, một hướng dẫn tập trung vào phần giới thiệu rất kỹ lưỡng, nơi chúng tôi tìm hiểu tất cả về công nghệ, cách chạy dịch vụ và hiển thị cổng, cách cam kết và xây dựng hình ảnh với Dockerfiles và một số thủ thuật khác. Sau đó, chúng tôi đã sử dụng supervisord để thay thế cho init script và systemd.

Hôm nay, chúng ta sẽ tìm hiểu về mạng. Cách chúng tôi có thể kết nối với các vùng chứa của mình, cách chúng tôi có thể truy cập máy chủ từ bên trong các phiên bản được sinh ra và quan trọng nhất là cách kết nối từ vùng chứa này sang vùng chứa khác mà không cần biết trước bất kỳ điều gì về cấu trúc liên kết. Điều này nên được thú vị. Giống như hai hướng dẫn trước, chúng tôi sẽ đi từng bước một và giải thích mọi thứ một cách chi tiết. Sau tôi.


Mục lục

  1. Cài đặt
  2. Mạng máy chủ đến vùng chứa
    1. Tóm tắt
  3. Bộ chứa để lưu trữ kết nối mạng
  4. Mạng vùng chứa đến vùng chứa
  5. Liên kết vùng chứa!
    1. Tệp máy chủ
    2. Kết nối với máy chủ, sử dụng tên của nó
  6. Đọc thêm
  7. Kết luận

Cài đặt

Trước tiên hãy tạo một số vùng chứa. Chúng tôi đã có hình ảnh của mình từ lần thử nghiệm trước, vì vậy không cần phải bắt đầu lại từ đầu. Chúng tôi sẽ chạy ba vùng chứa, mỗi vùng có dịch vụ SSH và Apache riêng. Bỏ qua khía cạnh bảo mật của nó, bởi vì chúng tôi đang cố gắng tập trung vào phần kết nối mạng.

Một điều chúng tôi sẽ làm ở đây mà chúng tôi chưa làm trong lần trước là chúng tôi sẽ đặt tên cho các thùng chứa của mình để dễ nhận biết hơn. Điều này được thực hiện bằng tùy chọn --name. Ví dụ:

docker run -d -ti -p 22 -p 80 --name net3 image-4:latest 

Chúng ta cũng hãy xem ba phiên bản của chúng ta có những địa chỉ IP nào:

[root@localhost ~]# docker kiểm tra net1 | grep -i ipaddr
"Địa chỉ IP":"172.17.0.5",

[root@localhost ~]# docker kiểm tra net2 | grep -i ipaddr
"Địa chỉ IP":"172.17.0.6",

[root@localhost ~]# docker kiểm tra net3 | grep -i ipaddr
"Địa chỉ IP":"172.17.0.7",

Đây là cấu hình ban đầu của chúng tôi cho thử nghiệm. Chúng tôi có ba vùng chứa, tất cả đều chạy trên cùng một máy chủ, với các dịch vụ của chúng và các cổng dịch vụ được hiển thị. Bây giờ, chúng ta có thể bắt đầu làm một số thứ khá thú vị.

Mạng máy chủ đến vùng chứa

Đây là phần dễ dàng, và sự thật mà nói, chúng ta đã làm điều này trong bài tập trước. Chúng tôi đã kết nối với các vùng chứa của mình bằng SSH và chúng tôi đã thử kiểm tra các cổng bằng telnet. Có, netcat (nc) cũng hoạt động tốt, vui lòng tắt klaxon bảo mật của bạn. Có hai cách để kết nối. Thứ nhất, bạn có thể truy cập trực tiếp vào các vùng chứa, sử dụng địa chỉ IP của chúng, như chúng tôi đã thực hiện trước đây.

ssh 172.17.0.5
Không thể thiết lập tính xác thực của máy chủ '172.17.0.5 (172.17.0.5)'. Dấu vân tay khóa ECDSA là 00:4b:de:91:60:e5:22:cc:f7:89:01:19:3e:61:cb:ea.
Bạn có chắc chắn muốn tiếp tục kết nối (có/không)? Vâng
Cảnh báo:Đã thêm vĩnh viễn '172.17.0.5' (ECDSA) vào danh sách các máy chủ đã biết.
mật khẩu của root@172.17.0.5:

Thứ hai, bạn cũng có thể truy cập các cổng được ánh xạ trên máy chủ tương ứng với các cổng dịch vụ bên trong vùng chứa. Nếu chúng ta chỉ xem thông tin PORTS trong đầu ra docker ps:

0.0.0.0:49162->22/tcp, 0.0.0.0:49161->80/tcp   net1
0.0.0.0:49163->22/tcp, 0.0.0.0:49164->80/tcp   net2
0.0.0.0:49165->22/tcp, 0.0.0.0:49166->80/tcp   net3

Trong ví dụ trên, đối với vùng chứa có tên là net1, cổng 22 được ánh xạ tới cổng 49162 trên máy chủ, có nghĩa là giao diện docker0, theo mặc định được gán mạng 172.17.42.1/16. Thật vậy, chúng ta thấy:

điện thoại 172.17.42.1 49163
Đang thử 172.17.42.1...
Đã kết nối với 172.17.42.1.
Ký tự thoát là '^]'.
SSH-2.0-OpenSSH_6.6.1

Bây giờ, tại sao bạn lại muốn sử dụng phương pháp thứ hai, vì nó khó hiểu và khó nhớ hơn? Câu trả lời là, nếu bạn không sử dụng ánh xạ động mà thay vào đó, bạn chỉ định các cổng máy chủ đã biết, đã cho, thì bạn có thể có địa hình rất rõ ràng về mạng vùng chứa của mình. Hơn nữa, nếu bạn muốn cho phép các vùng chứa của mình có thể truy cập được từ bên ngoài máy chủ, bạn sẽ cần chuyển tiếp IP và NAT. Nếu bạn sử dụng giao diện docker0 để liên lạc, bạn sẽ cần ít quy tắc iptables đơn giản hơn.

Bạn có thể xác minh điều này bằng cách chạy lệnh iptables -L và kiểm tra chuỗi DOCKER. Các quy tắc mới sẽ được thêm tự động bất cứ khi nào bạn chạy vùng chứa với tùy chọn -p.

Chuỗi DOCKER (1 tài liệu tham khảo)
nhắm mục tiêu    bảo vệ chọn nguồn      đích
CHẤP NHẬN     tcp  --  ở mọi nơi   172.17.0.5    tcp dpt:http
CHẤP NHẬN     tcp  --  ở mọi nơi   172.17.0.5    tcp dpt:ssh
CHẤP NHẬN     tcp  --  ở mọi nơi   172.17.0.6    tcp dpt:ssh
CHẤP NHẬN     tcp  --  ở mọi nơi   172.17.0.6    tcp dpt:http
CHẤP NHẬN     tcp  --  ở mọi nơi   172.17.0.7    tcp dpt:ssh
CHẤP NHẬN     tcp  --  ở mọi nơi   172.17.0.7    tcp dpt:http
CHẤP NHẬN     tcp  --  ở mọi nơi   172.17.0.8    tcp dpt:ssh
CHẤP NHẬN     tcp  --  ở mọi nơi   172.17.0.8    tcp dpt:http

Tuy nhiên, nếu bạn không có bất kỳ hạn chế bảo mật nào, thì phương thức động có thể khá hữu ích vì bạn không cần biết ánh xạ các cổng khi khởi động vùng chứa của mình. Bạn có thể lấy thông tin trong thời gian thực, phân tích cú pháp đầu ra docker ps. Tuy nhiên, đối với các dịch vụ, việc đặt địa chỉ IP tĩnh và các cổng đã biết thường hữu ích.

Tóm tắt

Bởi vì điều này hơi khó hiểu, hãy tóm tắt lại một cách ngắn gọn. Bất kỳ máy chủ lưu trữ docker nào cũng sẽ có một docker0 hoặc một cầu nối có tên tương tự đang chạy, thường là với /16 mạng con, mặc dù bạn có thể thay đổi tên mạng con hoặc thậm chí tên mạng. Đằng sau nó, bạn có thể có toàn bộ phạm vi vùng chứa, mỗi vùng chứa có địa chỉ IP riêng và một hoặc nhiều cổng được hiển thị.

Nếu bạn muốn kết nối với các vùng chứa này và các cổng liên quan của chúng, thì bạn có một số tùy chọn. Bạn có thể kết nối trực tiếp, nhưng sau đó bạn cần chuyển tiếp IP, NAT và các quy tắc tường lửa cho từng quy tắc và bạn cần biết địa chỉ IP.

Nếu bạn muốn kết nối bằng giao diện máy chủ (docker0) và phương thức cổng máy chủ, thì bạn không cần biết các vùng chứa của mình chạy như thế nào. Bạn chỉ cần biết ánh xạ các cổng máy chủ tới các cổng container. Nói cách khác, nếu bạn muốn vùng chứa của mình có thể truy cập được giữa nhiều nút máy chủ, bạn chỉ cần hiển thị giao diện máy chủ (docker0) với các máy chủ khác. Điều này làm cho các quy tắc chuyển tiếp IP, NAT và tường lửa trở nên đơn giản. Ví dụ:

0.0.0.0:30001->22/tcp net1
0.0.0.0:30007->22/tcp net4
0.0.0.0:30008->22/tcp net5

Ví dụ trên cho phép bạn kết nối với SSH của ba vùng chứa khác nhau. Nếu bạn sử dụng ánh xạ một-một, tức là cùng một cổng máy chủ và cổng vùng chứa (ví dụ:22:22), thì bạn bị giới hạn hiệu quả khi chỉ có một vùng chứa duy nhất với một dịch vụ duy nhất lắng nghe trên đó. Điều này giống như bộ định tuyến nhà của bạn. Bạn sẽ phải sử dụng các cổng khác nhau cho vùng chứa của mình để có thể sử dụng ánh xạ một đối một. Nhưng điều này gây nhầm lẫn vì bạn muốn các dịch vụ của mình chạy trên các cổng có thể dự đoán được.

Với ví dụ trên, chúng ta thấy rằng chúng ta có thể có 3 container sử dụng SSH. Bên trong, từ góc độ vùng chứa, nó luôn là cổng 22. Nhìn từ bên ngoài, số cổng xác định vùng chứa cũng như dịch vụ. Và đây trở thành tác phẩm duy nhất bạn cần biết mà không cần bận tâm đến những gì xảy ra đằng sau hậu trường.

Điều này có nghĩa là bạn có thể chỉ định động các cổng máy chủ khi tạo bộ chứa, sử dụng một số loại logic tập lệnh hoặc tương tự, sau đó sử dụng thông tin đó để xác định các cổng dịch vụ của bạn. Do đó, máy chủ lưu trữ vào mạng vùng chứa trở thành một công việc đơn giản và thanh lịch. Và bạn cũng có thể kết nối lại từ máy chủ này sang máy chủ khác mà không cần biết trước địa hình vùng chứa.

Bộ chứa để lưu trữ kết nối mạng

Đây là một phần thú vị hơn một chút. Các thùng chứa của bạn có thể phục vụ mục đích lâu dài và do đó, chúng có thể phải duy trì hoạt động trong một khoảng thời gian. Đổi lại, điều này có nghĩa là bạn có thể phải duy trì các vùng chứa, nghĩa là nâng cấp, vá lỗi, cập nhật tệp lưu trữ, v.v. Bạn cũng có thể đang sử dụng một công cụ quản lý cấu hình như Chef, Puppet hoặc Cfengine, vì vậy cũng có phần đó.

Câu hỏi lớn đầu tiên bạn cần đặt ra là container có thể liên lạc với thế giới bên ngoài không? Vâng, vâng. Trong hướng dẫn giới thiệu, chúng tôi đã tải xuống các bản cập nhật CentOS trực tiếp từ kho lưu trữ chính thức, vì vậy chúng tôi biết phần này hoạt động tốt. Làm thế nào về ping docker0:

Câu hỏi thứ hai, chúng ta có thể truy cập giao diện docker0 không và SAU ĐÓ kết nối với các cổng máy chủ của nó. Hãy tạm thời giả sử rằng bằng cách nào đó chúng ta đã được cung cấp thông tin cần thiết bên trong thùng chứa.

điện thoại 172.17.42.1 49162
Đang thử 172.17.42.1...
telnet:kết nối với địa chỉ 172.17.42.1:Không có tuyến đến máy chủ

Điều này sẽ không hoạt động vì chúng tôi chưa định cấu hình chuyển tiếp IP trên máy chủ của mình. Hơn nữa, chúng tôi sẽ cần các quy tắc tường lửa để cho phép lưu lượng cần thiết. Ở đây, nó trở nên phức tạp một chút, bởi vì nếu bạn không quen thuộc với iptables, bạn sẽ hơi khó khăn.

tiếng vang 1> /proc/sys/net/ipv4/ip_forward

Và các quy tắc iptables - một bộ hơi lỏng lẻo, lưu ý (trên máy chủ lưu trữ):

iptables -t filter -A FORWARD -d 172.17.0.0/16 \
-o docker0 -j CHẤP NHẬN
iptables -t filter -A FORWARD -s 172.17.0.0/16 \
-i docker0 -j CHẤP NHẬN
iptables -t filter -A FORWARD -i docker0 -o docker0 -j CHẤP NHẬN
iptables -t nat -A POSTROUTING -s 172.17.0.0/16 \
! -d 172.17.0.0/16 -p tcp -j MASQUERADE --to-ports 1016-65535 \
iptables -t nat -A POSTROUTING -s 172.17.0.0/16
! -d 172.17.0.0/16 -p udp -j MASQUERADE --to-ports 1016-65535 \
iptables -t nat -A POSTROUTING -s 172.17.0.0/16
! -d 172.17.0.0/16 -j MẶT MẠO

Cách thay thế đơn giản nhất là tắt tường lửa - hoặc cho phép tất cả. Điều này có nghĩa là chạy lệnh cần thiết, có thể là systemctl stop firewalld, iptables -F hoặc tương đương. Trong một số trường hợp, điều này có thể không thực hiện được vì bạn cần bảo mật bổ sung. Tuy nhiên, điều này cũng liên quan đến trường hợp sử dụng đầu tiên mà chúng ta đã thảo luận. Bây giờ, hãy tưởng tượng bạn phải tạo các quy tắc thủ công cho từng vùng chứa và các dịch vụ liên quan của nó.

Với các quy tắc kết nối mạng phù hợp, bạn sẽ có thể kết nối với các cổng máy chủ, điều này có nghĩa là nói chuyện với các vùng chứa khác, mặc dù không có gì trong địa chỉ IP hoặc cổng cụ thể yêu cầu mục tiêu phải là một vùng chứa khác. Hơn nữa, bạn cũng sẽ có thể kết nối với các thiết bị mạng khác trên máy chủ hoặc thậm chí có thể là máy chủ từ xa.

Mạng vùng chứa đến vùng chứa

Giống như bài hát của David Bowie, Ashes to Ashes, chỉ là không hay bằng. Đây có vẻ như là kịch bản hữu ích nhất. Một lần nữa, chúng ta có hai lựa chọn. Chúng tôi có thể thử kết nối trực tiếp với các vùng chứa khác hoặc chúng tôi có thể thử sử dụng các cổng được ánh xạ động docker0. Chúng tôi sẽ ăn gian. Chúng tôi sẽ sử dụng máy chủ và cổng máy chủ làm cổng vào vùng chứa. Bây giờ, phương pháp đầu tiên khá đơn giản. Hãy thử ping net2 và net3 từ net1.

Nó hoạt động mà không có bất kỳ vấn đề. Nhưng vấn đề là chúng tôi biết về các địa chỉ IP từ thế giới bên ngoài! Chúng tôi đã không nhận được thông tin này từ bên trong container. Thật vậy, vì lý do bảo mật cũng như thực tế vùng chứa cơ sở là một hình ảnh tương đối nhỏ, bạn không có sẵn bất kỳ công cụ mạng tuyệt vời nào theo mặc định. Bạn thậm chí sẽ không có sẵn tiện ích ifconfig. Ngoài ra, bạn cũng không thể thao tác iptables bên trong các thùng chứa:

iptables -L
iptables v1.4.21:không thể khởi tạo bảng iptables `filter':Quyền bị từ chối (bạn phải root)
Có lẽ iptables hoặc kernel của bạn cần được nâng cấp.

Do đó, phương pháp thứ hai, truy cập docker0 và kết nối với các cổng máy chủ có thể không thực sự khả thi, vì chúng tôi không thể thao túng các quy tắc tường lửa của máy chủ, không phải từ bên trong các vùng chứa. Đây là lý do tại sao chúng ta sẽ thảo luận về một phương pháp thứ ba.

Liên kết vùng chứa!

Cách thích hợp để thực hiện việc này là sử dụng tính năng --link. Điều này có nghĩa là, chúng tôi sẽ sinh ra các phiên bản mới trong khi liên kết chúng với các vùng chứa hiện có khác. Chức năng liên kết sẽ chèn tên máy chủ và địa chỉ IP của các bộ chứa được liên kết vào môi trường và tệp /etc/hosts của phiên bản mới. Có thể nghe hơi khó hiểu nên mình ví dụ nhé:

docker run -d -ti -p 80 --name web image-4:latest
8e689d8ae3ef43eeab3bfa9cf523e1cc6658dae5fc665f8cbf889db17db46c26

docker kiểm tra web | grep -i ipaddr
"Địa chỉ IP":"172.17.0.9",

nc -w1 -v 172.17.0.9 80
Ncat:Phiên bản 6.40 ( https://nmap.org/ncat )
Ncat:Đã kết nối với 172.17.0.9:80.

Chúng tôi có một vùng chứa đang chạy và nó được cho là một máy chủ Web. Bây giờ, chúng tôi muốn khách hàng có thể truy cập nó. Chúng tôi muốn sử dụng tên máy chủ, thay vì địa chỉ IP, vì chúng tôi có thể không có kiến ​​thức trước về địa hình. Hơn nữa, tên rất hữu ích vì chúng cho phép chúng tôi thay đổi bố cục mạng. Thật vậy, hãy tạo một thùng chứa máy khách và liên kết nó với máy chủ Web của chúng ta:

docker run -ti --name client --link web:web image-4:latest /bin/bash

Những gì chúng tôi có ở đây là như sau. Chúng tôi đang tạo liên kết nguồn:mục tiêu. Nói cách khác, máy chủ (vùng chứa) có tên web sẽ hiển thị bên trong vùng chứa mới của chúng tôi có tên máy khách là web. Nếu bạn sinh ra vùng chứa rồi đính kèm vào đó, bạn có thể kiểm tra môi trường bằng cách chạy lệnh env trong trình bao BASH:

WEB_PORT_80_TCP_PORT=80
WEB_PORT_80_TCP=tcp://172.17.0.9:80
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
NKT=/
WEB_PORT_22_TCP_ADDR=172.17.0.9
container_uuid=558a9db0-6d1e-d9d2-b62d-a8dbfbad0b2d
WEB_PORT_22_TCP=tcp://172.17.0.9:22
SHLVL=1
TRANG CHỦ =/gốc
WEB_NAME=/máy khách/web
WEB_PORT_80_TCP_PROTO=tcp
WEB_PORT_80_TCP_ADDR=172.17.0.9
LESSOPEN=||/usr/bin/lesspipe.sh %s
WEB_PORT=tcp://172.17.0.9:22
_=/usr/bin/env

Vì ánh xạ cùng tên có thể gây nhầm lẫn, hãy thử một ánh xạ khác:

docker run -ti --name client --link web:dedoimedo image-4:latest /bin/bash

Và sau đó chúng tôi nhận được:

Theo tùy chọn, nếu bạn đang sinh ra các thùng chứa chỉ cần là công nhân nhanh, thì bạn có thể muốn xem xét việc tạo chúng bằng tùy chọn run --rm. Đối với các tác vụ tồn tại trong thời gian ngắn, không có lý do gì để giữ các tệp vùng chứa trên đĩa và bạn có thể làm cho Docker tự động dọn sạch chúng. Đọc tài liệu chính thức:

Theo mặc định, hệ thống tệp của vùng chứa vẫn tồn tại ngay cả sau khi vùng chứa thoát. Điều này làm cho việc gỡ lỗi dễ dàng hơn rất nhiều (vì bạn có thể kiểm tra trạng thái cuối cùng) và bạn giữ lại tất cả dữ liệu của mình theo mặc định. Nhưng nếu bạn đang chạy các quy trình tiền cảnh ngắn hạn, các hệ thống tệp vùng chứa này thực sự có thể chồng chất lên nhau. Thay vào đó, nếu bạn muốn Docker tự động dọn sạch vùng chứa và xóa hệ thống tệp khi vùng chứa thoát, bạn có thể thêm cờ --rm.

docker run --rm -ti --name client --link web:dedoimedo image-4:latest /bin/bash

Tệp máy chủ

Điểm hay thứ hai về chức năng liên kết là các vùng chứa mới sẽ tự động có tệp /etc/hosts được điền các tên cần thiết, vì vậy bạn sẽ được thưởng thức. Nó sẽ giống như bên dưới, với các mục nhập IPv6 đã bị xóa:

[root@e1e92f6918dd /]# mèo /etc/hosts
172.17.0.11     e1e92f6918dd
127.0.0.1       máy chủ cục bộ
172.17.0.9      dedoimedo 8e689d8ae3ef web

Kết nối với máy chủ, sử dụng tên của nó

Và vì chúng tôi có cài đặt môi trường và độ phân giải tên máy chủ, nên nó trở nên giống như bất kỳ mạng nào ở bất kỳ đâu. Thực sự đơn giản, đáng nhớ và quan trọng nhất, có thể viết được.

Đọc thêm

Nếu bạn không nghĩ mình đã có đủ niềm vui, thì:

Hướng dẫn kết nối mạng nâng cao docker

Kết luận

Của bạn đi. Một chủ đề khủng khiếp khác được làm sáng tỏ. Vấn đề là, tôi tin rằng thách thức lớn nhất mà bạn sẽ gặp phải khi làm việc với bộ chứa Docker là cấu hình của các quy tắc tường lửa chứ không phải bất kỳ thứ gì không thể thiếu đối với phần kết nối mạng của công nghệ này. Nhưng một khi bạn đã hiểu rõ về nó, nó không khó hay phức tạp đến thế.

Chúng ta đã thấy cách khởi động vùng chứa và hiển thị các cổng, thực hiện máy chủ với vùng chứa, vùng chứa tới máy chủ và vùng chứa với mạng vùng chứa, thiết lập chuyển tiếp và sử dụng các liên kết để làm cho cuộc sống của chúng ta dễ dàng và dễ đoán hơn nhiều. Nói chung, đó là một hướng dẫn bận rộn nhưng hy vọng là thiết thực. Một lần nữa, nếu bạn có bất kỳ chủ đề nào khác, vui lòng đề xuất chúng. Và chúng tôi đã hoàn thành.

Tái bút Nếu bạn thích bài viết này, thì tốt hơn hết bạn nên gửi lại một chút tình yêu cho Dedoimedo!

Chúc mừng.