技术

如何使用RedisTemplate访问Redis数据结构 MySQL重要知识点 OAuth2认证授授权流程 分布式锁 服务调用 MQ的介绍 SpringCloud 使用链 Eureka 的点对点通信 介绍Eureka RabbitMQ与其它MQ的对比 Springboot 启动过程分析 Springboot 入门 Linux内存管理 自定义CNI IPAM 扩展Kubernetes 副本一致性 spring redis 源码分析 kafka实践 spring kafka 源码分析 Linux进程调度 让kafka支持优先级队列 Codis源码分析 Redis源码分析 C语言学习 《趣谈Linux操作系统》笔记 Kubernetes安全机制 jvm crash分析 Prometheus 学习 Kubernetes监控 Kubernetes 控制器模型 容器日志采集 容器狂占cpu怎么办? 容器狂打日志怎么办? Kubernetes资源调度-scheduler 时序性数据库介绍及对比 influxdb入门 maven的基本概念 《Apache Kafka源码分析》——server Kubernetes objects之编排对象 源码分析体会 自动化mock AIOps说的啥 从DevOps中挖掘docker的价值 《数据结构与算法之美》——算法新解 Kubernetes源码分析——controller mananger Kubernetes源码分析——apiserver Kubernetes源码分析——kubelet Kubernetes整体结构 ansible学习 Kubernetes源码分析——从kubectl开始 jib源码分析之Step实现 kubernetes实践 线程排队 jib源码分析之细节 从一个签名框架看待机制和策略 跨主机容器通信 jib源码分析及应用 docker环境下的持续构建 docker环境下的持续发布 一个容器多个进程 kubernetes yaml配置 marathon-client 源码分析 《持续交付36讲》笔记 程序猿应该知道的 mybatis学习 无锁数据结构和算法 《Container-Networking-Docker-Kubernetes》笔记 活用linux 命令 为什么很多业务程序猿觉得数据结构和算法没用? 串一串一致性协议 当我在说PaaS时,我在说什么 《数据结构与算法之美》——数据结构笔记 swagger PouchContainer技术分享体会 harbor学习 用groovy 来动态化你的代码 《深入剖析kubernetes》笔记 精简代码的利器——lombok 学习 java 语言的动态性 rxjava3——背压 rxjava2——线程切换 spring cloud 初识 JVM4——《深入拆解java 虚拟机》笔记 《how tomcat works》笔记 commons-pipeline 源码分析 hystrix 学习 rxjava1——概念 Redis 学习 TIDB 学习 分布式计算系统的那些套路 Storm 学习 AQS3——论文学习 Unsafe Spark Stream 学习 linux 文件系统 mysql 批量操作优化 《自己动手写docker》笔记 java8 实践 中本聪比特币白皮书 细读 区块链泛谈 比特币 大杂烩 总纲——如何学习分布式系统 forkjoin 泛谈 hbase 泛谈 看不见摸不着的cdn是啥 《jdk8 in action》笔记 程序猿视角看网络 calico 问题排查 bgp初识 mesos 的一些tips mesos 集成 calico calico AQS2——粗略的代码分析 我们能用反射做什么 web 跨域问题 《clean code》笔记 compensable-transaction 源码分析 硬件对软件设计的影响 elasticsearch 初步认识 mockito简介及源码分析 线上用docker要解决的问题 《Apache Kafka源码分析》——Producer与Consumer 停止容器 dns隐藏的一个坑 《mysql技术内幕》笔记2 《mysql技术内幕》笔记1 log4j学习 为什么netty比较难懂? 回溯法 apollo client源码分析及看待面向对象设计 java系并发模型的发展 从一个marathon的问题开始的 docker 环境(主要运行java项目)常见问题 Scala的一些梗 OpenTSDB 入门 spring事务小结 事务一致性 javascript应用在哪里 netty中的future和promise 《netty in action》读书笔记 netty对http2协议的解析 ssl证书是什么东西 一些tricky的code http那些事 苹果APNs推送框架pushy apple 推送那些事儿 编写java框架的几大利器 JVM3——java内存模型 java concurrent 工具类 java exception java io涉及到的一些linux知识 network channel network byte buffer 测试环境docker化实践 通用transport层框架pigeon netty(七)netty在框架中的使用套路 Nginx简单使用 《Linux内核设计的艺术》小结 从Go并发编程模型想到的 mesos深入 Macvlan Linux网络源代码学习2 《docker源码分析》小结 对web系统的一些理解 docker中涉及到的一些linux知识 hystrix学习 Linux网络源代码学习 Docker网络五,docker网络的回顾 zookeeper三重奏 数据库的一些知识 Spark 泛谈 commons-chain netty(六)netty回顾 Thrift基本原理与实践(三) Thrift基本原理与实践(二) Thrift基本原理与实践(一) Future 回调 Docker0.1.0源码分析 基于spring boot和Docker搭建微服务 通过Docker Plugin来扩展Docker Engine java gc Docker网络四,基于Centos搭建Docker跨主机网络 google guava的一些理解 Jedis源码分析 Redis概述 Docker回顾 深度学习是个什么鬼 Docker网络三,基于OVS实现Docker跨主机网络 Linux网络命令操作 JTA与TCC 换个角度看待设计模式 Scala初识 netty(四)netty对http协议的实现(废弃) netty(三)netty框架泛谈 向Hadoop学习NIO的使用 以新的角度看数据结构 AQS1——并发相关的硬件与内核支持 使用Ubuntu要做的一些环境准备 Docker网络二,libnetwork systemd 简介 那些有用的sql语句 异构数据库表在线同步 spring aop 实现原理简述——背景知识 quartz 源码分析 基于docker搭建测试环境(二) spring aop 实现原理简述 我们编程的那些潜意识 自己动手写spring(八) 支持AOP 自己动手写spring(七) 类结构设计调整 分析log日志 一次代码调试的过程 自己动手写spring(六) 支持FactoryBean 自己动手写spring(九) 总结 自己动手写spring(五) bean的生命周期管理 自己动手写spring(四) 整合xml与注解方式 自己动手写spring(三) 支持注解方式 自己动手写spring(二) 创建一个bean工厂 自己动手写spring(一) 使用digester varnish 简单使用 docker volume 关于docker image的那点事儿 基于docker搭建测试环境 分布式配置系统 JVM2——JVM和传统OS对比 git spring rmi和thrift maven/ant/gradle使用 再看tcp mesos简介 缓存系统——具体组件 缓存系统 java nio的多线程扩展 多线程设计模式/《Concurrency Models》笔记 回头看Spring IOC IntelliJ IDEA使用 Java泛型 vagrant 使用 Go 常用的一些库 Netty(一)初步了解 java mina Golang开发环境搭建(Windows下) java nio入门 ibatis自动生成类和文件 Python初学 Goroutine 调度模型猜想 一些编程相关的名词 虚拟网络 《程序员的自我修养》小结 VPN(Virtual Private Network) Hadoop安装与调试 Kubernetes持久化存储 Kubernetes 其它特性 访问Kubernetes上的服务 Kubernetes副本管理 Kubernetes pod 组件 使用etcd + confd + nginx做动态负载均衡 nginx安装与简单使用 在CoreOS集群上搭建Kubernetes 如何通过fleet unit files 来构建灵活的服务 CoreOS 安装 定制自己的boot2docker.iso CoreOS 使用 Go初学 JVM1——jvm小结 硬币和扑克牌问题 LRU实现 virtualbox 使用 os->c->java 多线程 容器类概述 zabbix 使用 zabbix 安装 Linux中的一些点 关于集群监控 ThreadLocal小结 我对Hadoop的认识 haproxy安装 docker快速入门

