[Kubernetes]浅谈容器网络
Veth Pair |
这部分内容主要介绍一个设备: Veth Pair .
作为一个容器,它可以声明直接使用宿主机的网络栈,即:不开启 Network Namespace .在这种情况下,这个容器启动后,直接监听的就是宿主机的 80 端口.
像这样直接使用宿主机网络栈的方式,虽然可以为容器提供良好的网络性能,但也会不可避免地引入共享网络资源的问题,比如端口冲突.所以,在大多数情况下,我们都希望容器进程能使用自己 Network Namespace 里的网络栈,即:拥有属于自己的 IP 地址和端口.
但是这个时候,就有另外一个问题了:这个别隔离的容器进程,该如何跟其他 Network Namespace 里的容器进程进行交互呢?
最直接的办法,就是把它们用一根网线连接起来;而如果想要实现多台主机之间的通信,那就需要用网线,把它们连接在一台交换机上.
在 Linux 中,能够起到虚拟交换机作用的网络设备,是网桥( Bridge ).它是一个工作在数据链路层( Data Link )的设备,主要功能是根据 MAC 地址学习来将数据包转发到网桥的不同端口( Port )上.
为了实现这个目的, Docker 项目会默认在宿主机上创建一个名叫 docker0 的网桥,凡是连接在 docker0 网桥上的容器,都可以通过它来进行通信.
但是,我们又该如何把这些容器"连接"到 docker0 网桥上呢?此时,我们就需要使用一种名叫 Veth Pair 的虚拟设备了.
Veth Pair 设备的特点是:它被创建出来后,总是以两张虚拟网卡( Veth Peer )的形式成对出现的.并且,从其中一个"网卡"发出的数据包,可以直接出现在与它对应的另一张"网卡"上,哪怕这两个"网卡"在不同的 Network Namespace 里面.这样,用来连接不同 Network Namespace 的"网线"就成为了可能.
举个例子 |
比如,现在我们启动了一个叫做 nginx-1 的容器:
$ docker run –d --name nginx-1 nginx
然后我们可以进入到这个容器中,查看一下它的网络设备:
# 在宿主机上
$ docker exec -it nginx-1 /bin/bash
# 在容器里
root@2b3c181aecf1:/# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.17.0.2 netmask 255.255.0.0 broadcast 0.0.0.0
inet6 fe80::42:acff:fe11:2 prefixlen 64 scopeid 0x20<link>
ether 02:42:ac:11:00:02 txqueuelen 0 (Ethernet)
RX packets 364 bytes 8137175 (7.7 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 281 bytes 21161 (20.6 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10<host>
loop txqueuelen 1000 (Local Loopback)
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
$ route
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
default 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
可以看到,在这个容器中,有一张叫做 eth0 的网卡,它正是一个 Veth Pair 设备在容器里的这一端.通过 route 命令,可以查看到 nginx-1 容器的路由表,能够看到,这个 eth0 网卡是这个容器里的默认路由设备;所有对 172.17.0.0/16 网段的请求,也会被交给 eth0 来处理(第二条 172.17.0.0 路由规则)
而这个 Veth Pair 设备的另一端,则在宿主机上.可以通过查看宿主机的网络设备看到它,如下所示:
# 在宿主机上
$ ifconfig
...
docker0 Link encap:Ethernet HWaddr 02:42:d8:e4:df:c1
inet addr:172.17.0.1 Bcast:0.0.0.0 Mask:255.255.0.0
inet6 addr: fe80::42:d8ff:fee4:dfc1/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:309 errors:0 dropped:0 overruns:0 frame:0
TX packets:372 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:18944 (18.9 KB) TX bytes:8137789 (8.1 MB)
veth9c02e56 Link encap:Ethernet HWaddr 52:81:0b:24:3d:da
inet6 addr: fe80::5081:bff:fe24:3dda/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:288 errors:0 dropped:0 overruns:0 frame:0
TX packets:371 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:21608 (21.6 KB) TX bytes:8137719 (8.1 MB)
$ brctl show
bridge name bridge id STP enabled interfaces
docker0 8000.0242d8e4dfc1 no veth9c02e56
通过 ifconfig 命令的输出,我们可以看到, nginx-1 容器对应的 Veth Pair 设备,在宿主机上是一张虚拟网卡,它的名字是: veth9c02e56 .并且,通过 brctl show 的输出,可以看到这张网卡被"插"在了 docker0 上.
如果此时,我们在这台宿主机上启动另一个 Docker 容器,比如 nginx-2 :
$ docker run –d --name nginx-2 nginx
$ brctl show
bridge name bridge id STP enabled interfaces
docker0 8000.0242d8e4dfc1 no veth9c02e56
vethb4963f3
会发现,有一个新的,名叫 vethb4963f3 的虚拟网卡,也被"插"在了 docker0 网桥上.此时,如果在 nginx-1 容器中 ping 一下 nginx-2 容器的 IP 地址( 172.17.0.3 ),就会发现,在同一宿主机上的两个容器,默认就是相互连通的.
以上整个流程,来一张示意图:(这样可以更清楚一些)
此时,应该就可以理解了,在默认情况下,被限制在 Network Namespace 里的容器进程,实际上是通过 Veth Pair 设备 + 宿主机网桥的方式,实现了和其他容器的数据交换.
所以,如果遇到容器连不通"外网"时,第一反应应该是先试试 docker0 网桥能不能 ping 通,然后查看一下跟 docker0 和 Veth Pair 设备相关的 iptables 规则是不是有异常,一般就能够找到问题的答案.
以上介绍的是单机容器网络的实现原理和 docker0 网桥的作用.在这里的关键在于,容器如果想要和外界进行通信,它发出的 IP 包就必须从它的 Network Namespace 里出来,来到宿主机上,而解决这个问题的方法就是:为容器创建一个一端在容器里充当默认网卡,另一端在宿主机上的 Veth Pair 设备.
思维扩展 |
看到这里,估计你会有另外一个疑问,那我如果想要"跨主机通信"呢?
在 Docker 的默认配置下,一台宿主机上的 docker0 网桥,和其他宿主机上的 docker0 网桥,没有任何关联,它们互相之间就没办法连通.
但是如果我们通过软件的方式,创建一个整个集群"公用"的网桥呢?然后把集群里所有的容器都连接到这个网桥上,是不是就可以相互通信了?
一点儿毛病都没.
这样,我们就可以画出如下的示意图:
通过示意图,能够看到,构建这种容器网络的核心在于:我们需要在已有的宿主机网络上,再通过软件构建出一个覆盖在已有宿主机网络之上的,可以把所有容器连通在一起的虚拟网络.这种技术就是: Overlay Network (覆盖网络).
但是这只是理论上,落实到实际,还是有些出入的.
后面我看时间和精力,如果可能,再写一篇关于"跨主机"通信的讲解文章(感觉有些难度,我不确定能够讲清楚,但是尽量)
以上内容来自我学习<深入剖析Kubernetes>专栏文章之后的一些见解,有偏颇之处,还望指出.
感谢您的阅读~
[Kubernetes]浅谈容器网络的更多相关文章
- 浅谈通信网络(三)——TCP/IP协议
简介 Transmission Control Protocol/Internet Protocol的简写,中译名为传输控制协议/因特网互联协议,又名网络通讯协议,是Internet最基本的协议.In ...
- 从 Kubernetes 谈容器网络
基本概念 在 Kubernetes 中.资源从管理粒度上分为三级:容器.Pod.Service. 容器 即 Docker 或者 Rocket 容器(1.0 中仅支持这两种容器). 容器是最低粒度的资源 ...
- 浅谈C#网络编程(一)
阅读目录: 基础 Socket编程 多线程并发 阻塞式同步IO 基础 在现今软件开发中,网络编程是非常重要的一部分,本文简要介绍下网络编程的概念和实践. Socket是一种网络编程接口,它是对传输层T ...
- 浅谈iOS网络编程之一入门
计算机网络,基本上可以抽象是端的通信.实际在通讯中会用到不同的设备,不同的硬件中,为了能友好的传输信息,那么建立一套规范就十分必要了.先来了解一些基本概念 了解网络中传输的都是二进制数据流. 2.了 ...
- [Cocos2d-x v3.x]浅谈容器Vector
转载请注明来自:star特530的CSDN博客 http://blog.csdn.net/start530/article/details/19170853 前两天有人问我说在3.0 beta2版本号 ...
- 小dai浅谈通信网络(一)——引子
说起通信网络,首先来看一个场景: 场景模式: 小明和小刚在闹市碰面. 小明对小刚大声喊道:"小刚,你好啊!" 小刚摇手答到:"你好,小明!" 就这么几句简单的话 ...
- 浅谈C#网络编程(二)
阅读目录: 异步IO 非阻塞式同步IO 基于回调的异步IO并发 异步IO 上篇提到用多线程处理多个阻塞同步IO而实现并发服务端,这种模式在连接数量比较小的时候非常适合,一旦连接过多,性能会急速下降. ...
- Android项目实战(四十四):浅谈Postman (网络请求调试插件)
前言: Postman是一款功能强大的网页调试与发送网页HTTP请求的Chrome插件. 在项目开发中,可以依赖此工具模拟API测试. 使用详解: 各种情况Api的模拟请求的Postman使用方 ...
- 【好书分享】容器网络到kubernetes网络
Nginx 公司的 Michael Hausenblas 发布了一本关于 docker 和 kubernetes 中的容器网络的小册子.这份资料一共 72 页,是大家由浅入深的了解 Docker 和 ...
随机推荐
- 浅谈background-size的几个属性值
前言: css应用中,我们常会碰到background-size的用法,不妨下面总结一下,以便后续查看. 一.先弄个简单的box框. <!DOCTYPE html> <html la ...
- centos 7 修改网卡名字
1.编辑网卡信息 cd /etc/sysconfig/network-scripts/ #进入网卡目录mv ifcfg-en067761 ifcfg-eth0 #重命名网卡 cat ifcfg-eth ...
- AtCoder ABC 042D いろはちゃんとマス目 / Iroha and a Grid
题目链接:https://abc042.contest.atcoder.jp/tasks/arc058_b 题目大意: 给定一个 H * W 的矩阵,其中左下角 A * B 区域是禁区,要求在不踏入禁 ...
- Windows平台安装TensorFlow Q&A
·本文讲的是Windows平台使用原生pip进行TensorFlow(CPU版本)安装的注意事项及常见问题解决方法 ·这是TensorFlow官网的安装介绍:在 Windows 上安装 TensorF ...
- CS程序自动更新实现原理及代码(支持多版本多文件更新)
公司主要项目为CS端,经常遇到客户需求变更及bug处理,在没有引用自动更新之前每次更新程序,必须手动对每个客户端进行更新,这样导致技术支持工作量特别大,也给客户不好的印象,因此我需要一个自动更新程序! ...
- Tutorial: Create a Windows Machine Learning UWP application (C#)
In this tutorial, we'll build a simple Universal Windows Platform application that uses a trained ma ...
- loj121-动态图连通性
Solution 线段树分治, 然后直接在线段树上dfs, 在进入/回溯的过程中维护并查集的merge/split. 对于split操作, 可以在merge时按秩合并, 然后利用栈记录, split时 ...
- logback日志模板
logback.xml <?xml version="1.0" encoding="UTF-8"?> <configuration> & ...
- magento 2 method config
1. 模板渲染静态文件: <?php echo $this->getViewFileUrl('requirejs::require.js'); ?> 2.
- 自动化测试框架【windows版】:JMeter + Ant + Jenkins
前提条件:windows安装了jmeter.ant.jenkins 安装方法参考汇总目录中对应的博文 截图看不清的,可以调大浏览器倍数看 jenkins驱动ant执行,ant驱动jmeter执行 an ...