0. k8s容器概括

docker的组成

  • cgroup做资源隔离
  • namespace做物理隔离
  • rootfs做系统隔离

exec的执行过程

  • 找到欲进入的容器的pid
  • 根据pid找到该容器对应的namespace
  • 通过setns进入到该命名空间
  • 执行某个命令
  • docker 创建容器时,可通过—net指定加入到某个容器网络,或宿主机网络;与上面setns同理
  • CMD 与 ENTRYPOINT的区别
    • cmd是可通过run后面的命令覆盖的
    • entrypoint是不可通过run后面的命令覆盖的,但是可以通过run后面的输入添加参数

docker 挂载

  • 在启动容器时,如果未指定宿主机,则自动挂载到宿主机的某目录上
  • 在容器进程创建后,chroot前,将某目录挂载到该容器对应的宿主机某目录下;由于挂载前容器进程已创建,故挂载事件只在这个容器里可见,宿主机上无法看到挂载点,同理,如果容器的该目录中有文件,在宿主机上并不会展示
  • 由于宿主机上看不到该挂载点,所以当执行docker commit时,并不会将挂载目录的内容提交到image中

k8s本质

  • 容器分为两部分
    • 容器的静态视图,即rootfs,也就是image内容
    • 容器的动态视图,即cgroup+namespace
  • 做为云提供商只要能将docker 镜像以容器的方式运行起来,即能加入到docker的生态圈中
  • k8s的组成
    • master之kube-apiserver
    • master之kube-scheduler
    • master之kube-controller-manager
    • node之kubelet
    • node之kube-proxy
  • kubelet控制容器过程中使用的规范
    • CRI:Container Runtime Interface
    • OCI:Open Container Initiative
    • CNI:Container Networking Interface
    • CSI:Container Storage Interface
    • Device Plugin
  • K8S中的概念
    • Service
    • Deployment
    • Pod
    • DaemonSet
    • StatefulSet
    • Secret
    • ConfigMap
    • Ingress

Pod的实质

  • Pod是一组共享Namespace的容器
  • Pod中存在一个基本的Infra容器,其它容器通过join该容器的方式实现共享Namespace
  • Pod 的生命周期只跟 Infra 容器一致,而与容器 A 和 B 无关。
  • 同一个 Pod 里面的所有用户容器来说,它们的进出流量,也可以认为都是通过 Infra 容器完成的
  • Init Container会先启动,启动完成并且退出后才会启动用户容器

深入理解pod

  • pod通过NodeName识别调度到哪个节点
  • 通过HostAliases设置hosts
  • ImagePullPolicy:Always IfNotPresent Never
  • postStart与preStop
  • pod的状态 Pending Running Succeeded Failed Unknown
  • Running指容器已经全部创建成功,并且至少有一个运行中(有可能还不可接收请求,正在启动中);而Running的子状态Ready指的是容器是否已正常运行,并且可接收外部请求
  • livenessProbe readinessProbe
  • podpreset 为pod设置公共字段

Headless Service 及 StatefulSet

  • Headless Service:无clusterip的 Service
  • StatefulSet:有状态的pod集合,即pod的名称及对应的启动node节点一致
    并且可以保证pod的启动顺序;另外保证Pod 拥有独立的 Volume,并且重启后仍然挂载该Volume

API对象

  • 组成:Group(API 组)、Version(API 版本)和 Resource(API 资源类型)三个部分组成
  • Kubernetes 里的核心 API 对象,比如:Pod、Node 等,是不需要 Group 的(即:它们 Group 是“”)
  • 核心的api直接在 /api 这个层级进行下一步的匹配过程
  • 对于 CronJob 等非核心 API 对象来说,Kubernetes 就必须在 /apis 这个层级里查找