标签


程序猿视角看网络

2018年03月08日

简介

数据中心网络架构浅谈(三) 中提到:之所以写,是想提供一个非网工的,云计算从业人员的视角。本文也尝试从一个 程序猿的视角,来汇总网络方面的一些知识。

网路通信

本小节来自《Paas实现与运维管理》的笔记。

我们将网络世界的物理设备抽象为三种:计算节点,交换节点和路由节点

  1. 因为计算节点不能两两相连,所以我们需要一个交换节点,负责转发数据。在数据链路层范围内

    • 计算节点在发送数据的时候,应用程序中不可能直接写目的主机的mac地址,所以我们需要一个虚拟地址,即ip地址。arp请求(广播)及arp缓存。
    • 交换节点收到一个包,在转发这个包的时候,没有mac地址与端口的映射,会先广播,然后建立mac地址与串口的映射关系。
  2. 因为一个交换节点负责不了世界上的所有计算节点,(不然广播域也太大了),所以我们需要一个路由节点。

    • 计算节点在发送数据时,通过ip+掩码来判断目的计算节点是否在一个子网内。当发现不在一个子网时,它会将数据包发送给子网内的路由节点(也就是网关)。
    • 路由器根据路由表中的策略来接收和发送包。这就不能叫转发了,因为路由器会修改数据包。路由表中的rule可以静态设置,也可以动态学习。

