Kubernetes-网络

本文涉及的产品
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
简介: 在实际生产中,我们面临多种多样的业务场景,导致业务之间的调用关系更加复杂化,从而对网络提出更高的要求,对于Kubernetes来说主要解决以下四个问题:1. Pod中容器与容器之间的通信问题;2. Pod与Pod之间的网络通信问题;3. Pod与Service之间的通信问题;4. 集群内部与外部的通信问题;

一、前言


本篇是Kubernetes第十一篇,大家一定要把环境搭建起来,看是解决不了问题的,必须实战,此篇文章概念比较多,后续我会继续出一些网络相关实战以及原理探索篇。

Kubernetes系列文章:
  1. Kubernetes介绍
  2. Kubernetes环境搭建
  3. Kubernetes-kubectl介绍
  4. Kubernetes-Pod介绍(-)
  5. Kubernetes-Pod介绍(二)-生命周期
  6. Kubernetes-Pod介绍(三)-Pod调度
  7. Kubernetes-Pod介绍(四)-Deployment
  8. Kubernetes-Service介绍(一)-基本概念
  9. Kubernetes-Service介绍(二)-服务发现
  10. Kubernetes-Service介绍(三)-Ingress(含最新版安装踩坑实践)


二、Kubernetes网络设计


在实际生产中,我们面临多种多样的业务场景,导致业务之间的调用关系更加复杂化,从而对网络提出更高的要求,对于Kubernetes来说主要解决以下四个问题:

  1. Pod中容器与容器之间的通信问题;
  2. Pod与Pod之间的网络通信问题;
  3. Pod与Service之间的通信问题;
  4. 集群内部与外部的通信问题;

第三和第四点我们在前面的章节已经讲过,大家可以在Service章节具体回忆下,重点介绍下第一、二点;

容器与容器之间的通信问题

介绍Pod时候我们说过Pod内部的容器共享Pod的命名空间的,因此在同一个Pod内的容器之间对于网络的各类操作,就和它们在同一台机器上一样,可以用localhost地址访问彼此的端口。

img

Pod与Pod之间的网络通信问题

每个Pod都有自己单独的IP,两个Pod既有可能运行在同一个Node上,也有可能运行在不同的Node上,因此对于Pod之间的通信可以分为两类:

同一个Node内的Pod之间的通信

对于在同一台机器上的两个Pod来说,都是连接到同一个docker0网桥上,它们的IP地址IP1、IP2都是从docker0网段上动态获取的,它们和网桥本身的IP3是同一个网段的,Pod1和Pod2处于同一局域网内,它们之间可以通过docker0作为路由进行通信。

img

不同Node上的Pod之间的通信

在Kubernetes的网络世界中,Pod之间假设是通过访问对方的Pod IP进行通信的,而不同Node之间的通信只能通过Node的物理网卡进行,Pod的IP地址是由各Node上的docker0网桥动态分配的。我们想要实现跨Node的Pod之间的通信,至少需要满足下面两个条件:

  1. Kubernetes集群中对Pod的IP分配不能有冲突;
  2. Pod IP 和Node IP之间的映射关系,通过Node IP转发到Pod IP;

根据条件1的要求,Kubernetes会再部署的时候对docker0的IP地址进行规划,保证每个Node上的docker0地址都没有冲突,此外Kubernetes会记录所有正在运行的Pod的IP分配信息,并将这些信息保存到etcd中,这样我们就可以知道Pod IP和Node IP之间的映射关系。

根据条件2要求,Pod中的数据在发送出去的时候,需要一个机制能够知道对方Pod的IP地址挂载到那个具体的Node上,这样就可以将数据发送到对应的宿主机上,宿主机将响应的数据转发到具体的docker0上,当数据到达docker0以后,就会将对应的数据转发到对应的容器上了。


三、CNI


Kubernetes本身并不负责网络通信,Kubernetes提供了容器网络接口CNI,具体的网络通信交给CNI插件来负责,开源的CNI插件非常多,像Flannel、Calico等,各大云厂商也都自己定制的CNI。

为什么会有CNI

CNI是Container Network Interface的缩写,简答说就是容器解决网络问题,提供的一个标准的,通用的接口。现在有各种各样的容器平台:docker,kubernetes,mesos,我们也有各种各样的容器网络解决方案:flannel,calico,weave,并且还有各种新的解决方案在不断涌现。如果每出现一个新的解决方案,我们都需要对两者进行适配,那么由此带来的工作量必然是巨大的,而且也是重复和不必要的。事实上,我们只要提供一个标准的接口,更准确的说是一种协议,就能完美地解决上述问题。一旦有新的网络方案出现,只要它能满足这个标准的协议,那么它就能为同样满足该协议的所有容器平台提供网络功能,而CNI正是这个标准接口协议。

