深入剖析Kubernetes之容器网络(二)

2023-11-01

Flannel 的 host-gw 模式

Flannel host-gw 示意图

在这里插入图片描述

  • 假设现在,Node 1 上的 Infra-container-1,要访问 Node 2 上的 Infra-container-2。
  • 当你设置 Flannel 使用 host-gw 模式之后,flanneld 会在宿主机上创建这样一条规则,以 Node 1 为例:
$ ip route
...
10.244.1.0/24 via 10.168.0.3 dev eth0
  • 这条路由规则的含义是:目的 IP 地址属于 10.244.1.0/24 网段的 IP 包,应该经过本机的 eth0 设备发出去(即:dev eth0);并且,它**下一跳地址(next-hop)**是 10.168.0.3(即:via 10.168.0.3)。
    • 所谓下一跳地址就是:如果 IP 包从主机 A 发到主机 B,需要经过路由设备 X 的中转。那么 X 的 IP 地址就应该配置为主机 A 的下一跳地址。
  • 从 host-gw 示意图中我们可以看到,这个下一跳地址对应的,正是我们的目的宿主机 Node 2。
  • 一旦配置了下一跳地址,那么接下来,当 IP 包从网络层进入链路层封装成帧的时候,eth0 设备就会使用下一跳地址对应的 MAC 地址,作为该数据帧的目的 MAC 地址。显然,这个 MAC 地址,正是 Node 2 的 MAC 地址。
  • 这样,这个数据帧就会从 Node 1 通过宿主机的二层网络顺利到达 Node 2 上。Node 2 的内核网络栈从二层数据帧里拿到 IP 包后,会“看到”这个 IP 包的目的 IP 地址是 10.244.1.3,即 Infra-container-2 的 IP 地址。这时候,根据 Node 2 上的路由表,该目的地址会匹配到第二条路由规则(也就是 10.244.1.0 对应的路由规则),从而进入 cni0 网桥,进而进入到 Infra-container-2 当中。
  • 也就是说,这台“主机”(Host)会充当这条容器通信路径里的“网关”(Gateway)。这也正是“host-gw”的含义。

host-gw 模式的工作原理,其实就是将每个 Flannel 子网(Flannel Subnet,比如:10.244.1.0/24)的“下一跳”,设置成了该子网对应的宿主机的 IP 地址。

  • host-gw 模式能够正常工作的核心,就在于 IP 包在封装成帧发送出去的时候,会使用路由表里的“下一跳”来设置目的 MAC 地址。这样,它就会经过二层网络到达目的宿主机。所以,Flannel host-gw 模式必须要求集群宿主机之间是二层连通的
  • 宿主机之间二层不连通的情况也是广泛存在的。比如,宿主机分布在了不同的子网(VLAN)里。但是,在一个 Kubernetes 集群里,宿主机之间必须可以通过 IP 地址进行通信,也就是说至少是三层可达的。否则的话,你的集群将不满足上一篇文章中提到的宿主机之间 IP 互通的假设(Kubernetes 网络模型)。

Calico

  • 在容器生态中,要说到像 Flannel host-gw 这样的三层网络方案,不得不提到这个领域里的“龙头老大”Calico 项目了。
  • Calico 项目提供的网络解决方案,与 Flannel 的 host-gw 模式,几乎是完全一样的。Calico 也会在每台宿主机上,添加一个格式如下所示的路由规则:
< 目的容器 IP 地址段 > via < 网关的 IP 地址 > dev eth0
  • 其中,网关的 IP 地址,正是目的容器所在宿主机的 IP 地址。
  • 三层网络方案得以正常工作的核心,是为每个容器的 IP 地址,找到它所对应的、“下一跳”的网关。
  • 不过,不同于 Flannel 通过 Etcd 和宿主机上的 flanneld 来维护路由信息的做法,Calico 项目使用了一个“重型武器”来自动地在整个集群中分发路由信息。这个“重型武器”,就是 BGP
    • BGP 的全称是 Border Gateway Protocol,即:边界网关协议。它是一个 Linux 内核原生就支持的、专门用在大规模数据中心里维护不同的“自治系统”之间路由信息的、无中心的路由协议。