修正自己以前的几个误区:

  1. 除了功能不同,交换节点和路由节点的另一个区别:交换节点并不修改package
  2. 实际上,计算节点通过交换节点向路由节点发送数据,交换节点转发包可以理解为透明。所以是:计算节点 ==> 路由节点 ==> 计算节点 实现跨网络传输
  3. 不仅计算节点有数据通信,路由节点也有数据通信
  4. 计算节点的广播(arp),交换节点的广播,路由节点的广播(RIP路由协议)。广播有的时候是为了请求信息,有的时候是为了通知。
  5. 在一个网络数据包传输的过程中(跨网络+路由器),都是源/目标mac在变,源/目标ip都没变

网络发现

Computer networkNetwork是一组可以相互通信的Endpoints,网络提供connectivity and discoverability

尤其是对于discoverability,在网络的各个层次都有体现

  1. dns,有专门的dns服务器,在host组装数据包之前 根据dns 将域名转换为ip
  2. arp,在host 发出frame之前,根据arp 获取目的主机的mac地址
  3. 路由器之间的路由同步协议
  4. 边界路由器之间的路由同步协议,比如bgp
  5. 在oveylay 网络中,经常将 虚拟机/容器/网段在哪个主机上 等信息保存在zk/etc中。

解决了discoverability,数据包发向哪里都明确了,交换设备通过简单的复制,将数据包转发给目的设备,提供connectivity

网络分层

The Layers of the OSI Model Illustrated

为什么网络要分层?因为是个复杂点的程序都要分层。

It conceptually divides computer network architecture into 7 layers in a logical progression. The lower layers deal with electrical signals, chunks of binary data, and routing of these data across networks. Higher levels cover network requests and responses, representation of data, and network protocols as seen from a user’s point of view.

层次 数据组织 概念 备注
Physical Layer bit    
Data Link Layer frame mac 1. checks for physical transmission errors
2. packages bits into data “frames”
3. manages physical addressing schemes such as MAC addresses
Network Layer package ip 1. 根据目的ip地址determine if the data has reached its final destination.
2. If the data has reached the final destination, this Layer 3 formats the data into packets delivered up to the Transport layer. Otherwise, the Network layer updates the destination address and pushes the frame back down to the lower layers.
3. adds the concept of routing above the Data Link layer
4. To support routing, the Network layer maintains logical addresses such as IP addresses for devices on the network.
5. manages the mapping between these logical addresses and physical addresses(ARP)
Transport Layer   error recovery, flow control, re-transmission. etc  

传统网络架构

网络间通信——网关和路由器

网关,默认网关,自动网关,路由,网关与路由器的关系

在没有路由器的情况下,两个网络之间是不能进行TCP/IP通信的,即使是两个网络连接在同一台交换机(或集线器)上,TCP/IP协议也会根据子网掩码(255.255.255.0)判定两个网络中的主机处在不同的网络里。而要实现两个网络之间的通信,则必须通过网关。

如果网络A中的主机发现数据包的目的主机不在本地网络中,就把数据包转发给它自己的网关,再由网关转发给网络B的网关,网络B的网关再转发给网络B的某个主机。

路由器使用静态路由或动态路由来决定网络间的最短路径。

