今日鸡汤
我们能够带进坟墓里的,归根结底,也只有尽心尽责的满足感,以及拼尽全力的证据。
今天好好搞一搞K8S网络模型和存储模型。
Linux网络基础
1. Namespace
Namespace设置的意图是什么?
独立的协议栈被隔离到不同的命名空间中,处于不同命名空间中的网络栈是完全隔离的,彼此之间无法通信。
每个 Namespace需要包含什么?
进程、套接字、网络设备等。
如何在Linux网络协议栈的基础上支持这些私有的独立的协议栈?
实现的核心:让Linux网络的全局变量成为一个Namespace变量的成员,然后为协议栈的函数调用加入一个Namespacee参数。所有网络设备都只属于一个命名空间(物理设备关联到root,虚拟设备创建并关联到给定的ns,但可以在不同的网络ns之间转移设备)。
不同ns网络如何相互通信呢?
使用Veth设备对,利用成对的Veth设备对能直接将两个网络ns连接起来。
# 创建Veth设备对
ip link add veth0 type veth peer name veth1
# 查看Veth设备对信息
ip link show
# 将veth1转移到netns1中
ip link set veth1 netns netns1
# 分配ip地址
ip netns exec netns1 ip addr add 10.1.1.1/24 dev veth1
# 启动
ip netns exec netns1 ip link set dev veth1 up
怎么查看对端的veth设备?
使用ethtool工具。
# Step1:查询对端接口在设备列表中的序列号
ip netns exec netns1 ethtool -S veth1
# Step2:通过grep查看特定序列号代表的设备
ip netns exec netns2 ip link | grep 5
Docker网络实现
docker支持几种网络模式?
四种。host;container;none;bridge(默认)
docker bridge模式如何支持网络的?
- Docker Deamon启动时会创建一个虚拟网桥(docker0),并给网桥分配一个子网。
- 每个docker容器,都创建一个虚拟以太网设备(Veth设备对),一端连接docker0,一端连接使用namespace容器内的eth0设备,然后从网桥地址段给eth0接口分配一个IP地址。
docker网络模型的局限是什么?
Docker没有考虑多主机互联的网络方案。在同一台机器内的容器之间可以互相通信,不同主机间的容器不能互相通信,甚至有可能因为在不同主机上的docker0地址段相同而导致不同主机的容器在相同的地址范围内。
可以协调好端口分配或使用动态端口分配技术来解决这个问题。
K8S网络模型
K8S网络要解决的问题
- 容器与容器的通信
- Pod到Pod的通信
- Pod与Service的通信
- 集群外部与内部组件的通信
K8S设计的基础原则
每个Pod都有一个独立的IP地址;所有Pod都在一个可以直连、扁平的网络空间中;Pod要求可以直接通过对方ip进行访问。
IP-per-Pod模型:IP以Pod为单位进行分配。一个Pod内部的所有容器共享一个网络堆栈。
K8S对集群网络的要求
1) 所有容器都可以在不用NAT的方式下同别的容器通信。
2)所有节点都可以在不用NAT的方式下同所有容器通信,反之亦然。
3)容器的地址和别人看到的地址是同一个地址。
K8S内容器到容器的通信是怎么做的?
同一个Pod内的容器共享同一个netns,所以各类网络操作可以直接操作,就像在同一台机器上。
K8S内Pod是怎么通信的?
分为两种情况,在同一个node上Pod的通信和不同node上的pod进行通信。
- 对于同一个node上的Pod,他们都通过Veth连接到同一个docker0网桥上,IP地址都是从docker0的网段上动态获取的,他们和网桥本身在同一个网段上,因此可以直接通信。
- 对于不同node上的Pod,只能通过宿主机的网卡进行。于是需要满足两个条件:
- 在整个K8S集群中对Pod进行IP分配,不能有冲突——Flannel管理资源分配
2)将Pod的IP与Node的IP关联起来
K8S中Pod的IP数据流的目标是哪里?
使用pause容器,将Pod里面的所有容器都连接到pause容器上,所有应用容器的端口映射都到pause容器上。
K8S中Service与Pod怎么通信?
使用kube-proxy服务。Service在多个pod之间抽象一些服务,而且可以在同一个service创建的pod中做负载均衡。kube-proxy 为每个新创建的服务都关联一个随机端口号,并创建负载均衡对象,直接和负载均衡到的Pod进行网络交互。
CNI网络模型
CNI网络模型是什么?
一种容器网络规范。包括容器和网络两种概念。
对容器网络的设置都通过插件来实现。CNI插件包括两种类型:CNI Plugin和IPAM。
CNI Plugin负责为容器配置网络资源,IPAM负责对容器IP地址进行分配管理。
CNI Plugin提供哪些操作?
ADD, DELETE, CHECK, VERSION
K8S存储模型
为什么K8S需要网络共享存储?
在docker容器中,为了实现数据的持久性存储,在宿主机和容器内做映射,可以保证在容器的生命周期结束,数据依旧可以实现持久性存储。
在k8s中,对于在同一节点的pod,可以使用本地数据卷来进行持久化存储。有三种方式:
1)emptyDir:Pod挂载在本地的磁盘或者内存,被称为emptyDir,称为临时空目录,随着Pod删除,也会被删除。适用于pod中容器之间的数据共享。
- gitrepo目录:只是emptydir上补添一个git命令来拉取文件而已。当pod创建时候,会拉取git(依赖于宿主机git命令驱动)仓库中数据克隆到本地,并且作为存储卷定义在pod之上。gitrepo基于emptyDir,此存储卷是emptyDir,git仓库中拉取的代码存放在emptyDir后被定义到pod。
- hostPath类型:映射node文件系统中的文件或者目录到pod里。可实现针对某一节点的数据持久化,如果节点宕机了,那数据就丢失了。应用于Pod中容器需要访问宿主机时。
对于分布在不同节点的pod,并不能实现不同节点之间持久性数据的共享,并且,在节点故障时,可能会导致数据的永久性丢失。为此,k8s就引入了外部存储卷的功能,通常是PVC和PV组合使用。
PV是对底层网络共享存储的抽象,将共享存储定义为一种“资源”。而PVC是用户对存储资源的一个“申请”,用户在创建应用时定义好需要的PVC,PVC会去找K8S当前可用的PV,进行绑定。使用完后进行清理和释放。
PV是怎样定义的?有什么关键参数?
- Storage:存储能力
- accessMode:访问模式,分为RWO(读写,被单个Node挂载)、ROX(只读,被多个Node挂载)、RWX(读写,被多个Node挂载)三种,不同存储提供商有不同的访问模式。
- storageClass:存储类别,当定义StorageClass的时候可以用做动态绑定。
- ReclaimPolicy:回收策略,有保留、回收空间和删除三种。
PV的生命周期?
四种。
- Available:可用,未与PVC绑定
- Bound:与PVC绑定
- Released:绑定的PVC已删除,资源释放但还没有回收
- Failed:自动资源回收失败
PVC和PV的生命周期是什么?
- 资源供应:静态和动态两种方式来创建PV。
- 资源绑定:系统根据PVC对存储资源的请求,在已存在的PV中选择一个绑定,如果没有PVC会一直pending,直到有符合要求的PV。
- 资源使用:Pod根据volume定义,将PVC挂载到容器内某个路径进行使用。
- 资源释放:用户删除PVC,与PVC绑定的PV会被标记为“已释放”。
- 资源回收:如何处理遗留数据。
K8S中PV的创建有哪些方式?
两种。静态和动态模式。
- 静态模式:管理员手工创建PV,定义他的属性。
缺点:当PVC申请的资源比PV的资源少时,整个PV空间都会被该PVC占据,造成资源浪费。 - 动态模式:管理员定义StorageClass,描述后端存储,标记为某种类型,比如Fast, Standard, Slow。
优势:通过声明StorageClass和PVC完成资源绑定。系统在为PVC找到合适的StorageClass后,将自动创建一个PV并完成与PVC的绑定,没有资源浪费。
Pod与PV与PVC的关系?
一个PV只能被一个PVC使用,一个PVC可被多个Pod使用。
网友评论