34、高级 Kubernetes 网络详解

Kubernetes网络详解

高级 Kubernetes 网络详解

1. Pod 与服务通信

在 Kubernetes 集群中,Pod 之间可以通过 IP 地址和端口直接通信,但这要求 Pod 知晓彼此的 IP 地址。然而,Kubernetes 集群中的 Pod 会不断地被销毁和创建。服务提供了一层间接性,即使响应请求的实际 Pod 集合不断变化,服务依然稳定。此外,每个节点上的 Kube - proxy 会负责将流量重定向到正确的 Pod,从而实现自动的高可用负载均衡。

1.1 外部访问

部分容器最终需要从外部世界访问,但 Pod 的 IP 地址在外部不可见。服务是实现外部访问的合适途径,但通常需要两次重定向。例如,云提供商的负载均衡器虽然支持 Kubernetes,但无法将流量直接导向运行能处理请求的 Pod 的节点。相反,公共负载均衡器会将流量导向集群中的任意节点,若该节点未运行所需的 Pod,该节点上的 Kube - proxy 会再次将流量重定向到合适的 Pod。

1.2 外部负载均衡器工作流程

graph LR
    A[外部负载均衡器] --> B[节点 1]
    A --> C[节点 2]
    A --> D[节点 3]
    B --> E[Kube - proxy]
    C --> F[Kube - proxy]
    D --> G[Kube - proxy]
    E --> H[Pod]
    F --> I[Pod]
    G --> J[Pod]

2. Kubernetes 网络与 Docker 网络对比

2.1 Docker 网络模型

Docker 网络遵循不同的模型,不过随着时间推移,它逐渐向 Kubernetes 模型靠拢。在 Docker 网络中,每个容器都有一个来自 172.xxx.xxx.xxx 地址空间的私有 IP 地址,且局限于其所在的节点。容器可以通过各自的 172.xxx.xxx.xxx IP 地址与同一节点上的其他容器通信。这对于 Docker 来说是合理的,因为它没有包含多个相互交互容器的 Pod 概念,而是将每个容器建模为具有自己网络标识的轻量级虚拟机。

2.2 Kubernetes 网络模型

在 Kubernetes 中,运行在同一节点上的不同 Pod 中的容器通常不能通过 localhost 连接(除非暴露主机端口,但这并不推荐)。因为 Kubernetes 可以在任何地方销毁和创建 Pod,所以不同的 Pod 通常不应依赖同一节点上的其他 Pod。Daemon sets 是一个显著的例外,但 Kubernetes 网络模型旨在适用于所有用例,不会为同一节点上不同 Pod 之间的直接通信添加特殊情况。

2.3 Docker 容器跨节点通信

Docker 容器跨节点通信时,容器必须将端口发布到主机。这显然需要进行端口协调,因为如果两个容器尝试发布相同的主机端口,它们会相互冲突。然后,容器(或其他进程)连接到主机的端口,该端口会将流量引入容器。一个很大的缺点是容器无法向外部服务自我注册,因为它们不知道其主机的 IP 地址。可以通过在运行容器时将主机的 IP 地址作为环境变量传递来解决这个问题,但这需要外部协调并使过程复杂化。

2.4 对比表格

对比项 Kubernetes 网络 Docker 网络
容器通信 不同 Pod 容器通常不能通过 localhost 连接 同一节点容器可通过私有 IP 通信
跨节点通信 服务与 Kube - proxy 实现 容器发布端口到主机
自我注册 服务自动注册 Pod 容器无法自我注册

3. 查找与发现

为了使 Pod 和容器能够相互通信,它们需要找到彼此。容器定位其他容器或自我宣告的方式有多种,也有一些架构模式允许容器间接交互,每种方法都有其优缺点。

3.1 自我注册

当容器运行时,它知道其所在 Pod 的 IP 地址。每个希望在集群中被其他容器访问的容器可以连接到某个注册服务,并注册其 IP 地址和端口。其他容器可以向注册服务查询所有已注册容器的 IP 地址和端口,并与之连接。当容器被正常销毁时,它会自动注销。如果容器异常死亡,则需要建立某种机制来检测。例如,注册服务可以定期 ping 所有已注册的容器,或者容器需要定期向注册服务发送保活消息。

