1. Docker ネットワークの実装原則
- Docker は Linux ブリッジを使用して、ホスト マシン上の Docker コンテナー ブリッジ (docker0) を仮想化します. Docker がコンテナーを起動すると、Container-IP と呼ばれる Docker ブリッジのネットワーク セグメントに従ってコンテナーに IP アドレスが割り当てられます。 Docker ブリッジは、各コンテナーのデフォルト ゲートウェイです。同じホスト内のコンテナは同じネットワーク ブリッジに接続されているため、コンテナはコンテナの Container-IP を介して直接通信できます。
簡単に言えば:
- docker0 は、docker のインストール時に自動的にインストールされるコンテナーの仮想ゲートウェイです。
- docker0 はコンテナーのゲートウェイであり、物理ネットワーク カードにバインドされ、NAT アドレス変換とポート マッピングを担当します。
- ifconfig を使用して表示する
[root@localhost ~]# ifconfig
docker0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500
inet 172.17.0.1 netmask 255.255.0.0 broadcast 172.17.255.255
inet6 fe80::42:2aff:feb3:122b prefixlen 64 scopeid 0x20<link>
ether 02:42:2a:b3:12:2b txqueuelen 0 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 2 bytes 180 (180.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
- The Docker bridge is virtualized by the host, not a real network device. 外部ネットワークをアドレス指定できないため、外部ネットワークは Container-IP を介してコンテナーに直接アクセスできません。外部アクセスによってコンテナーにアクセスしたい場合は、コンテナー ポートをホスト ホストにマッピングすることでアクセスできます (ポート マッピング)。つまり、docker run がコンテナーを作成するときに、 -p または -P パラメーターによって有効にされます。 、コンテナにアクセスするときは、[ホストIP]: [コンテナポート] アクセスコンテナを渡します
#例:
[root@localhost ~]# docker run -d --name test1 -P nginx #大写p随机映射端口(从32768开始)
[root@localhost ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
95ec3237479a nginx "/docker-entrypoint.…" 6 seconds ago Up 6 seconds 0.0.0.0:49153->80/tcp, :::49153->80/tcp test1
浏览器访问测试 192.168.113.127:49153
[root@localhost ~]# docker run -d --name test2 -p 41000:80 nginx #小写p指定映射端口
[root@localhost ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
0dfa28caa72b nginx "/docker-entrypoint.…" 3 seconds ago Up 2 seconds 0.0.0.0:41000->80/tcp, :::41000->80/tcp test2
浏览器访问测试 192.168.113.127:41000
2. Docker ネットワークモード
ネットワークモード | 例証する |
---|---|
ホスト | コンテナーは、独自のネットワーク カードを仮想化したり、独自の IP を構成したりしませんが、ホストの IP とポートを使用します。 |
容器 | 作成されたコンテナーは、独自のネットワーク カードを作成して独自の IP を構成するのではなく、IP とポート範囲を指定されたコンテナーと共有します。 |
なし | このモードはコンテナのネットワーク機能をオフにします |
橋 | デフォルトはこのモードで、各コンテナーに IP を割り当てて設定し、コンテナーを docker0 仮想ブリッジに接続し、docker0 ブリッジと iptables nat テーブル構成を介してホストと通信します。 |
カスタム ネットワーク | それはすべてあなた次第です |
1. Docker をインストールすると、自動的に 3 つのネットワーク、ブリッジ (コンテナーの作成はデフォルトでこのネットワークに接続されます)、なし、ホストが作成されます。
#查看docker网络列表
[root@localhost ~]# docker network ls #方法一
NETWORK ID NAME DRIVER SCOPE
8634fd81aada bridge bridge local
686fa85148f5 host host local
6b205bc8ef67 none null local
[root@localhost ~]# docker network list #方法二
NETWORK ID NAME DRIVER SCOPE
8634fd81aada bridge bridge local
686fa85148f5 host host local
6b205bc8ef67 none null local
2. docker run を使用して Docker コンテナーを作成する場合、 --net または --network オプションを使用して、コンテナーのネットワーク モードを指定できます。
ネットワークモード | ネットワーク モード コマンドを指定します。 |
---|---|
ホストモード | --net=host を使用して指定します |
なしモード | --net=none を使用して指定します |
コンテナー モード | --net=container:NAME_or_ID を使用して指定します |
ブリッジモード | --net=bridge で指定、デフォルト設定、省略可 |
3. ネットワークモードの詳細説明
3.1 ホストモード
-
ホスト コンテナーは、独自のネットワーク カードを仮想化したり、独自の IP を構成したりしませんが、ホストの IP とポートを使用します。
-
コンテナーの起動時にホスト モードが使用される場合、コンテナーは独立したネットワーク名前空間を取得しませんが、ネットワーク名前空間をホストと共有し、コンテナーは独自のネットワーク カードを仮想化したり、独自の IP を構成したりしません。ホストの IP とポートを使用しますが、ファイル システムやプロセス リストなどのコンテナーの他の側面はホストから分離されたままです
-
ホスト モードを使用するコンテナは、ホストの IP アドレスを直接使用して外部と通信でき、コンテナ内のサーバー ポートも NAT なしでホストのポートを使用できます.ホストの最大の利点は、ネットワークパフォーマンスは向上しますが、docker ホストには使用済みのポートが使用できなくなり、ネットワークの分離が良くありません。
3.2 コンテナモード
- 作成されたコンテナーは、独自のネットワーク カードを作成したり、IP を設定したりしませんが、指定されたコンテナーと IP とポート範囲を共有します。
- このモードは、新しく作成されたコンテナがホストと共有する代わりに、既存のコンテナとネットワーク名前空間を共有することを指定します. 新しく作成されたコンテナは、独自のネットワークカードを作成せず、独自の IP を構成しませんが、指定されたコンテナと IP を共有します. ポート同様に、2 つのコンテナーのネットワークの側面に加えて、ファイル システムやプロセス リストなどの他の要素も分離されています。
- 2 つのコンテナーのプロセスは、lo ネットワーク カード デバイスを介して通信できます。
#实例操作实验:
[root@nginx1 opt]# docker run -itd --name test1 centos:7 /bin/bash #--name选项可以给容器创建一个自定义名称
[root@nginx1 opt]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
35950288a708 centos:7 "/bin/bash" 22 seconds ago Up 21 seconds test1
[root@nginx1 opt]# docker inspect -f '{
{.State.Pid}}' 35950288a708 #查看容器进程号
[root@nginx1 opt]# ls -l /proc/28643/ns #查看容器的进程,网络,文件系统等命名空间编号
总用量 0
lrwxrwxrwx 1 root root 0 9月 6 19:23 ipc -> ipc:[4026532527]
lrwxrwxrwx 1 root root 0 9月 6 19:23 mnt -> mnt:[4026532525]
lrwxrwxrwx 1 root root 0 9月 6 19:21 net -> net:[4026532530]
lrwxrwxrwx 1 root root 0 9月 6 19:23 pid -> pid:[4026532528]
lrwxrwxrwx 1 root root 0 9月 6 19:23 user -> user:[4026531837]
lrwxrwxrwx 1 root root 0 9月 6 19:23 uts -> uts:[4026532526]
[root@nginx1 opt]# docker run -itd --name test2 --net=container:35950288a708 centos:7 /bin/bash
[root@nginx1 opt]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
29a672517519 centos:7 "/bin/bash" About a minute ago Up About a minute test2
[root@nginx1 opt]# docker inspect -f '{
{.State.Pid}}' 29a672517519
[root@nginx1 opt]# ls -l /proc/28960/ns #查看可以发现两个容器的 net namespace 编号相同
总用量 0
lrwxrwxrwx 1 root root 0 9月 6 19:30 ipc -> ipc:[4026532622]
lrwxrwxrwx 1 root root 0 9月 6 19:30 mnt -> mnt:[4026532620]
lrwxrwxrwx 1 root root 0 9月 6 19:30 net -> net:[4026532530]
lrwxrwxrwx 1 root root 0 9月 6 19:30 pid -> pid:[4026532623]
lrwxrwxrwx 1 root root 0 9月 6 19:30 user -> user:[4026531837]
lrwxrwxrwx 1 root root 0 9月 6 19:30 uts -> uts:[4026532621]
3.3 なしモード
- none モードでは、Docker コンテナーは独自のネットワーク名前空間を持ちますが、Docker コンテナーのネットワーク構成は実行しません。つまり、この Docker コンテナーには、ネットワーク カード、IP、ルーティング、およびその他の情報がありません。このネットワーク モードでは、コンテナーには lo ループバック ネットワークのみがあり、他のネットワーク カードはありません。このタイプのネットワークはインターネットに接続できず、閉じたネットワークはコンテナのセキュリティを十分に保証できます
3.4 ブリッジモード
- ブリッジモードはdockerのデフォルトのネットワークモードで、-netパラメータを書かなければブリッジモードです
Vmware の nat モードに相当するコンテナは、独立したネットワーク名前空間を使用し、docker0 仮想ネットワーク カードに接続します。docker0 ブリッジと iptables nat テーブルを介してホストとの通信を構成します。このモードでは、各コンテナーにネットワーク名前空間を割り当て、IP などを設定し、ホスト上の Docker コンテナーを仮想ネットワーク ブリッジに接続します。
(1) Docker プロセスが起動すると、ホスト上に docker0 という名前の仮想ネットワーク ブリッジが作成され、このホスト上で起動された Docker コンテナがこの仮想ブリッジに接続されます。仮想ブリッジの動作モードは物理スイッチの動作モードに似ているため、ホスト上のすべてのコンテナーはスイッチを介してレイヤー 2 ネットワークに接続されます。
(2) docker0 サブネットからコンテナーに IP を割り当て、docker0 の IP アドレスをコンテナーのデフォルト ゲートウェイとして設定します。ホスト上に仮想 NIC veth ペア デバイスのペアを作成します。Veth デバイスは常にペアで表示されます. これらはデータ チャネルを形成します. 1 つのデバイスから入力されたデータは、別のデバイスから出力されます. したがって、veth デバイスは、2 つのネットワーク デバイスを接続するためによく使用されます。
(3) Docker は veth ペア デバイスの一方の端を新しく作成されたコンテナーに配置し、それに eth0 (コンテナーのネットワーク カード) という名前を付け、もう一方の端を veth* のような類似の名前で名前を付けたホストに配置します。このネットワーク デバイスを docker0 ブリッジに追加します。brctl show コマンドで表示できます
(4) docker run -p を使用すると、実際に docker が iptables に DNAT ルールを作成し、ポートフォワーディング機能を実現します。iptables -t nat -vnL を使用して表示できます
3.5 カスタム ネットワーク
#直接使用bridge,无法支持指定IP运行docker
docker run -itd --name test1 --network bridge --ip 172.17.0.10 centos:7 /bin/bash
#1.创建自定义网络
#可以先自定义网络,再使用指定IP运行docker
[root@nginx1 opt]# docker network create --subnet=172.18.0.0/16 --opt "com.docker.network.bridge.name"="docker1" mynetwork
#docker1为执行ifconfig -a命令时,显示的网卡名,如果不使用--opt参数指定此名称,那你在使用ifconfig-a命令查看网络信总时,看到的是类似br-110eb56a0b22这样的名字,这显然不怎么好记
#mynetwork为执行docker network list命令时,显示的oridgek网络模式名称
#查看是否创建成功
[root@nginx1 opt]# ifconfig
docker1: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500
inet 172.18.0.1 netmask 255.255.0.0 broadcast 172.18.255.255
ether 02:42:52:ab:85:af txqueuelen 0 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
#再次创建就不会出错了
[root@nginx1 opt]# docker run -itd --name test5 --net mynetwork --ip 172.18.0.10 centos:7 /bin/bash
ps: オーバーレイ オーバーレイ ネットワーク
ip/mac vlan 仮想 MAC アドレス
3. リソース制御
1.CPUリソース制御
-
cgroups は非常に強力な Linux カーネル ツールで、名前空間によって分離されたリソースを制限するだけでなく、リソースの重みの設定、使用量の計算、プロセスの開始と停止の制御などを行うことができます。したがって、cgroup (コントロール グループ) は、リソースのクォータと測定を実現します。
-
cgroup には 4 つの主要な機能があります。
関数 | 例証する |
---|---|
リソースの制約 | タスクが使用するリソースの総量を制限する機能 |
優先順位の割り当て | 割り当てられた CPU タイム スライスの数とディスク IO 帯域幅のサイズを通じて、実際にはタスク実行の優先度を制御することと同じです。 |
リソース統計 | CPU時間、メモリ使用量など、システムのリソース使用量をカウントできます。 |
宇宙管制センター | cgroup は、タスクの中断や再開などの操作を実行できます |
1.1 CPU使用率の上限を設定する
-
Linux は CFS (完全公平スケジューラ) を使用して、各プロセスの CPU 使用率をスケジュールします。CFS のデフォルトのスケジューリング期間は 100 ミリ秒です
-
各コンテナ プロセスのスケジューリング サイクルと、このサイクル中に各コンテナが使用できる CPU 時間を設定できます。
-
--cpu-period を使用してスケジューリング期間を設定し、 --cpu-quota を使用してコンテナーが各期間で使用できる CPU 時間を設定します。どちらも併用可能
CFS 期間の有効な範囲は 1ms~1s であり、対応する --cpu-period の値の範囲は 1000~100000 であり、
コンテナの CPU クォータは 1ms 未満、つまり --cpu の値であってはなりません。 -クォータは >= 1000 でなければなりません
#1.查看CPU使用率
[root@nginx1 opt]# docker run -itd --name test3 centos:7 /bin/bash
[root@nginx1 opt]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7211583c640c centos:7 "/bin/bash" 45 seconds ago Up 44 seconds test3
[root@nginx1 opt]# cd/sys/fs/cgroup/cpu/docker/7211583c640c37beb5079f67f6e3657e3628ba8b8dde388ea69697532b155fe4/
[root@nginx1 7211583c640c37beb5079f67f6e3657e3628ba8b8dde388ea69697532b155fe4]# cat cpu.cfs_quota_us
-1
[root@nginx1 7211583c640c37beb5079f67f6e3657e3628ba8b8dde388ea69697532b155fe4]# cat cpu.cfs_period_us
100000
------------------------------------------------------------------------------------------------------------
#cpu.cfs_period_us:cpu分配的周期(微秒,所以文件名中用 us 表示),默认为100000
#cpu.cfs_quota_us:表示该control group限制占用的时间(微秒),默认为-1,表示不限制。 如果设为50000,表示占用50000/100000=50%的CPU
-----------------------------------------------------------------------------————————————————---------------
#2.进行CPU压力测试
[root@nginx1 docker]# docker exec -it 7211583c640c /bin/bash
[root@7211583c640c opt]# vim cpu.sh
#!/bin/bash
i=0
while true
do
let i++
done
[root@7211583c640c opt]# sh cpu.sh
#可再开启个终端查看
[root@nginx1 opt]# top #可以看到这个脚本占了很多的cpu资源
#3.设置CPU使用率
#设置50%的比例分配CPU使用时间上限
#可以重新创建一个容器并设置限额
docker run -itd --name test2 --cpu-quota 50000 centos:7 /bin/bash
或
[root@nginx1 ~]# echo 50000 > /sys/fs/cgroup/cpu/docker/7211583c640c37beb5079f67f6e3657e3628ba8b8dde388ea69697532b155fe4/cpu.cfs_quota_us
#进入容器在执行下脚本
[root@nginx1 docker]# docker exec -it 7211583c640c /bin/bash
[root@7211583c640c opt]# sh cpu.sh
#可再开启个终端查看
[root@nginx1 ~]# top #可以看到cpu占用率接近50%,cgroups对cpu的控制起了效果
1.2 CPUリソース使用率を設定する(複数コンテナ設定時のみ有効)
Docker は –cpu-shares で CPU シェアを指定します。デフォルト値は 1024 で、値は 1024 の倍数です。
#创建两个容器为 q1 和 q2,若只有这两个容器,设置容器的权重,使得q1和q2的CPU资源占比为1/3和2/3
[root@nginx1 ~]# docker run -itd --name q1 --cpu-shares 512 centos:7
[root@nginx1 ~]# docker run -itd --name q2 --cpu-shares 1024 centos:7
#分别进入容器,进行压力测试
[root@nginx1 ~]# docker exec -it q2 /bin/bash
[root@nginx1 ~]# docker exec -it q1 /bin/bash
#进入容器分别安装
[root@e631251e8a35 /]# yum install -y epel-release
[root@e631251e8a35 /]# yum install stress -y
[root@e631251e8a35 /]# stress -c 4
#查看容器运行状态(动态更新),因为我是4个CPU所以cpu值会这么大,正常的就是去掉前面百位数
[root@nginx1 /]# docker stats
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
af8bafc64df1 q2 242.36% 198.4MiB / 4.669GiB 4.15% 35.4MB / 574kB 0B / 25.3MB 7
e631251e8a35 q1 156.18% 198.5MiB / 4.669GiB 4.15% 35.4MB / 358kB 0B / 24.9MB 7
1.3 指定したCPUをバインドするコンテナを設定する
#先分配虚拟机4个CPU核数
[root@nginx1 /]# docker run -itd --name q3 --cpuset-cpus 1,3 centos:7 /bin/bash
#进入容器,进行压力测试
[root@nginx1 /]# docker exec -it q3 bash
[root@53a585a0396c /]# yum install -y epel-release
[root@53a585a0396c /]# yum install -y stress
[root@53a585a0396c /]# stress -c 4
#退出容器,执行 top 命令再按 1 查看CPU使用情况
[root@nginx1 /]# top
2. メモリ使用量の制限
[root@nginx1 /]# docker run -itd --name q4 -m 512m centos:7 /bin/bash
[root@nginx1 /]# docker stats
3.利用可能なスワップサイズを制限する
强调一下 --memory-swap 是必须要与 --memory一起使用的
正常情况下 --memory-swap的值包含容器可用内存和可用swap
所以 -m 300m --memory-swap=1g 的含义为:容器可以使用 300M 的物理内存,并且可以使用700M(1G - 300)的 swap
如果 --memory-swap设置为 0 或者不设置,则容器可以使用的 swap 大小为 -m 值的两倍
如果 --memory-swap 的值和 -m 值相同,则容器不能使用 swap
如果 --memory-swap值为 -1,它表示容器程序使用的内存受限,而可以使用的 swap 空间使用不受限制(宿主机有多少 swap 容器就可以使用多少)
#例:首先你的宿主机要有swap
#--vm 1:启动1个内存工作线程
#--vm-bytes 200M:每个线程分配200M内存
#如果让工作线程分配的内存超过 1g,分配的内存超过了限额,stress线程会报错,容器退出
docker run -itd -m 300m --memory-swap=1g centos:7 --vm 1 --vm-byres 200
'注意!一旦容器Cgroup使用的内存超过了限制的容量,Linux内核就会尝试收回这些内存'
'如果仍旧无法控制内存使用在这个设置的范围之内,就会杀死该进程!
4. ディスク IO クォータ制御 (blkio) の制限事項
--device-read-bps:限制某个设备上的读速度bps(数据量),单位可以是kb、mb(M)或者gb。
例:docker run -itd --name test4 --device-read-bps /dev/sda:1M centos:7 /bin/bash
--device-write-bps : 限制某个设备上的写速度bps(数据量),单位可以是kb、mb(M)或者gb
例:docker run -itd --name test5 --device-write-bps /dev/sda:1mb centos:7 /bin/bash
-----------------------------------------------------------------------
bps 是byte per second,每秒读写的数据量
iops是io per second,每秒IO的次数
可通过以下参数控制容器的bps 和iops:
-–device-read-bps ,限制读菜个设备的bps
-–device-write-bps,限制写某个设备的bps
-–device-read-iops,限制读某个设备的iops(次数)
-–device-write-iops,限制写入某个设备的iops(次数)
------------------------------------------------------------------------
#创建容器,并限制写速度
docker run -it --name test5 --device-write-bps /dev/sda:1mb centos:7 /bin/bash
#通过dd来验证写速度
dd if=/dev/zero of=test.out bs=1M count=10 oflag=direct #添加oflag参数以规避掉文件系统cache
10+0 records in
10+0 records out
10485760 bytes (10 MB) copied, 10.0025 s, 1.0 MB/s
#小知识:
#清理docker占用的磁盘空间
docker system prune -a
#可以用于清理磁盘,删除关闭的容器、无用的数据卷和网络