Kubernetes 简介
Kubernetes 可以实现容器集群的自动化部署、自动扩缩容、维护等功能。它拥有自动包装、自我修复、横向缩放、服务发现、负载均衡、 自动部署、升级回滚、存储编排等特性。
Kubernetes 被广泛地支持和集成到各大云服务提供商的容器服务中,国内有腾讯云 TKE 和阿里云 ACK 等。
1 架构设计
K8s 集群节点拥有 Master 和 Node 两种角色。它们的职责如下:
Master:官方叫做控制平面(Control Plane)或(控制节点),主要负责整个集群的管控,包含监控、编排、调度集群中的各类资源对象(如 Pod/Deployment 等),通常 Master 会占用一个单独的集群节点(不会运行应用容器),基于高可用可能会占用多台。 (提供 K8s 集群托管的云厂商也会为你的集群主节点提供高可用部署)
Node:数据平面(工作节点)。是集群中的承载实际工作任务的节点,直接负责对容器资源的控制,可以无限扩展。
2 Master节点
Master节点(控制节点) 由四个部分组成:API Server 、 etcd 、调度器(Scheduler)、控制器管理器(kube-controller-manager)
2.1 API Server
K8S核心组件之一,为集群中各类资源提供增删改查的 HTTP REST 接口,即操作任何资源都要经过 API Server
Master 节点=> kube-system 命名空间=> 运行的 Pod 之一 kube-apiserver 是 API Server 的具体实现。
与其通信有三种方式:
通过 REST API 访问
通过官方提供的 Client 来访问,本质上也是 REST API 调用
通过 kubectl 客户端访问,其本质上是将命令转换为 REST API 调用,是最主要的访问方式
2.2 etcd
K8s 使用 etcd 作为内部数据库,用于保存集群配置以及所有对象的状态信息。
只有 API Server 进程能直接读写 etcd。
为了保证集群数据安全性,建议为其考虑备份方案。
如果 etcd 不可用,应用容器仍然会继续运行,但用户无法对集群做任何操作(包括对任何资源的增删改查)。
2.3 调度器(Scheduler)
是 Pod 资源的调度器,用于监听刚创建还未分配 Node 的 Pod,为其分配相应 Node。
调度时会考虑资源需求、硬件/软件/指定限制条件以及内部负载情况等因素,所以可能会调度失败。
调度器也是操作 API Server 的各项接口来完成调度的。
比如 Watch 接口监听新建的 Pod,并搜索所有满足 Pod 需求的 Node 列表, 再执行 Pod 调度逻辑,调度成功后将 Pod 绑定到目标 Node 上。
2.4 控制器管理器(kube-controller-manager)
Controller 管理器实现了全部的后台控制循环,完成对集群的健康并对事件做出响应。
Controller 管理器是各种 Controller 的管理者,负责创建 controller,并监控它们的执行。
这些 Controller 包括 NodeController、ReplicationController 等
每个 controller 都在后台启动了一个独立的监听循环(可以简单理解为一个线程),负责监控 API Server 的变更。
Node 控制器:负责管理和维护集群中的节点。比如节点的健康检查、注册/注销、节点状态报告、自动扩容
Replication 控制器:确保集群中运行的 Pod 的数量与指定的副本数(replica)保持一致
当 Pod 组中的任何一个 Pod 被删除或故障时,Replication 控制器会自动创建新的 Pod 来作为替代
当 Pod 组内的 Pod 数量超过所定义的replica数量时,Replication 控制器会终止多余的 Pod
Endpoint 控制器:负责生成和维护所有 Endpoint 对象的控制器。Endpoint 控制器用于监听 Service 和对应 Pod 副本的变化
ServiceAccount 及 Token 控制器:为新的命名空间创建默认账户和 API 访问令牌。
等等控制器 . . .
kube-controller-manager 所执行的各项操作也是基于 API Server 进程的。
3 Node节点
Node 由三部分组成:kubelet、kube-proxy 和容器运行CRI时(如 docker/containerd)
3.1 kubelet
它是每个 Node 上都运行的主要代理进程。
kubelet 以 PodSpec 为单位来运行任务,后者是一种 Pod 的 yaml 或 json 对象。
kubelet 会运行由各种方式提供的一系列 PodSpec,并确保这些 PodSpec 描述的容器健康运行。
不是 k8s 创建的容器不属于 kubelet 管理范围,kubelet 也会及时将 Pod 内容器状态报告给 API Server,并定期执行 PodSpec 描述的容器健康检查。
同时 kubelet 也负责存储卷等资源的管理。
kubelet 会定期调用 Master 节点上的 API Server 的 REST API 以报告自身状态,然后由 API Server 存储到 etcd 中。
3.2 kube-proxy
每个节点都会运行一个 kube-proxy Pod。
作为 K8s Service 的网络访问入口,负责将 Service 的流量转发到后端的 Pod,并提供 Service 的负载均衡能力。
kube-proxy 会监听 API Server 中 Service 和 Endpoint 资源的变化,并将这些变化实时反应到节点的网络规则中,确保流量正确路由到服务
总结来说,kube-proxy 主要负责维护网络规则和四层流量的负载均衡工作。
3.3 容器运行时
负责直接管理容器生命周期。k8s 支持包含 docker、containerd 在内的任何基于 k8s cri(容器运行时接口)实现的 runtime。
4 K8s 的核心对象
为了完成对大规模容器集群的高效率、全功能性的任务编排,k8s 设计了一系列额外的抽象层,这些抽象层对应的实例由用户通过 Yaml 或 Json 描述文件进行描述, 然后由 k8s 的 API Server 负责解析、存储和维护。

