Kubernetes,K→S有8个字母,所以又作K8S。

1. 什么是K8S?

kubernetes,希腊语,舵手,container除了拥有容器的含义,也有集装箱的含义。

See the source image

Kubernetes 就像一个舵手开着轮船,载着一堆集装箱,把集装箱送到它们该去的地方。Kubernetes 也就一个“轮船”,来帮助我们管理这些集装箱,也就是管理这些容器。所以,Kubernetes就是一个管理容器的工具

更具体一点,Kubernetes 是一个自动化的容器编排平台,负责:

  • 应用的部署
  • 应用的弹性
  • 应用的管理

这些都是基于容器的。

2. K8S的核心功能

  • 服务发现
  • 负载均衡
  • 容器的自动装箱
    • 我们也会把它叫做 scheduling,就是“调度”,把一个容器放到一个集群的某一个机器上,Kubernetes 会帮助我们去做存储的编排,让存储的声明周期与容器的生命周期能有一个连接;
  • 自动化的容器恢复
    • 在一个集群中,经常会出现宿主机的问题或者说是操作系统的问题,导致容器本身的不可用,Kubernetes 会自动地对这些不可用的容器进行恢复;
  • 自动发布与回滚
    • 应用的自动发布与应用的回滚,以及与应用相关的配置密文的管理
  • 批量执行
    • 对于 job 类型任务,Kubernetes 可以去做批量的执行;
  • 水平伸缩
    • 为了让这个集群、这个应用更富有弹性,Kubernetes 也支持水平的伸缩。

2.1 调度

调度器

Kubernetes 可以把用户提交的容器放到 Kubernetes 管理的集群某一台节点上去。Kubernetes 的调度器是执行这项能力的组件,它会观察正在被调度的这个容器的大小、规格。比如说它所需要的 CPU以及它所需要的 memory,然后在集群中找一台相对比较空闲的机器来进行一次 placement,也就是一次放置的操作。

2.2 自动修复

节点健康检查

Kubernetes 有一个节点健康检查的功能,它会监测这个集群中所有的宿主机,当宿主机本身出现故障,或者软件出现故障的时候,这个节点健康检查会自动对它进行发现。 Kubernetes 会把运行在这些失败节点上的容器进行自动迁移,迁移到一个正在健康运行的宿主机上,来完成集群内容器的一个自动恢复

2.3 水平伸缩

业务负载检查

Kubernetes 有业务负载检查的能力,它会监测业务上所承担的负载,如果这个业务本身的 CPU 利用率过高,或者响应时间过长,它可以对这个业务进行一次扩容。之后它就可以通过负载均衡把原来达到的负载,平均分到扩容之后的负载上去,以此来提高响应的时间。

3. K8S的架构

image-20210711232144704

Kubernetes 架构是一个比较典型的二层架构和 server-client 架构。Master 作为中央的管控节点,会去与 Node 进行一个连接。所有 UI 的、clients、这些 user 侧的组件,只会和 Master 进行连接,把希望的状态或者想执行的命令下发给 Master,Master 会把这些命令或者状态下发给相应的节点,进行最终的执行。

4.1 Master

image-20210711232432510

Kubernetes 的 Master 包含四个主要的组件:API Server、Controller、Scheduler 以及 etcd。

  • API Server:顾名思义是用来处理 API 操作的,Kubernetes 中所有的组件都会和 API Server 进行连接,组件与组件之间一般不进行独立的连接,都依赖于 API Server 进行消息的传送
  • Controller:控制器,它用来完成对集群状态的一些管理
    • 比如自动对容器进行修复、自动进行水平扩张,都是由 Kubernetes 中的 Controller 来进行完成的;
  • Scheduler:调度器,完成调度的操作;
    • 把一个用户提交的 Container,依据它对 CPU、对 memory 请求大小,找一台合适的节点,进行放置;
  • etcd:是一个分布式的一个存储系统,API Server 中所需要的这些原信息都被放置在 etcd 中,etcd 本身是一个高可用系统,通过 etcd 保证整个 Kubernetes 的 Master 组件的高可用性。

API Server,它本身在部署结构上是一个可以水平扩展的一个部署组件;Controller 是一个可以进行热备的一个部署组件,它只有一个 active,它的调度器也是相应的,虽然只有一个 active,但是可以进行热备

4.2 Node