自我注册的优点包括:一旦通用注册服务就位(无需为不同目的进行定制),就无需担心跟踪容器;容器可以采用复杂的策略,在因本地条件不可用时(如容器繁忙不想接收更多请求)暂时注销,实现智能的去中心化动态负载均衡。缺点是注册服务是另一个非标准组件,容器需要了解它才能定位其他容器。

3.2 服务与端点

Kubernetes 服务可以被视为一种注册服务。属于某个服务的 Pod 会根据其标签自动注册。其他 Pod 可以查找端点以找到所有服务 Pod,或者直接向服务发送消息,该消息将被路由到其中一个后端 Pod。大多数情况下,Pod 会直接向服务发送消息,服务会将其转发到其中一个后端 Pod。

3.3 松散耦合的队列通信

如果容器可以在不知道彼此的 IP 地址、端口、服务 IP 地址或网络名称的情况下进行通信,并且大部分通信可以是异步和解耦的,那么队列可以促进这种松散耦合的系统。组件(容器)从队列中监听消息,响应消息,执行任务,并将有关进度、完成状态和错误的消息发布到队列。

队列的优点包括:
- 无需协调即可轻松增加处理能力,只需添加更多监听队列的容器。
- 可以通过队列深度轻松跟踪整体负载。
- 通过对消息和/或主题进行版本控制,可轻松让多个版本的组件并行运行。
- 通过让多个消费者以不同模式处理请求,可轻松实现负载均衡和冗余。

队列的缺点包括:
- 必须确保队列提供适当的持久性和高可用性,以免成为关键的单点故障。
- 容器需要使用异步队列 API(可以进行抽象)。
- 实现请求 - 响应需要在响应队列上进行有些繁琐的监听。

3.4 松散耦合的数据存储通信

另一种松散耦合的方法是使用数据存储(如 Redis)来存储消息,然后其他容器可以读取这些消息。虽然这是可行的,但这不是数据存储的设计目标,结果通常很繁琐、脆弱,并且性能不佳。数据存储是为数据存储而优化的,而不是为通信。不过,数据存储可以与队列结合使用,其中一个组件将一些数据存储在数据存储中,然后向队列发送消息表示数据已准备好处理。多个组件监听该消息并并行开始处理数据。

4. Kubernetes 入口

Kubernetes 提供了入口资源和控制器,旨在将 Kubernetes 服务暴露给外部世界。当然,用户也可以自行完成此操作,但对于特定类型的入口(如 Web 应用程序、CDN 或 DDoS 防护器),定义入口涉及的许多任务在大多数应用程序中是常见的。用户还可以编写自己的入口对象。入口对象通常用于智能负载均衡和 TLS 终止。

5. Kubernetes 网络插件

由于网络的多样性,不同的人希望以不同的方式实现网络,因此 Kubernetes 拥有网络插件系统,它足够灵活以支持任何场景。主要的网络插件是 CNI,此外还有一个更简单的网络插件 Kubenet。在详细介绍之前,先了解一下 Linux 网络的基础知识。

5.1 基本 Linux 网络

5.1.1 IP 地址和端口

网络实体通过 IP 地址进行标识。服务器可以在多个端口上监听传入连接,客户端可以在其网络内连接(TCP)或发送数据(UDP)到服务器。

5.1.2 网络命名空间

命名空间将一组网络设备分组,使得它们可以与同一命名空间中的其他服务器通信,但无法与即使物理上在同一网络中的其他服务器通信。可以通过网桥、交换机、网关和路由来连接网络或网络段。

5.1.3 子网、网络掩码和 CIDR

在设计和维护网络时,将网络划分为更小的子网是很有用的。子网可以通过表示子网大小(可容纳的主机数量)的位掩码来定义。例如,网络掩码 255.255.255.0 表示前三个八位字节用于路由,只有 256(实际为 254)个单独的主机可用。无类域间路由(CIDR)表示法通常用于此目的,因为它更简洁,编码更多信息,并且允许组合来自多个旧类(A、B、C、D、E)的主机。例如,172.27.15.0/24 表示前 24 位(三个八位字节)用于路由。

5.1.4 虚拟以太网设备

