《Kubernetes权威指南》读书笔记

概述

kubernetes是基于容器技术的分布式架构方案,是一个完备的分布式系统支撑平台,是一个容器编排引擎。

kubenrnetes的优点:

  • 方便开发复杂系统,可以把更多精力放在业务开发上。
  • 全面拥抱微服务架构。
  • 随时随地可以把系统整体搬迁到公有云。
  • 弹性扩容机制可以让我应对突发流量,在公有云上接借用务,减少公司硬件投入。
  • 横向扩容能力很强,添加Node就可以。

资源对象

我认为所谓资源对象就是用户可以通过yaml文件进行部署的对象,Kubernetes中的资源对象有:Pod、Service、Deployment、Job、RC、HorizontalPodAutoscaler(HPA)、Role、Ingress、EndPoint等

Pod

简述

Pod是kubernetes最小的调度单元。每一个Pod都有一个被称为根容器的pause容器和其他的业务容器。结构如下图所示:
在这里插入图片描述

为什么Kubernetes需要设计出Pod这种全新的模型?

  • 在一组容器都作为一个单元的情况下,我们难以对整体简单地进行判断及有效地控制。
  • Pod里多个业务容器共享Pause容器地IP,共享Pause容器挂载地Volume,简化了密切关联地业务容器之间地通信和文件共享问题。

Pod可以分为:

  • 静态Pod
    不存放到etcd中,而是存放在某个具体的Node上的一个具体的文件中,并且只在这个Node上运行。master不能删除它,只能由它所处的Node上手动删除。
  • 普通Pod
    放在etcd中,会被Master调度到某个Node上进行绑定,随后会被Kubelet进程实例化一组相关的Docker容器并启动。

Pod、容器和主机节点的关系如下图所示:
在这里插入图片描述

配置管理

Kubernetes提供了一种统一的集群配置管理方案——ConfigMap。ConfigMap以键值对的形式保存在kubernetes系统中,既可以用于表示一个变量的值,也可以用于表示一个完整配置文件的内容。

ConfigMap供容器使用的典型用法:

  1. 生成为容器内的环境变量。
    实际上就是在ConfigMap保存配置信息,在容器的yaml中指定ConfigMap,容器启动后就能获取其配置内容。
  2. 设置容器启动命令的启动参数。
  3. 以Volume的形式挂载为容器内部的文件或目录。
    就是在ConfigMap保存一个完整的文件,容器的yaml中指定ConfigMap及其存放路径,容器启动后就能在指定路径下获取整个文件。

可以通过YAML配置文件或者直接使用kubectl create configmap命令行的方式来创建。

ConfigMap的限制条件:

  • 必须在Pod之前创建。
  • 可以定义为属于某个Namespace,只有处于相同Namespace中的Pod可以引用它。
  • kubelet只支持可以被API Server管理的Pod使用ConfigMap,静态Pod不能用。
  • 对ConfigMap进行挂载的时候,容器内部只能挂载为目录,不能为文件。

容器内获取Pod信息

如何在容器内部获取外部的Pod信息,是通过Downward API实现的。它通过两种方式将Pod信息注入容器内部。

  • 环境变量,用于单个变量。
  • Volume挂载,将数组类信息生成文件挂载到容器内部。

Downward API的应用场景:
在某个集群中,需要实现一个服务注册的功能,也就是每个容器的所承载的服务需要被其他调用者发现,所以,可以在容器内部写一个预先启动脚本,通过Downward API获取容器的自身名称和IP,然后将这些信息写到注册中心去。

生命周期和重启策略

Pod的状态分为以下几种:

  • Pending
    已经创建了Pod,但是其内部还有容器没有创建。
  • Running
    Pod内部的所有容器都已经创建,只有由一个容器还处于运行状态或者重启状态。
  • Succeeed
    Pod内所有容器均已经成功执行并且退出,不会再重启。
  • Failed
    Pod内所有容器都退出,但至少有一个为退出失败状态。
  • Unknown
    由于某种原因不能获取该Pod的状态,可能是网络问题。

