阿里云K8S集群网络目前有两种方案,一种是flannel方案,另外一种是基于calico和弹性网卡eni的terway方案。Terway和flannel类似,不同的地方在于,terway支持Pod弹性网卡,以及NetworkPolicy功能。

今天这篇文章,我们以flannel为例,深入分析阿里云K8S集群网络的实现方法。我会从两个角度去分析,一个是网络的搭建过程,另外一个是基于网络的通信。我们的讨论基于当前的1.12.6版本。

鸟瞰

总体上来说,阿里云K8S集群网络配置完成之后,如下图,包括集群CIDR,VPC路由表,节点网络,节点的podCIDR,节点上的虚拟网桥cni0,连接Pod和网桥的veth等部分。

类似的图,大家可能在很多文章中都看过,但是因为其中相关配置过于复杂,比较难理解。这里我们可以把这些配置,分三种情况来理解:集群配置,节点配置以及Pod配置。与这三种情况对应的,其实是对集群网络IP段的三次划分:首先是集群CIDR,接着为每个节点分配podCIDR(即集群CIDR的子网段),最后在podCIDR里为每个Pod分配自己的IP。

集群网络搭建

初始阶段

集群的创建,基于云资源VPC和ECS,在创建完VPC和ECS之后,我们基本上可以得到如下图的资源配置。我们得到一个VPC,这个VPC的网段是192.168.0.0/16,我们得到若干ECS,他们从VPC网段里分配到IP地址。

集群阶段

在以上出初始资源的基础上,我们利用集群创建控制台得到集群CIDR。这个值会以参数的形式传给集群节点provision脚本,并被脚本传给集群节点配置工具kubeadm。kubeadm最后把这个参数写入集群控制器静态Pod的yaml文件kube-controller-manager.yaml。

集群控制器有了这个参数,在节点kubelet注册节点到集群的时候,集群控制器会为每个注册节点,划分一个子网出来,即为每个节点分配podCIDR。如上图,Node B的子网是172.16.8.1/25,而Node A的子网是172.16.0.128/25。这个配置会记录到集群node的podCIDR数据项里。

节点阶段

经过以上集群阶段,K8S有了集群CIDR,以及为每个节点划分的podCIDR。在此基础上,集群会下发flanneld到每个阶段上,进一步搭建节点上,可以给Pod使用的网络框架。这里主要有两个操作,第一个是集群通过Cloud Controller Manager给VPC配置路由表项。路由表项对每个节点有一条。每一条的意思是,如果VPC路由收到目的地址是某一个节点podCIDR的IP地址,那么路由会把这个网络包转发到对应的ECS上。第二个是创建虚拟网桥cni0,以及与cni0相关的路由。这些配置的作用是,从阶段外部进来的网络包,如果目的IP是podCIDR,则会被节点转发到cni0虚拟局域网里。

注意:实际实现上,cni0的创建,是在第一个使用Pod网络的Pod被调度到节点上的时候,由下一节中flannal cni创建的,但是从逻辑上来说,cni0属于节点网络,不属于Pod网络,所以在此描述。

Pod阶段

在前边的三个阶段,集群实际上已经为Pod之间搭建了网络通信的干道。这个时候,如果集群把一个Pod调度到节点上,kubelet会通过flannel cni为这个Pod本身创建网络命名空间和veth设备,然后,把其中一个veth设备加入到cni0虚拟网桥里,并为Pod内的veth设备配置ip地址。这样Pod就和网络通信的干道连接在了一起。这里需要强调的是,前一节的flanneld和这一节的flannel cni完全是两个组件。flanneld是一个daemonset下发到每个节点的pod,它的作用是搭建网络(干道),而flannel cni是节点创建的时候,通过kubernetes-cni这个rpm包安装的cni插件,其被kubelet调用,用来为具体的pod创建网络(分枝)。

理解这两者的区别,有助于我们理解flanneld和flannel cni相关的配置文件的用途。比如/run/flannel/subnet.env,是flanneld创建的,为flannel cni提供输入的一个环境变量文件;又比如/etc/cni/net.d/10-flannel.conf,也是flanneld pod(准确的说,是pod里的脚本install-cni)从pod里拷贝到节点目录,给flannel cni使用的子网配置文件。

通信

以上完成Pod网络环境搭建。基于以上的网络环境,Pod可以完成四种通信:本地通信,同节点Pod通信,跨节点Pod通信,以及Pod和Pod网络之外的实体通信。

其中本地通信,说的是Pod内部,不同容器之前通信。因为Pod内网容器之间共享一个网络协议栈,所以他们之间的通信,可以通过loopback设备完成。

同节点Pod之间的通信,是cni0虚拟网桥内部的通信,这相当于一个二层局域网内部设备通信。

跨节点Pod通信略微复杂一点,但也很直观,发送端数据包,通过cni0网桥的网关,流转到节点上,然后经过节点eth0发送给VPC路由。这里不会经过任何封包操作。当VPC路由收到数据包时,它通过查询路由表,确认数据包目的地,并把数据包发送给对应的ECS节点。而进去节点之后,因为flanneld在节点上创建了真的cni0的路由,所以数据包会被发送到目的地的cni0局域网,再到目的地Pod。

最后一种情况,Pod与非Pod网络的实体通信,需要经过节点上iptables规则做snat,而此规则就是flanneld依据命令行--ip-masq选项做的配置。

总结

以上是阿里云K8S集群网络的搭建和通信原理。我们主要通过网络搭建和通信两个角度去分析K8S集群网络。其中网络搭建包括初始阶段,集群阶段,节点阶段以及Pod阶段,这么分类有助于我们理解这些复杂的配置。而理解了各个配置,集群通信原理就比较容易理解了。

