从宏观上了解一下 k8s 的整体架构。

请你说一下 k8s 各个组件及其作用

功利一下吧,从面试角度来看。一般都会遇到一个问题“请你说一下 k8s 各个组件及其作用“。

Kubernetes 是一套编排系统。自动化容器化应用程序部署、扩展和管理的开源容器编排平台。有一些核心组件:

  1. kube-apiserver:Kubernetes 的 API 服务端,接受来自用户、命令行工具和其他组件的 API 请求,并处理它们;
  2. kube-scheduler:负责将新创建的 Pod 分配给集群中的节点,并根据一组策略选择最合适的节点;
  3. kube-controller-manager:运行多个控制器,这些控制器监控系统状态并尝试使系统达到期望状态,例如 ReplicaSet、Node 等;
  4. kubelet:运行在每个节点上,负责维护节点上的容器的生命周期,它与容器运行时交互,确保 Pod 中的容器正常运行;
  5. kube-proxy:在节点上维护⽹络规则,使服务能够在集群内部和外部进⾏⽹络通信,实现了服务 发现和负载均衡;
  6. container runtime
  7. coreDNS
  8. kube-dns

CoreDNS 和 Kube-dns

基本关系

  • CoreDNS 是 kube-dns 的继任者,从 Kubernetes 1.11 开始成为默认的集群 DNS 解决方案 2
  • 即使部署的是 CoreDNS,服务名称通常仍为 “kube-dns”(为保持兼容性),这可能导致混淆 2
  • 两者都实现相同的基本功能:为 Kubernetes 集群提供 DNS 服务

关键区别

  1. 架构差异:
    • CoreDNS: 单容器实现
    • kube-dns: 使用三个容器(kubedns、dnsmasq、sidecar)1
  2. 技术栈:
    • CoreDNS: 多线程 Go 实现
    • kube-dns: 使用 dnsmasq 进行缓存,是单线程 C 实现 1
  3. 负缓存:
    • CoreDNS: 默认部署启用负缓存
    • kube-dns: 默认未启用 1
  4. 资源消耗:
    • CoreDNS 通常使用更少的内存 1
  5. 性能表现:
    • CoreDNS: 外部名称查询表现更佳(约3倍性能)
    • kube-dns: 内部名称查询略微更好(约10%性能优势)1
  6. 可扩展性:
    • CoreDNS: 模块化设计,支持插件扩展

各自的适用场景

CoreDNS 适用场景:

  • 现代 Kubernetes 集群(1.11+)
  • 需要定制化 DNS 功能的场景
  • 重视配置灵活性的环境
  • 对外部域名查询性能有较高要求的场景
  • 内存资源相对受限的环境

kube-dns 适用场景:

  • 旧版 Kubernetes 集群(1.11 之前)
  • 内部服务发现查询频繁且性能要求极高的场景
  • 已有完善的 kube-dns 运维经验的团队

C/S 架构

从更高层来看,K8S 整体上遵循 C/S 架构,从这个角度来看,可用下面的图来表示其结构:

                               +-------------+                              
                               |             |                              
                               |             |               +---------------+
                               |             |       +-----> |     Node 1    |
                               | Kubernetes  |       |       +---------------+
+-----------------+            |   Server    |       |                      
|       CLI       |            |             |       |       +---------------+
|    (Kubectl)    |----------->| ( Master )  |<------+-----> |     Node 2    |
|                 |            |             |       |       +---------------+
+-----------------+            |             |       |       
                               |             |       |       +---------------+
                               |             |       +-----> |     Node 3    |
                               |             |               +---------------+
                               +-------------+               

当然在这里,只画出了一个 Master,在生产环境中,为了保障集群的高可用,我们通常会部署多个 Master 。

Master

Master 节点有几个重要的功能:

  • 接收:外部的请求和集群内部的通知反馈
  • 发布:对集群整体的调度和管理

下面是一个 control plane,如下图所示:

+----------------------------------------------------------+          
| Master                                                   |          
|              +-------------------------+                 |          
|     +------->|        API Server       |<--------+       |          
|     |        |                         |         |       |          
|     v        +-------------------------+         v       |          
|   +----------------+     ^      +--------------------+   |          
|   |                |     |      |                    |   |          
|   |   Scheduler    |     |      | Controller Manager |   |          
|   |                |     |      |                    |   |          
|   +----------------+     v      +--------------------+   |          
| +------------------------------------------------------+ |          
| |                                                      | |          
| |                Cluster state store                   | |          
| |                                                      | |          
| +------------------------------------------------------+ |          
+----------------------------------------------------------+          

Cluster state store

集群状态的持久化存储。并且有 watch 机制,可以快速的通知各组件变更。

目前 kubernetes 的存储层为 etcd,所以目前以 etcd 来代表集群状态存储服务,即:将所有状态存储到 etcd 实例中。

API Server

整个集群的入口。接收外部的信号和请求,并将一些信息写入到 etcd 中。

这个组件也承担了认证权限的功能。

Scheduler

调度器。持续关注集群中未被调度的 Pod,并根据各种条件

  • 资源的可用性;
  • 节点的亲和性;
  • 或者一些其他的比如 toleration 之类的限制条件。

通过绑定 API 将 Pod 调度/绑定到 Node 上。

调度程序一般只考虑调度开始时, Node 的状态,而不考虑在调度过程中 Node 的状态变化。

Node

核心组件:

+--------------------------------------------------------+       
| +---------------------+        +---------------------+ |       
| |      kubelet        |        |     kube-proxy      | |       
| |                     |        |                     | |       
| +---------------------+        +---------------------+ |       
| +----------------------------------------------------+ |       
| | Container Runtime (Docker)                         | |       
| | +---------------------+    +---------------------+ | |       
| | |Pod                  |    |Pod                  | | |       
| | | +-----+ +-----+     |    |+-----++-----++-----+| | |       
| | | |C1   | |C2   |     |    ||C1   ||C2   ||C3   || | |       
| | | |     | |     |     |    ||     ||     ||     || | |       
| | | +-----+ +-----+     |    |+-----++-----++-----+| | |       
| | +---------------------+    +---------------------+ | |       
| +----------------------------------------------------+ |       
+--------------------------------------------------------+  
 

kubelet

Kubelet 实现了集群中关于 node 和 Pod 的控制功能。

Container runtime

最主要的功能是下载镜像和运行容器。有一些实现,Docker、rkt、cri-o。

Kube Proxy

代理服务,使用 Service 访问到 Pod。

每隔 Node 上启动一个 kube-proxy 的进程,通过编排 iptables 规则来达到效果。

Kube-apiserver

一个请求依次会经过认证、授权、准入控制等环节,最终来到 kube-apiserver 实际处理逻辑。

kube-apiserver 包含的东西有很多,当你在终端下执行 ./kube-apiserver -h 时,会发现有大量的参数。

这些参数除了认证,授权,准入控制相关功能外,还有审计,证书,存储等配置。主体功能、原理了解后,这些参数也就会比较容易配置了。

K8s 的组件高可用

Kubernetes(K8s)通过多种⽅式实现⾼可⽤性,确保在集群中的组件故障或节点失效时,整 个系统仍然可⽤。以下是K8s实现⾼可⽤性的关键⽅法:

  1. 多节点部署:Kubernetes通常在多个节点上部署,每个节点运⾏着K8s的核⼼组件,如 kubeapiserver、etcd、kube-scheduler 和 kube-controller-manager。这种多节点架构确保了即 使某个节点发⽣故障,其他节点仍然可以继续提供服务。

  2. etcd 的多节点复制:etcd 是 K8s 的数据存储后端,它采⽤多节点复制(Raft协议)来确保数据 的⾼可⽤性。当 etcd 集群中的节点之⼀失败时,其他节点可以继续提供数据服务。

  3. 负载均衡:Kubernetes 使⽤负载均衡器来分发流量到多个 kube-apiserver 节点,以确保API请 求能够均匀分布到各个节点上。这可以防⽌某个节点成为单点故障。

  4. 控制器的冗余部署:K8s 的控制器组件,如 kube-controller-manager 和 kube-scheduler,通常以多个副本的⽅式运⾏,以确保即使其中⼀个实例失败,其他实例也可以继续监控和管理资 源。

  5. kubelet 的健康检查:K8s的kubelet组件会定期向API服务器发送节点的健康状态报告。如果 某个节点上的kubelet⽆法与API服务器通信,该节点将被标记为不可⽤,并且Pod将在其他可 ⽤节点上重新调度。

  6. Pod的副本和⾃动恢复:K8s⽀持创建多个Pod的副本,并且可以通过控制器(如 ReplicaSet)来确保在Pod发⽣故障时⾃动重新创建新的Pod实例,以保持服务的可⽤性。

  7. 多可⽤区部署:在云环境中,K8s可以跨多个可⽤区部署,以确保即使整个可⽤区发⽣故障, 集群仍然可⽤。这需要在不同可⽤区之间设置适当的⽹络和负载均衡配置。

  8. 备份和恢复策略:定期备份etcd数据是⼀种保障K8s⾼可⽤性的重要⽅法。这样,在发⽣严重 故障时,可以使⽤备份数据来恢复整个集群状态。

综合来说,Kubernetes通过多节点部署、数据复制、负载均衡、冗余控制器、节点健康检查、 Pod副本、多可⽤区部署以及备份恢复策略等多种机制来实现⾼可⽤性。这些⽅法确保了K8s集群 在⾯对故障或节点失效时能够继续提供稳定的服务,保证了应⽤程序的可靠性。

Pod 的几种探针

在Kubernetes中,Pod探针(Probe)是⼀种⽤于检查容器内部状态的机制,⽤于确定容器是 否正常运⾏。Pod探针主要有三种类型:⽣命周期探针、就绪性探针和启动探针。

  1. ⽣命周期探针(Liveness Probe): 作⽤:⽤于检查容器是否正在运⾏,如果探针失败,则Kubernetes会认为容器已经不再 运⾏,并尝试重新启动容器。 配置属性:

    1. httpGet:通过HTTP GET请求检查容器的健康状态。可以指定HTTP路径和端⼝。
    2. exec:通过在容器内运⾏命令来检查健康状态。可以执⾏⾃定义脚本或命令。
    3. tcpSocket:通过检查容器的 TCP 端口是否打开来确定健康状态。
  2. 就绪性探针(Readiness Probe): 作⽤:⽤于检查容器是否已准备好接受流量,如果探针失败,则Kubernetes将从服务负 载均衡中删除容器,直到探针成功为⽌。 配置属性:与⽣命周期探针类似,也可以使⽤httpGet、exec或tcpSocket进⾏配置。

  3. 启动探针(Startup Probe): 作⽤:⽤于检查容器是否已经启动成功,不同于⽣命周期探针,启动探针只在容器启动时 执⾏⼀次,⽽不会随后再次执⾏。 配置属性:同样可以使⽤httpGet、exec或tcpSocket进⾏配置,但是通常使⽤较⻓的超 时时间来等待容器的启动。

这些探针允许 Kubernetes 根据容器的健康状态来管理Pod的⽣命周期。通过配置适当的探针,可 以确保容器在不同情况下的正常运⾏、就绪性和启动状态,从⽽提⾼应⽤程序的可靠性和可⽤性。 根据应⽤程序的特点和需求,可以选择配置⼀个或多个探针。