什么是CNI

CNI是一个接口协议,用于连接容器管理系统和网络插件。前者提供一个容器所在的network namespace(从网络的角度来看,network namespace和容器是完全等价的),后者负责将network interface插入该network namespace中(比如veth的一端),并且在宿主机做一些必要的配置(例如将veth的另一端加入bridge中),最后对namespace中的interface进行IP和路由的配置。那么CNI的工作其实主要是从容器管理系统处获取运行时信息,包括network namespace的路径,容器ID以及network interface name,再从容器网络的配置文件中加载网络配置信息,再将这些信息传递给对应的插件,由插件进行具体的网络配置工作,并将配置的结果再返回到容器管理系统中。

img

CNI仅关注在创建容器时分配网络资源,和在销毁容器时删除网络资源,这使得CNI规范非常轻巧、易于实现,得到了广泛的支持。在CNI模型中只涉及两个概念:容器和网络。

容器(Container):是拥有独立Linux网络命名空间的环境,例如使用Docker或rkt创建的容器。容器需要拥有自己的Linux网络命名空间,这是加入网络的必要条件。

网络(Network):表示可以互连的一组实体,这些实体拥有各自独立、唯一的IP地址,可以是容器、物理机或者其他网络设备(比如路由器)等。

对容器网络的设置和操作都通过插件(Plugin)进行具体实现,CNI插件包括两种类型:CNI Plugin和IPAM(IP Address Management)Plugin。CNI Plugin负责为容器配置网络资源,IPAM Plugin负责对容器的IP地址进行分配和管理。IPAM Plugin作为CNI Plugin的一部分,与CNIPlugin协同工作。

插件介绍

CNI Plugin插件

CNI Plugin包括3个基本接口的定义:添加(ADD)、删除(DELETE)、检查(CHECK)和版本查询(VERSION)。这些接口的具体实现要求插件提供一个可执行的程序,在容器网络添加或删除时进行调用,以完成具体的操作。

添加:将容器添加到某个网络。主要过程为在Container Runtime创建容器时,先创建好容器内的网络命名空间(Network Namespace),然后调用CNI插件为该netns进行网络配置,最后启动容器内的进程。添加接口的参数如下:

  • Version:CNI版本号;
  • ContainerID:容器ID;
  • Network Namespace path:容器的网络命名空间路径,例如/proc/[pid]/ns/net;
  • Network configuration:网络配置JSON文档,用于描述容器待加入的网络;
  • Extra arguments:其他参数,提供基于容器的CNI插件简单配置机制;
  • Name of the interface inside the container:容器内的网卡名,返回的信息如下:
  • Interfaces list:网卡列表,根据Plugin的实现,可能包括Sandbox Interface名称、主机Interface名称、每个Interface的地址等信息;
  • IPs assigned to the interface:IPv4或者IPv6地址、网关地址、路由信息等;
  • DNS information:DNS相关的信息;

删除:容器销毁时将容器从某个网络中删除。删除接口的参数如下:

  • Version:CNI版本号;
  • ContainerID:容器ID;
  • Network Namespace path:容器的网络命名空间路径,例如/proc/[pid]/ns/net;
  • Network configuration:网络配置JSON文档,用于描述容器待加入的网络;
  • Extra arguments:其他参数,提供基于容器的CNI插件简单配置机制;
  • Name of the interface inside the container:容器内的网卡名;

检查:检查容器网络是否正确设置。检查接口的参数如下:

  • Version:CNI版本号;
  • ContainerID:容器ID;
  • Network Namespace path:容器的网络命名空间路径,例如/proc/[pid]/ns/net;
  • Network configuration:网络配置JSON文档,用于描述容器待加入的网络;
  • Extra arguments:其他参数,提供基于容器的CNI插件简单配置机制;
  • Name of the interface inside the container:容器内的网卡名;

版本查询:查询网络插件支持的CNI规范版本号。无参数,返回值为网络插件支持的CNI规范版本号。

IPAM Plugin插件

为了减轻CNI Plugin对IP地址管理的负担,在CNI规范中设置了一个新的插件专门用于管理容器的IP地址(还包括网关、路由等信息),被称为IPAM Plugin。通常由CNI Plugin在运行时自动调用IPAM Plugin完成容器IP地址的分配。

IPAM Plugin负责为容器分配IP地址、网关、路由和DNS,典型的实现包括host-local和dhcp。与CNI Plugin类似,IPAM插件也通过可执行程序完成IP地址分配的具体操作。IPAM可执行程序也处理传递给CNI插件的环境变量和通过标准输入(stdin)传入的网络配置参数。

