核心组件的运行机制
架构总览与核心交互模式
声明式API (Declarative API):
- 用户向系统提交一个“期望状态”(如:要有3个Nginx副本)。
- 系统持续工作,驱动当前状态向期望状态无限接近,用户无需发出“创建”、“扩容”等命令式指令。
监听-调和循环 (Reconcile Loop):
- 这是所有控制器的核心工作模式。每个控制器都通过Informer/List-Watch机制监听它们所关心资源(Pod、Service)的变化。
- 当监听到变化时,控制器将当前状态与API中声明的期望状态进行比对。
- 如果发现差异,控制器就会执行一系列操作(如创建新Pod),试图消除差异,使当前状态符合期望状态,这个过程就叫调和。
API Server - 集群的网关与交通枢纽
- 核心功能:所有RESTful操作的唯一入口,是其他所有组件交互的中枢。
- 认证 (Authentication):确认用户身份,支持客户端证书、Bearer Token等,API Server会依次尝试所有配置的认证方式。
- 授权 (Authorization):已认证的用户是否有权限执行操作,常用 RBAC 模式,判断用户是否拥有对某资源的权限(get, create)。
- 准入控制 (Admission Control):在授权之后、对象被持久化之前,对请求进行拦截和修改。
- 修改型:例如
MutatingAdmissionWebhook
,可以自动为Pod注入Sidecar容器(如Istio)或修改资源限制。 - 验证型:例如
ValidatingAdmissionWebhook
,可以基于自定义策略拒绝请求(如要求所有Pod都必须有app
标签)。
- 修改型:例如
- List-Watch:API Server支持客户端(如Controller)建立长连接来监听资源变化,是所有控制器能够实现实时调和的基石。
etcd:集群的状态真相之源
- 核心功能:分布式、高可用的键值存储数据库,持久化存储整个集群的所有配置数据和状态。
- 数据模型:采用层次化的键空间,例如
/registry/pods/<namespace>/<pod-name>
存储了一个Pod的完整JSON定义。 - 一致性协议:使用 Raft共识算法来保证集群中多个etcd实例之间的数据强一致性。任何写操作都必须经过集群多数节点确认,这意味着它通常是集群高可用的瓶颈,生产环境必须部署3个或以上奇数节点。
- Watch机制:API Server会监听etcd的变化,并将这些事件再转发给各个客户端(Controller),etcd是事件的最终来源。
Controller Manager:集群的自动化控制中心
- 核心功能:运行着一系列控制器,每个控制器都是一个独立的调和循环,负责管理某种资源。
- 详细机制(以Deployment控制器为例):
- 通过Informer监听Deployment和ReplicaSet的变化。
- 比较当前状态(实际的ReplicaSet状态)与期望状态(Deployment中定义的
replicas
)。 - 如果不一致,则调用API Server的接口,创建或删除ReplicaSet,使状态一致。
- 其他重要控制器:
- ReplicaSet控制器:监听ReplicaSet和Pod,确保运行的Pod副本数符合期望。
- Node控制器:监控Node状态,当Node失联时,负责标记Node为
NotReady
并驱逐其上的Pod。 - Endpoint控制器:监听Service和Pod的变化,维护Service的后端端点列表(Endpoints对象)。
- ServiceAccount控制器:确保每个命名空间都存在一个默认的ServiceAccount。
Scheduler:集群的智能调度大脑
- 核心功能:为新创建的、未调度的Pod(
spec.nodeName
为空的Pod)自动选择一个最合适的Node来运行。 - 过滤 (Filtering / Predicates):
- 调度器基于所有Node的当前状态,过滤出所有能够运行该Pod的节点,过滤完成后,得到一个可用节点列表。
- 检查策略:节点资源是否足够(CPU、内存)、端口冲突、节点选择器匹配、亲和性与反亲和性、卷拓扑等。
- 评分 (Scoring / Priorities):
- 调度器为过滤后的每个节点进行打分(0-100分),选择综合得分最高的节点。
- 评分策略:选择资源最空闲的节点(便于资源均衡)、选择与Pod亲和性高的节点、选择镜像已存在的节点等。
- 绑定 (Binding):确定最优节点后,调度器调用API Server的接口,将Pod的
spec.nodeName
字段更新为该节点名称,写操作会触发etcd的更新,之后该节点上的kubelet就会检测到这个Pod被分配给了自己,并开始创建容器。
Kubelet:节点上的 Pod 生命周期管理者
- 核心功能:运行在每个Node上的代理,负责保证Pod中的容器健康运行,它是Master和Node之间的桥梁。
- Pod来源:
- 来自API Server:监听被调度到本节点的Pod(主要来源)。
- 静态Pod (Static Pod):通过本地配置文件(如
/etc/kubernetes/manifests
)启动的Pod,kubelet会自动监控并启动它们,并为其在API Server创建一个镜像Pod对象,k8s控制平面组件(如API Server、Scheduler)通常就是以静态Pod方式运行的。
- 容器管理:通过 CRI 接口与容器运行时(Docker, containerd)交互,执行创建、删除容器等操作。
- 探针管理:执行用户配置的存活探针和就绪探针,并根据结果重启容器或通知Service更新端点。
- 资源监控:通过 cAdvisor 收集本节点和容器的CPU、内存、磁盘、网络使用情况等监控数据。
Kube Proxy:集群的网络代理
- 核心功能:维护节点上的网络规则,实现Service的负载均衡和服务发现功能。
- 监听:通过List-Watch监听API Server中Service和Endpoints的变化。
- 规则更新:当Service或后端Pod发生变化时,会更新本机的网络规则,确保发往Service虚拟IP的流量能被转发到实际的后端Pod。
- 三种模式:
- iptables模式(默认):使用Linux内核的iptables规则实现负载均衡。高性能,但规则链过长时性能会下降。
- ipvs模式:使用Linux内核的IP Virtual Server模块,为大型集群提供了更好的可扩展性和性能,支持更多的负载均衡算法。
- userspace模式(已弃用):流量在用户空间被转发,性能差。
深入分析集群安全机制
认证 (Authentication)
- X509客户端证书认证 (最常用、最安全)
- 工作原理:客户端使用由集群证书颁发机构签名的SSL证书来证明自己的身份,证书中的
subject
字段就是用户名和组信息。 - 流程:在
kubectl
与API Server建立TLS连接时,kubectl
会提供自己的证书(通常位于~/.kube/config
中),API Server使用集群的CA证书来验证该客户端证书的有效性和真实性。 - 适用场景:适用于人类用户和机器用户(如其他组件、CI/CD系统)的认证,是管理员访问集群的标准方式。
- 工作原理:客户端使用由集群证书颁发机构签名的SSL证书来证明自己的身份,证书中的
- 静态令牌文件 (Static Token File)
- 工作原理:API Server启动时指定一个包含
token
的CSV文件,客户端在请求头中携带Authorization: Bearer <token>
。 - 缺点:需要重启API Server来更新令牌,非常不灵活,不推荐用于生产环境。
- 工作原理:API Server启动时指定一个包含
- ServiceAccount令牌 (Pod身份认证)
- 工作原理:这是Pod与API Server通信的主要方式,当你创建一个ServiceAccount时,Kubernetes会自动为其创建一个Secret,其中包含一个签名的JWT令牌。
- Pod中的使用:该Secret会被自动挂载到Pod的
/var/run/secrets/kubernetes.io/serviceaccount/token
路径下,kubectl
或Pod内的应用程序可以使用这个令牌来认证。 - 流程:Pod中的进程使用此令牌与API Server交互,API Server通过验证JWT签名的有效性来认证Pod的身份。
- 其他认证方式
- Bootstrap Tokens:用于节点加入集群时的引导认证,是一种短期、预定义的令牌。
- OpenID Connect (OIDC):与第三方身份提供商集成,实现单点登录(SSO),这是企业级部署的推荐方式。
- Webhook Token Authentication:将令牌验证委托给外部的webhook服务,实现自定义认证逻辑。
授权 (Authorization)
RBAC - 基于角色的访问控制 (现行标准,最常用)
- Rule:规则,定义一组操作权限(如
apiGroups: [""], resources: ["pods"], verbs: ["get", "list", "create"]
)。 - Role 和 ClusterRole:角色,是规则的集合。
Role
作用于特定命名空间,ClusterRole
是集群范围的。 - Subject:主体,即被授予权限的对象,可以是
User
、Group
或ServiceAccount
。 RoleBinding 和 ClusterRoleBinding:绑定,将
Role/ClusterRole
中定义的权限授予一个Subject
,RoleBinding
可以将ClusterRole
的权限限制在特定命名空间内。优势:高度可配置、意图明确、易于审计和管理。
- Rule:规则,定义一组操作权限(如
ABAC - 基于属性的访问控制 (旧式,复杂)
- 工作原理:基于静态策略文件,策略文件包含一系列JSON格式的规则,每条规则指定了主体属性(如用户
alice
)、资源属性(如资源pods
)和操作属性(如动词get
)之间的匹配关系。 - 缺点:每次修改策略都需要重启API Server,难以管理和审计,基本已被RBAC取代。
- 工作原理:基于静态策略文件,策略文件包含一系列JSON格式的规则,每条规则指定了主体属性(如用户
Node授权 - 节点专用:授权kubelet对Node、Pod、Endpoint等资源的操作,确保kubelet只能操作绑定到其所在节点的Pod。
Webhook授权:将授权决策委托给外部的RESTful服务,实现自定义授权逻辑。
准入控制 (Admission Control)
- 工作机制:API Server接收到请求并通过认证授权后,会将请求对象依次发送给一系列准入控制器。每个控制器都可以:
- 验证 (Validating):检查对象是否符合某些标准,如果不符合则拒绝请求。
- 变更 (Mutating):修改传入的对象(例如,注入一个Sidecar容器或设置默认的资源限制)。
- 重要内置控制器:
- NamespaceLifecycle:防止在正在终止的命名空间中创建新资源。
- LimitRanger:强制执行命名空间中的
LimitRange
对象,为Pod设置默认的计算资源请求和限制。 - ResourceQuota:强制执行命名空间中的
ResourceQuota
对象,限制命名空间的总资源消耗。 - DefaultStorageClass:如果用户没有指定存储类,则为PersistentVolumeClaim设置一个默认的StorageClass。
- 动态准入控制 (Webhook) - 扩展性的核心
- ValidatingAdmissionWebhook:API Server将请求发送到外部webhook进行校验。
- MutatingAdmissionWebhook:API Server将请求发送到外部webhook进行修改,这是服务网格(如Istio)自动注入Sidecar容器的实现原理,它在用户不知情的情况下修改Pod Spec,注入
istio-proxy
容器。
- ServiceAccount的自动化
- 每个命名空间都有一个默认的
default
ServiceAccount。 - Pod可以通过
spec.serviceAccountName
字段指定要使用的ServiceAccount。如果不指定,则使用默认的。 - 对应的Secret令牌会被自动挂载到Pod的
/var/run/secrets/kubernetes.io/serviceaccount
目录下。
- 每个命名空间都有一个默认的
- Secret对象
- 用于存储敏感信息(密码、令牌、密钥)。
- 数据以Base64编码存储(并非加密!),提供基本的数据混淆。
- 注意:默认情况下,Secret以明文形式存储在etcd中,任何有etcd访问权限的人都能看到,必须启用静态加密才能保证其安全。
网络原理
Kubernetes 网络模型与基础
- Kubernetes网络模型的三条核心法则:
- 法则一:所有Pod都可以在不使用NAT的情况下与所有其他Pod通信。
- 法则二:所有节点都可以在不使用NAT的情况下与所有Pod通信。
- 法则三:Pod自己看到的IP地址(
ip addr show
)与别人看到的它的IP地址是同一个。
- 网络命名空间:每个Pod都拥有自己独立的网络命名空间,拥有自己独立的IP地址、端口空间、路由表和防火墙规则。
- 容器运行时网络:Docker的网络基础,包括
docker0
网桥、veth pair
(虚拟以太网设备对),一个veth pair
像一根网线,一端插在Pod的网络命名空间里(命名为eth0
),另一端插在宿主机的docker0
网桥上。
Pod网络解决方案 (CNI)
- CNI简介:
- 容器网络接口是一个标准的插件规范。它定义了一套简单的命令(如
ADD
,DEL
,CHECK
)和配置格式。 - kubelet会在创建Pod时(
pause
容器启动后)调用配置的CNI插件,为Pod配置网络,销毁Pod时也会调用插件进行清理。
- 容器网络接口是一个标准的插件规范。它定义了一套简单的命令(如
- 主流网络方案实现原理:
- Overlay Network :在底层网络之上再构建一个虚拟网络,将原始Pod数据包封装在另一个网络包(如UDP)进行隧道传输。
- 纯三层路由:要求底层网络设备支持路由。每个节点都知道其他节点Pod网段的路由,数据包通过路由直接转发,无封装。
- Underlay Network:Pod直接使用底层网络的IP地址,与主机网络处于同一层级。
外部接入网络 (Ingress)
- Ingress 不是 Service:它是一个API对象,描述的是流量路由规则,本身不具备流量处理能力。
- Ingress Controller:这是流量的实际处理者,它是一个 Deployment/Pod,通常以
DaemonSet
或Deployment
形式运行在集群内,它负责监听Ingress对象的变化,并动态配置自己(如Nginx的配置文件)来实现这些规则。 - 工作原理:
- 用户创建Ingress资源,定义“将
foo.example.com
的流量路由到my-service:80
”。 - Ingress Controller检测到这个变化。
- Ingress Controller(如Nginx)重新加载配置,使得访问
foo.example.com
的请求被反向代理到my-service
的ClusterIP上。 - Ingress Controller自身需要通过一个
LoadBalancer
或NodePort
类型的Service暴露到集群外部。
- 用户创建Ingress资源,定义“将
存储原理和应用
Volume 详解 - Pod 内的存储抽象
- emptyDir
- Volume类型:本地Volume类型(临时存储)。
- 工作原理:Pod被调度到节点时,在节点上创建一个空目录;Pod被删除时,目录及其内容也被清除。
- 用途:用于同一个Pod内多个容器之间的临时数据共享(如一个容器生产日志,另一个容器处理日志),不适合存储重要数据。
- nfs
- Volume类型:网络Volume类型(持久化存储)。
- 工作原理:将远程NFS服务器(Network File System)上的目录挂载到Pod中。
- 用途:经典的共享存储方案,允许多个Pod以读写模式共享同一存储空间,简单但性能和生产环境高可用性需谨慎考量。
- configMap / secret
- Volume类型:网络Volume类型(持久化存储)。
- 工作原理:将Kubernetes的ConfigMap或Secret对象中的数据以文件形式挂载到容器内,更新ConfigMap/Secret,已挂载的文件内容可以自动更新(依赖缓存时效性)。
- 用途:向容器注入配置信息和敏感数据,实现配置与镜像解耦。
- 云厂商Volume类型:
awsElasticBlockStore
(EBS),azureDisk
,gcePersistentDisk
等。- 工作原理:将云平台提供的块存储设备挂载到Pod中。
- 特点:通常是RWO(ReadWriteOnce) 模式,即只能被单个节点同时挂载进行读写,适合数据库等需要块设备特性的应用。
PV 和 PVC - 存储与计算的解耦
PersistentVolume (PV) - 集群级别的存储资源
- 定义:由集群管理员预先配置好的一块网络存储,它是集群中的资源,就像节点(Node)一样。
- 创建者:管理员。
- 关注点:定义存储的具体细节,如容量、访问模式(RWO, ROX, RWX)、存储类型(NFS, Ceph RBD)、以及如何连接到该存储的具体参数(如NFS path, server)。
apiVersion: v1 kind: PersistentVolume metadata: name: pv-nfs-example spec: capacity: storage: 10Gi # 存储容量 accessModes: # 访问模式 - ReadWriteMany # 可被多个节点读写 persistentVolumeReclaimPolicy: Retain # 回收策略,删除PVC后,PV如何处理 nfs: # 具体的存储类型和参数 path: /data/nfs server: nfs-server.example.com
PersistentVolumeClaim (PVC) - 用户对存储的请求
- 定义:是用户(应用开发者)对存储的请求,它类似于Pod,Pod消耗节点资源,而PVC消耗PV资源。
- 创建者:用户/开发者。
- 关注点:声明所需的存储规格,如大小、访问模式,不关心底层实现细节。
apiVersion: v1 kind: PersistentVolumeClaim metadata: name: my-app-pvc spec: accessModes: - ReadWriteMany resources: requests: storage: 5Gi # 请求5G存储 # storageClassName: "" # 可选,指定存储类名称
绑定与使用流程
- 用户创建一个PVC,指定需要5Gi的RWX存储。
- Kubernetes存储控制器会寻找一个满足要求的PV(如上面创建的10Gi的NFS PV)。
- 找到后,将PVC和PV绑定。绑定是排他的,一个PV只能绑定一个PVC。
- 用户在Pod中通过
volumes
字段引用PVC名称(而不是PV名称)。 - Pod被调度时,系统会确保Pod能访问到与其PVC绑定的PV所代表的实际存储。
apiVersion: v1 kind: Pod metadata: name: my-pod spec: containers: - name: app image: nginx volumeMounts: - mountPath: "/var/www/html" name: app-storage volumes: - name: app-storage persistentVolumeClaim: claimName: my-app-pvc # 关键:引用PVC名称
生命周期与回收策略 - persistentVolumeReclaimPolicy
- Retain(保留):删除PVC后,PV仍然存在,数据被保留,管理员可以手动回收卷,最安全。
- Delete(删除):删除PVC后,自动删除后端存储资产(如云盘),最方便但也最危险。
- Recycle(回收)- 已弃用:删除数据并让PV可被新的PVC使用。已被Dynamic Provisioning取代。
Dynamic Provisioning - 存储的自动化
核心概念:
- StorageClass (SC):定义了“存储类”,描述了可以动态创建PV的模板和创建者(Provisioner)。
- Provisioner:负责真正创建底层存储设备的组件(如
nfs-client-provisioner
,ebs.csi.aws.com
)。
工作流程:
管理员创建一个StorageClass,指定provisioner和参数。
用户创建一个PVC,并在其中指定
storageClassName
为上述SC的名字。关键:这个PVC不需要绑定一个现有的PV。
SC对应的provisioner会监听到这个“未绑定”的PVC,并自动地、按需地创建对应的后端存储和PV。
新创建的PV会自动绑定到请求它的PVC上。
# 1. 管理员创建StorageClass apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: fast-ssd provisioner: ebs.csi.aws.com # 指定使用AWS EBS的CSI驱动 parameters: type: gp3 --- # 2. 用户创建PVC,指定StorageClass apiVersion: v1 kind: PersistentVolumeClaim metadata: name: my-dynamic-pvc spec: accessModes: - ReadWriteOnce storageClassName: fast-ssd # 关键:指定存储类名 resources: requests: storage: 100Gi
CSI - 容器存储接口
- CSI:一个标准化的接口,允许存储厂商编写自己的插件而无需将代码合并到Kubernetes核心代码中。
- 工作原理:
- CSI驱动通常以DaemonSet和StatefulSet的形式部署在集群中。
- 它向kubelet和Controller Manager注册自己。
- 当需要操作存储时(create/delete/mount),kubelet会通过Unix Domain Socket调用本机的CSI驱动来执行具体操作。
- 带来的好处:
- 生态繁荣:存储厂商可以独立开发和发布驱动。
- 功能扩展:支持了诸如卷快照、卷克隆、卷扩容等高级特性。