Pod的重启策略包括:

  • Always:当容器失效,kubelet自动重启该容器。
  • OnFailure:当容器终止运行且退出码不为0,由kubelet自动重启。
  • Never:不论容器的状态如何,kubelet都不会重启该容器。

触发重启间隔:
kubelet自动重启失效容器的时间间隔以sync-frequency乘以2n来计算,例如1、2、4、8,最长延时5分钟,在成功重启容器的10分钟后重置该事件。

每种控制器对Pod的重启策略要求如下:

  • RC和DaemonSet:必须设置为Always,需要保证这俩玩意持续运行。
  • Job:OnFailure或者Never,确保容器执行完成后不再重启。
  • kubelet:在Pod失效时自动重启它。

健康和服务可用性检查

Kubernetes通过两类探针来检查Pod的健康状况,kubelet定期执行这两类探针来诊断容器的健康状态:

  • LivenessProbe:用于判断容器是否处于Running状态,如果不是,kubelet就会杀掉该容器给i,并根据重启策略做相应的处理。如果容器不包含该探针,那么kubelet就会默认返回值都是success。
  • ReadinessProbe:用于判断容器是否启动完成,容器服务是否可用(Ready)。如果该探针检测到失败,则Pod的状态将被修改,将会从服务可用列表中剔除。

在配置Pod的yaml文件中可以添加探针参数,探针具有三种实现方式:

  • ExecAction:在容器内部执行一个命令,该命令返回码为0表示容器健康。
  • TCPSocketAction:通过容器的IP地址和端口号执行TCP检查,如果能够建立TCP连接,则表示容器健康。
  • HTTPGetAction:通过容器的IP地址和端口号以及路径调用HTTP GET方法,如果状态码大于200且小于等于400,表示容器装填健康。

对于使用每种探针,都需要设置两个参数:

  • initialDelaySeconds:启动后进行首次检测的等待时间。
  • timeoutSeconds:检测指令发送后的超时等待时间。

Pod Readiness Gates:
ReadinessProbe可能无法满足一些复杂的服务可用性状态的判断。所以引入Pod Readiness Gates。
通过该机制,用户可以将自定义的ReadinessProbe探测方式设置到Pod上,帮助kubernetes设置Pod何时到达服务可用状态。其流程就是由外部服务器来判断服务的状态,用户提供一个外部服务接口来向kubenetes反馈Pod相应的状态。

调度

在实际的生产环境中,我们很少直接创建一个Pod进行使用,大多数情况下都是通过RC、Deployment、DaemonSet、Job等控制器完成一组Pod的创建、调度以及生命周期的控制。下面对基本的调度方式进行介绍。

1.Deployment 或 RC 全自动调度
Deployment 或 RC可以自动部署容器的多个副本,以及持续监控和维持副本的数量。

2.NodeSelector定向调度
首先在节点上打上标签,在yaml中的NodeSelector属性中添加目标节点的标签,Pod只能被调用到具有标签的Node上。

3.Node亲和性调度
用于替换NodeSelector,目前有两种亲和性表达:

  • 必须满足指定规则才能调度Pod到指定Node上,和NodeSelector很像。
  • 强调优先满足指定规则,调度器才会尝试将Pod调度到优先满足的Node,并不强求。

4.Pod亲和与互斥调度
让用户从另一个角度控制了Pod可以运行的节点。也是通过标签进行设置。

5.污点和容忍
污点和容忍需要配合使用。在节点上设置污点标签,除非Pod配置了相应的容忍,否则Pod可能无法被调度到有污点的节点上。
污点也有软限制和硬限制,如果是硬限制,那么Pod无法被部署到这个污点节点。

常见用例:

  • 独占节点:通过强制污点的设置,给一些应用打上容忍,这样可以让这些应用独占这批节点。
  • 具有特殊硬件设备的节点。
  • 定义Pod驱逐行为,以应对节点故障。没有设置容忍的Pod会被驱逐,只是了容忍时间的节点会在指定时间后被驱逐。

6.Pod优先级调度
为了提高Node资源的利用率,让所有负载的总量大于集群可以提供的资源,这样在资源不足的时候,可以剔除优先级低的服务。