从网关和路由器的定义来看,如果只是简单地连接两个网络,那么只需要网关就足够了。因为只有两个网络,不需要决定网络间最短路径。如果需要连接多个网络,为了保证网络的可靠性,网络结构需要设计为全网状或部分网状,这样,为了网络间的通信,需要网关和路由器两种设备(比如网络A到网路D有两种路径,A-B-D/A-C-D,需要网关连通B和C,需要路由器决策选取哪种路径),因为当前路由器集成了网关的功能,所以只使用路由器一种设备就可以了。

抛开这些陈年往事,从现在情境看,网关实质上是一个网络通向其他网络的IP地址。路由器是一个设备,可以做网关使用。它是一种连接多个网络或网段的网络设备,从而构成一个更大的网络。

linux 的路由表

笔者的直观感受 一直是,路由是路由器做的事儿,既然如此,为了linux 中还有一个路由表?

普通的主机与路由器之间的根本区别在于:主机不会将一个报文从一个接口转发到另一个接口,而路由器可以转发报文。但是,一个普通路由算法可以被用在路由器上,同样也可以用在一台普通主机上。当一台主机可以用作路由器时,我们通常说这台主机嵌入了路由器的功能。这种具备嵌入路由器功能的主机平常不会转发报文,除非我们对它进行了配置,使它开启这种功能。

Linux路由分析提到: Linux默认情况下会丢掉不属于本机IP的数据包(类似的,网卡默认会丢弃mac地址不是本网卡的数据包,除非开启混杂模式)。将net.ipv4.ip_forward设置为1后,会开启路由功能,Linux会像路由器一样对不属于本机的IP数据包进行路由转发。linux 有路由表,是因为开启了路由功能。

root@ubuntu-1:/home/ops# ip route
default via 10.0.2.2 dev enp0s3
10.0.2.0/24 dev enp0s3  proto kernel  scope link  src 10.0.2.15
172.17.0.0/16 dev docker0  proto kernel  scope link  src 172.17.0.1 linkdown
172.32.135.128/26 via 192.168.56.103 dev tunl0  proto bird onlink
blackhole 172.32.185.64/26  proto bird
172.32.185.70 dev calie34960bc671  scope link
172.32.185.71 dev cali6d5e7989019  scope link
172.32.243.0/26 via 192.168.56.102 dev tunl0  proto bird onlink
192.168.56.0/24 dev enp0s8  proto kernel  scope link  src 192.168.56.101

如何看待这个输出 route table explanation

proto,发现该路由的路由协议(即路由来源),一般是协议名,proto kernel 表示 The route was installed by the kernel during autoconfiguration.

scope,The scope of a route in Linux is an indicator of the distance to the destination network.

  • Link-local address are supposed to be used for addressing nodes on a single link. Packets originating from or destined to a link-local address will not be forwarded by a router. 还有一种说法 valid only on this device
  • Site,valid only within this site (IPv6)
  • Host,A host address is something that will only exist within the host machine itself. For instance 127.0.0.1 is a host address commonly assigned to the loopback interface. The loopback interface has no external connectivity and so it’s scope is confined to within that of the host machine.
  • A global address is what you might currently consider a “normal” address. Global which is visible on and routable across an external network.

数据中心网络架构

数据中心网络架构和传统网络架构的不同:数据中心网络架构 更侧重局域网,更多的使用交换机, 交换机之间怎么连接都可以玩出花活儿来,比如fabric。

路由器的每一个port 都对应一个网卡(三层交换机类似,有待验证),都有ip和mac地址,这是其与二层交换机port 不同的地方,后者只是一个port。

整体结构

数据中心网络架构 也可以说是一种 网络硬件设备架构

