以下内容作为这段时间研究Kubernetes网络的总结,一口气写完,代表了当前对Kubernetes网络的认知,可能有误,权当摆龙门阵。K8s网络的核心问题 我们理一理Kubernetes相关概念和网络的关系
- Pod:调度的基本单位,一个pod内的所有容器共享一个主机IP
- Deployment:管理Pod的资源
- StatefulSet:同样是管理Pod的资源,只不过是有状态的,其管理的主机IP创建后就不变了
- DaemonSet:也是管理Pod的资源
- Service:为Pod提供稳定的前端IP,同时能够通过QFDN的形式提供稳定的域名
- Ingress:允许以域名的形式访问Service
- 同一个集群内,Pod之间要能够相互通信
- Service提供负载均衡作用
- 需要有一个域名解析系统,为Service提供域名
- Ingress提供应用层网关作用
- 网络策略:限制网络资源之间网络访问的规则
K8s网络的底层原理
- Pod之间相互通信
- Pod只是逻辑抽象,最终管理的还是容器,只不过Pod的实现,是先启动一个简单的pause容器,占据一个网络命名空间,其它容器创建时加入这个命名空间就行了
- 对于多节点集群,还涉及到IP划分的问题,一个简单的方案是:在集群的CIDR为每个主机划分一个子网,Pod从所属主机的IP池申请一个IP即可。flannel就是这样的实现
- 同节点上的Pod,只需要通过veth pair + linux bridge的方式即可实现通信
- 跨节点的Pod,则需要进行协调,一般的实现方式有
- 隧道协议:即网络插件直接将原IP包再包一层,在Node之间进行转发,到达目标节点后再拆包然后路由到目标Pod。隧道一般有一个发送前装包,发送后拆包的步骤,这一般通过tun设备实现。
- 直接路由:直接配置路由表,纯转发,没有封包的动作,性能好。但这要求所有节点都必须在同一个物理网络下。如果跨物理网络了,则需要BGP边界网关协议
- Service负载均衡
- 这个一般有两种实现方式:iptables和IPVS。都是配置一系列规则,但iptables本身是为防火墙而生,有规则麻烦效率低的缺点,在超大规模集群中这就是问题,IPVS是实现在内核层的负载均衡,专门用来负载均衡,效率高,但也有功能单一的缺点,注入NAT之类的功能还是需要iptables辅助
- Ingress应用层网关
- 这就是一个纯应用层的东西,直接将Nginx改造成Nginx-Ingress-Controller就能实现。正是由于其所处的位置,与应用有很大关系,切入点比较好,因此产生了一大堆Ingress-Controller:Kong、ApiSix、Traefik。。。
- 服务发现
- 即如何发现集群内的其它服务,有两种实现方式
- 环境变量:将集群内的所有服务IP通过环境变量的形式注入
- 域名解析系统:用域名的方式解析得到服务的IP
- 即如何发现集群内的其它服务,有两种实现方式
- 网络策略
- 简单的实现也可以通过iptables实现
- 但是更高效的可以通过eBPF实现,它能在没有多少性能损失的情况下实现对网络包的任意处理,低至4层,高至7层,可以说强大无比。Cilium就是在他的基础上开发的。
- Linux Network Namespace
- Veth pair
- Linux Bridge
- tun设备
- 隧道协议:IPIP、VXLAN等
- iptables
- IPVS
- eBPF
- DNS
- Kube-proxy
- Kubelet
- API Server
- ETCD
- Scheduler
- RC
- CoreDNS
- Kube-proxy:其主要职责就是负责Service的实现,它定期拉取集群的网络配置,更新自己的规则。有三种工作模式
- userspace:这种情况下,Kube-poxy自己就是负载均衡器
- iptables:将配置的访问规则转换为本机的iptables规则,这种情况下负载均衡由iptables实现
- IPVS:效率更高
- CoreDNS:负责域名解析系统
- CNI插件:CNI接口基本来说就两个
- 为容器添加Network
- 为容器删除Network
- 为Pod分配IP地址
- 保证Pod之间的连通性
- 提供Pod之间的网络访问策略
Kube-poxy应该说是建立在CNI之上的,它不管Service背后的网络是否能够被访问到,只管将数据包转发过去就行了。保证这个数据包能够正确到达目的地是CNI插件的事情。
K8s网络的解决方案 通常所说的K8s网络解决方案,指的就是各种CNI插件。这是CNI插件的主页:https://github.com/containernetworking/cni。可以看到不只是Kubernetes采用了CNI,Open Shift、Mesos等都采用了CNI。
- Flannel:功能简单,因此配置简单,使用方便。但是也有性能一般、IP浪费等情况出现。这是元老级别的CNI插件
- Callico:工作在三层,即IP层,纯路由方式实现,因此速度应该比较快。纯三层的有点就是可以直接路由,没有NAT、封拆包等性能损耗的东西。但是规模稍大的集群,则需要通过BGP连接同集群下的两个数据中心
- Cilium:基础功能和Flannel差不多,但采用了eBPF,功能和性能都应该会非常强大。最为典型的一点是,它能够在内核中对7层数据做处理,这个就很强了。
- Weave:一个多主机网络,去中心化。没搞懂它特殊在哪里
K8s和Service Mesh之间的关系 我们可以看到,K8s的网络包括CNI插件解决的是最最基本的问题:可达性。但是在实际开发中,还有大量的应用层面的共性任务需要处理
- 日志采集
- 链路追踪
- 服务熔断和降级
- 灰度发布
- 。。。
至于说Service Mesh和网络有什么关系呢?
我们知道,传统K8s的网络架构如下
- CNI为网络基座,提供基本可用性
- Service提供访问固定入口和负载均衡
- Pod作为最小的网络单元
- Kube-proxy拦截的是进入节点的流量
- sidecar拦截的是进入Pod的流量
- 说到将Service融入每个Pod,Cilium也做了类似的事,不过更进一步,它是在内核层面做这件事,Istio是通过用户态程序Envoy实现,相比之下效率慢了不少。那Envoy和Cilium的关系是什么呢?
还是一个应用层、一个网络基础层,它们之间的关系大概如下
文章图片
- 有了Istio,还需要CNI插件吗?
当然还是需要的,尽管Istio自己也有提供CNI插件,但那也是CNI插件呀。
推荐阅读
- java|Docker部署homeassitant
- java|docker-compose安装教程
- ansible|ansible 建 kubernetes 证书签名请求_最简单的 kubernetes 高可用安装方式!(文末送书)...
- 云原生|【云原生 | Kubernetes 系列】K8s 实战 使用 Kustomize 对 Kubernetes 对象进行声明式管理
- Dock窗口预览DockView Mac
- java|出现错误java:警告:源反行版 9,需要目标发行版1.9
- Netty学习系列|Netty学习七(编解码之自定义通信协议)
- Netty学习系列|Netty学习六(编解码之粘包和拆包)
- docker|docker mysql外部_Docker 安装MySQL以及外部访问