我们在工作中应用了docker容器化技术,服务的部署、维护和扩展都方便了很多。然而,近期在私有化部署过程中,由于不同服务器环境的复杂多变,常常遇到网络方面的问题,现象为容器服务运行正常,但宿主机、容器之间网络不通。

本篇博客旨在总结:

  • Linux虚拟网络及docker网络的基础知识
  • 遇到网络问题时排查问题思路
  • 常用指令和工具的使用

以上三部分作为之后的参考,本篇文章也将会在日后实践过程中逐渐补充。本篇为第一篇,主要介绍基础知识

Linux网络虚拟化基础

Network Namespace

网络命名空间,是Linux 2.6.x内核版本之后提供的功能,主要用于资源的隔离。namespace是实现网络虚拟化的重要功能,使用它,一个Linux系统可以抽象出多个网络子系统,各个子系统都有自己独立的网卡、路由表、iptables、协议栈等网络资源。不管是虚拟机还是容器,运行时仿佛自己都在独立的网络中。

ip netns命令用于完成对ns的各种操作,ip netns exec子命令用于在namespace执行指令。

Veth Pair(Virtual Ethernet Pair)

成对虚拟设备端口。它总是成对出现,一端连着协议栈,一端彼此连着。从其中一个端口发出的数据包,可以直接出现在与它对应的另一个端口上,即使它们在不同的namespace中。



如上图,一对veth-pair直接将两个namespace连接在一起。

  • 使用如下图所示命令,测试veth pair功能

Bridge 网桥

veth pair打破了Network Namespace的限制,实现了不同Network Namespace之间的通信。但是veth pair的局限性也很明显,只能实现两个网络接口的通信。

Linux中引入网桥来实现多个网络接口之间的通信,可以将一台机器上的若干接口连通起来。在OSI网络模型中,网桥属于数据链路层。

和网桥相关的操作使用命令brctl,需要先安装bridge-utils工具包。安装指令:

yum install bridge-utils

iptables/Netfilter

请参考:iptables详解(1):iptables概念

Docker网络基础

Docker支持四种网络模式:host模式,container模式,none模式和bridge模式。默认使用的是桥接模式。

使用docker network ls指令可以查看到宿主机上所有的Docker网络:

Bridge 桥接模式

Docker在启动时,默认会自动创建网桥设备docker0,Docker在运行时,守护进程通过docker0为docker的容器提供网络通信服务。

当Docker启动容器时,会创建一对Veth Pair,并将其中一个veth网络设备附加到网桥docker0,另一个加入容器的network namespace中。

根据上一节中关于网桥的定义,我们很容易画出示意图:

由上图可得,容器可以通过网桥互相通信。如果不想使用默认的网桥设备,也可以在启动docker daemon的时候使用 --bridge==BRIDGE参数指定其他网桥。