虚拟以太网(veth)设备代表物理网络设备。当创建一个与物理设备链接的 veth 时,可以将该 veth(以及扩展的物理设备)分配到一个命名空间中,在该命名空间中,来自其他命名空间的设备无法直接访问它,即使它们在物理上位于同一本地网络中。

5.1.5 网桥

网桥将多个网络段连接到一个聚合网络,以便所有节点可以相互通信。网桥在 OSI 网络模型的 L1(物理)和 L2(数据链路)层进行操作。

5.1.6 路由

路由通常基于路由表连接单独的网络,路由表指示网络设备如何将数据包转发到其目的地。路由通过各种网络设备(如路由器、网桥、网关、交换机和防火墙,包括普通的 Linux 主机)来实现。

5.1.7 最大传输单元

最大传输单元(MTU)决定了数据包的最大大小。例如,在以太网网络中,MTU 为 1500 字节。MTU 越大,有效负载与报头的比率越好,但最小延迟会降低,因为必须等待整个数据包到达,而且如果发生故障,必须重新传输整个数据包。

5.2 Pod 网络

Pod、主机和全球互联网在网络层面通过 veth0 建立关系,可用以下 mermaid 流程图表示:

graph LR
    A[全球互联网] --> B[主机]
    B --> C[Pod]
    B <--> C(veth0)

5.3 Kubenet

Kubenet 是一个非常基础的网络插件,它为每个 Pod 创建一个名为 cbr0 的 Linux 网桥和一个 veth。云提供商通常使用它来设置节点之间的通信路由规则,或在单节点环境中使用。veth 对使用主机 IP 地址范围内的 IP 地址将每个 Pod 连接到其主机节点。

5.3.1 要求

Kubenet 插件有以下要求:
- 节点必须分配一个子网,以便为其 Pod 分配 IP 地址。
- 版本 0.2.0 或更高版本需要标准的 CNI 网桥、lo 和 host - local 插件。
- Kubelet 必须使用 --network - plugin = kubenet 参数运行。
- Kubelet 必须使用 --non - masquerade - cidr = <clusterCidr> 参数运行。

5.3.2 设置 MTU

MTU 对网络性能至关重要。Kubernetes 网络插件(如 Kubenet)会尽力推断最佳 MTU,但有时需要手动干预。如果现有网络接口(如 Docker 的 docker0 网桥)设置了较小的 MTU,Kubenet 会重用它。例如,IPSEC 由于 IPSEC 封装开销需要降低 MTU,但 Kubenet 网络插件不会考虑这一点。解决方案是避免依赖 MTU 的自动计算,而是通过 --network - plugin - mtu 命令行开关告诉 Kubelet 网络插件应使用的 MTU。目前,只有 Kubenet 网络插件会考虑此命令行开关。

5.4 容器网络接口(CNI)

CNI 既是一个规范,也是一组用于编写网络插件的库,用于配置 Linux 容器(不仅仅是 Docker)中的网络接口。该规范实际上源于 rkt 网络提案,并且有很多组织在使用 CNI,如 Kubernetes、Kurma、Cloud foundry、Nuage、RedHat、Mesos 等。

5.4.1 CNI 插件列表

CNI 团队维护了一些核心插件,也有很多第三方插件为 CNI 的成功做出了贡献,如下表所示:
| 插件名称 | 描述 |
| ---- | ---- |
| Project Calico | 三层虚拟网络 |
| Weave | 多主机 Docker 网络 |
| Contiv networking | 基于策略的网络 |
| Cilium | 用于容器的 BPF 和 XDP |
| Multus | 多插件 |
| CNI - Genie | 通用 CNI 网络插件 |
| Flannel | 为 Kubernetes 设计的容器网络结构 |
| Infoblox | 企业级容器 IP 地址管理 |

5.4.2 容器运行时

CNI 为网络应用容器定义了插件规范,但插件必须插入到提供某些服务的容器运行时中。在 CNI 的上下文中,应用容器是一个可网络寻址的实体(有自己的 IP 地址)。对于 Docker,每个容器都有自己的 IP 地址;对于 Kubernetes,每个 Pod 有自己的 IP 地址,Pod 是 CNI 容器,而不是 Pod 内的容器。rkt 的应用容器也类似于 Kubernetes 的 Pod,可能包含多个 Linux 容器。运行时的工作是配置网络,然后执行一个或多个 CNI 插件,并以 JSON 格式将网络配置传递给它们。