PV与PVC

  • PVC是对PV的声明
  • PVC与PV绑定的条件,spec下的配置一致,storageClassName相同
  • PVC与PV绑定后,会在PVC的spec.volumeName上填入所绑定的PV
  • PV的挂载
    • Attach:为虚拟机挂载远程磁盘的操作,该操作由Volume Controller 负责维护
    • Mount:将磁盘设备格式化并挂载到 Volume 宿主机目录;该操作必须在node上执行,故该操作由kubelet中的一个goroutine完成
  • StorageClass:声明一种存储类型
    • PVC声明存储的大小,当PVC上存在StorageClassName时,并且存在命名为该Name的StorageClass时,就可以根据PVC及StorageClass创建出对应的PV,从而实现动态绑定的效果
    • 如果不存在PVC上StorageClassName对应的StorageClass时,会进行静态绑定
    • 当PVC的StorageClassName为“”时,则该PVC只能和StorageClassName同样为“”的PV绑定
  • Local Persistent Volume:本地持久化挂载
    • 创建本地挂载时,指定该挂载点的节点
    • Local Persistent Volume尚不支持动态绑定PV
    • Pod绑定该PV对应的PVC
    • 创建StorageClass描述PV延时绑定,延时到pod调度时,根据调度的结果及PV中对应的节点,取节点交集启动该Pod;防止出现提前绑定PV和PVC后,Pod不能调度到该节点的情况

单节点容器网络

  • veth pair:一个成对的端口,所有从这对端口一 端进入的数据包都将从另一端出来,反之也是一样
  • docker0: docker容器网桥,所有的容器虚拟网卡,均接入到该网桥上,即所有容器网卡接收的数据包,都由docker0处理
  • ARP: 通过三层的 IP 地址找到对应的二层 MAC 地址的协议。
  • route命令
    • 查看机器路由配置
    • 匹配某目标地址段网络由哪个网关处理
    • 如果未匹配到路由规则,则由默认的路由处理
  • 容器间A->B的网络通信过程
    • 在A容器中通过路由规则匹配到处理的网卡
    • 该网卡是一对veth pair网卡,当流量进入该网卡时,即进入到了host上与之对应的网卡上
    • host与之对应的虚拟网卡插在了docker 网桥 docker0上
    • docker0网桥通过目标mac查找到对应的端口,即B容器在host上对应的veth pair网卡
    • 数据包由veth pair进入到容器内
    • 上述省略了ARP的前置过程,具体ARP的过程与上述过程类似

多节点容器网络

  • Overlay Network:通过软件构建一个覆盖在已有宿主机网络之上的、可以把所有容器连通在一起的虚拟网络
  • Overlay Network 本身,可以由每台宿主机上的一个“特殊网桥”共同组成
  • 当 Node 1 上的 Container 1 要访问 Node 2 上的 Container 3 的时候,Node 1 上的“特殊网桥”在收到数据包之后,能够通过某种方式,把数据包发送到正确的宿主机,比如 Node 2 上。
  • 而 Node 2 上的“特殊网桥”在收到数据包后,也能够通过某种方式,把数据包转发给正确的容器,比如 Container 3

