深入原理64式:13 kubernetes网络模型

1 kubernetes网络模型
原则:
每个pod都拥有独立的IP地址,所有pod可以连通。
一个pod内所有容器共享一个网络堆栈(即网络明明空间,
包括IP地址,网络设备等),同一个pod内的容器可以通过localhost连接对方的端口。

2 Docker网络基础
使用了:
网络命名空间,Veth设备对,网桥,路由等。

2.1 网络命名空间
作用:不同命名空间中的网络栈时完全隔离,用于实现不同容器之间网络的隔离。
实现:让全局变量成为一个网络命名空间变量的成员,协议栈的函数调用加入Namespace参数。

实现不同命名空间的网络相互通信:
通过Veth设备对,打通不同协议栈的壁垒,一端连接这个网络命名空间的协议栈,一端连接另一个网络命名空间的协议栈。
网络命名空间操作:
创建命名空间:
ip netns add <name>

在命名空间内执行命令:
ip netns exec <name> <commnd>

2.2 Veth设备对
作用:在不同的网络命名空间进行通信,连接两个网络命名空间,
Veth设备成对出现。
通过ethtool工具查看Veth对的对端在哪里。

Usage: ip link add [link DEV] [ name ] NAME
         [ txqueuelen PACKETS ]
         [ address LLADDR ]
         [ broadcast LLADDR ]
         [ mtu MTU ]
         [ numtxqueues QUEUE_COUNT ]
         [ numrxqueues QUEUE_COUNT ]
         type TYPE [ ARGS ]
ip link只能看链路层的状态,看不到ip地址
# ip link add eth1 name Test type bridge :创建一个名字是Test的类型是bridge的eth1端口

2.3 网桥
作用: 是二层虚拟网络设备,把网络接口连接起来,使得网口之间报文能够互相转发。
原理: 解析报文,读取目标MAC地址信息,和自己记录的MAC表结合,决策转发目标网口。
网桥会学习源MAC地址,转发报闻,只需要向特定网口进行转发。
实现: 通过一个虚拟的网桥设备来实现桥接。这个虚拟设备可以绑定若干个以太网接口设备。
桥接只在数据链路层实现。
网桥常用命令:
新增网桥设备:
brctl addbr xxxxx
为网桥增加网口(即物理网卡)
brctl addif xxxxx ethx
无路网卡做为网口工作在链路层,不需要IP地址
ifconfig ethx 0.0.0.0
给网桥配置一个IP地址:
ifconfig brxxx xxx.xxx.xxx.xxx
这样网桥就有了IP地址,而连接到网桥的网卡就是纯链路层设备。

2.4 Iptabes/Netfilter
网络协议栈中有回调函数挂结点,可以对数据包进行操作,例如:
过滤,修改等。整个挂结点技术叫做Netfilter和Iptables。

Netfilter:
在内核中执行挂接规则。

Iptables:
在用户模式下运行的进程,维护内核中Netfilter的规则表。

挂结点规则:
===    上层协议处理    ===
INPUT            路由
^
|            OUTPUT
路由->    FORWARD->    |
^
|
PREROUTAING        POSTROUTING
^
|            |
===    接口设备    ===


2.5 路由
作用: IP层数据转发时,会使用路由表决定转发到哪里。
实现: IP层维护一张路由表,用该表做决策。
路由表条目:
目的IP地址: 可以时某台主机地址,也可以时网络地址
下一个路由器的IP地址: 用来转发从相应接口接收到的IP数据报文。
标志: 目的IP地址是主机地址还是网络地址
网络接口规范: 数据报文的网络接口规范。

路由规则:
1条目的第一个字段匹配目的IP地址(主机)或部分匹配IP地址(网络),将指示下一个路由器的
IP地址。
2 没有匹配,就搜索匹配的网络ID,若找到,则数据报文会转发到指定的路由器上。
3 都不匹配,报文转发到默认路由器。