边界网关
在这里插入图片描述

  • 在这个图中,我们有两个自治系统(Autonomous System,简称为 AS):AS 1 和 AS 2。而所谓的一个自治系统,指的是一个组织管辖下的所有 IP 网络和路由器的全体。你可以把它想象成一个小公司里的所有主机和路由器。在正常情况下,自治系统之间不会有任何“来往”。但是,如果这样两个自治系统里的主机,要通过 IP 地址直接进行通信,我们就必须使用路由器把这两个自治系统连接起来。
  • 比如,AS 1 里面的主机 10.10.0.2,要访问 AS 2 里面的主机 172.17.0.3 的话。它发出的 IP 包,就会先到达自治系统 AS 1 上的路由器 Router 1。
  • 而在此时,Router 1 的路由表里,有这样一条规则,即:目的地址是 172.17.0.2 包,应该经过 Router 1 的 C 接口,发往网关 Router 2(即:自治系统 AS 2 上的路由器)。
  • 所以 IP 包就会到达 Router 2 上,然后经过 Router 2 的路由表,从 B 接口出来到达目的主机 172.17.0.3。
  • 但是反过来,如果主机 172.17.0.3 要访问 10.10.0.2,那么这个 IP 包,在到达 Router 2 之后,就不知道该去哪儿了。因为在 Router 2 的路由表里,并没有关于 AS 1 自治系统的任何路由规则。
  • 所以这时候,网络管理员就应该给 Router 2 也添加一条路由规则,比如:目标地址是 10.10.0.2 的 IP 包,应该经过 Router 2 的 C 接口,发往网关 Router 1。
  • 像上面这样负责把自治系统连接在一起的路由器,我们就把它形象地称为:边界网关。它跟普通路由器的不同之处在于,它的路由表里拥有其他自治系统里的主机路由信息。
  • 用了 BGP 之后,你可以认为,在每个边界网关上都会运行着一个小程序,它们会将各自的路由表信息,通过 TCP 传输给其他的边界网关。而其他边界网关上的这个小程序,则会对收到的这些数据进行分析,然后将需要的信息添加到自己的路由表里。这样,Router 2 的路由表里,就会自动出现 10.10.0.2 和 10.10.0.3 对应的路由规则了。\
  • 所以说, BGP,就是在大规模网络中实现节点路由信息共享的一种协议

  • Calico 项目的架构。它由三个部分组成:

    • Calico 的 CNI 插件。这是 Calico 与 Kubernetes 对接的部分。
    • Felix。它是一个 DaemonSet,负责在宿主机上插入路由规则(即:写入 Linux 内核的 FIB 转发信息库),以及维护 Calico 所需的网络设备等工作。
    • BIRD。它就是 BGP 的客户端,专门负责在集群里分发路由规则信息。
  • 除了对路由信息的维护方式之外,Calico 项目与 Flannel 的 host-gw 模式的另一个不同之处,就是它不会在宿主机上创建任何网桥设备。这时候,Calico 的工作方式,如下所示:
    在这里插入图片描述

  • 其中的绿色实线标出的路径,就是一个 IP 包从 Node 1 上的 Container 1,到达 Node 2 上的 Container 4 的完整路径。

  • 可以看到,Calico 的 CNI 插件会为每个容器设置一个 Veth Pair 设备,然后把其中的一端放置在宿主机上(它的名字以 cali 前缀开头)。

  • 此外,由于 Calico 没有使用 CNI 的网桥模式,Calico 的 CNI 插件还需要在宿主机上为每个容器的 Veth Pair 设备配置一条路由规则,用于接收传入的 IP 包。比如,宿主机 Node 2 上的 Container 4 对应的路由规则,如下所示: 10.233.2.3 dev cali5863f3 scope link

  • 有了这样的 Veth Pair 设备之后,容器发出的 IP 包就会经过 Veth Pair 设备出现在宿主机上。然后,宿主机网络栈就会根据路由规则的下一跳 IP 地址,把它们转发给正确的网关。接下来的流程就跟 Flannel host-gw 模式完全一致了。

  • 最核心的“下一跳”路由规则,就是由 Calico 的 Felix 进程负责维护的。这些路由规则信息,则是通过 BGP Client 也就是 BIRD 组件,使用 BGP 协议传输而来的。

  • 假如我们有两台处于不同子网的宿主机 Node 1 和 Node 2,对应的 IP 地址分别是 192.168.1.2 和 192.168.2.2。需要注意的是,这两台机器通过路由器实现了三层转发,所以这两个 IP 地址之间是可以相互通信的。可是它对应的 Node 2 跟 Node 1 却根本不在一个子网里,没办法通过二层网络把 IP 包发送到下一跳地址。在这种情况下,就需要为 Calico 打开 IPIP 模式

