kubernetes theory


目录:

kubernetes(k8s)是管理docker

Kubernetes目前在GitHub进行维护:https://github.com/kubernetes

官网:https://kubernetes.io

Kubernetes文社区:https://www.kubernetes.org.cn/docs

Kubernetes中文指南/云原生应用架构实践手册:

​ https://jimmysong.io/kubernetes-handbook/

博客参考:

​ https://my.oschina.net/adailinux

​ https://www.cnblogs.com/saneri/category/923407.html

​ https://blog.51cto.com/tryingstuff

Kubernetes这个名字源自希腊语,意思是"舵手",也是"管理者","治理者","飞行员"等词的源头。k8s是Kubernetes的简称(用数字『8』替代中间的8个字母『ubernete』)

image-20221115160531069

Kubernetes 是 Google 团队发起并维护的基于 Docker 的开源容器集群管理系统,它不仅支持常见的云平台,而且支持内部数据中心

建于 Docker 之上的 Kubernetes可以构建一个容器的调度服务,其目的是让用户透过 Kubernetes 集群来进行云端容器集群的管理,而无需用户进行复杂的设置工作。系统会自动选取合适的工作节点来执行具体的容器集群调度处理工作。其核心概念是 Container Pod。一个 Pod 由一组工作于同一物理工作节点的容器构成。这些组容器拥有相同的网络命名空间IP以及存储配额,也可以根据实际情况对每一个 Pod进行端口映射

此外,Kubernetes 工作节点会由主系统进行管理,节点包含了能够运行 Docker 容器所用到的服务

项目简介

image-20221115161316974

image-20221115161325157

Kubernetes 是 Google 团队发起的开源项目,它的目标是管理跨多个主机的容器,提供基本的部署,维护以及运用伸缩,主要实现语言为 Go 语言。Kubernetes 是:

A. 易学:轻量级,简单,容易理解

B. 便携:支持公有云,私有云,混合云,以及多种云平台

C. 可拓展:模块化,可插拔,支持钩子,可任意组合

D. 自修复:自动重调度,自动重启,自动复制

特点:自动装箱自我修复水平扩展服务发现服务负载均衡自动发布回滚密钥配置管理存储编排任务批处理执行

Kubernetes 构建于 Google 数十年经验,一大半来源于 Google 生产环境规模的经验。结合了社区最佳的想法和实践。

在分布式系统中,部署,调度,伸缩一直是最为重要的也最为基础的功能。Kubernetes 就是希望解决这一序列问题的。

Kubernetes 能够运行在任何地方!

虽然 Kubernetes 最初是为 GCE 定制的,但是在后续版本中陆续增加了其他云平台的支持,以及本地数据中心的支持

Kubernetes并不是传统的PaaS(平台即服务)系统。

  • Kubernetes不限制支持应用的类型,不限制应用框架。限制受支持的语言runtimes (例如, Java, Python, Ruby),满足12-factor applications 。不区分 "apps" 或者"services"。 Kubernetes支持不同负载应用,包括有状态、无状态、数据处理类型的应用。只要这个应用可以在容器里运行,那么就能很好的运行在Kubernetes上。

  • Kubernetes不提供中间件(如message buses)、数据处理框架(如Spark)、数据库(如Mysql)或者集群存储系统(如Ceph)作为内置服务。但这些应用都可以运行在Kubernetes上面。

  • Kubernetes不部署源码不编译应用。持续集成的 (CI)工作流方面,不同的用户有不同的需求和偏好的区域,因此,我们提供分层的 CI工作流,但并不定义它应该如何工作。

  • Kubernetes允许用户选择自己的日志、监控和报警系统。

  • Kubernetes不提供或授权一个全面的应用程序配置 语言/系统(例如,jsonnet)。

  • Kubernetes不提供任何机器配置、维护、管理或者自修复系统。

另一方面,大量的Paas系统都可以运行在Kubernetes上,比如Openshift、Deis、Gondor。可以构建自己的Paas平台,与自己选择的CI系统集成。

由于Kubernetes运行在应用级别而不是硬件级,因此提供了普通的Paas平台提供的一些通用功能,比如部署,扩展,负载均衡,日志,监控等。这些默认功能是可选的。

另外,Kubernetes不仅仅是一个"编排系统";它消除了编排的需要。"编排"的定义是指执行一个预定的工作流:先执行A,之B,然C。相反,Kubernetes由一组独立的可组合控制进程组成。怎么样从A到C并不重要,达到目的就好。当然集中控制也是必不可少,方法更像排舞的过程。这使得系统更加易用、强大、弹性和可扩展

CI/CD (持续集成,持续交付,持续部署)

Interg delivery deployment

Continuous Integration and Continuous Deployment (CI/CD)

Drive secure automation and deployment at massive scale

快速上手

目前,Kubernetes 支持在多种环境下的安装,包括本地主机(Fedora、centos等)、云服务(Google GAE、AWS 、阿里云等)。然而最快速体验 Kubernetes 的方式显然是本地通过 Docker 的方式来启动相关进程

下图展示了在单节点使用 Docker 快速部署一套 Kubernetes 的拓扑。

image-20221115161649643

在 Docker 中启动 Kubernetes

Kubernetes 依赖 etcd 服务来维护所有主节点的状态。

基本概念

image-20221115161718166

  • 节点(Node):一个节点是一个运行 Kubernetes 中的主机

  • 容器组(Pod):一个 Pod 对应于由若干容器组成的一个容器组,同个组内的容器共享一个存储卷(volume)

  • 容器组生命周期(pos-states):包含所有容器状态集合,包括容器组状态类型,容器组生命周期,事件,重启策略,以及 replication controllers

  • Replication Controllers:主要负责指定数量的 pod 在同一时间一起运行

  • 服务(services):一个 Kubernetes 服务是容器组逻辑的高级抽象,同时也对外提供访问容器组的策略

  • 卷(volumes):一个卷就是一个目录,容器对其有访问权限

  • 标签(labels):标签是用来连接一组对象的,比如容器组。标签可以被用来组织和选择子对象

  • 接口权限(accessing_the_api):端口,IP 地址和代理的防火墙规则

  • web 界面(ux):用户可以通过 web 界面操作 Kubernetes

  • 命令行操作(cli):kubectl命令

节点

在 Kubernetes 中,节点是实际工作的点,节点可以是虚拟机或者物理机器,依赖于一个集群环境。每个节点都有一些必要的服务以运行容器组,并且它们都可以通过主节点来管理。必要服务包括 Docker,kubelet 和kube-proxy

容器状态

容器状态用来描述节点的当前状态。现在,其中包含三个信息:

主机IP
kubectl get nodes -o wide | awk '{print $6}'

主机 IP 需要云平台来查询,Kubernetes 把它作为状态的一部分来保存。如果 Kubernetes 没有运行在云平台上,节点 ID 就是必需的。IP 地址可以变化,并且可以包含多种类型的 IP 地址,如公共 IP,私有 IP,动态 IP,ipv6 等等

节点周期