查看LOCAL表(包含本地设备地址,供linux协议栈识别本地地址,进行本地各个不同网络接口之间的数据转发)
ip route show table local type local
样例输出:
10.8.1.54 dev tun0 proto kernel scope host src 10.8.1.54 
127.0.0.0/8 dev lo proto kernel scope host src 127.0.0.1 
127.0.0.1 dev lo proto kernel scope host src 127.0.0.1 
172.17.0.1 dev docker0 proto kernel scope host src 172.17.0.1 
172.19.0.1 dev br-042eb6f5d4dc proto kernel scope host src 172.19.0.1 
192.168.0.199 dev wlp3s0 proto kernel scope host src 192.168.0.199 
192.168.122.1 dev virbr0 proto kernel scope host src 192.168.122.1

MAIN表:用于各类网络IP地址的转发。

路由表的查看:
ip route list
样例输出:
10.8.1.54 dev tun0 proto kernel scope host src 10.8.1.54 
127.0.0.0/8 dev lo proto kernel scope host src 127.0.0.1 
127.0.0.1 dev lo proto kernel scope host src 127.0.0.1 
172.17.0.1 dev docker0 proto kernel scope host src 172.17.0.1 
172.19.0.1 dev br-042eb6f5d4dc proto kernel scope host src 172.19.0.1 

netstat -rn
样例输出:
Kernel IP routing table
Destination     Gateway         Genmask         Flags   MSS Window  irtt Iface
0.0.0.0         192.168.0.100   0.0.0.0         UG        0 0          0 wlp3s0
10.8.0.0        10.8.1.53       255.255.0.0     UG        0 0          0 tun0
10.8.0.1        10.8.1.53       255.255.255.255 UGH       0 0          0 tun0
172.19.0.0      0.0.0.0         255.255.0.0     U         0 0          0 br-042eb6f5d4dc

解释:
标志U表示是可达路由;标志为G,说明这个网络接口连接的是网关,否则说明是直连主机

3 Docker的网络实现
bridge模式下:
Docker Daemon首次启动会创建一个虚拟的网桥,默认名字是docker0,给网桥分配一个子网。
Docker创建出来的每个容器,都会创建一个虚拟以太网设备(Veth设备对),其中一端关联到网桥上,另一端使用网络命名空间映射到容器的eth0设备,然后从网桥的地址段内给eth0接口分配一个IP地址。

3.1 Docker桥接网络模型
    Node1
    容器1,容器2
    eth0    eth0    <==ip2
    
    ethxx    ethxx
    docker0网桥    <==ip1
    
    路由
    eth0        <==ip3

解释:
ip1是网桥的ip地址,通常172开头,该地址和主机IP地址不重叠。
ip2是Docker在启动容器时,在这个地址段随机选择的没有使用的ip地址。
启动后,Docker将Veth对的名字映射到eth0网络接口。
ip3是主机的网卡地址。外部一般看不到ip1和ip2的。
作用: 同一台机器内容器之间可以相互通信,不同主机容器不能相互通信。

ip addr可以看到
7: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN 
    link/ether 02:42:e0:a8:f2:65 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 scope global docker0
       valid_lft forever preferred_lft forever

iptables -- 对表、链、规则进行配置
iptables-save -- dump 已配置的规则,可以用 > 重定向到一个文件中
iptables-restore -- 从之前导出的iptable规则配置文件加载规则。

iptables-save|grep docker0
样例输出如下:
-A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE
-A DOCKER -i docker0 -j RETURN
-A FORWARD -o docker0 -j DOCKER
-A FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -i docker0 ! -o docker0 -j ACCEPT
-A FORWARD -i docker0 -o docker0 -j ACCEPT
-A DOCKER-ISOLATION -i br-042eb6f5d4dc -o docker0 -j DROP
-A DOCKER-ISOLATION -i docker0 -o br-042eb6f5d4dc -j DROP

3.2 Docker网络局限
没有考虑多主机互联的网络解决方案。