5.4.3 CNI 插件

CNI 插件的工作是将网络接口添加到容器网络命名空间中,并通过 veth 对将容器连接到主机。然后,它应通过 IPAM(IP 地址管理)插件分配 IP 地址并设置路由。

容器运行时(Docker、rkt 或任何其他符合 CRI 的运行时)将 CNI 插件作为可执行文件调用。插件需要支持以下操作:
- 将容器添加到网络
- 从网络中移除容器
- 报告版本

插件使用简单的命令行界面、标准输入/输出和环境变量。网络配置以 JSON 格式通过标准输入传递给插件,其他参数定义为环境变量:
- CNI_COMMAND :指示所需的操作;ADD、DEL 或 VERSION。
- CNI_CONTAINERID :容器 ID。
- CNI_NETNS :网络命名空间文件的路径。
- CNI_IFNAME :要设置的接口名称;插件必须遵守此接口名称,否则返回错误。
- CNI_ARGS :用户在调用时传递的额外参数。字母数字键值对用分号分隔,例如 FOO = BAR;ABC = 123
- CNI_PATH :搜索 CNI 插件可执行文件的路径列表。路径由特定于操作系统的列表分隔符分隔,例如 Linux 上的 : 和 Windows 上的 ;

如果命令成功,插件返回零退出代码,并且生成的接口(在 ADD 命令的情况下)以 JSON 格式流式传输到标准输出。以下是调用 CNI 插件的 ADD 命令的结果示例:

{
    "cniVersion": "0.3.0",
    "interfaces": [
        {
            "name": "<name>",
            "mac": "<MAC address>",
            "sandbox": "<netns path or hypervisor identifier>"
        }
    ],
    "ip": [
        {
            "version": "<4 - or - 6>",
            "address": "<ip - and - prefix - in - CIDR>",
            "gateway": "<ip - address - of - the - gateway>",
            "interface": <numeric index into 'interfaces' list>
        }
    ],
    "routes": [
        {
            "dst": "<ip - and - prefix - in - cidr>",
            "gw": "<ip - of - next - hop>"
        }
    ],
    "dns": {
        "nameservers": <list - of - nameservers>,
        "domain": <name - of - local - domain>,
        "search": <list - of - additional - search - domains>,
        "options": <list - of - options>
    }
}

输入的网络配置包含很多信息,例如:

{
    "cniVersion": "0.3.0",
    "name": "dbnet",
    "type": "bridge",
    "bridge": "cni0",
    "ipam": {
        "type": "host - local",
        "subnet": "10.1.0.0/16",
        "gateway": "10.1.0.1"
    },
    "dns": {
        "nameservers": [ "10.1.0.1" ]
    }
}

可以添加额外的特定于插件的元素,在这个例子中, bridge: cni0 元素是特定网桥插件能理解的自定义元素。

【四轴飞行器】非线性三自由度四轴飞行器模拟器研究(Matlab代码实现)内容概要:本文围绕非线性三自由度四轴飞行器模拟器的研究展开,重点介绍了基于Matlab的建模与仿真方法。通过对四轴飞行器的动力学特性进行分析,构建了非线性状态空间模型,并实现了姿态与位置的动态模拟。研究涵盖了飞行器运动方程的建立、控制系统设计及数值仿真验证等环节,突出非线性系统的精确建模与仿真优势,有助于深入理解飞行器在复杂工况下的行为特征。此外,文中还提到了多种配套技术如PID控制、状态估计与路径规划等,展示了Matlab在航空航天仿真中的综合应用能力。; 适合人群:具备一定自动控制理论基础和Matlab编程能力的高校学生、科研人员及从事无人机系统开发的工程技术人员,尤其适合研究生及以上层次的研究者。; 使用场景及目标:①用于四轴飞行器控制系统的设计与验证,支持算法快速原型开发;②作为教学工具帮助理解非线性动力学系统建模与仿真过程;③支撑科研项目中对飞行器姿态控制、轨迹跟踪等问题的深入研究; 阅读建议:建议读者结合文中提供的Matlab代码进行实践操作,重点关注动力学建模与控制模块的实现细节,同时可延伸学习文档中提及的PID控制、状态估计等相关技术内容,以全面提升系统仿真与分析能力。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值