如果成功完成了容器IP地址的分配,则IPAM插件应该通过标准输出(stdout)返回JSON报文。包括ips、routes和dns三段内容:

  • ips段:分配给容器的IP地址(也可能包括网关);
  • routes段:路由规则记录;
  • dns段:DNS相关的信息;

四、Kubernetes网络插件


Kubernetes管理的是集群,Kubernetes中的网络要解决的核心问题就是每台主机的IP地址网段划分,以及单个容器的IP地址分配。需要做到以下几点:

  1. 保证每个Pod拥有一个集群内唯一的IP地址;
  2. 保证不同节点的IP地址划分不会重复;
  3. 保证跨节点的Pod可以互相通信;
  4. 保证不同节点的Pod可以与跨节点的主机互相通信;

Kubernetes目前支持两种网络插件的实现。

CNI插件:根据CNI规范实现其接口,以与插件提供者进行对接。

kubenet插件:使用bridge和host-local CNI插件实现一个基本的cbr0。

为了在Kubernetes集群中使用网络插件,需要在kubelet服务的启动参数上设置下面两个参数:

  • --network-plugin-dir:kubelet启动时扫描网络插件的目录。
  • --network-plugin:网络插件名称,对于CNI插件,设置为cni即可,无须关注--network-plugin-dir的路径。对于kubenet插件,设置为kubenet,目前仅实现了一个简单的cbr0 Linux网桥。

在设置--network-plugin="cni"时,kubelet还需设置下面两个参数。

  • --cni-conf-dir:CNI插件的配置文件目录,默认为/etc/cni/net.d。该目录下配置文件的内容需要符合CNI规范。
  • --cni-bin-dir:CNI插件的可执行文件目录,默认为/opt/cni/bin。

开源容器网络方案

Kubernetes的网络模型假定了所有Pod都在一个可以直接连通的扁平网络空间中。若需要实现这个网络假设,需要实现不同节点上的Docker容器之间的互相访问,然后运行Kubernetes。目前已经有多个开源组件支持容器网络模型。如Flannel、Open vSwitch、直接路由和Calico。

Flannel

Flannel是一种基于overlay网络的跨主机容器网络解决方案,即将TCP数据包封装在另一种网络包里面进行路由转发和通信,Flannel是CoreOS开发,Flannel之所以可以搭建Kubernetes依赖的底层网络,是因为它能实现以下两点:

  1. 它能协助Kubernetes,给每一个Node上的Docker容器都分配互相不冲突的IP地址;
  2. 它能在这些IP地址之间建立一个Overlay Network,通过这个网络将数据包原封不动地传递到目标容器内

image.png

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

Flannel之间的底层通信协议的可选技术包括UDP、VxLan、AWS VPC等多种方式。通过源flanneld封包、目标flanneld解包,最终docker0收到的就是原始的数据,对容器应用来说是透明的,感觉不到中间Flannel的存在。

Flannel每次分配的地址段都在同一个公共区域获取,存储在集中的etcd上,从而实现不同Node上的Pod分配的IP不产生冲突。Flannel通过修改Docker的启动参数将分配给它的地址段传递进去。

通过如上方式,Flannel就控制了每个Node上的docker0地址段的地址,从而保障了所有Pod的IP地址在同一个水平网络中且不产生冲突。Flannel完美地实现了对Kubernetes网络的支持,但是它引入了多个网络组件,在网络通信时需要转到flannel0网络接口,再转到用户态的flanneld程序,到对端后还需要走这个过程的反过程,所以也会引入一些网络的时延损耗。另外,Flannel模型默认采用了UDP作为底层传输协议,UDP本身是非可靠协议,虽然两端的TCP实现了可靠传输,但在大流量、高并发的应用场景下还建议多次测试。

Calico

Calco组件简介

Calico是一个基于BGP的纯三层的网络方案,与OpenStack、Kubernetes、AWS、GCE等云平台都能够良好地集成。Calico在每个计算节点都利用Linux Kernel实现了一个高效的vRouter来负责数据转发。每个vRouter都通过BGP1协议把在本节点上运行的容器的路由信息向整个Calico网络广播,并自动设置到达其他节点的路由转发规则。

Calico保证所有容器之间的数据流量都是通过IP路由的方式完成互联互通的。Calico节点组网时可以直接利用数据中心的网络结构(L2或者L3),不需要额外的NAT、隧道或者Overlay Network,没有额外的封包解包,能够节约CPU运算,提高网络效率。

img