7.在每个Node上都调度一个Pod
也就是DaemonSet,这种用法的需求有:在每个Node上都运行一个存储进程、日志采集程序或者性能监控程序。

8.批处理调度
通过Job资源对象来定义并启动一个批处理任务,主有有几种模式:

  • 一个Job对象对应一个待处理任务。
  • Job启动固定个Pod,然后去消费一个任务队列。
  • Job动态启动数量不固定的Pod去消费任务队列。
  • 静态方式分配任务,而不是队列模式。

Job可以分为三种:

  • Job只启动一个Pod串行执行,只有Pod异常,才会重新启动Pod,Pod执行结束,Job就结束。
  • Job启动多个Pod并行执行,正常结束的Pod满足一定个数,Job才结束。
  • Job启动多个Pod并行执行,只要有一个正常结束,Job就结束。

9.定时任务:
新型Job,Cron Job。顾名思义,就是执行一段时间就结束的Job。

10.自定义调度器
需要自己边界调度器脚本。

升级和回滚

升级

当集群中的服务需要升级,我们就需要停止服务的所有Pod,并下载替换新的Pod,如果集群规模很大,我们就需要通过滚动升级的方式来保持服务性能和可用性。

所谓滚动升级,就是不会将所有Pod一次性全给升级了,而是每次升级一部分,其他部分还是可以正常提供服务的,至少还是有可用的Pod存在。

在yaml中的spec.strategy中可以指定Pod的升级策略,滚动升级还可配置具体的每次同时升级的比例。也可以不采用滚动升级。

回滚

我们可以将Pod回滚到从前的旧版本。

扩缩容

在实际生产中,我们会遇到因为资源紧张需要缩容,业务增多需要扩容的情况。可用通过Deployment的Scale机制来完成这些工作。

扩容操作提供了手动和自动的两种方式:

  • 手动模式:可以通过kubectl scale命令或RESTful 接口对Deployment进行Pod数量进行设置。
  • 自动模式:需要用户根据性能指标或者自定义业务指标,并指定Pod的数量范围,系统自动在这个范围内更具性能指标的变化进行调整容量。

HPA控制器:
用于实现基于CPU使用率等性能指标进行自动扩缩容的功能。其工作原理就是通过kubernetes中某个Metrics Server持续采集Pod的性能指标数据,然后反馈给HPA,HPA根据当前的副本和目标副本的偏移,调整Pod的数量。

在这里插入图片描述

HorizontalPodAutoscaler:
意思是Pod横向自动扩容,通过分析RC控制的所有Pod的负载变化情况,确定是否需要调整Pod的数量。
kubernetes通过HorizontalPodAutoscaler资源对象提供给用户来定义扩缩容的规则。现在有v1和v2两个版本,v1仅支持基于CPU使用率的自动扩容,v2支持任意指标的自动扩容。


Service

是Kubernetes核心的资源对象,每个Service其实就是微服务架构中的微服务。Service可以为一组具有相同功能的容器应用提供一个统一的入口地址,并将请求进行负载分后到后端的各个容器应用上,Service与后端的Pod副本集群式通过Label Selector进行匹配对接的。

Pod、RC与Service的逻辑关系如图所示。

在这里插入图片描述

其实我们可以直接通过IP和端口访问Pod,但是如果Pod崩了重启之后,IP可能会发生改变,而通过Service来访问Pod就能避免这个问题。

Endpoints

当我们在Service中添加标签选择器时,系统会给Service自动创建一个和这个Service同名的Endpoints资源对象,用于标识访问Service时获取的Pod位置。

如果我们内部需要访问外部的服务,可以创建一个不带标签选择器的Service,然后手动床创建一个和Service同名的Endpoints,用于指向实际的外部后端访问地址。

在这里插入图片描述

均衡负载

Service可以通过变迁选择器匹配多个后端Pod,然后通过均衡负载机制来将请求转发到不同的Pod上。

Kubernetes提供了两种负载分发策略:

  • RoundRobin:轮询模式,轮询将请求转发到各个Pod上。
  • SessionAffinity:基于客户端IP地址进行会话保持的模式,即第1次将某个客户端发起的请求转发到了某个Pod,那么之后相同的客户端发送的请求都会被发到这个Pod上。