Kubernetes 从懵圈到熟练 – 集群网络详解(转)的更多相关文章

  1. K8s 从懵圈到熟练 – 集群网络详解

    作者 | 声东 阿里云售后技术专家 导读:阿里云 K8S 集群网络目前有两种方案:一种是 flannel 方案:另外一种是基于 calico 和弹性网卡 eni 的 terway 方案.Terway ...

  2. Kubernetes从懵圈到熟练:读懂这一篇,集群节点不下线

    排查完全陌生的问题,完全不熟悉的系统组件,是售后工程师的一大工作乐趣,当然也是挑战.今天借这篇文章,跟大家分析一例这样的问题.排查过程中,需要理解一些自己完全陌生的组件,比如systemd和dbus. ...

  3. Kubernetes 从懵圈到熟练:集群服务的三个要点和一种实现

    作者 | 声东 阿里云售后技术专家 文章来源:Docker,点击查看原文. 以我的经验来讲,理解 Kubernetes 集群服务的概念,是比较不容易的一件事情.尤其是当我们基于似是而非的理解,去排查服 ...

  4. Kubernetes K8S之Taints污点与Tolerations容忍详解

    Kubernetes K8S之Taints污点与Tolerations容忍详解与示例 主机配置规划 服务器名称(hostname) 系统版本 配置 内网IP 外网IP(模拟) k8s-master C ...

  5. Kubernetes K8S之CPU和内存资源限制详解

    Kubernetes K8S之CPU和内存资源限制详解 Pod资源限制 备注:CPU单位换算:100m CPU,100 milliCPU 和 0.1 CPU 都相同:精度不能超过 1m.1000m C ...

  6. Kubernetes K8S之资源控制器Job和CronJob详解

    Kubernetes的资源控制器Job和CronJob详解与示例 主机配置规划 服务器名称(hostname) 系统版本 配置 内网IP 外网IP(模拟) k8s-master CentOS7.7 2 ...

  7. Kubernetes K8S之affinity亲和性与反亲和性详解与示例

    Kubernetes K8S之Node节点亲和性与反亲和性以及Pod亲和性与反亲和性详解与示例 主机配置规划 服务器名称(hostname) 系统版本 配置 内网IP 外网IP(模拟) k8s-mas ...

  8. K8s 从懵圈到熟练 – 镜像拉取这件小事

    作者 | 声东 阿里云售后技术专家 导读:相比 K8s 集群的其他功能,私有镜像的自动拉取,看起来可能是比较简单的.而镜像拉取失败,大多数情况下都和权限有关.所以,在处理相关问题的时候,我们往往会轻松 ...

  9. kubernetes创建资源对象yaml文件例子--pod详解

    apiVersion: v1 #指定api版本,此值必须在kubectl apiversion中 kind: Pod #指定创建资源的角色/类型 metadata: #资源的元数据/属性 name: ...

随机推荐

  1. LeetCode 680. 验证回文字符串 Ⅱ(Valid Palindrome II) 1

    680. 验证回文字符串 Ⅱ 680. Valid Palindrome II 题目描述 给定一个非空字符串 s,最多删除一个字符.判断是否能成为回文字符串. 每日一算法2019/5/4Day 1Le ...

  2. [转帖]再谈IO的异步,同步,阻塞和非阻塞

    再谈IO的异步,同步,阻塞和非阻塞 https://yq.aliyun.com/articles/53674?spm=a2c4e.11155435.0.0.48bfe8efHUE8wg   krypt ...

  3. ~json库的使用

    一.json简介 json全称"JavaScript Object Notation"(JavaScript对象表示法)它是一种基于文本,独立于语言的轻量级数据交换格式.易于让人阅 ...

  4. golang之格式化fmt.Printf

    当使用fmt包打印一个数值时,我们可以用%d.%o或%x参数控制输出的进制格式,就像下面的例子: o := 0666 fmt.Printf("%d %[1]o %#[1]o\n", ...

  5. hadoop 伪分布启动-fs格式化

    1.独立模式(standalone|local) nothing! 本地文件系统. 不需要启用单独进程. 2.pesudo(伪分布模式) 等同于完全分布式,只有一个节点. SSH: //(Socket ...

  6. 网页调试js时,如何知道某个事件对应哪段js代码?

    有时候我们需要知道某个事件对应的js代码,比如点击一个div元素时,出现下拉框,我想知道这个功能对应的js代码,那就可以按下图操作: 勾选click事件,重新运行,那么就会在每个click事件那里设置 ...

  7. SQL Server2008导入导出数据库

    一.导出数据库 1.新建一个.bak的文本 右击数据库-->Tasks-->BackUp-->Remove原来的数据库-->Add后选择之前建立的.bak档 二.导入数据库 1 ...

  8. ASP.NET Core 2.1 中的 HttpClientFactory (Part 1) HttpClientFactory介绍

    原文:https://www.stevejgordon.co.uk/introduction-to-httpclientfactory-aspnetcore  发表于:2018年1月 ASP.NET ...

  9. 依赖: libcheese-gtk23 (>= 3.4.0)

    unity-control-center : 依赖: libcheese-gtk23 (>= 3.4.0) 但是它将不会被安装                         依赖: libch ...

  10. springboot接收date类型参数

    springboot接收日期类型参数,实现自动转换. 1. 当请求类型为json,date类型字段为 json 字段时,可以使用如下两种方法 1.1. 当前参数加两个注解(有些文章说接收只需要加 @D ...