更新时间:2022 年 12 月 7 日
官网介绍:Kubernetes 是什么? | Kubernetes
Kubernetes 是自动化容器操作的开源平台,支持的操作包括部署,调度和节点集群间扩展等。Kubernetes 这个名字源于希腊语,又称 k8s(k8s 这个缩写是因为 k 和 s 之间有八个字符)
Kubernetes 建立在 Google 十几年来大规模生产工作的经验基础之上,结合了社区中好的想法和实践,是容器编排的佼佼者。 在 2014 年,Google开源了 Kubernetes 项目
应用部署方式发展图
传统部署时代
早期,各个组织机构在物理服务器上运行应用程序。传统部署无法为物理服务器中的应用程序定义资源边界,这会导致资源分配问题。 例如,如果在物理服务器上运行多个应用程序,则可能会出现一个应用程序占用大部分资源的情况, 结果可能导致其他应用程序的性能下降。 一种解决方案是在不同的物理服务器上运行每个应用程序,但是由于资源利用不足而无法扩展, 并且维护许多物理服务器的成本很高
虚拟化部署时代
作为解决方案,引入了虚拟化。虚拟化技术允许你在单个物理服务器的 CPU 上运行多个虚拟机(VM)。 虚拟化允许应用程序在 VM 之间隔离,并提供一定程度的安全,因为一个应用程序的信息 不能被另一应用程序随意访问
虚拟化技术能够更好地利用物理服务器上的资源,并且因为可轻松地添加或更新应用程序 而可以实现更好的可伸缩性,降低硬件成本等等
虚拟化部署带来良好的隔离机制。但是,由于每个 VM 是一台完整的计算机,在虚拟化硬件之上运行所有组件,包括其自己的操作系统。所以对宿主机资源的整体利用上并不理想,而且
容器部署时代
容器类似于 VM,但是它们具有被放宽的隔离属性,可以在应用程序之间共享操作系统(OS)。 因此,容器被认为是轻量级的。容器与 VM 类似,具有自己的文件系统、CPU、内存、进程空间等。 由于它们与基础架构分离,因此可以跨云和 OS 发行版本进行移植
容器优点:
资源利用:高效率和高密度
敏捷应用程序的创建和部署:与使用 VM 镜像相比,提高了容器镜像创建的简便性和效率
持续开发、集成和部署:通过快速简单的回滚(由于镜像不可变性),支持可靠且频繁的 容器镜像构建和部署
关注开发与运维的分离:在构建/发布时而不是在部署时创建应用程序容器镜像, 从而将应用程序与基础架构分离
跨开发、测试和生产的环境一致性:在不同计算机中以相同环境运行
以应用程序为中心的管理:提高抽象级别,从在虚拟硬件上运行 OS 到使用逻辑资源在 OS 上运行应用程序
松散耦合、分布式、弹性、解放的微服务:应用程序被分解成较小的独立部分, 并且可以动态部署和管理 - 而不是在一台大型单机上整体运行
容器是打包和运行应用程序的很好的方式。但在生产环境中,要同时管理很多容器并不容易。 例如,容器故障转移、容器内应用升级等等情况,既要保证业务的正常,又要完成容器的切换,导致运维人员工作量剧增
Kubernetes 就是解决这些问题的绝佳方案,Kubernetes 提供了一个弹性运行分布式系统的框架,可以实现诸多功能
服务发现和负载均衡
Kubernetes 可以使用 DNS 名称或自己的 IP 地址公开容器,如果进入容器的流量很大, Kubernetes 可以负载均衡并分配网络流量,从而使部署稳定。
存储编排
Kubernetes 允许你自动挂载你选择的存储系统,例如本地存储、公共云提供商等
自动部署和回滚
可以自动化 Kubernetes 来为你的部署创建新容器, 删除现有容器并将它们的所有资源用于新容器
自动完成装箱计算
Kubernetes 允许你指定每个容器所需 CPU 和内存(RAM)。 当容器指定了资源请求时,Kubernetes 可以做出更好的决策来管理容器的资源
自我修复
Kubernetes 重新启动失败的容器、替换容器、杀死不响应用户定义的 运行状况检查的容器,并且在准备好服务之前不将其通告给客户端。
密钥与配置管理
Kubernetes 允许你存储和管理敏感信息,例如密码、OAuth 令牌和 ssh 密钥。 你可以在不重建容器镜像的情况下部署和更新密钥和应用程序配置,也无需在堆栈配置中暴露密钥
Kubernetes 不是传统的、包罗万象的 PaaS(平台即服务)系统
由于 Kubernetes 在容器级别而不是在硬件级别运行,它提供了 PaaS 产品共有的一些普遍适用的功能, 例如部署、扩展、负载均衡、日志记录和监视。 但是,Kubernetes 不是单体系统,默认解决方案都是可选和可插拔的,提供的功能也远远比不上传统的 PaaS 系统。 Kubernetes 只是提供了构建开发人员平台的基础,且在重要的地方保留了用户的选择和灵活性
官网组件详解:Kubernetes 组件 | Kubernetes
一个 Kubernetes 集群由一组被称作节点(Node)的机器组成。这些节点上运行 Kubernetes 所管理的容器化应用
节点类型
集群至少需要有一个控制面节点和一个工作节点(可以是同一个)
主要组件图
控制平面的组件可以分散在集群的各个节点上运行,但为了方便管理,通常会在同一个计算机上启动所有控制平面组件, 并且不会在此计算机上运行应用容器,这个计算机即作为控制面节点
控制平面的组件可以对集群做出全局决策调度,以及检测和响应集群事件(例如,当不满足部署的 replicas
字段时,启动新的 Pod
控制平面组件生产中建议高可用部署
参考:Kubernetes API 概念 | Kubernetes
API Server 组件公开了 Kubernetes API,Kubernetes API 是通过 HTTP 提供的基于资源 (RESTful) 的编程接口。 它支持通过标准 HTTP 方法(POST、PUT、PATCH、DELETE、GET)进行检索、创建、更新和删除主要资源,还支持通过 watch 实现高效的资源变更通知。 Kubernetes 还提供了一致的列表操作,以便 API 客户端可以有效地缓存、跟踪和同步资源的状态。
Kubernetes API 服务器的主要实现是 kube-apiserver,它是 Kubernetes 控制面的前端,也是其他组件的交互中心。kube-apiserver 设计上考虑了水平伸缩,也就是说,可以运行 kube-apiserver 的多个实例,并在这些实例之间平衡流量,并可以动态添加和剔除实例
关于 API 的使用,可以查阅官网:参考 | Kubernetes
kube-apiserver 组件的详细配置可以参考:kube-apiserver | Kubernetes
参考:Kubelet 认证/鉴权 | Kubernetes
kube-apiserver 是管理用户访问的入口,所以具有认证与鉴权的功能
认证方式
认证方式详见:用户认证 | Kubernetes
常用认证方式有:
鉴权策略
鉴权策略详见:鉴权概述 | Kubernetes
常见的鉴权方式有:
etcd 是兼具一致性和高可用性的 key/value 类型的数据库,其保存了 Kubernetes 所有的集群数据,生产环境通常需要高可用部署,并做定时备份
etcd 集群可以在集成在控制面节点,也可以单独部署在其他机器节点
注:只有 kube-apiserver 组件会对 etcd 做数据操作,其他组件的数据操作都是通过调用 kube-apiserver 组件
要了解 etcd 更深层次的信息,请参考官方文档 etcd 文档
kubernetes 常用的 etcd 操作:为 Kubernetes 运行 etcd 集群 | Kubernetes
kube-scheduler 负责监视新创建的、未指定运行节点的 Pods,选择节点让 Pod 在上面运行
调度策略所考虑的因素,包括单个 Pod 和 Pod 集合的资源需求、硬件/软件/策略约束、亲和性和反亲和性规范、数据位置、工作负载间的干扰和最后时限
调度策略和自定义配置参考:调度 | Kubernetes
kube-scheduler 的调度依赖于 kube-apiserver 和工作节点上的 kubelet 通信
Node 上的 kubelet 通过 kube-apiserver 监听 kube-scheduler 产生的 pod 绑定信息,然后获取对应的 Pod 清单,下载 Image 并启动容器
kube-scheduler 组件的详细配置可以参考:kube-scheduler | Kubernetes
kube-controller-manager 是负责运行 控制器 进程的组件。控制器可以通过 api-server 监控集群的公共状态,并尽力维持健康状态。从逻辑上讲,每个控制器 都是一个单独的进程, 但是为了降低复杂性,它们都被编译到同一个可执行文件,并在一个进程中运行
控制器包括:
kube-controller-manager 组件的详细配置可以参考:kube-controller-manager | Kubernetes
当某个 Node 意外宕机时,kube-controller-manager 会及时发现,并执行自动化修复流程,确保集群中的 Pod 处于预期的工作状态
流程如下
相关参数
# 节点控制器对节点状态进行同步的重复周期(心跳周期)
--node-monitor-period duration 默认值:5s
# 在将一个 Node 标记为不健康之前允许其无响应的时长上限。
# 必须比 kubelet 的 nodeStatusUpdateFrequency 大 N 倍,这里 N 指的是 kubelet 发送节点状态的重试次数
--node-monitor-grace-period duration 默认值:40s
# 在失效的节点上删除 Pod 时为其预留的宽限期
--pod-eviction-timeout duration 默认值:5m0s
节点组件在每个节点上运行,维护运行的 Pod 并提供 Kubernetes 实际的应用运行环境
kubelet 是在每个 Node 节点上运行的主要 “节点代理”。它可以使用以下之一向 apiserver 注册: 主机名(hostname);覆盖主机名的参数;某云驱动的特定逻辑
kubelet 是基于 PodSpec 来工作的。每个 PodSpec 是一个描述 Pod 的 YAML 或 JSON 对象。 kubelet 接受通过各种机制(主要是通过 apiserver)提供的一组 PodSpec,并确保这些 PodSpec 中描述的容器处于运行状态且运行状况良好。 kubelet 不会管理非 Kubernetes 创建的容器
除了来自 apiserver 的 PodSpec 之外,还可以通过以下两种方式将容器清单(manifest)提供给 kubelet
文件(File):利用命令行参数传递路径。kubelet 周期性地监视此路径下的文件是否有更新。 监视周期默认为 20s,且可通过参数进行配置
HTTP 端点(HTTP endpoint):利用命令行参数指定 HTTP 端点。 此端点的监视周期默认为 20 秒,也可以使用参数进行配置
kubelet 组件的详细配置可以参考:kubelet | Kubernetes
主要功能
周期性向 kube-apiserver 汇报 Node 节点的状态信息
接受指令并创建 Pod,调用容器运行时运行
准备 Pod 所需要的数据卷
返回 Pod 的运行状态
在 Node 上执行容器健康检查
参考:kube-proxy 配置 (v1alpha1) | Kubernetes
kube-proxy 是集群中每个工作节点上运行的网络代理, 是实现 Kubernetes 服务(Service) 的一部分
网络代理反映了每个节点上 Kubernetes API 中定义的服务,并且可以执行简单的 TCP、UDP 和 SCTP 流转发,或者在一组后端进行 循环 TCP、UDP 和 SCTP 转发。 用户必须使用 apiserver API 创建服务才能配置代理。
kube-proxy 维护节点上的网络规则。这些网络规则允许从集群内部或外部的网络会话与 Pod 进行网络通信。如果操作系统提供了数据包过滤层并可用的话,kube-proxy 会通过它来实现网络规则。否则, kube-proxy 仅转发流量本身
kube-proxy 组件的详细配置可以参考:kube-proxy | Kubernetes
kube-proxy 会监听 API Server 中服务(Service)对象,再通过管理 iptables 或 ipvs 规则,来实现数据流量的转发
目前 Linux 平台上 kube-proxy 支持三种工作模式(通过 --proxy-mode
指定)
参考:IPVS vs. IPTABLES
ipvs 相对 iptables 效率会更高一些,使用 ipvs 模式需要在运行 kube-proxy 的节点上安装 ipset
软件包,并且加载 ip_vs_*
及 nf_conntrack
内核模块(如果方便查看规则还需要安装 ipvsadm)。当 kube-proxy 以 ipvs 代理模式启动时,kube-proxy 将验证节点上是否安装了 ipvs 模块,如果未安装,则 kube-proxy 将回退到 iptables 代理模式
使用 ipvs 模式,kube-proxy 监听 API Server 中 Service 对象和 Endpoints,然后调用宿主机内核 Netlink 接口创建 ipvs 规则并定时同步
访问服务时,流量将被重定向到其中一个后端 Pod,ipvs 提供了很多负载均衡算法(通过 --ipvs-scheduler
指定),例如:rr(轮询调度)、lo(最小连接数)、dh(目标哈希)、sh(源哈希)、sed(最短期望延迟)、nq(不排队调度)等。使用算法需要加载对应 ip_vs_{算法}
的内核模块
参考:容器运行时 | Kubernetes
容器运行时是负责运行容器的软件,Kubernetes 提供了 Kubernetes CRI (容器运行环境接口) ,支持实现了该接口的任何容器运行时,例如 Docker、 containerd、CRI-O 以及 Kubernetes CRI (容器运行环境接口) 的其他实现软件
OCI(Open Container Initiative)
OCI 由 Docker、CoreOS 以及其他容器相关公司创建于 2015 年,目前主要有两个标准文档:容器运行时标准 (runtime spec)和 容器镜像标准(image spec)
runc 是 Docker 捐赠给 OCI 的一个符合标准的 runtime 实现,目前 Docker、Containerd 引擎内部都是基于 runc 构建的
CRI(Container Runtime Interface)
参考:容器运行时接口(CRI) | Kubernetes
CRI 是 Kubernetes 制定的一系列接口规范,它使 kubelet 能够使用各种容器运行时,无需重新编译集群组件
容器运行时接口(CRI)是 kubelet 和容器运行时(Container Runtimes)之间通信的主要协议
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DgpuRYpU-1671292565210)(./00-k8s-synopsis/03-kubelet-call-chain.svg)]
在 kubernetes v1.23.x 以及之前版本,kubelet 内置了 dockershim 组件,以实现对 docker 的调用
在 kubernetes v1.24.x 以及之后版本,官方正式将 dockershim 组件从 kubelet 中删除,如果希望继续使用 Docker Engine 作为容器运行时,则需要手动安装 cri-dockerd 组件。cri-dockerd 详见:Mirantis/cri-dockerd (github.com)
从 kubernetes v1.24.x 以及之后版本开始,用户使用 Kubernetes 时需要优先选择 containerd 或 CRI-O 作为容器运行时,可以看到 containerd 或 CRI-O 的调用链会比使用 docker 短,效率更高,出错几率更小
插件使用 Kubernetes 资源(DaemonSet、 Deployment等)实现集群功能。 因为这些插件提供集群级别的功能,插件中命名空间域的资源属于 kube-system
命名空间
下面描述众多插件中的几种。有关可用插件的完整列表,请参见 插件(Addons)
尽管其他插件都并非严格意义上的必需组件,但几乎所有 Kubernetes 集群都应该 有集群 DNS, 因为很多示例都需要 DNS 服务
集群 DNS 是一个 DNS 服务器,和环境中的其他 DNS 服务器一起工作,它为 Kubernetes 服务提供 DNS 记录
Kubernetes 启动的容器会自动将此 DNS 服务器包含在其 DNS 搜索列表中
Dashboard 是 Kubernetes 集群的通用的、基于 Web 的用户界面。 它使用户可以管理集群中运行的应用程序以及集群本身,进行简单的故障排除
kubectl
参考:命令行工具 (kubectl) | Kubernetes
kubectl
是一个管理 kubernetes 的命令行工具,它使用 Kubernetes API 与 Kubernetes 集群的控制面进行通信
针对配置信息,kubectl
在 $HOME/.kube
目录中查找一个名为 config
的配置文件。 你可以通过设置 KUBECONFIG
环境变量或设置 --kubeconfig
参数来指定其它 kubeconfig 文件
容器资源监控 将关于容器的一些常见的时间序列度量值保存到一个集中的数据库中,并提供用于浏览这些数据的界面
集群层面日志 机制负责将容器的日志数据保存到一个集中的日志存储中,该存储能够提供搜索和浏览接口