Headless Service
当我们想要自定义的负载均衡策略,那么就可以通过这个方式实现,即Service设置ClusterIP属性为None,然后只通过标签选择器将后端的Pod列表返回给调用的客户端,然后客户端就可以自行决定Pod的访问。

外部访问Service或Pod

Pod和Service都是kubernetes集群内部的虚拟概念,所以集群外的客户端无法通过虚拟IP访问Service或者Pod,下面介绍几种访问方式。

1.将容器应用的端口映射到物理机。

这里又分为两中情况:

  • 通过设置容器级别的hostPort属性,将容器应用的端口号映射到物理机上。
  • 通过设置Pod级别的hostNetwork=true,该Pod所有的容器端口都将被直接映射到物理机上。

2.将Service的端口号映射到物理机。

  • 通过nodePort映射到物理机,同时设置Service的类型为NodePort。
  • 通过设置LoadBalancer映射到云服务商提供的LoadBalancer地址。

DNS

作为服务发现机制的基本功能,在集群内需要通过服务吗对服务进行访问,就需要一个集群范围内的DNS服务器来完成从服务名到ClusterIP的解析。

从Kubernetes1.11开始,集群的DNS服务由CoreDNS提供。高性能、插件式、易扩展。

CoreDNS总体架构如图所示。
在这里插入图片描述

Ingress

是kubernetes的一种资源对象,用于将不同的URL的访问请求转发到后端不同的Service,实现HTTP层的业务路由机制。Kubernetes使用了一个Ingress策略定义和一个绝体的Ingress Controller,两者结合并实现了一个完整的Ingress负载均衡器。

Ingress的工作原理如下图所示,感觉就像是做了一个RequestMapping,检测不同的路径,然后转发到不同的后端上。
在这里插入图片描述

Ingress的策略配置:

  • 转发到单个后端服务上。
  • 同一域名下,不同URL路径被转发到不同的服务上。
  • 不同域名被转发到不同的服务上。
  • 不适用域名的转发规则。就是直接用IP端口。

Ingress的TLS安全设置

为了Ingress提供HTTPS的安全访问,可以给Ingress中的域名进行TLS安全证书设置。步骤如下:

  1. 创建自签名的密钥和SSL证书文件;
  2. 将证书保存到Kubernetes的一个Secret资源对象上;
  3. 将该Secret对象设置到Ingress中。

核心组件

Kubernetes结构如下图所示。
在这里插入图片描述

API Server

Kubernetes API Server的核心功能是提供Kubernetes各类资源对象的增删改查以及HTTP Rest接口,成为集群内各个模块的数据交互和通信的中心,是整个系统的数据总线和数据中心。功能如下:

  • 集群管理的API入口。
  • 资源配额控制的入口。
  • 提供了完备的集群安全机制。

Kubernetes API Server通过一个名为kube-apiserver的进程提供服务,该进程运行在Master节点上。该进程默认在本机端口的8080提供REST服务。同时可以启动HTTPS安全端口6443来启动安全机制。
通过命令行工具kubectl来与Kubernetes API Server交互的时候,也是通过REST调用。

API Server是决定Kubernetes集群整体性能的关键因素,设计者通过以下方式来保证其性能:

  • API Server拥有大量高效的底层代码,使用协程+队列的轻量级高性能并发代码。
  • 不同List接口结合异步Watch接口,不断解决了集群中各种资源对象性能同步问题,也提升了集群实时响应各种请求的灵敏度。
  • 采用高性能的etcd数据库而非传统的关系型数据库,解决了数据的可靠性问题和数据访问层的性能。

API Server的架构

  1. API层:主要以REST方式提供各种API接口。
  2. 访问控制层:当客户端访问API接口时,该层负责对用户进行鉴权。
  3. 注册表层:Kubernetes把所有的资源对象都保存到了注册表中,针对注册表中的各种资源都定义了:资源对象的类型、如何创建资源对象、如何转换资源对象的不同版本。
  4. etcd数据库:用于持久化存储kubernetes资源对象的KV数据库。