通常来说节点有 Pending,Running,Terminated 三个周期,如果 Kubernetes 发现了一个节点并且其可用,那么 Kubernetes 就把它标记为 Pending。然后在某个时刻,Kubernetes 将会标记其为 Running。节点的结束周期称为 Terminated。一个已经 Terminated 的节点不会接受和调度任何请求,并且已经在其上运行的容器组也会删除。

节点状态

节点的状态主要是用来描述处于 Running 的节点。当前可用的有NodeReachable 和 NodeReady。以后可能会增加其他状态。NodeReachable 表示集群可达。NodeReady 表示 kubelet 返回 Status Ok 并且 HTTP 状态检查健康。

节点管理

节点并非 Kubernetes 创建,而是由云平台创建,或者就是物理机器、虚拟机。在 Kubernetes 中,节点仅仅是一条记录,节点创建之后,Kubernetes 会检查其是否可用。在 Kubernetes 中,节点用如下结构保存:

{
  "id": "10.1.2.3",
  "kind": "Minion",
  "apiVersion": "v1beta1",
  "resources": {
    "capacity": {
      "cpu": 1000,
      "memory": 1073741824
    },
  },
  "labels": {
    "name": "my-first-k8s-node",
  },
}

Kubernetes 校验节点可用依赖于 ID。在当前的版本中,有两个接口可以用来管理节点:节点控制和 Kube 管理。

节点控制

在 Kubernetes 主节点中,节点控制器是用来管理节点的组件。主要包含:

  • 集群范围内节点同步

  • 单节点生命周期管理

节点控制有一个同步轮寻,主要监听所有云平台的虚拟实例,会根据节点状态创建和删除。可以通过--node_sync_period标志来控制该轮寻。如果一个实例已经创建,节点控制将会为其创建一个结构。同样的,如果一个节点被删除,节点控制也会删除该结构。在 Kubernetes 启动时可用通过 --machines标记来显示指定节点。同样可以使用 kubectl 来一条一条的添加节点,两者是相同的。通过设置 --sync_nodes=false标记来禁止集群之间的节点同步,你也可以使用 api/kubectl 命令行来增删节点。

容器组

在 Kubernetes 中,使用的最小单位是容器组,容器组是创建,调度,管理的最小单位。 一个容器组使用相同的 Docker 容器并共享卷(挂载点)。一个容器组是一个特定应用的打包集合,包含一个或多个容器。

和运行的容器类似,一个容器组被认为只有很短的运行周期。容器组被调度到一组节点运行,直到容器的生命周期结束或者其被删除。如果节点死掉,运行在其上的容器组将会被删除而不是重新调度。(也许在将来的版本中会添加容器组的移动)。

容器组设计的初衷

资源共享和通信

容器组主要是为了数据共享和它们之间的通信。

在一个容器组中,容器都使用相同的网络地址和端口,可以通过本地网络来相互通信。每个容器组都有独立的 IP,可用通过网络来和其他物理主机或者容器通信

容器组有一组存储卷(挂载点),主要是为了让容器在重启之后可以不丢失数据。

容器组管理

容器组是一个运用管理和部署的高层次抽象,同时也是一组容器的接口。容器组是部署、水平放缩的最小单位。

容器组的使用

容器组可以通过组合来构建复杂的运用,其本来的意义包含:

  • 内容管理,文件和数据加载以及本地缓存管理等。

  • 日志和检查点备份,压缩,快照等。

  • 监听数据变化,跟踪日志,日志和监控代理,消息发布等。

  • 代理,网桥

  • 控制器,管理,配置以及更新

替代方案

为什么不在一个单一的容器里运行多个程序?

  • 1.透明化。为了使容器组中的容器保持一致的基础设施和服务,比如进程管理和资源监控。这样设计是为了用户的便利性。

  • 2.解偶软件之间的依赖。每个容器都可能重新构建和发布,Kubernetes 必须支持热发布和热更新(将来)。

  • 3.方便使用。用户不必运行独立的程序管理,也不用担心每个运用程序的退出状态。

  • 4.高效。考虑到基础设施有更多的职责,容器必须要轻量化。

容器组的生命状态

包括若干状态值:pending、running、succeeded、failed。

pending

容器组已经被节点接受,但有一个或多个容器还没有运行起来。这将包含某些节点正在下载镜像的时间,这种情形会依赖于网络情况。

running

容器组已经被调度到节点,并且所有的容器都已经启动。至少有一个容器处于运行状态(或者处于重启状态)。

succeeded

所有的容器都正常退出。

failed

容器组中所有容器都意外中断了。

容器组生命周期

通常来说,如果容器组被创建了就不会自动销毁,除非被某种行为触发,而触发此种情况可能是人为,或者复制控制器所为。唯一例外的是容器组由 succeeded 状态成功退出,或者在一定时间内重试多次依然失败。

如果某个节点死掉或者不能连接,那么节点控制器将会标记其上的容器组的状态为 failed。

举例如下。

容器组状态 running,有 1 容器,容器正常退出
    记录完成事件
    如果重启策略为:
        始终:重启容器,容器组保持 running
        失败时:容器组变为 succeeded
        从不:容器组变为 succeeded
容器组状态 running,有1容器,容器异常退出
    记录失败事件
    如果重启策略为:
        始终:重启容器,容器组保持 running
        失败时:重启容器,容器组保持 running
        从不:容器组变为 failed
容器组状态 running,有2容器,有1容器异常退出
    记录失败事件
    如果重启策略为:
        始终:重启容器,容器组保持 running
        失败时:重启容器,容器组保持 running
        从不:容器组保持 running
            当有2容器退出
        记录失败事件
        如果重启策略为:
            始终:重启容器,容器组保持 running
            失败时:重启容器,容器组保持 running
            从不:容器组变为 failed
容器组状态 running,容器内存不足
    标记容器错误中断
    记录内存不足事件
    如果重启策略为:
        始终:重启容器,容器组保持 running
        失败时:重启容器,容器组保持 running
        从不:记录错误事件,容器组变为 failed
容器组状态 running,一块磁盘死掉
    杀死所有容器
    记录事件
    容器组变为 failed
    如果容器组运行在一个控制器下,容器组将会在其他地方重新创建
容器组状态 running,对应的节点段溢出
    节点控制器等到超时
    节点控制器标记容器组 failed
    如果容器组运行在一个控制器下,容器组将会在其他地方重新创建

架构设计

任何优秀的项目都离不开优秀的架构设计

基本考虑

如果让我们自己从头设计一套容器管理平台,有如下几个方面是很容易想到的:

  1. 分布式架构,保证扩展性

  2. 逻辑集中式的控制平面 + 物理分布式的运行平面;

  3. 一套资源调度系统,管理哪个容器该分配到哪个节点上

  4. 一套对容器内服务进行抽象和 HA 的系统

Kubernetes组件架构图(面试必问):

Master节点

image-20221115164503462

image-20221115165422312