数据中心网络架构浅谈(一)要点:

  1. 数据中心网络架构、三层网络架构、大二层网络架构 是什么?
  2. 数据中心网络,本质上是一个局域网, 但机器很多,为了减少网络广播等考虑,通常会划分几个子网。
  3. 一个交换机最多也就几百个端口,再多的话,交换这么多数据太忙了,接那么多物理机 接口也挺麻烦的。所以,一个交换机是无法支撑一个数据中心网络架构的
  4. 交换机可以只是单纯的连接物理机,提供连通性,比如access switch(通常一个机架一个)。也可以是一个子网入口,或者一个词POD(Point Of Delivery)
  5. 互联网的发展,使得数据中心以南北流量(数据中心的主机与外网相互访问)为主转变为东西流量(数据中心内主机彼此访问)为主。比如hadoop 集群就只是内网彼此访问
  6. 虚拟化的流行 大大提高了单台服务器的利用率,单台服务器网络流量也随之提高
  7. 东西流量要求原来的 三层网络架构 的核心交换机(core switch)具备很高的性能,代价较高

数据中心网络架构浅谈(二)

  1. Fabric网络架构,fabric 一词的由来

数据中心网络架构浅谈(三)

  1. 虚拟网络 和 物理网络是紧密联系的。
  2. overlay网络,只要求物理网络提供连通性。只要hostA(192.168.0.0/16)和 hostB(172.16.0.0/16)连通,就可以提供一个10.10.0.0/16 网络来。物理网络上跑的 数据包 还都是 hostA和 hostB的。

二层网络与三层网络

二层网络结构和三层网络结构的对比在这里的二层、三层是按照逻辑拓扑结构进行的分类,并不是说ISO七层模型中的数据链路层和网络层,而是指数据中心网络架构,具体的说是核心层,汇聚层和接入层,这三层都部署的就是三层网络结构,二层网络结构没有汇聚层。数据中心网络架构浅谈(一)

  1. 二层交换机根据MAC地址表进行数据包的转发,有则转发,无则泛洪。即将数据包广播发送到所有端口,如果目的终端收到给出回应,那么交换机就可以将该MAC地址添加到地址表中。但频繁这样做,在大规模网络架构中会形成网络风暴,限制了二层网络的规模。
  2. 三层交换机工作原理文中提到了vlan场景下的三层交换过程。如果来一个非同一网段ip1,交换机可以通过查询过程建立ip1与port1 的映射关系,此后,去向ip1的包直接由port1转发。

其它:

为什么三层交换机无法替代路由器? - 萧骁的回答 - 知乎提高三层交换机与路由器的区别时提到:

  1. 三层交换机: 三层交换技术就是将路由技术与交换技术合二为一的技术。在对第一个数据流进行路由后,它将会产生一个MAC地址与IP地址的映射表,当同样的数据流再次通过时,将根据此表直接从二层通过而不是再次路由,从而消除了路由器进行路由选择而造成网络的延迟,提高了数据包转发的效率。三层交换技术就是二层交换技术+三层转发技术。它解决了局域网中网段划分之后,网段中子网必须依赖路由器进行管理的局面,解决了传统路由器低速、复杂所造成的网络瓶颈问题。三层交换机的路由功能通常比较简单,因为它所面对的主要是简单的局域网连接。
  2. 路由器,本质是维护ip与port的关系,其处理过程从不涉及mac。路由器的重点是向网络中广播和更新自己的路由信息。路由器一般由基于微处理器的软件路由引擎执行数据包交换,虽然也适用于局域网之间的连接,但更主要的是路由功能,更多的体现在不同类型网络之间的互联上。
  3. 三层交换机的最重要的目的是加快大型局域网内部的数据交换,所具有的路由功能也是为这目的服务的,能够做到一次路由,多次转发。对于数据包转发等规律性的过程由硬件高速实现,更适用于数据交换频繁的局域网中。

交换机,维基百科解释:是一个扩大网络的器材,能为子网络中提供更多的port,以便连接更多的电脑。

二层交换机、三层交换机和路由器的基本工作原理和三者之间的主要区别出于安全和管理方便的考虑,主要是为了减小广播风暴的危害,必须把大型局域网按功能或地域等因素化成一个个小的局域网,这就使得VLAN技术在网络中得到大量应用,而不同VLAN之间的通信都要经过路由器来完成转发,随着网间互访的不断增加。单纯使用路由器来实现网间访问,不但由于端口数量有限,而且路由速度较慢。从而限制了网络的规模和访问速度。基于这种情况三层交换机便应用而生。