Controller Manager

Controller Manager作为集群内部的自动化管理控制中心,负责集群内的Node、Pod副本、EndPoint、Namespace、服务账号、资源定额等管理,当某个Node宕机了,Controller Manager会及时发现故障并自动化修复,确保集群始终处于预期的工作状态。

Controller Manager内部包含了很多子控制器,每个控制器负责Controller Manager一部分的功能,例如节点控制、Pod副本数量控制之类的。

Scheduler

Scheduler在整个系统中承担了承上启下的重要功能,承上是指负责接收Controller Manager创建新的Pod,部署到合适的Node,启下是指部署工作完成之后,目标Node上的Kubelet服务进程接管后继工作,负责Pod生命周期。

Scheduler当前提供的默认调度流程分为以下两步:

  1. 预选调度过程,即遍历所有目标Node,筛选出符合要求的Node。
  2. 确定最优的节点。

Scheduler具有多种预选策略包括:

  • NoDiskConflict
  • PodFitsResources
  • PodSelectorMatches
  • podFitsHost
  • CheckNodeLabelPresence
  • CheckSerciceAffinity
  • PodFitsPorts

Scheduler中的优选策略包括:

  • LeastRequestedPriority
  • CalculateNodeLabelPriority
  • BalancedResourceAllocation

kubelet

集群中每个Node都会启动一个kubelet服务进程,该进程用于处理Master下发到本节点的任务,管理Pod以及Pod中的容器。每个kubelet都会在APIServer中注册节点自身的信息,定期向Master汇报节点资源和使用情况。

上面提到的探针也是可以由kubelet调用,用户获取容器的健康状况。

kubelet通过cAdvisor来获取其所在节点及容器的数据。cAdvisor自动查找节点上所有容器的性能数据,并在Node上的4194暴露一个简单的UI界面。

kube-proxy

集群中每个Node上都会运行一个kube-proxy服务进程,他是Service的透明代理兼均衡负载器,其核心功能是将某个Service的访问转发到后端的多个Pod上。

在这里插入图片描述
从kubernetes1.8开始,词用了IPVS(IP Virtual Server)模式,用于路由规则的配置。相比iptables,IPVS具有如下优势:

  • 为大型集群提供了更好的扩展性和性能。采用哈希表的数据结构,更高效。
  • 支持更复杂的负载均衡算法。
  • 支持服务器健康检查和连接重试。
  • 可以动态修改ipset的集合。

安全

Kubernetes通过一系列的机制来实现集群的安全控制,其中包括API Server的认证授权、准入控制机制及保护敏感信息的Secret机制。集群的安全性目标有:

  • 保证容器与其所在宿主机的隔离。
  • 限制容器给基础设施或其它容器带来干扰。
  • 最小权限原则,每个组件只执行它的授权行为。
  • 明确组件边界划分。
  • 划分普通用户和管理员角色。在必要的时候将管理员权限给普通用户。
  • 允许拥有Secret的应用在集群中允许。

API Server认证

Kubernetes中所有资源访问和修改都是通过API Server的REST接口来实现的,所以,集群安全的关键在于如何识别认证客户端的身份,以及随后访问的权限的授权。

集群提供了三种级别的客户端认证方式:

  • 最严格的HTTPS证书认证
    基于CA根证书签名的双向数字证书认证方式。其实就是HTTPS中SSL协议认证和数据加密的过程。不同的是,这里是双向的,也就是客户端也要有自己的证书,让服务端来验证客户端的身份。
  • HTTP Token认证
    通过一个Token来是被合法用户,就是用一个很长的特殊编码方式并且很难被模仿的字符串Token来表明客户端的身份。默认采用的就是这个方式。
  • HTTP Base认证
    通过用户名+密码的方式。

API Server授权