flannel之UDP的实现原理

  • flannel通过etcd保存不同容器子网对应的节点ip
  • 在启动docker时,可通过指定pid的方式,实现不同节点的容器网络ip段不同
  • Flannel 会在宿主机上创建出一系列的路由规则
  • Flannel是一个 TUN 设备(Tunnel 设备)
  • 在 Linux 中,TUN 设备是一种工作在三层(Network Layer)的虚拟网络设备
  • TUN 设备的功能非常简单,即:在操作系统内核和用户应用程序之间传递 IP 包
  • 节点1上的A容器访问节点2上的B容器的过程,假设A容器的ip是100.96.1.2,B容器的ip是100.96.2.3
    • 由于目的地址 100.96.2.3 并不在 Node 1 的 docker0 网桥的网段里,所以这个 IP 包会被交给默认路由规则,通过容器的网关进入 docker0 网桥
    • 由于目的地址100.96.2.3,匹配不到node1节点路由表中 docker0 网桥对应的 100.96.1.0/24 网段,只能匹配到第二条、也就是 100.96.0.0/16 对应的这条路由规则,从而进入到一个叫作 flannel0 的设备中
    • 当操作系统将一个 IP 包发送给 flannel0 设备之后,flannel0 就会把这个 IP 包,交给创建这个设备的应用程序,也就是 Flannel 进程。这是一个从内核态(Linux 操作系统)向用户态(Flannel 进程)的流动方向
    • 反之,如果 Flannel 进程向 flannel0 设备发送了一个 IP 包,那么这个 IP 包就会出现在宿主机网络栈中,然后根据宿主机的路由表进行下一步处理。这是一个从用户态向内核态的流动方向
    • flanneld 看到了这个 IP 包的目的地址,是 100.96.2.3,先从etcd中根据该地址查询到节点的ip,然后把它发送给了 Node 2 宿主机
    • 每台宿主机上的 flanneld,都监听着一个 8285 端口,所以 flanneld 只要把 UDP 包发往 Node 2 的 8285 端口即可
    • flanneld 会直接把这个 IP 包发送给它所管理的 TUN 设备,即 flannel0 设备
    • 然后在节点2的路由表中寻找这个 IP 包的下一步流向
    • Linux 内核就会按照这条路由规则,把这个 IP 包转发给 docker0 网桥
    • docker0 网桥会扮演二层交换机的角色,将数据包发送给正确的端口,进而通过 Veth Pair 设备进入到 container-2 的 Network Namespace 里
    • 由于上述过程中,存在多次用户态与内核态之间的数据拷贝,所以性能很差