Calico IPIP 模式工作原理
在这里插入图片描述

网络隔离

  • 在 Kubernetes 里,网络隔离能力的定义,是依靠一种专门的 API 对象来描述的,即:NetworkPolicy
    • Kubernetes 里的 Pod 默认都是“允许所有”(Accept All)的,即:Pod 可以接收来自任何发送方的请求;或者,向任何接收方发送请求。而如果你要对这个情况作出限制,就必须通过 NetworkPolicy 对象来指定。
  • 一个完整的 NetworkPolicy 对象的示例,如下所示:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: test-network-policy
  namespace: default
spec:
  podSelector:
    matchLabels:
      role: db
  policyTypes:
  - Ingress
  - Egress
  ingress:
  - from:
    - ipBlock:
        cidr: 172.17.0.0/16
        except:
        - 172.17.1.0/24
    - namespaceSelector:
        matchLabels:
          project: myproject
    - podSelector:
        matchLabels:
          role: frontend
    ports:
    - protocol: TCP
      port: 6379
  egress:
  - to:
    - ipBlock:
        cidr: 10.0.0.0/24
    ports:
    - protocol: TCP
      port: 5978

  • podSelector 字段的作用:定义这个 NetworkPolicy 的限制范围,比如:当前 Namespace 里携带了 role=db 标签的 Pod。一旦 Pod 被 NetworkPolicy 选中,那么这个 Pod 就会进入“拒绝所有”(Deny All)的状态,即:这个 Pod 既不允许被外界访问,也不允许对外界发起访问。NetworkPolicy 定义的规则,其实就是“白名单”
  • policyTypes 字段,定义了这个 NetworkPolicy 的类型是 ingress 和 egress,即:它既会影响流入(ingress)请求,也会影响流出(egress)请求。
  • ingress 字段里,定义了 from 和 ports,即:允许流入的“白名单”和端口。其中,这个允许流入的“白名单”里,指定了三种并列的情况,分别是:ipBlock、namespaceSelector 和 podSelector。
  • egress 字段里,定义了 to 和 ports,即:允许流出的“白名单”和端口。这里允许流出的“白名单”的定义方法与 ingress 类似。只不过,这一次 ipblock 字段指定的,是目的地址的网段。
  • 这个 NetworkPolicy 对象的例子,指定的隔离规则如下所示:
    • 该隔离规则只对 default Namespace 下的,携带了 role=db 标签的 Pod 有效。限制的请求类型包括 ingress(流入)和 egress(流出)。
    • Kubernetes 会拒绝任何访问被隔离 Pod 的请求,除非这个请求来自于以下“白名单”里的对象,并且访问的是被隔离 Pod 的 6379 端口。这些“白名单”对象包括:
      • default Namespace 里的,携带了 role=fronted 标签的 Pod;
      • 任何 Namespace 里的、携带了 project=myproject 标签的 Pod;
      • 任何源地址属于 172.17.0.0/16 网段,且不属于 172.17.1.0/24 网段的请求。
      • Kubernetes 会拒绝被隔离 Pod 对外发起任何请求,除非请求的目的地址属于 10.0.0.0/24 网段,并且访问的是该网段地址的 5978 端口。
  • 如果要使上面定义的 NetworkPolicy 在 Kubernetes 集群里真正产生作用,CNI 网络插件就必须是支持 Kubernetes 的 NetworkPolicy 的。在具体实现上,凡是支持 NetworkPolicy 的 CNI 网络插件,都维护着一个 NetworkPolicy Controller,通过控制循环的方式对 NetworkPolicy 对象的增删改查做出响应,然后在宿主机上完成 iptables 规则的配置工作。
  • 在 Kubernetes 生态里,目前已经实现了 NetworkPolicy 的网络插件包括 Calico、Weave 和 kube-router 等多个项目,但是并不包括 Flannel 项目。所以说,如果想要在使用 Flannel 的同时还使用 NetworkPolicy 的话,需要再额外安装一个网络插件,比如 Calico 项目,来负责执行 NetworkPolicy。
  • 在设置好上述“隔离”规则之后,网络插件还需要想办法,将所有对被隔离 Pod 的访问请求,都转发到上述 KUBE-NWPLCY-CHAIN 规则上去进行匹配。并且,如果匹配不通过,这个请求应该被“拒绝”。
  • Kubernetes 网络插件对 Pod 进行隔离,其实是靠在宿主机上生成 NetworkPolicy 对应的 iptable 规则来实现的