4 kubernetes的网络实现
4.1 容器到容器的通信
同一个Pod内的容器共享一个网络命名空间,就像在同一台机器上一样,可以用localhost地址访问彼此端口。
优点: 简单,安全。
两个容器可以直接使用linux的本地IPC(进程间通信),例如消息队列或管道。

4.2 同一个node内的pod之间的通信
每个pod有真实的全局ip地址。
同一个Node内的Pod关系如下:

=======        Node1        ========
Pod1                    Pod2
容器1    容器2                容器1    容器2
共享网络空间                共享网络空间
eth0    ip1                eth0    ip2

ethxxx                ethxxx
            ip3
            docker0网桥
            路由
            eth0

分析:
Pod1和Pod2都通过Veth连接在同一个docker0网桥上的,它们的IP地址
IP1,IP2都是从docker0的网段上动态获取的,和网前本身的IP3是同一个网段。
Pod1, Pod2的Linux协议栈上默认路由都是docker0的地址。
总结:
同一个Node上的pod都关联在同一个docker0网桥上,地址段相同,所以pod之间能够直接通信的。

4.3 不同Node上的Pod之间通信
docker0网段与宿主机网卡是不同的IP网段,不同Node之间的通信只能通过
宿主机的物理网卡进行。
k8s会记录正在运行的Pod的IP分配信息到etcd中(作为Service的Endpoint)。
这些私有IP信息对于Pod到Pod的通信是分重要。
支持不同Node上的Pod之间通信的条件:
1) 对k8s集群中Pod的ip分配规划不能冲突。
2) 将Pod的IP和所在Node的IP关联,通过这个关联让Pod可以互相访问。
解决方法:
1) 部署k8s,对docker0的IP地址规划,保证没有冲突
2) 知道对方Pod的IP地址挂在哪个具体的Node上,将数据发送到宿主机的
网卡上,然后在宿主机将相应的数据转到具体的docker0上。

eth0:光纤以太网口卡,Fiber Ethernet Adapter0。也就是物理网卡,
    即实际的网络接口设备。


===Node1                ===Node2
Pod1                    Pod2
容器1    容器2                容器1    容器2
共享网络空间                共享网络空间
eth0    ip1                eth0    ip2

ethxxx                ethxxx
docker0网桥                docker0网桥
路由                    路由
eth0    ip3                eth0 ip4
=======================>

5 Kubernetes网络策略
Network Policy对Pod之间的网络通信进行限制和准入控制,设置方式为
将Pod的Label作为查询条件,设置允许访问的Pod列表,查询条件可以作用域Pod
和Namespace级别。

1) 网络隔离
作用于Namespace级别的所有Pod。

6 开源的网络组件
定义所有Pod都可以直接连通。
6.1 Flannel
1) 给每个Node上的容器分配不冲突IP地址
2) 在IP地址间建立覆盖网络(Overlay Network),通过覆盖网络,将数据原封不动
地传递到目标容器内。

原理:
1)Flannel创建了一个名为flannel0地网桥,这个网桥地一端连接docker0网桥,另一端
连接一个去叫作flanneld的服务进程。
2) flanneld进程连接etcd,利用etcd来管理可分配的IP地址段资源,
同时监控etcd中每个pod的实际地址,并在内存中建立了一个Pod节点路由表;
3) 然后下连docker0和物理网络,使用内存中的Pod节点路由表,将docker0发给它
的数据包包装起来,利用物理网络的连接将数据包投递到目标flanneld上,从而
完成Pod到Pod之间的直接的地址通信。

Flannel底层通信协议:
可以使用UDP,只要能通到对端的Flannel就可以。

Flannel如何做到为不同Node上的Pod分配的IP不产生冲突:
Flannel使用了etcd存储,每次分配的地址段都在公共区域获取,就可以不冲突了。
Flannel分配好地址段后,通过修改Docker的启动参数将分配给它的地址段传递进去。
--bip=172.17.18.1/24
通过这些操作,Flannel控制了每个Node上的docker0地址段的地址,也就保障了所有
Pod的IP地址在同一个水平网络中且不产生冲突。