4.1 Pod
Pod 是 k8s 调度的基本单元,它封装了一个或多个容器。Pod 中的容器会作为一个整体被 k8s 调度到一个 Node 上运行。
Pod 一般代表单个 app,由一个或多个关系紧密的容器组成。这些容器拥有共同的生命周期,作为一个整体被编排到 Node 上。并且它们 共享存储卷、网络和计算资源。k8s 以 Pod 为最小单位进行调度等操作。
4.2 控制器
一般来说,用户不会直接创建 Pod,而是创建控制器来管理 Pod,因为控制器能够更细粒度的控制 Pod 的运行方式,比如副本数量、部署位置等。 控制器包含下面几种:
Replication 控制器(以及 ReplicaSet 控制器 ):负责保证 Pod 副本数量符合预期(涉及对 Pod 的启动、停止等操作);
Deployment 控制器:是高于 Replication 控制器的对象,也是最常用的控制器,用于管理 Pod 的发布、更新、回滚等;
StatefulSet 控制器:与 Deployment 同级,提供排序和唯一性保证的特殊 Pod 控制器。用于管理有状态服务,比如数据库等。
DaemonSet 控制器:与 Deployment 同级,用于在集群中的每个 Node 上运行单个 Pod,多用于日志收集和转发、监控等功能的服务。并且它可以绕过常规 Pod 无法调度到 Master 运行的限制;
Job 控制器:与 Deployment 同级,用于管理一次性任务,比如批处理任务;
CronJob 控制器:与 Deployment 同级,在 Job 控制器基础上增加了时间调度,用于执行定时任务。
4.3 Service
Service是对一组 Pod 的抽象,它定义了 Pod 的逻辑集合以及访问该集合的策略。
前面的 Deployment 等控制器只定义了 Pod 运行数量和生命周期, 并没有定义如何访问这些 Pod,由于 Pod 重启后 IP 会发生变化,没有固定 IP 和端口提供服务。Service 对象就是为了解决这个问题。
Service 可以自动跟踪并绑定后端控制器管理的多个 Pod,即使发生重启、扩容等事件也能自动处理, 同时提供统一 IP 供前端访问
通过 Service 就可以获得服务发现的能力,部署微服务时就无需单独部署注册中心组件
4.4 Ingress
Ingress不是一种服务类型,而是一个路由规则集合。
通过 Ingress 规则定义的规则,可以将多个 Service 组合成一个虚拟服务(如前端页面+后端 API)。
可实现业务网关的作用,类似 Nginx 的用法,可以实现负载均衡、SSL 卸载、流量转发、流量控制等功能。
4.5 Storge
Storage是 Pod 中用于存储的抽象,它定义了 Pod 的存储卷,包括本地存储和网络存储;它的生命周期独立于 Pod 之外,可进行单独控制。
4.6 资源划分
命名空间(Namespace):k8s 通过 namespace 对同一台物理机上的 k8s 资源进行逻辑隔离。
标签(Labels):是一种语义化标记,可以附加到 Pod、Node 等对象之上,然后更高级的对象可以基于标签对它们进行筛选和调用, 例如 Service 可以将请求只路由到指定标签的 Pod,或者 Deployment 可以将 Pod 只调度到指定标签的 Node。
注解(Annotations):也是键值对数据,但更灵活,它的 value 允许包含结构化数据。一般用于元数据配置,不用于筛选。 例如 Ingress 中通过注解为 nginx 控制器配置禁用 ssl 重定向。
5. 运行应用的流程
将某种编程语言所构建的应用打包为镜像,将该应用需要的镜像版本、对外暴露端口号和所需 CPU、内存等需求定义到 K8s Pod 模板,部署 Pod 模板并观察运行状态,调整模板配置以适应新的需求。
如果应用需要故障自愈等高级功能,则使用更高级的控制器如 Deployment、DaemonSet 等定义 Pod 模板即可。
6. K8S DNS
每个 K8s 集群都有自己独立的 DNS 服务,用于为集群中的 Pod 提供域名解析服务。
集群 DNS 服务有一个静态 IP,每个新启动的 Pod 内部都会在/etc/resolve.conf 中硬编码这个 IP 作为 DNS 服务器。
每当新的 Service 被发布到集群中的时候,同时也会在集群 DNS 服务中创建一个域名记录(对应其后端 Pod IP),这样 Pod 就可以通过 Service 的域名访问其对应的服务。
一些比较特殊的 Pod 也会注册到集群 DNS 服务器, 比如 StatefulSet 管理下的每个 Pod(以PodName-0-*, PodName-1-*的形式)。
集群的 DNS 服务器由集群内一个名为kube-dns的 Service 提供,它将 DNS 请求均衡转发到每个节点上的coredns-*Pod。
集群 DNS 服务使用CoreDNS作为后端,CoreDNS 是一个由 Go 实现的高性能且灵活的 DNS Server,支持使用自定义插件来扩展功能