所谓的二层设备、三层设备,都是这些设备上跑的程序不同而已。什么叫二层设备呀,就 是只把 MAC 头摘下来,看看到底是丢弃、转发,还是自己留着。那什么叫三层设备呢?就是把 MAC 头摘下来之后,再把 IP 头摘下来,看看到底是丢弃、转发,还是自己留着。

vlan

[VLAN是二层技术还是三层技术-车小胖的回答知乎] (https://www.zhihu.com/question/52278720/answer/140914508)先用生活里的例子来比喻一下什么是VLAN,以及VLAN解决哪些问题。在魔都中心城区,经常有一些大房子被用来群租,有时大客厅也会放几张床用于出租,睡在客厅里的人肯定不爽的,因为有打呼噜的、有磨牙的、有梦游的、有说梦话的,一地鸡毛。为了克服以上的互相干扰,房东将客厅改造成若干个小房间,小房间还有门锁,这样每个房间就有了自己的私密空间,又可以有一定的安全性,至少贵重的物品可以放在房间里不怕别人拿错了。

隔断间形象的解释了划分vlan的理由,一个vlan一个广播域。我们将大广播域所对应的网段10.1.0.0/16分割成255个,那它们所对应的网段为10.1.1.0/24、10.1.2.0/24、10.1.3.0/24…10.1.255.0/24,它们对应的VLAN ID为1、2、3…255,这样每个广播域理论可以容纳255个终端,广播冲突的影响指数下降。

为何要一个VLAN一个网段?先来看看若是同一个网段会有什么问题?

计算机发送数据包的基本过程:

  1. 如果要访问的目标IP跟自己是一个网段的(根据CIDR就可以判断出目标端IP和自己是否在一个网段内了),就不用经过网关了,先通过ARP协议获取目标端的MAC地址,源IP直接发送数据给目标端IP即可。
  2. 如果访问的不是跟自己一个网段的,就会先发给网关,然后再由网关发送出去,网关就是路由器的一个网口,网关一般跟自己是在一个网段内的,通过ARP获得网关的mac地址,就可以发送出去了

从中可以看到,两个vlan 若是同一个网段,数据包会不经网关 直接发往目的ip,也就是第一种方式,会先通过ARP广播获取目的ip的MAC地址,而arp 广播只会在源ip本身的vlan 中广播(vlan限定了广播域),因此永远也无法拿到目的ip的mac地址。

若是一个vlan 一个网段,按照上述基本过程

  1. 数据包会先发往网关(你必须为pc配置一个网关)
  2. 网关进行数据转发

这里要注意:

  1. vlan是实现在二层交换机上的,二层交换机没有网段的概念,只有路由器/三层交换机才有网段的概念。
  2. vlan网段的配置是配置在路由器的子接口上,每个子接口(Sub-Interface)采用802.1Q VLAN ID封装,这样就把网段和对应的VLAN联系了起来,子接口通常作为此网段的缺省网关。如果采用三层交换机来替代路由器,则使用 Interface VLAN ID 来将VLAN与网段联系起来,和使用路由器类似。

其它

隧道技术

为什么需要IP隧道?为了在TCP/IP网络中传输其他协议的数据包

Linux Networking/IPIP Encapsulation

Linux ipip隧道及实现

隧道都是静态建立的,隧道一端有一个IP地址,另一端也有唯一的IP地址

PPP、PPTP和L2TP等协议或软件不是基于内核模块的,Linux系统内核实现的IP隧道技术主要有三种,都是不加密的。对于ip 连通的hostA 和 hostB来说(可以直接连通,或者hostA ==> routeA ==> routeB ==> hostB):

  1. ipip,点对点tunnel,hostA和hostB 均包含tunnel设备(负责解封包)
  2. gre,解封包在 routeA 和 route B 上完成,hostA 和host B 只需要配置路由即可。因而支持广播。
  3. sit

为什么隧道封装是Docker多数网络项目的共同选择?

  1. 对于厂商来说,docker网络可能跨多个环境,统一acl等比较复杂
  2. 容器相较于虚拟机在一台主机上的密度大大增加