在用户认证之后,需要对用户执行一个授权流程,通过一个授权策略来决定一个API调用是否合法。目前支持一下几种授权策略:

  • AlwaysDeny:拒绝所有请求,一般用于测试。
  • AlwaysAllow:接收所有请求,Kubernetes默认配置。
  • ABAC:(Attribute Based Access Control):基于属性的访问控制,表示使用用户配置的授权规则对用户请求匹配和控制。
  • Webhook:通过调用外部REST服务对用户进行授权,将授权职责交给外部服务器。
  • RBAC(Role Based Access Control):基于角色的访问控制。这个比较复杂,通过Role资源对象创建出角色以及该角色的权限,然后通过RoleBinding资源对象将用户名和Role进程绑定,这样就能让指定的用户具有角色以及对应的权限。
  • Node:是一种专用模式,用于对kubelet发出的请求进行访问控制。

Admission Control

在完成授权之后,客户端的调用请求还需要准入控制的一个准入控制链的层层把关,才能获得成功的响应。

准入控制配备了一个准入控制器的插件列表,里面有三十多个插件,对请求一层层地检测,对请求的合法性等等进程控制,用户也可以自定义控制规则,然后写入插件列表。

Service Account

这是一种账号,是给运行在Pod中的进程使用的,用于给进程提供身份证明。当Pod内部需要访问API Server的时候,就需要用到这个账号进行认证。

其原理是利用一种类似于HTTP Token的方式——Service Account Auth。

Kubernets之所以要创建两套独立的账号系统:

  • User账号是给人用的,Service Account是给Pod里的进程使用的,面向对象不同。
  • User账号是全局的,Service Account属于某个Namespace。
  • User账号是与后端的数据库同步的,使用比较复杂,而Service Account的使用是轻量级的。
  • Service Account具有隔离性。

Secret

Secret是Kubernetes的一种资源对象,用于保管私密数据,比如密码、Token等,同时,将数据放在Secret里面,比直接发放在Pod或者Docker Image种更安全,也便于使用和分发。

Secret创建以后有三种方式使用:

  • 在创建Pod时,通过Pod指定ServiceAccount来自动使用Secret。
  • 通过挂载该Secret到Pod来使用。
  • 在Docker镜像下载时使用,通过指定Pod的spc.ImagePullSecrets来引用。

PodSecurityPolicy

为了精确控制Pod对资源的使用方式,可以通过PodSecurityPolicy资源对象进行Pod安全策略管理。

PodSecurityPolicy对象种可以设置各种字段来控制Pod的运行策略,例如是否允许Pod共享主机进程空间,是否允许使用卷的类型,是否允许共享主机的路径之类的。

在设置了PodSecurityPolicy策略之后,系统将对Pod和Container级别的安全设置进行校验,不满足PodSecurityPolicy安全策略的就会拒绝创建。

Pod级别可以设置的安全策略如下:

  • runAsUser:容器内运行程序的用户ID。
  • runAsGroup:容器内运行程序的用户组ID。
  • runAsNonRoot:是否必须以非root用户运行程序。
  • fsGroup:SELinux相关设置。
  • seLinuxOptions:SELinux相关设置。
  • SupplementalGroups:允许容器使用启它用户组ID。
  • sysctls:允许调整内核参数。

Container级别也差不多。

网络

网络模型

Kubernetes网络模型设计的基础原则是:每个Pod都拥有一个独立的IP地址,并假定所有Pod都在一个可以直接连通的、扁平的网络空间中。按照这个原则抽象出来的模型被称为IP-per-Pod模型。

Docker原生的通过动态端口映射方式实现的多节点访问模式的问题:

  • Docker原生网络的动态端口映射会引入端口管理的复杂性。
  • 访问者看到的IP地址和端口与服务提供者实际绑定的不同(因为NAT的缘故)。
  • 导致标准的DNS名字解析服务也不适用,服务注册和发现机制也复杂了,因为Pod自身很难知道自己对外暴露的IP。

Kubernetes对集群网络有如下要求:

  • 所有容器都可以在不用NAT的方式下同别的容器通信。
  • 所有节点都可以在不用NAT的方式下同所有容器通信。
  • 容器的地址和外部看到的是一致的。

网络实现

