从宏观上了解一下 k8s 的整体架构。
请你说一下 k8s 各个组件及其作用
功利一下吧,从面试角度来看。一般都会遇到一个问题“请你说一下 k8s 各个组件及其作用“。
Kubernetes 是一套编排系统。自动化容器化应用程序部署、扩展和管理的开源容器编排平台。有一些核心组件:
- kube-apiserver:Kubernetes 的 API 服务端,接受来自用户、命令行工具和其他组件的 API 请求,并处理它们;
- kube-scheduler:负责将新创建的 Pod 分配给集群中的节点,并根据一组策略选择最合适的节点;
- kube-controller-manager:运行多个控制器,这些控制器监控系统状态并尝试使系统达到期望状态,例如 ReplicaSet、Node 等;
- kubelet:运行在每个节点上,负责维护节点上的容器的生命周期,它与容器运行时交互,确保 Pod 中的容器正常运行;
- kube-proxy:在节点上维护⽹络规则,使服务能够在集群内部和外部进⾏⽹络通信,实现了服务 发现和负载均衡;
- container runtime
- coreDNS
- kube-dns
CoreDNS 和 Kube-dns
基本关系
- CoreDNS 是 kube-dns 的继任者,从 Kubernetes 1.11 开始成为默认的集群 DNS 解决方案 2
- 即使部署的是 CoreDNS,服务名称通常仍为 “kube-dns”(为保持兼容性),这可能导致混淆 2
- 两者都实现相同的基本功能:为 Kubernetes 集群提供 DNS 服务
关键区别
- 架构差异:
- CoreDNS: 单容器实现
- kube-dns: 使用三个容器(kubedns、dnsmasq、sidecar)1
- 技术栈:
- CoreDNS: 多线程 Go 实现
- kube-dns: 使用 dnsmasq 进行缓存,是单线程 C 实现 1
- 负缓存:
- CoreDNS: 默认部署启用负缓存
- kube-dns: 默认未启用 1
- 资源消耗:
- CoreDNS 通常使用更少的内存 1
- 性能表现:
- CoreDNS: 外部名称查询表现更佳(约3倍性能)
- kube-dns: 内部名称查询略微更好(约10%性能优势)1
- 可扩展性:
- 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实现⾼可⽤性的关键⽅法:
-
多节点部署:Kubernetes通常在多个节点上部署,每个节点运⾏着K8s的核⼼组件,如 kubeapiserver、etcd、kube-scheduler 和 kube-controller-manager。这种多节点架构确保了即 使某个节点发⽣故障,其他节点仍然可以继续提供服务。
-
etcd 的多节点复制:etcd 是 K8s 的数据存储后端,它采⽤多节点复制(Raft协议)来确保数据 的⾼可⽤性。当 etcd 集群中的节点之⼀失败时,其他节点可以继续提供数据服务。
-
负载均衡:Kubernetes 使⽤负载均衡器来分发流量到多个 kube-apiserver 节点,以确保API请 求能够均匀分布到各个节点上。这可以防⽌某个节点成为单点故障。
-
控制器的冗余部署:K8s 的控制器组件,如 kube-controller-manager 和 kube-scheduler,通常以多个副本的⽅式运⾏,以确保即使其中⼀个实例失败,其他实例也可以继续监控和管理资 源。
-
kubelet 的健康检查:K8s的kubelet组件会定期向API服务器发送节点的健康状态报告。如果 某个节点上的kubelet⽆法与API服务器通信,该节点将被标记为不可⽤,并且Pod将在其他可 ⽤节点上重新调度。
-
Pod的副本和⾃动恢复:K8s⽀持创建多个Pod的副本,并且可以通过控制器(如 ReplicaSet)来确保在Pod发⽣故障时⾃动重新创建新的Pod实例,以保持服务的可⽤性。
-
多可⽤区部署:在云环境中,K8s可以跨多个可⽤区部署,以确保即使整个可⽤区发⽣故障, 集群仍然可⽤。这需要在不同可⽤区之间设置适当的⽹络和负载均衡配置。
-
备份和恢复策略:定期备份etcd数据是⼀种保障K8s⾼可⽤性的重要⽅法。这样,在发⽣严重 故障时,可以使⽤备份数据来恢复整个集群状态。
综合来说,Kubernetes通过多节点部署、数据复制、负载均衡、冗余控制器、节点健康检查、 Pod副本、多可⽤区部署以及备份恢复策略等多种机制来实现⾼可⽤性。这些⽅法确保了K8s集群 在⾯对故障或节点失效时能够继续提供稳定的服务,保证了应⽤程序的可靠性。
Pod 的几种探针
在Kubernetes中,Pod探针(Probe)是⼀种⽤于检查容器内部状态的机制,⽤于确定容器是 否正常运⾏。Pod探针主要有三种类型:⽣命周期探针、就绪性探针和启动探针。
-
⽣命周期探针(Liveness Probe): 作⽤:⽤于检查容器是否正在运⾏,如果探针失败,则Kubernetes会认为容器已经不再 运⾏,并尝试重新启动容器。 配置属性:
- httpGet:通过HTTP GET请求检查容器的健康状态。可以指定HTTP路径和端⼝。
- exec:通过在容器内运⾏命令来检查健康状态。可以执⾏⾃定义脚本或命令。
- tcpSocket:通过检查容器的 TCP 端口是否打开来确定健康状态。
-
就绪性探针(Readiness Probe): 作⽤:⽤于检查容器是否已准备好接受流量,如果探针失败,则Kubernetes将从服务负 载均衡中删除容器,直到探针成功为⽌。 配置属性:与⽣命周期探针类似,也可以使⽤httpGet、exec或tcpSocket进⾏配置。
-
启动探针(Startup Probe): 作⽤:⽤于检查容器是否已经启动成功,不同于⽣命周期探针,启动探针只在容器启动时 执⾏⼀次,⽽不会随后再次执⾏。 配置属性:同样可以使⽤httpGet、exec或tcpSocket进⾏配置,但是通常使⽤较⻓的超 时时间来等待容器的启动。
这些探针允许 Kubernetes 根据容器的健康状态来管理Pod的⽣命周期。通过配置适当的探针,可 以确保容器在不同情况下的正常运⾏、就绪性和启动状态,从⽽提⾼应⽤程序的可靠性和可⽤性。 根据应⽤程序的特点和需求,可以选择配置⼀个或多个探针。