然而这还不够,Docker容器还需要与外网进行相互通信。这里涉及到NAT相关知识。

  • NAT

    网络地址转换,就是替换IP报文头部的地址信息。NAT通常部署在一个组织的网络出口位置,通过将内部网络IP地址替换为出口的IP地址,提供公网可达性和上层协议的链接地址。(请参考:NAT相关科普
  • SNAT

    源地址转换即内网地址向外访问时,发起访问的内网ip地址转换为指定的ip地址(可指定具体的服务以及相应的端口或端口范围),这可以使内网中使用保留ip地址的主机访问外部网络,即内网的多部主机可以通过一个有效的公网ip地址访问外部网络。

使用iptables -t nat -vnL指令查看宿主机NAT表。

查看规则:

2051 125K MASQUERADE all -- * !docker0 172.17.0.0/16 0.0.0.0/0

这条规则就关系着Docker容器与外界的通信,含义为将源地址为172.17.0.0/16的数据包(就是docker容器中发出的数据),如果不是从docker0网卡发出时,做SNAT转换,将IP包的源地址替换为相应网卡的地址。

对于外界来说,从docker容器内发出的请求,和宿主机发出的请求相同。

外界想要访问Docker容器的服务呢?

在启动docker容器时,我们使用 -p参数指定端口,这时其实是在iptables中添加了规则,如下图所示:

DNAT规则,将发送到宿主机的流量转发到真正提供服务的容器IP端口上。

host模式

Docker容器与宿主机使用相同的网络环境,直接使用宿主机的IP和端口及其他网络设备。这样虽然避免了很多桥接带来的网络问题,但同时也容易造成网络环境的混淆和冲突,比如端口被占用等。不推荐。

container

指定与某一容器共享网络。

none

不配置任何网络。

--link

docker容器之间还可以通过--link阐述进行通信,当提供服务的容器只希望个别容器能够访问时,我们可以使用该指令,提供更为高效、安全的连接方式。

小结

对Linux虚拟网络基础知识的简单学习后,有助于理清楚下一步排查问题思路。

下一篇博客将介绍目前遇到问题时的排查思路和解决方案,并列举一些常用工具。

Linux虚拟网络:Docker网络知识之基础篇的更多相关文章

  1. Docker虚拟化实战学习——基础篇(转)

    Docker虚拟化实战学习——基础篇 2018年05月26日 02:17:24 北纬34度停留 阅读数:773更多 个人分类: Docker   Docker虚拟化实战和企业案例演练 深入剖析虚拟化技 ...

  2. Retrofit + RxJava + OkHttp 让网络请求变的简单-基础篇

    https://www.jianshu.com/p/5bc866b9cbb9 最近因为手头上的工作做完了,比较闲,想着做一些优化.看到以前用的那一套网络框架添加一个请求比较麻烦,并且比较难用,所以想改 ...

  3. 新一代Java程序员必学的Docker容器化技术基础篇

    Docker概述 **本人博客网站 **IT小神 www.itxiaoshen.com Docker文档官网 Docker是一个用于开发.发布和运行应用程序的开放平台.Docker使您能够将应用程序与 ...

  4. ESXi5 中克隆Linux虚拟主机的网络配置

    虚拟化技术果然非常方便,尤其是windows主机,克隆后在网络管理中改一下IP即可. 但对于Linux来说就有点麻烦,只修改IP还不行,还有MAC地址,网卡指定等,这个规程对应新手来说没有大半天搞不定 ...

  5. Linux ubuntu下docker容器安装和基础命令

    Docker介绍: 云计算就好比大货轮,docker就是集装箱虚拟机虽然可以隔离出很多"子电脑",但占用空间更大,启动更慢,虚拟机软件可能还要花钱(例如VMWare). 而容器技术 ...

  6. C#网络编程(一)基础篇

    简介: C#网络编程API包含在System.Net和System.Net.Sockets命名空间下,大部分网络操作都可以在其中找到相应的类来实现:包括Socket的创建和连接,网络流收发方法的封装, ...

  7. docker进阶之路-基础篇 | 二:portainer安装与基本使用

    转载请注明作者及出处: 作者:银河架构师 原文链接:https://www.cnblogs.com/luas/p/12061755.html ​简介 Portainer 是轻量级,跨平台,开源的管理D ...

  8. docker进阶之路-基础篇 | 一:环境搭建

    转载请注明作者及出处: 作者:银河架构师 原文链接:https://www.cnblogs.com/luas/p/12061747.html 一.准备工作 查看内核 Docker 要求 CentOS ...

  9. cocos2d-x知识巩固-基础篇(1)

    有段时间没有学习cocos2dx了,作为新人,自己觉得还是要稳扎稳打,一点点的去积累,梳理好每一个知识点,这样对自己的成长能够有一个更清晰的认识,以便做更好的提高. 从2013年8月开始接触cocos ...

随机推荐

  1. Java实现 LeetCode 791 自定义字符串排序(桶排序)

    791. 自定义字符串排序 字符串S和 T 只包含小写字符.在S中,所有字符只会出现一次. S 已经根据某种规则进行了排序.我们要根据S中的字符顺序对T进行排序.更具体地说,如果S中x在y之前出现,那 ...

  2. Java实现 LeetCode 790 多米诺和托米诺平铺(递推)

    790. 多米诺和托米诺平铺 有两种形状的瓷砖:一种是 2x1 的多米诺形,另一种是形如 "L" 的托米诺形.两种形状都可以旋转. XX <- 多米诺 XX <- &q ...

  3. Java实现 LeetCode 617 合并二叉树(遍历树)

    617. 合并二叉树 给定两个二叉树,想象当你将它们中的一个覆盖到另一个上时,两个二叉树的一些节点便会重叠. 你需要将他们合并为一个新的二叉树.合并的规则是如果两个节点重叠,那么将他们的值相加作为节点 ...

  4. Android中如何使用Listview

    第一步 首先在xml文件中声明一个List View控件,并且标明id (这一步其实不用说,怕自学Android的小白不懂,就好比当初的我,哈哈) <?xml version="1.0 ...

  5. Java实现 洛谷 P1583 魔法照片

    import java.util.*; class Main{ public static void main(String[] args) { Scanner in = new Scanner(Sy ...

  6. DirectX11 With Windows SDK--31 阴影映射

    前言 阴影既暗示着光源相对于观察者的位置关系,也从侧面传达了场景中各物体之间的相对位置.本章将起底最基础的阴影映射算法,而像复杂如级联阴影映射这样的技术,也是在阴影映射的基础上发展而来的. 学习目标: ...

  7. 恕我直言,我怀疑你并不会用 Java 枚举

    开门见山地说吧,enum(枚举)是 Java 1.5 时引入的关键字,它表示一种特殊类型的类,默认继承自 java.lang.Enum. 为了证明这一点,我们来新建一个枚举 PlayerType: p ...

  8. zabbix通过Web场景监控URL

    选择主机添加应用集       添加Web监控 选在相应主机,并添加Web监控 按照方式新建Web场景 注意: 名称统一规则:相应的域名 应用集:选择之前创建的 或者 新建一个,名称为“URL 告警” ...

  9. 2 个步骤为 VSCode 配置工程头文件路径!

    我用 VSCode 来 Coding,这个编辑器需要自己配置头文件路径,就是自动建立一个 c_cpp_properties.json 文件来管理头文件路径,然后需要用哪些库就手动加上即可,方法很简单, ...

  10. 使用navicat连接mysql连接错误:Lost connection to Mysql server at 'waiting for initial communication packet'

    使用navicat时,报错截图如下: 原因分析: mysql开启了DNS的反向解析功能,这样mysql对连接的客户端会进行DNS主机名查找. mysql处理客户端解析过程: 当mysql的client ...