flannel之VXLAN的实现原理

  • VLAN:
    • 通过VLAN在二层交换机上隔离不同的端口,以实现网络隔离的效果
    • 隔离的优点,防止广播数据帧在网络中范围传播,从而节省带宽及机器对这部分功能处理的cpu消耗
    • 隔离的缺点
      • 两个VLAN的网络无法直接通信
      • VLAN最多划分4096个,现已无法满足大规模云计算IDC的需求
      • 无法解决同一交换机中多租户的网络地址重叠的问题
      • 虚拟化技术的出现增加了交换机的负担,为了保证集群中所有虚机可以正常通信,交换机必须保存每台虚机的MAC地址,这样就导致了交换机中的MAC表异常庞大,从而影响交换机的转发性能
      • 虚拟机迁移范围受网络架构限制
    • 静态VLAN,通过指定交换机的端口划分VLAN
    • 动态VLAN之基于MAC地址的VLAN,通过查询并记录端口所连计算机上网卡的MAC地址来决定端口的所属
    • 动态VLAN之基于子网的VLAN,通过所连计算机的IP地址,来决定端口所属VLAN的
    • 动态VLAN之基于用户的VLAN,根据交换机各端口所连的计算机上当前登录的用户,来决定该端口属于哪个VLAN,这里的用户识别信息,一般是计算机操作系统登录的用户,比如可以是Windows域中使用的用户名
  • Overlay:https://support.huawei.com/enterprise/zh/doc/EDOC1100023543?section=j015
    • Overlay网络是将已有的物理网络(Underlay网络)作为基础,在其上建立叠加的逻辑网络,实现网络资源的虚拟化
    • Overlay网络是建立在已有物理网络上的虚拟网络,具有独立的控制和转发平面,对于连接到Overlay的终端设备(例如服务器)来说,物理网络是透明的,从而可以实现承载网络和业务网络的分离。
    • 解决的问题
      • 针对虚拟机规模受网络规格限制:虚拟机发出的数据包封装在IP数据包中,对网络只表现为封装后的网络参数。因此,极大降低了大二层网络对MAC地址规格的需求。
      • 针对网络隔离能力限制:Overlay技术扩展了隔离标识的位数(24比特),极大扩展了隔离数量
      • 针对虚拟机迁移范围受网络架构限制:Overlay将以太报文封装在IP报文之上,通过路由在网络中传输。通过路由网络,虚拟机迁移不受网络架构限制。而且路由网络具备良好的扩展能力、故障自愈能力、负载均衡能力
    • Overlay技术有多种,例如VXLAN、NVGRE、STT等,其中VXLAN是目前获得最广泛支持的Overlay技术。
  • VTEP:用于建立VxLAN隧道的端点设备成为VTEP,封装和解封装在VTEP节点上进行
  • VNI:
    • VXLAN头部包含有一个VXLAN标识(即VNI,VXLAN Network Identifier)
    • 只有在同一个VXLAN上的虚拟机之间才能相互通信
    • VNI在数据包之中占24比特,故可支持1600万个VXLAN的同时存在,远多于VLAN的4094个,因此可适应大规模租户的部署
  • VXLAN:VXLAN技术是网络Overlay技术的一种实现,对于Overlay技术,笔者的理解是:在基于物理网络拓扑的基础上通过一定的技术来构建虚拟的、不同于物理网络拓扑的逻辑网络,而物理网络的拓扑结构对于Overlay终端而言是透明的,终端不会感知到物理网络的存在,而仅仅能感知到逻辑网络结构。对于终端的视角,网络的情况和直接通过物理设备实现逻辑拓扑的效果是相同的。
    • ARP及数据传输流程:VM1——VTEP1——物理交换机——VTEP2——VM2
      • VM1给VM2发送了一个TCP报文
      • VTEP1收到报文后检查VM1和VM2是否属于一个VNI,(如果不属于将转发给VXLAN网关)检查后属于一个VNI,需要转发给VTEP2
      • VTEP1封装VXLAN报文以单播的形式发送给VTEP2
      • VTEP2收到报文后解封装,查找流表。VM2是自己下联终端
      • VTEP2单播的形式发送给VM2,至此一个报文发送完毕
  • docker clan网络请求过程
    • 当 Node 2 启动并加入 Flannel 网络之后,在 Node 1(以及所有其他节点)上,生成一条Node 2节点ip对应flannel1.1的路由规则;同时会自动生成node 2 VTEP 设备的arp记录
    • 当容器A发出请求后,这个网络数据包,先到达docker0
    • docker0发现不是该节点的docker网络,会根据路由规则匹配到flannel1.1,即node1的VTEP 设备,暂称之为源VTEP
    • “源 VTEP 设备”收到“原始 IP 包”后,就要想办法把“原始 IP 包”加上一个目的 MAC 地址,封装成一个二层数据帧,然后发送给“目的 VTEP 设备”;而mac地址,在加入flannel网络时,即已在节点上生成了对应的arp记录
    • 然后会在源VTEP中进行一系列的封包处理后将封装后的数据包发送至目标VTEP
    • 目标VTEP收到数据包后,会先进行解封处理,取出原始的ip地址
    • 解封后,根据目的虚机或容器ip,匹配路由规则,发到docker0网桥

flannel之Host-gw的实现原理

  • 在路由规则中,指定如果目标ip是某ip,则下一跳为某个节点,该节点即为该容器所在节点
  • 通过Host-gw方式的性能损耗大概在10%
  • 而其它vxlan的损耗大概在25%

k8s之Service

  • Service 的clusterIp是一个VIP
  • 当创建一个Service后,kube-proxy会通过informer监听到该事件,然后会在节点上创建一系列的iptables,使得对Service ClusterIP的访问,随机请求到后续的三个节点上
  • Kube-proxy之IPVS模式
    • iptables模式会在节点上创建大量的iptables规则,这会严重制约pod数量
    • 当创建了 Service 之后,kube-proxy 首先会在宿主机上创建一个虚拟网卡(叫作:kube-ipvs0),并为它分配 Service VIP 作为 IP 地址
    • 而接下来,kube-proxy 就会通过 Linux 的 IPVS 模块,为这个 IP 地址设置三个 IPVS 虚拟主机(即三个pod),并设置这三个虚拟主机之间使用轮询模式 (rr) 来作为负载均衡策略
    • 在大规模集群里,非常建议 kube-proxy 设置–proxy-mode=ipvs 来开启这个功能。它为 Kubernetes 集群规模带来的提升,还是非常巨大的

—————————————————————————
0-17