iptables 的知识

  • iptables 只是一个操作 Linux 内核 Netfilter 子系统的“界面”。顾名思义,Netfilter 子系统的作用,就是 Linux 内核里挡在“网卡”和“用户态进程”之间的一道“防火墙”。它们的关系,可以用如下的示意图来表示:
    在这里插入图片描述

  • 可以看到,这幅示意图中,IP 包“一进一出”的两条路径上,有几个关键的“检查点”,它们正是 Netfilter 设置“防火墙”的地方。在 iptables 中,这些“检查点”被称为:链(Chain)。这是因为这些“检查点”对应的 iptables 规则,是按照定义顺序依次进行匹配的。这些“检查点”的具体工作原理,可以用如下所示的示意图进行描述:
    在这里插入图片描述

  • 当一个 IP 包通过网卡进入主机之后,它就进入了 Netfilter 定义的流入路径(Input Path)里。

  • 在这个路径中,IP 包要经过路由表路由来决定下一步的去向。而在这次路由之前,Netfilter 设置了一个名叫 PREROUTING 的“检查点”。在 Linux 内核的实现里,所谓“检查点”实际上就是内核网络协议栈代码里的 Hook(比如,在执行路由判断的代码之前,内核会先调用 PREROUTING 的 Hook)。

  • 而在经过路由之后,IP 包的去向就分为了两种:

    • 第一种,继续在本机处理;这时候,IP 包将继续向上层协议栈流动。在它进入传输层之前,Netfilter 会设置一个名叫 INPUT 的“检查点”。到这里,IP 包流入路径(Input Path)结束。接下来,这个 IP 包通过传输层进入用户空间,交给用户进程处理。而处理完成后,用户进程会通过本机发出返回的 IP 包。这时候,这个 IP 包就进入了流出路径(Output Path)。此时,IP 包首先还是会经过主机的路由表进行路由。路由结束后,Netfilter 就会设置一个名叫 OUTPUT 的“检查点”。然后,在 OUTPUT 之后,再设置一个名叫 POSTROUTING“检查点”。
    • 第二种,被转发到其他目的地。在这种情况下,这个 IP 包不会进入传输层,而是会继续在网络层流动,从而进入到转发路径(Forward Path)。在转发路径中,Netfilter 会设置一个名叫 FORWARD 的“检查点”。而在 FORWARD“检查点”完成后,IP 包就会来到流出路径。而转发的 IP 包由于目的地已经确定,它就不会再经过路由,也自然不会经过 OUTPUT,而是会直接来到 POSTROUTING“检查点”。
  • 所以说,POSTROUTING 的作用,其实就是上述两条路径,最终汇聚在一起的“最终检查点”

  • iptables 表的作用,就是在某个具体的“检查点”(比如 Output)上,按顺序执行几个不同的检查动作(比如,先执行 nat,再执行 filter)。

  • 数据包在 Linux Netfilter 子系统里完整的流动过程,如下所示:
    在这里插入图片描述

你知道的越多,你不知道的越多。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

深入剖析Kubernetes之容器网络(二) 的相关文章

