Kubernetes
Kubernetes是什么?
Kubernetes 是一个可移植的、可扩展的开源平台,用于管理容器化的工作负载和服务,可促进声明式配置和自动化。Kubernetes 拥有一个庞大且快速增长的生态系统。Kubernetes 的服务、支持和工具广泛可用。
容器部署时代: 容器类似于 VM,但是它们具有轻量级的隔离属性,可以在应用程序之间共享操作系统(OS)。因此,容器被认为是轻量级的。容器与 VM 类似,具有自己的文件系统、CPU、内存、进程空间等。由于它们与基础架构分离,因此可以跨云和OS 分发进行移植。
Kubernetes能做什么?
服务发现和负载均衡
Kubernetes 可以使用 DNS 名称或自己的 IP 地址公开容器,如果到容器的流量很大,Kubernetes 可以负载均衡并分配网络流量,从而使部署稳定。
存储编排
Kubernetes 允许您自动挂载您选择的存储系统,例如本地存储、公共云提供商等。
自动部署和回滚
您可以使用 Kubernetes 描述已部署容器的所需状态,它可以以受控的速率将实际状态更改为所需状态。例如,您可以自动化 Kubernetes 来为您的部署创建新容器,删除现有容器并将它们的所有资源用于新容器。
自动二进制打包
Kubernetes 允许您指定每个容器所需 CPU 和内存(RAM)。当容器指定了资源请求时,Kubernetes 可以做出更好的决策来管理容器的资源。
自我修复
Kubernetes 重新启动失败的容器、替换容器、杀死不响应用户定义的运行状况检查的容器,并且在准备好服务之前不将其通告给客户端。
密钥与配置管理
Kubernetes 允许您存储和管理敏感信息,例如密码、OAuth 令牌和 ssh 密钥。您可以在不重建容器镜像的情况下部署和更新密钥和应用程序配置,也无需在堆栈配置中暴露密钥。
Kubernetes 组件
控制平面组件(Control Plane Components)
控制平面的组件对集群做出全局决策(比如调度),以及检测和响应集群事件
kube-apiserver
Kubernetes 控制面的前端。
etcd
etcd 是兼具一致性和高可用性的键值数据库,可以作为保存Kubernetes 所有集群数据的后台数据库。(用于持久化存储Kubernetes资源对象的KV数据库)
kube-scheduler
主节点上的组件,该组件监视那些新创建的未指定运行节点的 Pod,并选择节点让 Pod 在上面运行。
kube-controller-manager
在主节点上运行控制器的组件。
从逻辑上讲,每个控制器都是一个单独的进程,但是为了降低复杂性,它们都被编译到同一个可执行文件,并在一个进程中运行。
这些控制器包括:(Replication Controller、Node Controller、 ResourceQuota Controller 、 Namespace Controller、ServiceAccount Controller、 Token Controller、 Service Controller、Endpoint Controller)
-
节点控制器(Node Controller): 负责在节点出现故障时进行通知和响应。
-
副本控制器(Replication Controller): 负责为系统中的每个副本控制器对象维护正确数量的 Pod。
-
端点控制器(Endpoints Controller): 填充端点(Endpoints)对象(即加入 Service 与 Pod)。
-
服务帐户和令牌控制器(Service Account& Token Controllers): 为新的命名空间创建默认帐户和 API 访问令牌.
cloud-controller-manager
云控制器管理器是 1.8 的 alpha 特性。
与 kube-controller-manager 类似,cloud-controller-manager 将若干逻辑上独立的 控制回路组合到同一个可执行文件中,供你以同一进程的方式运行。 你可以对其执行水平扩容(运行不止一个副本)以提升性能或者增强容错能力。
下面的控制器都包含对云平台驱动的依赖:
-
节点控制器(Node Controller): 用于在节点终止响应后检查云提供商以确定节点是否已被删除
-
路由控制器(Route Controller): 用于在底层云基础架构中设置路由
-
服务控制器(Service Controller): 用于创建、更新和删除云提供商负载均衡器
Node 组件
kubelet
一个在集群中每个节点上运行的代理。它保证容器都运行在 Pod 中。
kubelet 接收一组通过各类机制提供给它的 PodSpecs,确保这些 PodSpecs 中描述的容器处于运行状态且健康。kubelet 不会管理不是由 Kubernetes 创建的容器。
kube-proxy
kube-proxy 是集群中每个节点上运行的网络代理,实现 Kubernetes Service 概念的一部分。
kube-proxy 维护节点上的网络规则。这些网络规则允许从集群内部或外部的网络会话与 Pod 进行网络通信。
理解 Kubernetes 对象
Kubernetes 架构
控制面到节点
从控制面(apiserver)到节点有两种主要的通信路径。 第一种是从 apiserver 到集群中每个节点上运行的 kubelet 进程。 第二种是从 apiserver 通过它的代理功能连接到任何节点、Pod 或者服务
API 服务器到 kubelet
从 apiserver 到 kubelet 的连接用于:
-
获取 Pod 日志
-
挂接(通过 kubectl)到运行中的 Pod
-
提供 kubelet 的端口转发功能。
apiserver 到节点、Pod 和服务
从 apiserver 到节点、Pod 或服务的连接默认为纯 HTTP 方式,因此既没有认证,也没有加密。 这些连接可通过给 API URL 中的节点、Pod 或服务名称添加前缀 https
来运行在安全的 HTTPS 连接上。 不过这些连接既不会验证 HTTPS 末端提供的证书,也不会提供客户端证书。 因此,虽然连接是加密的,仍无法提供任何完整性保证。 这些连接 目前还不能安全地 在非受信网络或公共网络上运行。
SSH 隧道
Kubernetes 支持使用 SSH 隧道来保护从控制面到节点的通信路径。在这种配置下,apiserver 建立一个到集群中各节点的 SSH 隧道(连接到在 22 端口监听的 SSH 服务) 并通过这个隧道传输所有到 kubelet、节点、Pod 或服务的请求。 这一隧道保证通信不会被暴露到集群节点所运行的网络之外。
SSH 隧道目前已被废弃。除非你了解个中细节,否则不应使用。 Konnectivity 服务是对此通信通道的替代品。
Konnectivity 服务
作为 SSH 隧道的替代方案,Konnectivity 服务提供 TCP 层的代理,以便支持从控制面到集群的通信。 Konnectivity 服务包含两个部分:Konnectivity 服务器和 Konnectivity 代理,分别运行在 控制面网络和节点网络中。Konnectivity 代理建立并维持到 Konnectivity 服务器的网络连接。 启用 Konnectivity 服务之后,所有控制面到节点的通信都通过这些连接传输。
容器:
容器运行时
容器运行环境是负责运行容器的软件。
Kubernetes 支持多个容器运行环境: Docker、 containerd、cri-o、 rktlet 以及任何实现 Kubernetes CRI (容器运行环境接口)。
创建大型集群
支持
在 v1.19 版本中, Kubernetes 支持的最大节点数为 5000。更具体地说,我们支持满足以下所有条件的配置:
-
节点数不超过 5000
-
Pod 总数不超过 150000
-
容器总数不超过 300000
-
每个节点的 pod 数量不超过 100
污点和容忍度
节点亲和性(详见这里) 是 Pod 的一种属性,它使 Pod 被吸引到一类特定的节点。 这可能出于一种偏好,也可能是硬性要求。 Taint(污点)则相反,它使节点能够排斥一类特定的 Pod。
容忍度(Tolerations)是应用于 Pod 上的,允许(但并不要求)Pod 调度到带有与之匹配的污点的节点上。
污点和容忍度(Toleration)相互配合,可以用来避免 Pod 被分配到不合适的节点上。 每个节点上都可以应用一个或多个污点,这表示对于那些不能容忍这些污点的 Pod,是不会被该节点接受的
Kubernetes 调度器
在 Kubernetes 中,调度 是指将 Pod 放置到合适的 Node 上,然后对应 Node 上的 Kubelet 才能够运行这些 pod。
kube-scheduler 调度流程
kube-scheduler 给一个 pod 做调度选择包含两个步骤:
-
过滤
-
打分
过滤阶段会将所有满足 Pod 调度需求的 Node 选出来。例如,PodFitsResources 过滤函数会检查候选 Node 的可用资源能否满足 Pod 的资源请求。在过滤之后,得出一个 Node 列表,里面包含了所有可调度节点;通常情况下,这个 Node 列表包含不止一个 Node。如果这个列表是空的,代表这个 Pod 不可调度。
在打分阶段,调度器会为 Pod 从所有可调度节点中选取一个最合适的 Node。根据当前启用的打分规则,调度器会给每一个可调度节点进行打分。
最后,kube-scheduler 会将 Pod 调度到得分最高的 Node 上。如果存在多个得分最高的 Node,kube-scheduler 会从中随机选取一个。
驱逐策略
Kubelet 能够主动监测和防止计算资源的全面短缺。 在资源短缺的情况下,kubelet 可以主动地结束一个或多个 Pod 以回收短缺的资源。 当 kubelet 结束一个 Pod 时,它将终止 Pod 中的所有容器,而 Pod 的 Phase 将变为 Failed。 如果被驱逐的 Pod 由 Deployment 管理,这个 Deployment 会创建另一个 Pod 给 Kubernetes 来调度
代理
用户在使用 Kubernetes 的过程中可能遇到几种不同的代理(proxy):
kubectl proxy:
-
运行在用户的桌面或 pod 中
-
从本机地址到 Kubernetes apiserver 的代理
-
客户端到代理使用 HTTP 协议
-
代理到 apiserver 使用 HTTPS 协议
-
指向 apiserver
-
添加认证头信息
apiserver proxy:
-
是一个建立在 apiserver 内部的“堡垒”
-
将集群外部的用户与群集 IP 相连接,这些IP是无法通过其他方式访问的
-
运行在 apiserver 进程内
-
客户端到代理使用 HTTPS 协议 (如果配置 apiserver 使用 HTTP 协议,则使用 HTTP 协议)
-
通过可用信息进行选择,代理到目的地可能使用 HTTP 或 HTTPS 协议
-
可以用来访问 Node、 Pod 或 Service
-
当用来访问 Service 时,会进行负载均衡
kube proxy:
-
在每个节点上运行
-
代理 UDP、TCP 和 SCTP
-
不支持 HTTP
-
提供负载均衡能力
-
只用来访问 Service
apiserver 之前的代理/负载均衡器:
-
在不同集群中的存在形式和实现不同 (如 nginx)
-
位于所有客户端和一个或多个 API 服务器之间
-
存在多个 API 服务器时,扮演负载均衡器的角色
外部服务的云负载均衡器:
-
由一些云供应商提供 (如 AWS ELB、Google Cloud Load Balancer)
-
Kubernetes 服务类型为 LoadBalancer 时自动创建
-
通常仅支持 UDP/TCP 协议
-
SCTP 支持取决于云供应商的负载均衡器实现
-
不同云供应商的云负载均衡器实现不同
service
集群功能模块之间的通信
API Server 与kubelet通信:每个Node上的kubelet每隔一个时间周期,就会调用一次API Server的REST接口报告自身状态,API Server在接收到这些信息后,会将节点状态信息更新到etcd中。此外,kubelet也通过API Server的Watch接口监听Pod信息,如果监听到新的Pod副本被调度绑定到本节点,则执行Pod对应的容器创建和启动逻辑;如果监听到Pod对象被删除,则删除本节点上相应的Pod容器;如果监听到修改Pod的信息,kubelet机会相应的修改本节点Pod的信息。
kube-controller-manager进程与API Server的交互。
kube-scheduler与API Server的交互。Scheduler通过API Server的Watch接口监听到新建Pod副本的信息后,会检索所有符合该Pod要求的Node列表,开始执行Pod调度逻辑,在调度成功后将Pod绑定到目标节点上。
为了缓解集群各模块对API Server的访问压力, 各功能模块都采用缓存机制来缓存数据,通过访问缓存数据来来间接访问API Server。
https://www.funtl.com/zh/service-mesh-kubernetes/#%E6%9C%AC%E8%8A%82%E8%A7%86%E9%A2%91
https://kubernetes.io/zh/docs/tutorials/stateless-application/expose-external-ip-address/
https://jimmysong.io/kubernetes-handbook/concepts/