image-20210711232742597

  • Pod:Kubernetes 的 Node 是真正运行业务负载的,每个业务负载会以 Pod 的形式运行。

  • Kubelet:一个 Pod 中运行的一个或者多个容器,真正去运行这些 Pod 的组件的是叫做 kubelet,也就是 Node 上最为关键的组件,它通过 API Server 接收到所需要 Pod 运行的状态,然后提交 Container Runtime 组件中。

  • Storage Plugin:在 OS 上去创建容器所需要运行的环境,最终把容器或者 Pod 运行起来,也需要对存储跟网络进行管理。Kubernetes 不直接进行网络存储的操作,他们会靠 Storage Plugin 或者是网络的 Plugin 来进行操作。用户自己或者云厂商都会去写相应的 Storage Plugin 或者 Network Plugin,去完成存储操作或网络操作

  • Kube-proxy:在 Kubernetes 自己的环境中,也会有 Kubernetes 的 Network,它是为了提供 Service network 来进行搭网、组网的。完成 service 组网的组件;利用了 iptable 的能力来进行组建 Kubernetes 的 Network,就是 cluster network,以上就是 Node 上面的四个组件

Kubernetes 每个 Node 上,都会运行上面几个组件。

4. K8S组件之间的交互

img

  • 提交pod部署请求:用户可以通过 UI 或者 CLI 提交一个 Pod 给 Kubernetes 进行部署
  • 请求至API Server:这个 Pod 请求首先会通过 CLI 或者 UI 提交给 Kubernetes API Server
  • API Server写入etcd: API Server 会把这个信息写入到它的存储系统 etcd
  • Scheduler一直在watch: Scheduler 会通过 API Server 的 watch 或者叫做 notification 机制得到这个信息:有一个 Pod 需要被调度。
    • 使用过etcd的童鞋肯定能反应过来,这其实就是etcd的能力
  • Scheduler调度: 这个时候 Scheduler 会根据它的内存状态进行一次调度决策,在完成这次调度之后,它会向 API Server报告:Pod需要被调度到某一个节点上。
  • API Server写入etcd: API Server 接收到这次操作之后,会把这次的结果再次写到 etcd 中,然后 API Server 会通知相应的节点进行这次 Pod 真正的执行启动
  • Kubelet也一直在watch:相应节点的 kubelet 会得到这个通知
  • Kubelet调Container runtime: kubelet 就会去调 Container runtime 来真正去启动配置这个容器和这个容器的运行环境:
    • 调度 Storage Plugin 来去配置存储
    • 调度 network Plugin 去配置网络。

以上就是这些组件之间相互沟通相互通信,协调来完成一次Pod的调度执行操作的。当然我们很容易可以看出,etcd几乎作为了整个k8s的通信中间件,无论是master中的各组件,还是master与node之间。

5. K8S的核心概念与API

5.1 Pod

Pod 是 Kubernetes 的一个最小调度以及资源单元。用户可以通过 KubernetesPod API 生产一个 Pod,让 Kubernetes 对这个 Pod 进行调度,也就是把它放在某一个 Kubernetes 管理的节点上运行起来。

一个 Pod 简单来说是对一组容器的抽象,它里面会包含一个或多个容器。在 Pod 里面,我们也可以去定义容器所需要运行的方式。比如说运行容器 Command ,以及运行容器的环境变量等等。Pod 这个抽象也给这些容器提供了一个共享的运行环境,它们会共享同一个网络环境,这些容器可以用 localhost 来进行直接的连接。而 Pod 与 Pod 之间,是互相有隔离的。

5.2 Volume

Volume 就是卷的概念,它是用来管理 Kubernetes 存储的,是用来声明在 Pod 中的容器可以访问文件目录的,一个卷可以被挂载在 Pod 中一个或者多个容器的指定路径下面。而 Volume 本身是一个抽象的概念,一个 Volume 可以去支持多种的后端的存储。比如说 Kubernetes 的 Volume 就支持了很多存储插件:

  • 它可以支持本地的存储
  • 可以支持分布式的存储,比如说像 ceph,GlusterFS ;
  • 它也可以支持云存储,比如说阿里云上的云盘、AWS 上的云盘、Google 上的云盘等等。

image-20210712003219012

5.3 Deployment