===CoreOS Machine            ===CoreOS Machine
Pod1        Pod2            Pod1        Pod2
容器1,容器2    容器1,容器2        容器1,容器2    容器1,容器2
veth0        veth1            veth0        veth1
10.1.15.2/24    10.1.15.3/24        10.1.20.2/24    10.1.20.3/24
    docker0                docker0
    10.1.15.1/24                10.1.20.1/24
    
    flannel0                flannel0
    10.1.15.0/16                10.1.20.0/16
    flanneld                flanneld

    eth0                    eth0
    192.168.0.100                192.168.0.200
    ==========    packet    =========


MAC    OuterIP            UDP    InnerIP        Payload
    source:192/168.0.100        source:10.1.15.2
                        dest: 10.1.20.3

参考:
Kubernetes权威指南第2版
https://www.cnblogs.com/teezzy/p/9565122.html
https://baike.baidu.com/item/ipc/91622?fr=aladdin

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Kubernetes 原理剖析与实战应用】 开篇 | 如何深入掌握 Kubernetes? 云原生基石:初识 Kubernetes 01 | 前世今生:Kubernetes 是如何火起来的? 02 | 高屋建瓴:Kubernetes 的架构为什么是这样的? 03 | 集群搭建:手把手教你玩转 Kubernetes 集群搭建 04 | 核心定义:Kubernetes 是如何搞定“不可变基础设施”的? 「关注公众号【云世】,免费获取全系列课程内容」 05 | K8s Pod:最小调度单元的使用进阶及实践 Kubernetes 进阶:部署高可用的业务 06 | 无状态应用:剖析 Kubernetes 业务副本及水平扩展底层原理 07 | 有状态应用:Kubernetes 如何通过 StatefulSet 支持有状态应用? 08 | 配置管理:Kubernetes 管理业务配置方有哪些? 09 | 存储类型:如何挑选合适的存储插件? 10 | 存储管理:怎样对业务数据进行持久化存储? 11 | K8s Service:轻松搞定服务发现和负载均衡 12 | Helm Charts:如何在生产环境中释放部署生产力? 守护神:业务的日志与监控 「关注公众号【云世】,免费获取全系列课程内容」 13 | 服务守护进程:如何在 Kubernetes 中运行 DaemonSet 守护进程? 14 | 日志采集:如何在 Kubernetes 中做日志收集与管理? 15 | Prometheus:Kubernetes 怎样实现自动化服务监控告警? 16 | 迎战流量峰值:Kubernetes 怎样控制业务的资源水位? 17 | 案例实战:教你快速搭建 Kubernetes 监控平台 安全无忧:集群的安全性与稳定性 18 | 权限分析:Kubernetes 集群权限管理那些事儿 19 | 资源限制:如何保障你的 Kubernetes 集群资源不会被打爆 20 | 资源优化:Kubernetes 中有 GC(垃圾回收)吗? 21 | 优先级调度:你必须掌握的 Pod 抢占资源调度 22 | 安全机制:Kubernetes 如何保障集群安全? 23 | 最后的防线:怎样对 Kubernetes 集群进行灾备和恢复? 「关注公众号【云世】,免费获取全系列课程内容」 加餐:问题答疑和优秀留言展示 知其所以然:底层核心原理及可扩展性 24 | 调度引擎:Kubernetes 如何高效调度 Pod? 25 | 稳定基石:带你剖析容器运行时以及 CRI 原理 26 | 网络插件:Kubernetes 搞定网络原来可以如此简单? 27 | K8s CRD:如何根据需求自定义你的 API? 28 | 面向 K8s 编程:如何通过 Operator 扩展 Kubernetes API? 特别放送 「关注公众号【云世】,免费获取全系列课程内容」 29 | Kubernetes 中也有定时任务吗? 30 | Kubectl 命令行工具使用秘笈 结束语 结束语 | Cloud Native is Eating the World:时代在召唤云原生 「关注公众号【云世】,免费获取全系列课程内容」
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值