Kubernetes Master提供集群的独特视角,并且拥有一系列组件,比如Kubernetes API Server。API Server提供可以用来和集群交互的REST端点。master节点包括用来创建和复制Pod的Replication Controller。 k8s中的master指的是集群控制节点,每一个k8s集群都需要一个master节点来负责整个集群的管理和控制,k8s的控制命令由它来负责运行,master节点通常布置为HA模式,因为一旦master宕机或者不可用,整个集群的容器应用管理都会失效

  • apiserver 对外暴露 Kubernetes API,所有对集群的操作都是通过这组API完成,包括客户端下达应用编排命令给 Kubernetes 集群;kubelet 上报集群资源使用情况;以及各个组件之间的交互都是通过这套 API 完成的。

  • controller-manager 负责整个 Kubernetes 的管理工作,保证集群中各种资源处于期望状态,当监控到集群中某个资源状态与期望状态不符时,controller-manager 会触发调度操作。

  • scheduler 调度器负责 Kubernetes 集群的具体调度工作,接收来自于controller-manager 触发的调度操作请求,然后根据请求规格、调度约束、整体资源情况进行调度计算,最后将任务发送到目标节点由的kubelet组件执行。

  • etcd 是一个高效KV存储系统。在Kubernetes环境中主要用于存储所有需要持久化的数据。

  • coredns 负责集群内的解析

  • flannel 基础网络组件

  • Docker或Rocket:Kubernetes使用的容器技术来创建容器。

Node节点

image-20221115165742057

节点(上图橘色方框)是物理或者虚拟机器,作为Kubernetes worker,通常称为Minion。每个节点都运行如下Kubernetes关键组件: node节点在k8s集群中是作为工作负载节点,master管理node节点是通过node节点上的kubelet进程向master节点注册自己,然后master节点会将node节点纳管进集群管理范围之内,kubelet进程会定期向master节点汇报自己的情况,以便master节点能够时刻了解各个node节点的状态信息。

node节点上有以下重要进程:

  • Kubelet:是 Node 节点上核心组件。负责与 docker daemon 进行交互运行 docker 容器;配置网络和数据卷;向master节点注册以及报活的作用外,还承担着pod对应容器的创建,启动,停止等任务

  • Kube-proxy:Service使用其将链接路由到Pod,该进程实现kubernetes server的通信和负载均衡机制。主要负责 Service Endpoint 到 POD 实例的请求转发及负载均衡的规则管理

  • Docker或Rocket:Kubernetes使用的容器技术来创建容器。

Master+Node

参考:https://www.cnblogs.com/chanix/p/11731388.html

Master Master上运行的Pod(或开放的Port)包括:

coredns 负责集群内的解析
etcd 服务发现机制(键值对存放).负责保存k8s Cluster的配置信息和各种资源状态信息.数据发生变化时,etcd会快速通知k8s的相关组件.
kube-apiserver 是供CLI或UI等外部组件访问Cluster的API.
kube-controller-manager 例如replication controller负责管理Deployment.
kube-scheduler 决定将Pod放到哪个Node上运行.
kube-proxy 通过proxy代理,将请求转发给对应的后端node的Pod
kube-flannel(Pod network) 可以提供Pod间相互通信的基础.比如flannel.

Node Node上运行的Pod或Deamon/Port包括:

kubelet Node的agent,当Scheduler确定在哪个Node上运行Pod后,将Pod配置信息(image,volume)发给该节点kubelet.kubelet据此创建容器,并向Master报告状态.
kube-proxy service代表了后端的多个Pod,外界通过service访问Pod.service接收到的请求通过kube-proxy转发给Pod.若有多个副本,kube-proxy会实现负载均衡.
kube-flannel(Pod network) 可以提供Pod间相互通信的基础.比如flannel

Kubernetes的架构图

下面这张图完整展示了 Kubernetes 的运行原理

image-20221116172958914

可见,Kubernetes 首先是一套分布式系统,由多个节点组成,节点分为两类:一类是属于管理平面的主节点/控制节点(Master Node);一类是属于运行平面的工作节点(Worker Node)。

显然,复杂的工作肯定都交给控制节点去做了,工作节点负责提供稳定的操作接口和能力抽象即可。

从这张图上,我们没有能发现 Kubernetes 中对于控制平面的分布式实现,但是由于数据后端自身就是一套分布式的数据库 Etcd,因此可以很容易扩展到分布式实现

控制平面

主节点服务

主节点上需要提供如下的管理服务:

  • apiserver是整个系统的对外接口,提供一套 RESTful 的 Kubernetes API,供客户端和其它组件调用

  • scheduler负责对资源进行调度,分配某个 pod 到某个节点上。是 pluggable 的,意味着很容易选择其它实现方式;

  • controller-manager负责管理控制器,包括 endpoint-controller(刷新服务和 pod 的关联信息)和 replication-controller(维护某个 pod 的复制为配置的数值)

① 在这张系统架构图中,我们把服务分为运行在工作节点上的服务和组成集群级别控制板的服务。

② Kubernetes节点有运行应用容器必备的服务,而这些都是受Master的控制。

③ 每个节点上当然都要运行Docker。Docker来负责所有具体的映像下载和容器运行。

④ Kubernetes主要由以下几个核心组件组成:

  • etcd 保存了整个集群的状态;

  • apiserver 提供了资源操作的唯一入口,并提供认证、授权、访问控制、API注册和发现等机制;

  • scheduler 负责资源的调度,按照预定的调度策略将Pod调度到相应的机器上;

  • controller manager 负责维护集群的状态,比如故障检测、自动扩展、滚动更新等;

  • kubelet 负责维护容器的生命周期,同时也负责Volume(CVI)和网络(CNI)的管理;

  • Container runtime 负责镜像管理以及Pod和容器的真正运行(CRI);

  • coredns 负责为整个集群提供DNS服务

  • kube-proxy 负责为Service提供cluster内部的服务发现和负载均衡;

⑤ 除了核心组件,还有一些推荐的Add-ons:

  • Ingress Controller 为服务提供外网入口

  • Dashboard提供GUI

  • Fluentd-elasticsearch提供集群日志采集、存储与查询

  • Heapster提供资源监控(1.14后就淘汰了)

  • Federation提供跨可用区的集群

etcd

这里etcd 即作为数据后端,又作为消息中间件

通过etcd 来存储所有的主节点上的状态信息,很容易实现主节点的分布式扩展

组件可以自动的去侦测 Etcd 中的数值变化来获得通知,并且获得更新后的数据来执行相应的操作

工作节点

  • kubelet 是工作节点执行操作的 agent负责具体的容器生命周期管理,根据从数据库中获取的信息来管理容器,并上报 pod 运行状态等;

  • kube-proxy是一个简单的网络访问代理同时也是一个 Load Balancer。它负责将访问到某个服务的请求具体分配给工作节点上的 Pod(同一类标签)。

image-20221116173256749

Proxy 代理对服务的请求

分层架构

Kubernetes设计理念和功能其实就是一个类似Linux的分层架构,如下图所示

image-20221116173349142

  • 核心层:Kubernetes最核心的功能,对外提供API构建高层的应用,对内提供插件式应用执行环境

  • 应用层:部署(无状态应用、有状态应用、批处理任务、集群应用等)和路由(服务发现、DNS解析等)

  • 管理层:系统度量(如基础设施、容器和网络的度量),自动化(如自动扩展、动态Provision等)以及策略管理(RBAC、Quota、PSP、NetworkPolicy等)

  • 接口层:kubectl命令行工具、客户端SDK以及集群联邦

  • 生态系统:在接口层之上的庞大容器集群管理调度的生态系统,可以划分为两个范畴

 

  • Kubernetes外部:日志、监控、配置管理、CI、CD、Workflow、FaaS、OTS应用、ChatOps等

  • Kubernetes内部:CRI、CNI、CVI、镜像仓库、Cloud Provider、集群自身的配置和管理等