Deployment 是在 Pod 这个抽象上更为上层的一个抽象,它可以定义一组 Pod 的副本数目、以及这个 Pod 的版本。 一般用 Deployment 这个抽象来做应用的真正的管理,而 Pod 是组成 Deployment 最小的单元。

image-20210712003201220

Kubernetes 是通过控制器去维护 Deployment 中 Pod 的数目,它也会去帮助 Deployment 自动恢复失败的 Pod

比如说我定义一个 Deployment,这个 Deployment 里面需要两个 Pod,当一个 Pod 失败的时候,控制器就会监测到,然后再去新生成一个 Pod,它重新把 Deployment 中的 Pod 数目恢复。

通过控制器以指定发布的策略以控制版本。比如说进行滚动升级,进行重新生成的升级,或者进行版本的回滚。

5.4 Service

Service 提供了一个或者多个 Pod 实例的稳定访问地址。

image-20210712003022065

一个 Deployment 可能有两个甚至更多个完全相同的 Pod。

对于一个外部的用户来讲,访问哪个 Pod 其实都是一样的,所以会希望做一次负载均衡,在做负载均衡的同时,只想访问某一个固定的 VIP( Virtual IP), 虚拟IP,而不希望得知每一个具体的 Pod 的 IP 地址。这个 pod 本身可能终止,如果一个 Pod 失败了,可能会唤起另外一个新的。对一个外部用户来讲,提供了多个具体的 Pod 地址,这个用户要不停地去更新 Pod 地址,当这个 Pod 再失败重启之后,我们希望有一个抽象,把所有 Pod 的访问能力抽象成一个第三方的一个 IP 地址,实现这个的 Kubernetes 的抽象就叫 Service。

实现 Service 有多种方式:

  • Kubernetes 支持 Cluster IP
  • kuber-proxy 的组网
    • nodePort
    • LoadBalancer

5.5 Namespaces

Namespace 是用来做一个集群内部的逻辑隔离的,它包括鉴权、资源管理等。Kubernetes 的每个资源,比如 Pod、Deployment、Service 都属于一个 Namespace,同一个 Namespace 中的资源需要命名的唯一性,不同的 Namespace 中的资源可以重名。

所以以上结构大致应该是这样的:

  • Namespaces:
    • Deployment(Service)
      • Pod1(Volume)
        • container1
        • container2
        • container3
      • Pod2(Volume)
        • container1
        • container2
        • container3

6. K8S的api

Kubernetes API 是由 HTTP+JSON 组成的:用户访问的方式是 HTTP,访问的 API 中的content是 JSON 格式的。Kubernetes 的 kubectl,Kubernetes UI,或者有时候用 curl,直接与 Kubernetes 进行沟通,都是使用 HTTP + JSON 这种形式。

image-20210712004020998

如果我们去提交一个 Pod,它的 content 内容都是用 JSON 或者是 YAML 表达的:

  • apiVersion: API 的 version
  • Kind: 描述操作的哪个资源
  • Metadata: 资源的名称,比如nginx,pod的名字
    • lable: 标签
      • KeyValuePair键值对,这些 label 是可以被 selector,也就是选择器所查询的。这个能力实际上跟我们的 sql 类型的 select 语句是非常相似的,这个可以实操时体会一下,通过 label,kubernetes 的 API 层就可以对这些资源进行一个筛选,那这些筛选也是 kubernetes 对资源的集合所表达默认的一种方式。例如:
        • Deployment可能是代表一组的 Pod,它是一组 Pod 的抽象,一组 Pod 就是通过 label selector 来表达的。
        • Service 对应的一组 Pod,就是一个 service 要对应一个或者多个的 Pod,来对它们进行统一的访问,这个描述也是通过 label selector 来进行 select 选取的一组 Pod。
        • 所以可以看到 label 是一个非常核心的 kubernetes API 的概念
    • annotation: 对资源的额外的一些用户层次的描述
  • Spec: 描述Pod预期的状态-
    • container:pod内部需要有哪些 container 被运行
      • image:容器的镜像是什么
      • port:容器运行后暴露的端口是什么

当我们从 Kubernetes API 中去获取这个资源的时候,一般来讲在 Spec 下面会有一个项目叫 status,它表达了这个资源当前的状态;比如说一个 Pod 的状态可能是正在被调度、或者是已经 running、或者是已经被 terminates,就是被执行完毕了。