Calico在小规模集群中可以直接互联,在大规模集群中可以通过额外的BGP route reflector来完成。Calico基于iptables还提供了丰富的网络策略,实现了Kubernetes的Network Policy策略,提供容器间网络可达性限制的功能。

Calico架构

image.png

Calico的主要组件:

Felix:Calico Agent,运行在每个Node上,负责为容器设置网络资源(IP地址、路由规则、iptables规则等),保证跨主机容器网络互通;

etcd:Calico使用的后端存储;

BGP Client:负责把Felix在各Node上设置的路由信息通过BGP协议广播到Calico网络;

Route Reflector:通过一个或者多个BGP Route Reflector来完成大规模集群的分级路由分发;

CalicoCtl:Calico命令行管理工具;

本文主要参考《Kubernetes权威指南实战》
相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
相关文章
|
15天前
|
人工智能 弹性计算 运维
ACK Edge与IDC:高效容器网络通信新突破
本文介绍如何基于ACK Edge以及高效的容器网络插件管理IDC进行容器化。
|
4月前
|
Kubernetes 负载均衡 网络安全
Kubernetes 网络模型与实践
【8月更文第29天】Kubernetes(K8s)是当今容器编排领域的佼佼者,它提供了一种高效的方式来管理容器化应用的部署、扩展和运行。Kubernetes 的网络模型是其成功的关键因素之一,它支持服务发现、负载均衡和集群内外通信等功能。本文将深入探讨 Kubernetes 的网络模型,并通过实际代码示例来展示服务发现和服务网格的基本概念及其实现。
173 1
|
4月前
|
Kubernetes Devops 持续交付
DevOps实践:使用Docker和Kubernetes实现持续集成和部署网络安全的守护盾:加密技术与安全意识的重要性
【8月更文挑战第27天】本文将引导读者理解并应用DevOps的核心理念,通过Docker和Kubernetes的实战案例,深入探讨如何在现代软件开发中实现自动化的持续集成和部署。文章不仅提供理论知识,还结合真实示例,旨在帮助开发者提升效率,优化工作流程。
|
4天前
|
Kubernetes 网络协议 应用服务中间件
Kubernetes Ingress:灵活的集群外部网络访问的利器
《Kubernetes Ingress:集群外部访问的利器-打造灵活的集群网络》介绍了如何通过Ingress实现Kubernetes集群的外部访问。前提条件是已拥有Kubernetes集群并安装了kubectl工具。文章详细讲解了Ingress的基本组成(Ingress Controller和资源对象),选择合适的版本,以及具体的安装步骤,如下载配置文件、部署Nginx Ingress Controller等。此外,还提供了常见问题的解决方案,例如镜像下载失败的应对措施。最后,通过部署示例应用展示了Ingress的实际使用方法。
19 2
|
2月前
|
Kubernetes 网络协议 网络安全
k8s中网络连接问题
【10月更文挑战第3天】
210 7
|
2月前
|
Kubernetes 应用服务中间件 nginx
搭建Kubernetes v1.31.1服务器集群,采用Calico网络技术
在阿里云服务器上部署k8s集群,一、3台k8s服务器,1个Master节点,2个工作节点,采用Calico网络技术。二、部署nginx服务到k8s集群,并验证nginx服务运行状态。
983 1
|
3月前
|
Kubernetes 容器 Perl
Kubernetes网络插件体系及flannel基础
文章主要介绍了Kubernetes网络插件体系,特别是flannel网络模型的工作原理、配置和测试方法。
125 3
|
2月前
|
Kubernetes 容器
基于Ubuntu-22.04安装K8s-v1.28.2实验(三)数据卷挂载NFS(网络文件系统)
基于Ubuntu-22.04安装K8s-v1.28.2实验(三)数据卷挂载NFS(网络文件系统)
180 0
|
4月前
|
Kubernetes Cloud Native 网络安全
云原生入门指南:Kubernetes和容器化技术云计算与网络安全:技术融合的新篇章
【8月更文挑战第30天】在云计算的浪潮中,云原生技术如Kubernetes已成为现代软件部署的核心。本文将引导读者理解云原生的基本概念,探索Kubernetes如何管理容器化应用,并展示如何通过实践加深理解。
|
1天前
|
Prometheus Kubernetes 监控
OpenAI故障复盘 - 阿里云容器服务与可观测产品如何保障大规模K8s集群稳定性
聚焦近日OpenAI的大规模K8s集群故障,介绍阿里云容器服务与可观测团队在大规模K8s场景下我们的建设与沉淀。以及分享对类似故障问题的应对方案:包括在K8s和Prometheus的高可用架构设计方面、事前事后的稳定性保障体系方面。

热门文章

最新文章

推荐镜像

更多