随机推荐

  • 03-Mybatis增删改查的简单功能实现

    增删改查的实现 在上文中已经建立了mybatis的环境 并且创建了UserMapper xml userMapper 并且完成了一个简单的查询操作 已经可以成功的运行 环境可以正常的跑起来了 下面对整个数据库的基础操作 增删改查的代码进行编
  • elementUI+Vue+json-server做简单的文章后台管理

    elementUI Vue json server做简单的文章后台管理 最近刚接触elementUI不久 为了加深学习理解 便利用elementUI做了个简单练习 在CSDN上写记录一下学习过程 顺便整理回顾一下整个过程 创建项目 vue
  • Android Broadcast注册、发送、接收流程随笔

    Broadcast的注册过程 要动态注册广播 需要调用registerReceiver方法 它在ContextWrapper中实现 会调用mBase registerReceiver方法 mBase具体指向ContextImpl regis
  • java技术总结

    1 js 中正则表达式写法 var 注意不要加引号 加了引号就是一个字符串 不加引号才是正则对象 var new RegExp 此处不可以有 等效于Java写法 2 关于jquery中的 1 是jquery类 的别称 相当于java中的ob
  • 攻防世界web新手-simple_php

    文章目录 XCTF simple php 知识点 源码分析 解题思路 XCTF simple php 题目编号 GFSJ0485 知识点 本题主要考察php的弱类型比较 源码分析
  • 华为鸿蒙系统无缝更新,华为鸿蒙系统已陆续推送! 安卓系统可无缝升级: 升级包容量高达6GB...

    相信大家都知道 自从华为手机业务遭受到芯片断供危机以后 也是直接将会把重点放在软件系统层面 很多花粉们都纷纷期待 华为鸿蒙OS系统早日转正的一天 而华为终端CEO余承东表示 华为鸿蒙OS系统将会在四月份迎来首次推送升级 而华为Mate X2
  • python split(),os.path.split()和os.path.splitext()函数用法

    文章来源 https blog csdn net T1243 3 article details 80170006 coding utf 8 author lei import os os path join 将分离的部分合成一个整体 fi
  • 订单枚举实例

    摘要 订单状态 public enum OrderState 摘要 不限制 All 0 摘要 待付款 UnPaid 1 摘要 已取消 Cancel 2 摘要 待确认 Process 3
  • 【Linux】网络层 — IP协议

    Linux 博客主页 一起去看日落吗 分享博主的在Linux中学习到的知识和遇到的问题 博主的能力有限 出现错误希望大家不吝赐教 分享给大家一句我很喜欢的话 看似不起波澜的日复一日 一定会在某一天让你看见坚持的意义 祝我们都能在鸡零狗碎里找
  • ServerSocket实现超简单HTTP服务器

    1 相关知识简介 HTTP协议 HTTP是常用的应用层协议之一 是面向文本的协议 HTTP报文传输基于TCP协议 TCP协议包含头部与数据部分 而HTTP则是包含在TCP协议的数据部分 如下图 HTTP报文本质上是一个TCP报文 数据部分携
  • librdkafka的安装和使用

    安装 下载https github com edenhill librdkafka 预备环境 The GNU toolchain GNU make pthreads zlib optional for gzip compression su
  • SSL连接的JAVA实现

    SSL连接分为双向认证和单向认证 其中双向认证表示服务器和客户端都需要分别校验对方的身份 单向认证则只需要客户端校验服务器的身份 SSL的双向认证的流程如下图 从以上流程可见 要完成双向认证 服务器端和客户端都需要验证对方的证书 然后再进行
  • Android configChanges属性和configChanges()方法总结

    简介 在Android系统默认的情况下 Configuration改变都会销毁并重建当前Activity 例如当 屏幕方向 或 键盘显示隐藏 变化时 如果不希望重新创建Activity实例 可以在manifest xml文件中可以指定参数a
  • 2019年数学建模美赛经验总结

    北京时间2019年1月29号上午9时 数模美赛结束 美赛结束已经10多天了 我在这次竞赛中负责建模和编程 趁现在记忆还比较清晰 写下这篇博客记录第一次参加数学建模美赛的经历 补更 2019年4月20日公布成绩 笔者最终获得了美赛一等奖 目录
  • 主流加密方式和工具比较

    相关术语 缩写 全称 描述 CryFS CryFS 一种安全的文件加密的工具 Fuse框架 Filesystem In UserSpace 一个实现在用户空间的文件系统框架 loop loop 像块设备一样访问一个文件 dev mapper
  • 字符串压缩(三)之短字符串压缩

    一 通用算法的短字符压缩 开门见山 我们使用一段比较短的文本 Narrator It is raining today So Peppa and George cannot play outside Peppa Daddy it s sto
  • 直接使用ip和数据库实例名登录PL/SQL

    以往我一直以为登录PLSQL的时候 除了固定的用户密码以外 需要先用ORACLE的客户端配置本地服务 然后再登录PLSQL的时候 DataBase选项选择配置的本地服务名 今天因为一位同事的win10机器无法安装oracle客户端 因此 在
  • Hive 常用DML操作

    一 加载文件数据到表 1 1 语法 LOAD DATA LOCAL INPATH filepath OVERWRITE INTO TABLE tablename PARTITION partcol1 val1 partcol2 val2 L
  • Scrapy入门教程实例

    Scrapy Scrapy是一个为了爬取网站数据 提取结构性数据而编写的应用框架 可以应用在包括数据挖掘 信息处理或存储历史数据等一系列的程序中 scrapy的整体框架如下所示 Scrapy主要包含了以下几个组件 引擎 Scrapy 用来处
  • 深入剖析Kubernetes之容器网络(二)

    文章目录 Flannel 的 host gw 模式 Calico 网络隔离 Flannel 的 host gw 模式 Flannel host gw 示意图 假设现在 Node 1 上的 Infra container 1 要访问 Node