Docker组件分析一:docker-proxy

2020-11-13

查看/usr/bin下与docker有关的二进制执行文件:

-rwxr-xr-x. 1 1000 1000 34519704 7 18 2019 containerd
-rwxr-xr-x. 1 1000 1000 6038112 7 18 2019 containerd-shim
-rwxr-xr-x. 1 1000 1000 65632394 7 18 2019 docker
-rwxr-xr-x. 1 1000 1000 71650528 7 18 2019 dockerd
-rwxr-xr-x. 1 1000 1000 764144 7 18 2019 docker-init
-rwxr-xr-x. 1 1000 1000 2851084 7 18 2019 docker-proxy
-rwxr-xr-x. 1 1000 1000 19491032 7 18 2019 ctr
-rwxr-xr-x. 1 1000 1000 8514432 7 18 2019 runc

这些组件根据工作职责可以分为以下三大类。

  • Docker 相关的组件:docker、dockerd、docker-init 和 docker-proxy
  • containerd 相关的组件:containerd、containerd-shim 和 ctr
  • 容器运行时相关的组件:runc

先看docker-proxy。docker-proxy 主要是用来做端口映射的。当我们使用docker run命令启动容器时,如果使用了 -p 参数,docker-proxy 组件就会把容器内相应的端口映射到主机上来,底层是依赖于iptables实现的。

使用以下命令启动一个 nginx 容器并把容器的 80 端口映射到主机的 8080 端口

[root@k8s-master bin]# docker run --name=nginx -d -p 8080:80 nginx

查看一下启动的容器 IP:

[root@k8s-master bin]# docker inspect --format '{{ .NetworkSettings.IPAddress }}' nginx
172.17.0.2

ps 命令查看一下主机上是否有 docker-proxy 进程

[root@k8s-master bin]# ps aux |grep docker-proxy
root 48045 0.0 0.1 103292 4144 ? Sl 15:19 0:00 /usr/bin/docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 8080 -container-ip 172.17.0.2 -container-port 80
root 82391 0.0 0.0 112824 980 pts/0 S+ 15:45 0:00 grep --color=auto docker-proxy

查看一下主机上 iptables nat 表的规则

[root@k8s-master bin]# iptables -L -nv -t nat
Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
16 1557 cali-PREROUTING all -- * * 0.0.0.0/0 0.0.0.0/0 /* cali:6gwbT8clXdHdC1b1 */
24 2087 KUBE-SERVICES all -- * * 0.0.0.0/0 0.0.0.0/0 /* kubernetes service portals */
2 113 DOCKER all -- * * 0.0.0.0/0 0.0.0.0/0 ADDRTYPE match dst-type LOCAL
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Chain OUTPUT (policy ACCEPT 3 packets, 180 bytes)
pkts bytes target prot opt in out source destination
16367 986K cali-OUTPUT all -- * * 0.0.0.0/0 0.0.0.0/0 /* cali:tVnHkvAo15HuiPy0 */
16409 989K KUBE-SERVICES all -- * * 0.0.0.0/0 0.0.0.0/0 /* kubernetes service portals */
1890 113K DOCKER all -- * * 0.0.0.0/0 !127.0.0.0/8 ADDRTYPE match dst-type LOCAL
Chain POSTROUTING (policy ACCEPT 3 packets, 180 bytes)
pkts bytes target prot opt in out source destination
16371 986K cali-POSTROUTING all -- * * 0.0.0.0/0 0.0.0.0/0 /* cali:O3lYWMrLQYEMJtB5 */
16769 1010K KUBE-POSTROUTING all -- * * 0.0.0.0/0 0.0.0.0/0 /* kubernetes postrouting rules */
0 0 MASQUERADE all -- * !docker0 172.17.0.0/16 0.0.0.0/0
0 0 MASQUERADE tcp -- * * 172.17.0.2 172.17.0.2 tcp dpt:80
Chain DOCKER (2 references)
pkts bytes target prot opt in out source destination
0 0 RETURN all -- docker0 * 0.0.0.0/0 0.0.0.0/0
0 0 DNAT tcp -- !docker0 * 0.0.0.0/0 0.0.0.0/0 tcp dpt:8080 to:172.17.0.2:80

通过最后一行规则我们可以得知,通过DNAT服务(目标地址转换)当我们访问主机的 8080 端口时,iptables 会把流量转发到 172.17.0.2 的 80 端口

Gitalking ...