本文由 CNCF + Alibaba 云原生技术公开课 整理而来
Kubernetes 是一个开源系统、一个自动化的容器编排平台,它负责容器化应用的部署、弹性伸缩和管理。
Kubernetes 将构成应用的容器按逻辑单位进行分组以便于管理和发现。Kubernetes 基于Google公司在运行生产负载上的15年经验打造,并融合了来自社区的最佳建议与实践。
Kubernetes核心功能
- 核心功能:
服务的发现与负载的均衡
容器的自动调度
容器的自动恢复
应用的自动发布与回滚,以及与应用相关的配置密文的管理
Job 类型任务的批量执行
应用的弹性伸缩
- 自动调度:
Kubernetes 可以把用户提交的容器自动调度到 Kubernetes 管理的集群的某一个节点上去,让容器运行起来。Kubernetes 的调度器是执行调度的组件,它会观察正在被调度的这个容器的大小、规格。
Kubernetes 会根据容器所需要的 CPU 以及它所需要的 Memory,然后通过调度算法,在集群中找一个资源相对比较空闲的节点来进行一次放置操作。
- 自动修复:
Kubernetes 有一个节点健康检查的功能,它会监测这个集群中所有的节点,当节点本身出现故障,或者软件出现故障的时候,这个节点健康检查会自动对它进行发现。
Kubernetes 会把运行在这些失败节点上的容器进行自动迁移,迁移到一个正在运行的健康节点上,来完成集群内容器的一个自动恢复。
- 弹性伸缩:
Kubernetes 有业务负载检查的能力,它会监测业务上所承担的负载,如果这个业务本身的 CPU 使用率过高,或者响应时间过长,它可以对这个业务进行一次扩容。
在业务高峰期之前,可以手动增加容器的副本来进行扩容;在业务高峰期之后,可以手动减少容器的副本来进行缩容。另外,Kubernetes 还可以通过配置 HPA
来完成容器的自动化弹性伸缩。
Kubernetes架构
Kubernetes 架构是一个比较典型的二层架构和 C/S 架构。Kubernetes 集群中有两种角色:Master
和 Node
,Master
作为中央的管控节点,会去与 Node
进行一个连接。
用户侧的组件只会和 Master
进行连接,把希望的状态或者想执行的命令传递给 Master
,Master
会把这些状态或者命令下发给相应的节点,进行最终的执行。
Master
:
Kubernetes 的 Master
包含四个主要的组件:API Server
、Controller
、Scheduler
以及 etcd
。
API Server:用来处理 API 操作,Kubernetes 中所有的组件都会和 API Server 进行连接,组件与组件之间一般不进行独立的连接,都依赖于 API Server 进行消息的传送
Controller:控制器,它用来完成对集群状态的一些管理。对容器的自动修复、弹性伸缩,都是由 Controller 来完成的
Scheduler:调度器,完成调度的操作——把用户提交的 Container,依据它对 CPU、Memory 等资源的请求大小,找一个合适的节点进行放置
etcd:分布式的存储系统,API Server 中所需要的这些原信息都被放置在 etcd 中。etcd 本身是一个高可用系统,通过 etcd 保证整个 Kubernetes 的 Master 组件的高可用性
Node
:
Kubernetes 的 Node
是真正运行业务负载的,每个业务负载会以 Pod
的形式运行。一个 Pod
中运行着一个或者多个容器,真正去运行这些 Pod
的组件的是叫做 Kubelet
,也就是 Node
上最为关键的组件,它通过 API Server
接收到所需要 Pod
运行的状态,然后提交到容器运行时中。
在 OS 上去创建容器所需要运行的环境,最终把容器或者 Pod
运行起来,还需要对网络、存储进行管理。Kubernetes 并不会直接进行网络、存储的操作,它会依赖 Network Plugin 和 Storage Plugin 来进行操作。可以使用云厂商的 Network Plugin 和 Storage Plugin 来完成网络、存储的操作,用户自己也可以开发自己的 Network Plugin 和 Storage Plugin,只要符合 Kubernetes 的规范即可。
在 Kubernetes 集群环境中,也会有 Kubernetes 自己的网络,它是为了提供 Service network 来进行组网的。真正完成组网的组件的是 Kube-proxy
,它利用了 iptables
的能力来进行组建 Kubernetes 的网络。
Kubernetes 的 Node
并不会直接和用户进行交互,它的交互只会通过 Master 上的 API Server
来完成。而用户是通过 Master
向节点下发这些信息的。Kubernetes 每个 Node
上,都会运行 Kubelet
、Kube-proxy
、Contaniner Runtime、Network Plugin、Storage Plugin 这几个组件。
- 组件交互过程:
用户可以通过 UI 或者 CLI 提交一个 Pod
给 Kubernetes 进行部署,这个 Pod
请求首先会通过 CLI 或者 UI 提交给 API Server
,下一步 API Server
会把这个信息写入到它的存储系统 etcd
,之后 Scheduler
会通过 API Server
的 watch 机制得到这个信息:有一个 Pod
需要被调度。
此时 Scheduler
会根据 Pod
的资源请求进行一次调度算法判断,在完成判断之后,它会向 API Server
报告这个 Pod 需要被调度到集群的哪个 Node
节点上。API Server
接收到消息之后,会把结果再次写到 etcd
中,然后 API Server
会通知对应的节点进行 Pod
真正的启动执行。对应节点上的 kubelet
会得到这个通知,Kubelet
就会去调 Container Runtime
来真正去启动配置这个容器和这个容器的运行环境,去调度 Network Plugin 去配置网络,Storage Plugin 来去配置存储。
Kubernetes概念
Pod
:
最小的调度以及资源单元
由一个或多个容器组成
定义容器运行的方式(Command、环境变量等)
提供给容器共享的运行环境(网络、进程空间)
Pod
是 Kubernetes 的一个最小调度以及资源的单元。用户可以通过 Kubernetes 的 Pod API
生产一个 Pod
,让 Kubernetes 对这个 Pod
进行调度,也就是把它放在某一个 Kubernetes 管理的节点上运行起来。一个 Pod
简单来说是对一组容器的抽象,它里面会包含一个或多个容器。
在 Pod
里面,可以去定义容器所需要运行的方式。比如运行容器的 Command,以及运行容器的环境变量等。Pod
这个抽象也给这些容器提供了一个共享的运行环境,它们会共享同一个网络和存储。
Volume
:
声明在 Pod 中的容器可访问的文件目录
可以被挂载在 Pod 中(一个或多个)容器的指定路径下
支持多种后端存储的抽象:本地存储、分布式存储、云存储等
Volume
就是卷的概念,它是用来管理 Kubernetes 存储的,是用来声明在 Pod
中的容器可以访问的文件目录,一个卷可以被挂载在 Pod 中一个或者多个容器的指定路径下面。
而 Volume
本身是一个抽象的概念,一个 Volume
可以支持多种后端的存储。Kubernetes 的 Volume
支持很多存储插件,它可以支持本地的存储、分布式的存储(ceph,GlusterFS)、云存储(云厂商的云盘)等。
Deployment
:
定义一组 Pod 的副本数目、版本等
通过 Controller 维持 Pod 的数目:自动恢复失败的 Pod
通过 Controller 以指定的策略控制版本:滚动升级、重新生成、回滚等
Deployment
是在 Pod
这个抽象上更为上层的一个抽象,它可以定义一组 Pod
的副本数目、以及 Pod
的版本。一般用 Deployment
这个抽象来做应用的真正管理,而 Pod
是组成 Deployment
最小的单元。
Kubernetes 是通过 Controller
去维护 Deployment
中 Pod
的数目,它也会去帮助 Deployment
自动恢复失败的 Pod
。通过 Controller
还可以自定义发布的策略,如滚动升级、重建升级,或者进行版本的回滚。
Service
:
提供访问一个或多个 Pod 实例的稳定访问地址
支持多种访问方式实现:Cluster IP、NodePort、LoadBalancer
Service
提供了一个或者多个 Pod
实例的稳定访问地址。
对一个外部用户来讲,如果提供多个具体的 Pod
地址,当 Pod
失败重启之后,这个用户就需要不停地去更新 Pod
地址,这显然是不合理的。因此 Kubernetes 希望有一个抽象,把对所有 Pod
的访问抽象成一个第三方的 IP 地址,实现的这个抽象就是 Service
。
实现 Service
有多种方式,Kubernetes 支持 Cluster IP
、NodePort
、 LoadBalancer
。
Namespace
:
一个集群内部的逻辑隔离机制(鉴权、资源额度)
大多数资源对象都属于一个Namespace
同一个 Namespace 中相同类型的资源命名唯一
Namespace
用于实现一个集群内部的逻辑隔离,它包括鉴权、资源管理等。Kubernetes 的每个资源,Pod
、Deployment
、Service
都属于一个 Namespace
,同一个 Namespace
中相同类型的资源命名唯一,不同的 Namespace
中相同类型的资源可以重名。
Kubernetes API
Kubernetes API 是由 HTTP + JSON 组成的:用户访问的方式是 HTTP,访问的 API 中的内容是 JSON 格式的。Kubernetes 的 kubectl
、Kubernetes UI,或者curl
,直接与 Kubernetes 进行沟通,都是使用 HTTP + JSON 这种形式。
当创建或获取一个 Pod
时,它的内容都是用 JSON 或 YAML 表达的,两者中 YAML 格式更为常见。在一个 YAML 文件中,对资源的描述分为几个部分:
Spec 部分:
apiVsersion 指定 API 的版本;
kind 指定资源类型(如 Pod);
metadata 表示元数据,在其中 name 指定资源名称,labels 给资源打上标签,方便管理,annotation 对资源添加用户层次的注释;
spec 表示期望资源达到的状态,在其中可以指定运行哪些容器、容器名称、容器镜像、容器端口、容器内部命令以及存储卷等;
Status 部分:
当从 Kubernetes API 中获取资源对象时,一般在 Spec 部分下面还有一个部分叫 Status,它表示这个资源对象当前的状态。
Controller 会比较资源的 Spec 和 Status,使 Status 不断的向 Spec 终态趋近,最终达到 Spec 期望状态。
yaml 文件示例:
apiVersion: v1
kind: Pod
metadata:
name: nginx
namespace: default
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
metadata
中包含 labels
,它可以是一组键值对,这些键值对可以被 selector
查询。通过 label
,Kubernetes API 可以对资源进行一个筛选,比如一个 Deployment
可能代表一组 Pod
,通过 label
就可以筛选出特定的一组 Pod
,同样的 Service
也是如此。