Kubernets网络主要解决以下问题:

  • 容器到容器之间的直接通信。
    也就是Pod内部的通信,直接访问localhost的端口就能实现。
  • Pod到Pod的直接通信。
    同一个Node中的Pod之间通过Docker bridge就可以通信,不同Node中的Pod需要通过Docker bridge和路由管理插件,例如Flannel。
  • Pod到Service之间的通信。
  • 集群外部与内部组件的通信。

CNI

CNI是一种容器网络规范,定义了荣光其允许环境与网络插件之间的简单接口规范,通过一个JSON Schema定义CNI插件提供的输入和输出参数,一个容器可以通过绑定多个网络插件加入多个网络中。

CNI提供了一种应用容器的插件化网络解决方案,定义对容器网络进行操作和配置的规范,通过插件的形式对CNI接口直接进行实现。

CNI插件包括两种:

  • CNI Plugin
    负责容器配置网络资源。
  • IPAM Plugin
    负责对容器的IP地址进行管理和分配。

Kubernets支持两种网络插件:

  • CNI插件:根据CNI规范实现其接口,以与插件提供者直接对接。
  • kubenet插件:使用bridge和host-local CNI插件实现一个基本cbr0。

目前已有多个开源支持CNI网络插件:Calico、Canal、Flannel、Weave Net等。

网络策略

为了使用Network Policy,Kubernetes引入了一个新的资源对象NetworkPolicy,用于设置Pod间网络访问策略。然后还需要通过第三方插件提供的策略控制器进行策略的实现。

NetworkPolicy可以定义Pod的作用范围、网络策略类型、允许访问的白名单之类的。

存储

Kubernetes通过PV和PVC两个资源对象实现对存储的管理子系统。

PV

PersistentVolume是对底层网络共享存储的抽象,将共享存储定义为一种资源,主要包括:

  • 存储能力:目前只支持存储空间容量的设置。
  • 存储卷模式:就是支持的文件系统和块硬件设备。
  • 访问模式:用于描述用户的应用对资源的访问权限,包括读写权。
  • 存储类型:通过StorageClassName参数指定一个StorageClass资源对象名, 设置存储类别。
  • 回收策略:可以选择保留、回收空间和删除策略。
  • 节点亲和性:可以通过该功能使得只能通过某些Node访问Volume,使用这些卷的Pod将被调度到对应的Node上。

PV的生命周期:

  1. 可用状态,还未与PVC绑定。
  2. 绑定状态。
  3. PVC被删除,资源以及释放,但没与被集群回收。
  4. 自动资源回收失败。

PVC

是用户对存储资源的需求申请,主要包括存储空间请求、访问模式、PV选择条件和存储类别信息的设置。

如果PVC被删除了,那么绑定在上面的PV也可能被删除。

Pod、PVC、PV、存储空间的关系如下:
在这里插入图片描述
Kubernets支持两种资源供应模式:

  • 静态模式:管理员手动创建PV,在定义PV时需要将后端存储的特性进行设置。
  • 动态模式:通过StorageClass的设置对后端存储进行描述,PVC对存储的类型进行声明,系统自动完成PV的创建与PVC的绑定。

StorageClass

是存储资源的抽象定义,对用户设置的PVC申请屏蔽后端存储的细节,一方面减少了用户对于存储资源细节的关注,还减轻了管理员手工管理PV的工作。基于StorageClass的动态资源供应模式将成为云平台的标准存储配置模式。

CSI存储机制

该机制用于在Kubernetes与外部存储系统之间建立一套标准的存储管理接口,通过该接口为容器提供存储服务。

上面提到的,通过PV、PVC和StorageClass的方式以及可以实现很好的基于插件的存储管理机制,但是这些资源对象都是Kubernetes内部的,是紧耦合的开发模式,不利于开发。于是,Kubernetes才推出了CSI接口,使得外部插件能够使用原生存储机制为容器提供存储服务。

CSI中主要包括两类组件:

  • Controller
    提供存储服务视角对存储资源和存储卷进行管理和操作。建议部署为单实例Pod,保证存储插件只运行一个控制器。
  • Node
    对主机(Node)上的Volume进行管理和操作。建议部署为Daemonset,每个Node上都运行一个。
posted @ 2021-01-13 15:26  lippon  阅读(326)  评论(0编辑  收藏  举报