kubernetes设计理念

Kubernetes重要概念介绍

原文出自:www.hangge.com  

转载请保留原文链接:https://www.hangge.com/blog/cache/detail_2428.html

Cluster、Master、Node 介绍

1,Cluster

  • Cluster(集群) 是计算、存储和网络资源的集合,Kubernetes 利用这些资源运行各种基于容器的应用

  • 最简单的Cluster 可以只有一台主机(它既是Mater 也是Node

2,Master

  • Master 是Cluster 的大脑,它的主要职责是调度,即决定将应用放在哪里运行。

  • Master 运行Linux 操作系统,可以是物理机或者虚拟机。

  • 为了实现高可用,可以运行多个Master

3,Node

  • Node 的职责是运行容器应用。

  • Node 由Master 管理,Node 负责监控并汇报容器的状态,并根据Master 的要求管理容器的生命周期。

  • Node 运行在Linux 操作系统,可以是物理机或者是虚拟机

Pod 介绍

1,Pod

  • Pod 是Kubernetes 的最小工作单元。

  • 每个Pod 包含一个或多个容器。Pod 中的容器会作为一个整体被Master 调度到一个Node 上运行。

2,Kubernetes 引入 Pod 的两个目的

(1)可管理性

  • 有些容器天生就是需要紧密联系,一起工作。Pod 提供了比容器更高层次的抽象,将它们封装到一个部署单元中。

  • Kubernetes 以Pod 为最小单位进行调度、扩展、共享资源、管理生命周期。

(2)通信和资源共享

  • Pod 中的所有容器使用同一个网络namespace,即相同的IP 地址和Port 空间。它们可以直接用localhost 通信。

  • 同样的,这些容器可以共享存储,当Kubernetes 挂载volume 到Pod,本质上是将volume 挂载到Pod 中的每一个容器。

3,Pod 的两种使用方式

(1)运行单一容器

  • one-container-per-PodKubernetes 最常见的模型,这种情况下,只是将单个容器简单封装成Pod

  • 即便是只有一个容器,Kubernetes 管理的也是 Pod 而不是直接管理容器。

(2)运行多个容器

  • 对于那些联系非常紧密,而且需要直接共享资源的容器,应该放在一个Pod 中。

  • 比如下面这个 Pod 包含两个容器:一个 File Puller,一个是Web ServerFile Puller会定期从外部的Content Manager 中拉取最新的文件,将其存放在共享的volume 中。Web Server 从volume 读取文件,响应Consumer 的请求。这两个容器是紧密协作的,它们一起为Consumer 提供最新的数据;同时它们也通过volume 共享数据。所以放到一个Pod 是合适的

Controller

1,基本介绍

Kubernetes 通常不会直接创建Pod,而是通过Controller 来管理Pod 的。Controller 中定义了Pod 的部署特性,比如有几个副本,在什么样的Node 上运行等。为了满足不同的业务场景,Kubernetes 提供了多种Controller,包括DeploymentReplicaSetDaemonSetStatefuleSetJob 等。

2,各个 Controller 介绍

(1)Deployment

  • Deployment 是最常用的Controller,比如我们可以通过创建Deployment 来部署应用的。

  • Deployment 可以管理Pod 的多个副本,并确保Pod 按照期望的状态运行。

(2)ReplicaSet

  • ReplicaSet实现了Pod 的多副本管理。

  • 使用Deployment 时会自动创建ReplicaSet,也就是说Deployment 是通过ReplicaSet 来管理Pod 的多个副本,我们通常不需要直接使用 ReplicaSet

(3)DaemonSet

  • DaemonSet 用于每个Node 最多只运行一个Pod 副本的场景。正如其名称所揭示的,DaemonSet 通常用于运行 daemon

(4)StatefuleSet

  • StatefuleSet 能够保证Pod 的每个副本在整个生命周期中名称是不变的。而其他Controller 不提供这个功能,

  • 当某个Pod 发生故障需要删除并重新启动时,Pod 的名称会发生变化。同时StatefuleSet 会保证副本按照固定的顺序启动、更新或者删除。

(5)Job

  • Job 用于运行结束就删除的应用。而其他Controller 中的Pod 通常是长期持续运行

Service

1,Service

  • Deployment 可以部署多个副本,每个Pod 都有自己的IP。而Pod 很可能会被频繁地销毁和重启,它们的IP 会发生变化,用IP 来访问Deployment 副本不太现实。

  • Service 定义了外界访问一组特定Pod 的方式。Service 有自己的IP 和端口,Service 为 Pod 提供了负载均衡

Namespace

(1)Namespace 可以将一个物理的Cluster 逻辑上划分成多个虚拟Cluster每个 Cluster 就是一个 Namespace不同 Namespace 里的资源是完全隔离的

(2)Kubernetes 默认创建了两个Namespace

  • default:创建资源时如果不指定,将被放到这个Namespace 中。

  • kube-systemKubernetes自己创建的系统资源将放到这个Namespace 中

Kubernetes设计理念与分布式系统

分析和理解Kubernetes的设计理念可以使我们更深入地了解Kubernetes系统,更好地利用它管理分布式部署的云原生应用,另一方面也可以让我们借鉴其在分布式系统设计方面的经验。

(1)API设计原则

对于云计算系统,系统API实际上处于系统设计的统领地位,正如本文前面所说,K8s集群系统每支持一项新功能,引入一项新技术,一定会新引入对应的API对象,支持对该功能的管理操作,理解掌握的API,就好比抓住了K8s系统的牛鼻子。K8s系统API的设计有以下几条原则:

  • 所有API应该是声明式的。正如前文所说,声明式的操作,相对于命令式操作,对于重复操作的效果是稳定的,这对于容易出现数据丢失或重复的分布式环境来说是很重要的。另外,声明式操作更容易被用户使用,可以使系统向用户隐藏实现的细节,隐藏实现的细节的同时,也就保留了系统未来持续优化的可能性。此外,声明式的API,同时隐含了所有的API对象都是名词性质的,例如Service、Volume这些API都是名词,这些名词描述了用户所期望得到的一个目标分布式对象。

  • API对象是彼此互补而且可组合的。这里面实际是鼓励API对象尽量实现面向对象设计时的要求,即"高内聚,松耦合",对业务相关的概念有一个合适的分解,提高分解出来的对象的可重用性。事实上,K8s这种分布式系统管理平台,也是一种业务系统,只不过它的业务就是调度和管理容器服务。

  • 高层API以操作意图为基础设计。如何能够设计好API,跟如何能用面向对象的方法设计好应用系统有相通的地方,高层设计一定是从业务出发,而不是过早的从技术实现出发。因此,针对K8s的高层API设计,一定是以K8s的业务为基础出发,也就是以系统调度管理容器的操作意图为基础设计。

  • 低层API根据高层API的控制需要设计。设计实现低层API的目的,是为了被高层API使用,考虑减少冗余、提高重用性的目的,低层API的设计也要以需求为基础,要尽量抵抗受技术实现影响的诱惑。

  • 尽量避免简单封装,不要有在外部API无法显式知道的内部隐藏的机制。简单的封装,实际没有提供新的功能,反而增加了对所封装API的依赖性。内部隐藏的机制也是非常不利于系统维护的设计方式,例如PetSet和ReplicaSet,本来就是两种Pod集合,那么K8s就用不同API对象来定义它们,而不会说只用同一个ReplicaSet,内部通过特殊的算法再来区分这个ReplicaSet是有状态的还是无状态。

  • API操作复杂度与对象数量成正比。这一条主要是从系统性能角度考虑,要保证整个系统随着系统规模的扩大,性能不会迅速变慢到无法使用,那么最低的限定就是API的操作复杂度不能超过O(N),N是对象的数量,否则系统就不具备水平伸缩性了。

  • API对象状态不能依赖于网络连接状态。由于众所周知,在分布式环境下,网络连接断开是经常发生的事情,因此要保证API对象状态能应对网络的不稳定,API对象的状态就不能依赖于网络连接状态。

  • 尽量避免让操作机制依赖于全局状态,因为在分布式系统中要保证全局状态的同步是非常困难的。

(2)控制机制设计原则

  • 控制逻辑应该只依赖于当前状态。这是为了保证分布式系统的稳定可靠,对于经常出现局部错误的分布式系统,如果控制逻辑只依赖当前状态,那么就非常容易将一个暂时出现故障的系统恢复到正常状态,因为你只要将该系统重置到某个稳定状态,就可以自信的知道系统的所有控制逻辑会开始按照正常方式运行。
  • 假设任何错误的可能,并做容错处理。在一个分布式系统中出现局部和临时错误是大概率事件。错误可能来自于物理系统故障,外部系统故障也可能来自于系统自身的代码错误,依靠自己实现的代码不会出错来保证系统稳定其实也是难以实现的,因此要设计对任何可能错误的容错处理。
  • 尽量避免复杂状态机,控制逻辑不要依赖无法监控的内部状态。因为分布式系统各个子系统都是不能严格通过程序内部保持同步的,所以如果两个子系统的控制逻辑如果互相有影响,那么子系统就一定要能互相访问到影响控制逻辑的状态,否则,就等同于系统里存在不确定的控制逻辑。
  • 假设任何操作都可能被任何操作对象拒绝,甚至被错误解析。由于分布式系统的复杂性以及各子系统的相对独立性,不同子系统经常来自不同的开发团队,所以不能奢望任何操作被另一个子系统以正确的方式处理,要保证出现错误的时候,操作级别的错误不会影响到系统稳定性。
  • 每个模块都可以在出错后自动恢复。由于分布式系统中无法保证系统各个模块是始终连接的,因此每个模块要有自我修复的能力,保证不会因为连接不到其他模块而自我崩溃。
  • 每个模块都可以在必要时优雅地降级服务。所谓优雅地降级服务,是对系统鲁棒性的要求,即要求在设计实现模块时划分清楚基本功能和高级功能,保证基本功能不会依赖高级功能,这样同时就保证了不会因为高级功能出现故障而导致整个模块崩溃。根据这种理念实现的系统,也更容易快速地增加新的高级功能,以为不必担心引入高级功能影响原有的基本功能。

Kubernetes的核心技术概念和API对象

API对象是K8s集群中的管理操作单元。K8s集群系统每支持一项新功能,引入一项新技术,一定会新引入对应的API对象,支持对该功能的管理操作。例如副本集Replica Set对应的API对象是RS。

每个API对象都有3大类属性:元数据metadata、规范spec和状态status

元数据是用来标识API对象的,每个对象都至少有3个元数据:namespace,name和uid;除此以外还有各种各样的标签labels用来标识和匹配不同的对象:

例如用户可以用标签env来标识区分不同的服务部署环境,分别用env=dev、env=testing、env=production来标识开发、测试、生产的不同服务。

规范描述了用户期望K8s集群中的分布式系统达到的理想状态(Desired State)

例如用户可以通过复制控制器Replication Controller设置期望的Pod副本数为3

status描述了系统实际当前达到的状态(Status)

例如系统当前实际的Pod副本数为2;那么复制控制器当前的程序逻辑就是自动启动新的Pod,争取达到副本数为3

K8s中所有的配置都是通过API对象的spec去设置的,也就是用户通过配置系统的理想状态来改变系统,这是k8s重要设计理念之一,即所有的操作都是声明式(Declarative)的而不是命令式(Imperative)的。声明式操作在分布式系统中的好处是稳定,不怕丢操作或运行多次,例如设置副本数为3的操作运行多次也还是一个结果,而给副本数加1的操作就不是声明式的,运行多次结果就错了

(1)容器组(Pod)

K8s有很多技术概念,同时对应很多API对象,最重要的也是最基础的是微服务Pod。Pod是在K8s集群中运行部署应用或服务的最小单元,它是可以支持多容器的。Pod的设计理念是支持多个容器在一个Pod中共享网络地址和文件系统,可以通过进程间通信和文件共享这种简单高效的方式组合完成服务。Pod对多容器的支持是K8s最基础的设计理念。

比如你运行一个操作系统发行版的软件仓库,一个Nginx容器用来发布软件,另一个容器专门用来从源仓库做同步,这两个容器的镜像不太可能是一个团队开发的,但是他们一块儿工作才能提供一个微服务;这种情况下,不同的团队各自开发构建自己的容器镜像,在部署的时候组合成一个微服务对外提供服务

Pod是K8s集群中所有业务类型的基础,可以看作运行在K8s集群中的小机器人,不同类型的业务就需要不同类型的小机器人去执行。目前K8s中的业务主要可以分为长期伺服型(long-running)、批处理型(batch)、节点后台支撑型(node-daemon)和有状态应用型(stateful application);分别对应的小机器人控制器为Deployment、Job、DaemonSet和PetSet,本文后面会一一介绍

pod是k8s中最基本也是最重要的一个概念,每一个pod的组成是由一个或者多个业务容器加上一个称之为"根容器"的pause容器构成。Pod概念的提出,使同一业务的容器有了一个整体管理的对象,不同业务、主机之间pod的通信可以通过podIP进行通信,同时pause根容器可以代表整个pod容器组的状态,利于我们准确的掌握整个pod的状态。

pod还分为静态pod和普通的pod。前者并不是存放在etcd中的,而是在具体的node节点的具体文件中,执行也只能在存放该pod的node节点上进行运行;普通pod一经启动,就会存储在etcd中,随后被master调度到具体的node上进行绑定,然后该node上的kubelet实例化一组相关的容器

Pod安排在节点上,包含一组容器和卷。同一个Pod里的容器共享同一个网络命名空间,可以使用localhost互相通信Pod是短暂的,不是持续性实体。你可能会有这些问题:

  • 如果Pod是短暂的,那么我怎么才能持久化容器数据使其能够跨重启而存在呢? 是的,Kubernetes支持的概念,因此可以使用持久化的卷类型。

  • 是否手动创建Pod,如果想要创建同一个容器的多份拷贝,需要一个个分别创建出来么?可以手动创建单个Pod,但是也可以使用Replication Controller使用Pod模板创建出多份拷贝,下文会详细介绍。

  • 如果Pod是短暂的,那么重启时IP地址可能会改变,那么怎么才能从前端容器正确可靠地指向后台容器呢?这时可以使用Service,下文会详细介绍。

(2)复制控制器(Replication Controller,RC)

replicaition controller简称RC,RC的作用就是定义了一个期望场景,RC的定义包含以下信息:

  • pod的期待的副本数(replicas)

  • 用于筛选目标pod的label selector

  • 当pod副本数量小于预期数量时,用于创建新pod的模板

RC的作用主要是当我们提交了一个定义好的RC到k8s集群后,master节点上的controller manager组件就会得到通知,定期检查当前系统中存活的目标pod,并确保目标pod的实例的数量刚好等于RC中定义的期望值,如果多了,就停掉一些,少了就自行创建。RC可以保证集群应用的高可用性,并且减少保证HA的运维工作

RC是K8s集群中最早的保证Pod高可用的API对象。通过监控运行中的Pod来保证集群中运行指定数目的Pod副本。指定的数目可以是多个也可以是1个;少于指定数目,RC就会启动运行新的Pod副本;多于指定数目,RC就会杀死多余的Pod副本。即使在指定数目为1的情况下,通过RC运行Pod也比直接运行Pod更明智,因为RC也可以发挥它高可用的能力,保证永远有1个Pod在运行。RC是K8s较早期的技术概念,只适用于长期伺服型的业务类型,比如控制小机器人提供高可用的Web服务

(3)副本集(Replica Set,RS)

RS是新一代RC,提供同样的高可用能力区别主要在于RS后来居上,能支持更多种类的匹配模式。副本集对象一般不单独使用,而是作为Deployment的理想状态参数使用

(4)部署(Deployment)

deployment为Pod和Replica Set(升级版的 Replication Controller)提供声明式更新

部署表示用户对K8s集群的一次更新操作。部署是一个比RS应用模式更广的API对象,可以是创建一个新的服务,更新一个新的服务,也可以是滚动升级一个服务

滚动升级一个服务,实际是创建一个新的RS,然后逐渐将新RS中副本数增加到理想状态,将旧RS中的副本数减小到0的复合操作;这样一个复合操作用一个RS是不太好描述的,所以用一个更通用的Deployment来描述。以K8s的发展方向,未来对所有长期伺服型的的业务的管理,都会通过Deployment来管理

(5)服务(Service)

Service是k8s里最核心的资源对象之一,k8s中的每个service其实就是我们经常提起的微服务架构里面的一个"微服务"

RC、RS和Deployment只是保证了支撑服务的微服务Pod的数量,但是没有解决如何访问这些服务的问题。

一个Pod只是一个运行服务的实例,随时可能在一个节点上停止,在另一个节点以一个新的IP启动一个新的Pod,因此不能以确定的IP和端口号提供服务。要稳定地提供服务需要服务发现和负载均衡能力。服务发现完成的工作,是针对客户端访问的服务,找到对应的的后端服务实例。在K8s集群中,客户端需要访问的服务就是Service对象。

每个Service会对应一个集群内部有效的虚拟IP,集群内部通过虚拟IP访问一个服务。在K8s集群中微服务的负载均衡是由Kube-proxy实现的。Kube-proxy是K8s集群内部的负载均衡器。它是一个分布式代理服务器,在K8s的每个节点上都有一个;这一设计体现了它的伸缩性优势,需要访问服务的节点越多,提供负载均衡能力的Kube-proxy就越多,高可用节点也随之增多。与之相比,我们平时在服务器端做个反向代理做负载均衡,还要进一步解决反向代理的负载均衡和高可用问题

如果Pods是短暂的,那么重启时IP地址可能会改变,怎么才能从前端容器正确可靠地指向后台容器呢?\ Service是定义一系列Pod以及访问这些Pod的策略的一层抽象。Service通过Label找到Pod组。因为Service是抽象的,所以在图表里通常看不到它们的存在,这也就让这一概念更难以理解。

现在,假定有2个后台Pod,并且定义后台Service的名称为'backend-service',lable选择器为(tier=backend, app=myapp)。backend-service 的Service会完成如下两件重要的事情:

  • 会为Service创建一个本地集群的DNS入口,因此前端Pod只需要DNS查找主机名为 'backend-service',就能够解析出前端应用程序可用的IP地址。

  • 现在前端已经得到了后台服务的IP地址,但是它应该访问2个后台Pod的哪一个呢?Service在这2个后台Pod之间提供透明的负载均衡,会将请求分发给其中的任意一个(如下面的动画所示)。通过每个Node上运行的代理(kube-proxy)完成这里有更多技术细节。

下述动画展示了Service的功能。注意该图作了很多简化。如果不进入网络配置,那么达到透明的负载均衡目标所涉及的底层网络和路由相对先进。如果有兴趣,这里有更深入的介绍。

image-20221207105023291

有一个特别类型的Kubernetes Service,称为\'LoadBalancer\',作为外部负载均衡器使用,在一定数量的Pod之间均衡流量。比如,对于负载均衡Web流量很有用

Pod、RC、service之间的关系:

image-20221207105035090

k8s的service定义了一个服务的访问入口地址,前端的应用(pod)通过这个入口访问背后的一组由pod组成的集群实例。Service与后端pod副本集群之间则是通过label selector来实现"无缝对接"。而RC的作用实际是保证service的服务能力和服务质量

(6)任务(Job)

Job是K8s用来控制批处理型任务的API对象。批处理业务与长期伺服业务的主要区别是批处理业务的运行有头有尾,而长期伺服业务在用户不停止的情况下永远运行。

Job管理的Pod根据用户的设置把任务成功完成就自动退出了。成功完成的标志根据不同的spec.completions策略而不同:单Pod型任务有一个Pod成功就标志完成;定数成功型任务保证有N个任务全部成功;工作队列型任务根据应用确认的全局成功而标志成功

(7)后台支撑服务集(DaemonSet)

长期伺服型和批处理型服务的核心在业务应用,可能有些节点运行多个同类业务的Pod,有些节点上又没有这类Pod运行;而后台支撑型服务的核心关注点在K8s集群中的节点(物理机或虚拟机),要保证每个节点上都有一个此类Pod运行。

节点可能是所有集群节点也可能是通过nodeSelector选定的一些特定节点典型的后台支撑型服务包括,存储,日志和监控等在每个节点上支持K8s集群运行的服务

(8)有状态服务集(PetSet)

K8s在1.3版本里发布了Alpha版的PetSet功能。在云原生应用的体系里,有下面两组近义词;第一组是无状态(stateless)、牲畜(cattle)、无名(nameless)、可丢弃(disposable);第二组是有状态(stateful)、宠物(pet)、有名(having name)、不可丢弃(non-disposable)。RC和RS主要是控制提供无状态服务的,其所控制的Pod的名字是随机设置的,一个Pod出故障了就被丢弃掉,在另一个地方重启一个新的Pod,名字变了、名字和启动在哪儿都不重要,重要的只是Pod总数

PetSet是用来控制有状态服务,PetSet中的每个Pod的名字都是事先确定的,不能更改。PetSet中Pod的名字的作用,并不是《千与千寻》的人性原因,而是关联与该Pod对应的状态。

对于RC和RS中的Pod,一般不挂载存储或者挂载共享存储,保存的是所有Pod共享的状态,Pod像牲畜一样没有分别(这似乎也确实意味着失去了人性特征);对于PetSet中的Pod,每个Pod挂载自己独立的存储,如果一个Pod出现故障,从其他节点启动一个同样名字的Pod,要挂载上原来Pod的存储继续以它的状态提供服务。

适合于PetSet的业务包括数据库服务MySQL和PostgreSQL,集群化管理服务Zookeeper、etcd等有状态服务。PetSet的另一种典型应用场景是作为一种比普通容器更稳定可靠的模拟虚拟机的机制。

传统的虚拟机正是一种有状态的宠物,运维人员需要不断地维护它,容器刚开始流行时,我们用容器来模拟虚拟机使用,所有状态都保存在容器里,而这已被证明是非常不安全、不可靠的。使用PetSet,Pod仍然可以通过漂移到不同节点提供高可用,而存储也可以通过外挂的存储来提供高可靠性,PetSet做的只是将确定的Pod与确定的存储关联起来保证状态的连续性。PetSet还只在Alpha阶段,后面的设计如何演变,我们还要继续观察。

(9)集群联邦(Federation)

K8s在1.3版本里发布了beta版的Federation功能。在云计算环境中,服务的作用距离范围从近到远一般可以有:同主机(Host,Node)、跨主机同可用区(Available Zone)、跨可用区同地区(Region)、跨地区同服务商(Cloud Service Provider)、跨云平台。

K8s的设计定位是单一集群在同一个地域内,因为同一个地区的网络性能才能满足K8s的调度和计算存储连接要求。而联合集群服务就是为提供跨Region跨服务商K8s集群服务而设计的

每个K8s Federation有自己的分布式存储、API Server和Controller Manager。用户可以通过Federation的API Server注册该Federation的成员K8s Cluster。

当用户通过Federation的API Server创建、更改API对象时,Federation API Server会在自己所有注册的子K8s Cluster都创建一份对应的API对象。在提供业务请求服务时,K8s Federation会先在自己的各个子Cluster之间做负载均衡,而对于发送到某个具体K8s Cluster的业务请求,会依照这个K8s Cluster独立提供服务时一样的调度模式去做K8s Cluster内部的负载均衡。而Cluster之间的负载均衡是通过域名服务的负载均衡来实现的。

所有的设计都尽量不影响K8s Cluster现有的工作机制,这样对于每个子K8s集群来说,并不需要更外层的有一个K8s Federation,也就是意味着所有现有的K8s代码和机制不需要因为Federation功能有任何变化。

(10)存储卷(Volume)

K8s集群中的存储卷跟Docker的存储卷有些类似,只不过Docker的存储卷作用范围为一个容器,而K8s的存储卷的生命周期和作用范围是一个Pod

每个Pod中声明的存储卷由Pod中的所有容器共享。K8s支持非常多的存储卷类型,特别的,支持多种公有云平台的存储,包括AWS,Google和Azure云;支持多种分布式存储包括GlusterFS和Ceph;也支持较容易使用的主机本地目录hostPath和NFSK8s还支持使用Persistent Volume Claim即PVC这种逻辑存储,使用这种存储,使得存储的使用者可以忽略后台的实际存储技术(例如AWS,Google或GlusterFS和Ceph),而将有关存储实际技术的配置交给存储管理员通过Persistent Volume来配置

volume是pod中能够被多个容器访问的共享存储目录。k8s中的volume的生命周期和pod的上面周期相同,因此,当pod中的容器重启和这终止时,其数据也不会丢失 。Volume的类型也多种多样,其对应的实现的功能也多种多样,详细可以看官方文档对这些volume的详细解释。

官方文档地址:http://docs.kubernetes.org.cn/429.html

(11)持久存储卷(Persistent Volume,PV)和持久存储卷声明(Persistent Volume Claim,PVC)

参考:https://www.hi-linux.com/posts/14136.html

PV和PVC使得K8s集群具备了存储的逻辑抽象能力,使得在配置Pod的逻辑里可以忽略对实际后台存储技术的配置,而把这项配置的工作交给PV的配置者,即集群的管理者。存储的PV和PVC的这种关系,跟计算的Node和Pod的关系是非常类似的;PV和Node是资源的提供者,根据集群的基础设施变化而变化,由K8s集群管理员配置;而PVC和Pod是资源的使用者,根据业务服务的需求变化而变化,有K8s集群的使用者即服务的管理员来配置。

Kubernetes 持久化存储方式

Kubernetes 目前可以使用 PersistentVolumePersistentVolumeClaimStorageClass 三种 API 资源来进行持久化存储,下面分别介绍下各种资源的概念。

PV

PV 的全称是:PersistentVolume(持久化卷)。PersistentVolume 是 Volume 的一种类型,是对底层的共享存储的一种抽象。PV 由集群管理员进行创建和配置,就像节点 (Node) 是集群中的资源一样,PV 也是集群资源的一种。PV 包含存储类型、存储大小和访问模式PV 的生命周期独立于 Pod,例如:当使用它的 Pod 销毁时对 PV 没有影响

PersistentVolume 通过插件机制实现与共享存储的对接。Kubernetes 目前支持以下插件类型:

  • GCEPersistentDisk

  • AWSElasticBlockStore

  • AzureFile

  • AzureDisk

  • FC (Fibre Channel)

  • FlexVolume

  • Flocker

  • NFS

  • iSCSI

  • RBD (Ceph Block Device)

  • CephFS

  • Cinder (OpenStack block storage)

  • Glusterfs

  • VsphereVolume

  • Quobyte Volumes

  • HostPath

  • VMware Photon

  • Portworx Volumes

  • ScaleIO Volumes

  • StorageOS

PVC

PVC 的全称是:PersistentVolumeClaim(持久化卷声明),PVC 是用户对存储资源的一种请求。PVC 和 Pod 比较类似,Pod 消耗的是节点资源,PVC 消耗的是 PV 资源。Pod 可以请求 CPU 和内存,而 PVC 可以请求特定的存储空间和访问模式。对于真正使用存储的用户不需要关心底层的存储实现细节,只需要直接使用 PVC 即可。

StorageClass

由于不同的应用程序对于存储性能的要求也不尽相同,比如:读写速度、并发性能、存储大小等。如果只能通过 PVC 对 PV 进行静态申请,显然这并不能满足任何应用对于存储的各种需求。为了解决这一问题,Kubernetes 引入了一个新的资源对象:StorageClass,通过 StorageClass 的定义,集群管理员可以先将存储资源定义为不同类型的资源,比如快速存储、慢速存储等。

当用户通过 PVC 对存储资源进行申请时,StorageClass 会使用 Provisioner(不同 Volume 对应不同的 Provisioner)来自动创建用户所需 PV。这样应用就可以随时申请到合适的存储资源,而不用担心集群管理员没有事先分配好需要的 PV。

  • 自动创建的 PV 以 \${namespace}-\${pvcName}-\${pvName} 这样的命名格式创建在后端存储服务器上的共享数据目录中。

  • 自动创建的 PV 被回收后会以 archieved-\${namespace}-\${pvcName}-\${pvName} 这样的命名格式存在后端存储服务器上。

Kubernetes 访问存储资源的方式

Kubernetes 目前可以使用三种方式来访问存储资源。

  • 直接访问

该种方式移植性比较差可扩展能力差。把 Volume 的基本信息完全暴露给用户,有安全隐患。

image-20221207105227318

  • 静态 PV

集群管理员提前手动创建一些 PV。它们带有可供集群用户使用的实际存储的细节,之后便可用于 PVC 消费。

image-20221207105243729

注:这种方式请求的 PVC 必须要与管理员创建的 PV 保持一致,如:存储大小和访问模式,否则不能将 PVC 绑定到 PV 上。

  • 动态 PV

当集群管理员创建的静态 PV 都不匹配用户的 PVC 时,PVC 请求存储类 StorageClass,StorageClass 动态的为 PVC 创建所需的 PV。

image-20221207105317783

注:此功能需要基于 StorageClass。集群管理员必须先创建并配置好请求的 StorageClass只有请求的 StorageClass 存在的情况下才能进行动态的创建**

(12)节点(Node)

K8s集群中的计算能力由Node提供,最初Node称为服务节点Minion,后来改名为Node。K8s集群中的Node也就等同于Mesos集群中的Slave节点,是所有Pod运行所在的工作主机,可以是物理机也可以是虚拟机

不论是物理机还是虚拟机,工作主机的统一特征是上面要运行kubelet管理节点上运行的容器

(13)密钥对象(Secret)

Secret是用来保存和传递密码、密钥、认证凭证这些敏感信息的对象

使用Secret的好处是可以避免把敏感信息明文写在配置文件里。

在K8s集群中配置和使用服务不可避免的要用到各种敏感信息实现登录、认证等功能,例如访问AWS存储的用户名密码。

为了避免将类似的敏感信息明文写在所有需要使用的配置文件中,可以将这些信息存入一个Secret对象,而在配置文件中通过Secret对象引用这些敏感信息。这种方式的好处包括:意图明确,避免重复,减少暴漏机会

(14)用户帐户(User Account)和服务帐户(Service Account)

顾名思义,用户帐户为人提供账户标识,而服务账户为计算机进程和K8s集群中运行的Pod提供账户标识。

用户帐户和服务帐户的一个区别是作用范围;用户帐户对应的是人的身份,人的身份与服务的namespace无关,所以用户账户是跨namespace的;而服务帐户对应的是一个运行中程序的身份,与特定namespace是相关的

(15)名称空间(Namespace)

名称空间为K8s集群提供虚拟的隔离作用,K8s集群初始有两个名字空间,分别是默认名称空间default和系统名称空间kube-system,除此以外,管理员可以可以创建新的名字空间满足需要

(16)RBAC访问授权

K8s在1.3版本中发布了alpha版的基于角色的访问控制(Role-based Access Control,RBAC)的授权模式。相对于基于属性的访问控制(Attribute-based Access Control,ABAC),RBAC主要是引入了角色(Role)和角色绑定(RoleBinding)的抽象概念。

在ABAC中,K8s集群中的访问策略只能跟用户直接关联;而在RBAC中,访问策略可以跟某个角色关联,具体的用户在跟一个或多个角色相关联。显然,RBAC像其他新功能一样,每次引入新功能,都会引入新的API对象,从而引入新的概念抽象,而这一新的概念抽象一定会使集群服务管理和使用更容易扩展和重用

(17)Label

Label

k8s中的label是一个键值对,label可以附加到各种k8s的资源上,label的定义是在资源对象定义的时候定义,也可以在对象创建后进行添加。

Label的作用主要是应用于通过给指定的资源对象绑定一个或者多个不同的label,实现多维度的资源分组管理的功能

Label就相当于给某个资源对象打了一个标签,然后通过label selector来查询和筛选具有某些label的对象进行相关操作,来达到资源对象的分组管理功能

正如图所示,一些Pod有Label(image-20221207105513875)。一个Label是attach到Pod的一对键/值对,用来传递用户定义的属性。

比如:你可能创建了一个"tier"和"app"标签,通过Label(tier=frontend, app=myapp)来标记前端Pod容器,使用Label(tier=backend, app=myapp)标记后台Pod。然后可以使用Selectors选择带有特定Label的Pod,并且将Service或者Replication Controller应用到上面。

Replication Controller

是否手动创建Pod,如果想要创建同一个容器的多份拷贝,需要一个个分别创建出来么,能否将Pods划到逻辑组里? Replication Controller确保任意时间都有指定数量的Pod"副本"在运行。如果为某个Pod创建了Replication Controller并且指定3个副本,它会创建3个Pod,并且持续监控它们。如果某个Pod不响应,那么Replication Controller会替换它,保持总数为3.如下面的动画所示:

image-20221207105536992

如果之前不响应的Pod恢复了,现在就有4个Pod了,那么Replication Controller会将其中一个终止保持总数为3。如果在运行中将副本总数改为5,Replication Controller会立刻启动2个新Pod,保证总数为5。还可以按照这样的方式缩小Pod,这个特性在执行滚动升级时很有用。

当创建Replication Controller时,需要指定两个东西:

  1. Pod模板:用来创建Pod副本的模板

  2. Label:Replication Controller需要监控的Pod的标签。

现在已经创建了Pod的一些副本,那么在这些副本上如何均衡负载呢?我们需要的是Service。

(18)statefulset

在kubernetes系统里,pod的管理对象RC、deployment、Daemonset和job都是面向的无状态服务。但实际业务中是会有有状态服务的,例如一些具有固定身份ID,固定集群规模,集群中的数据需要持久化到永久存储的这些有状态服务。

如果使用RC/Deployment来实现有状态服务,就会发现这些服务的身份固定就实现不了,因为每个pod的名字是随机产生的,ip地址也是在运行期间才确定但是可能发生变化的,无法事先就为服务确定一个确定的ip,此外,为了满足持久化存储到永久存储中,这种pod还需要外接存储设备,为了解决这些问题,就引入了新的statefulset的概念。

Statefulset中的的pod具有固定的身份和稳定的ip,可以来发现集群内部的其他成员,他控制的pod的启停是有顺序的,在操作第N个pod之前,前N-1个pod已经操作完成,并且statefulset的pod采用的是稳定的持久化存储卷,采用PV/PVC来实现,删除pod时,默认不会删除相关的存储卷,来保证数据安全

(18)namespace

namespace在k8s中,很多情况下是用于多租户的资源隔离。

Namespace通过将集群内部的资源对象"分配"到不同的namespace中,形成逻辑上的不同的资源小组,资源项目,便于不同的分组在资源使用时的管理

(19)annotation

与label类似,都是key/value键值对,不同的是label的格式有严格的命名规则,而Annotation是用户任意定义的附加信息,方便外部工具进行查找

免责声明: 本文部分内容转自网络文章,转载此文章仅为个人收藏,分享知识,如有侵权,请联系博主进行删除。