Kubernetes 核心概念
云原生与微服务
云原生的定义中包含微服务、容器、服务网格、不可变基础设施和声明式 API 等代表技术,构建云原生应用主要依靠这些关键技术。
需要区分的是,云原生更侧重应用程序的运行环境,它是以 Kubernetes 和容器为基础的云环境;而微服务架构对应的是应用程序的软件架构。两者处在不同层面,只是在实践中往往同时出现。
微服务的优势
- 敏捷开发:微服务可以让服务更敏捷地开发上线,符合互联网业务快速迭代的特征。
- 技术自由:不需要局限在同一种语言。
- 弹性扩缩容:微服务可以灵活地应对服务的扩缩容问题。
- 组织匹配:微服务架构可以非常好地与组织架构相匹配。
Service Mesh 核心组件
服务拆分之后,服务间通信、配置、治理都需要基础设施来兜底。Service Mesh 把这些能力从业务代码中下沉出来,通常由以下组件构成。
- 服务注册中心:服务间通信的基础组件。服务注册自身节点,让调用方发现被调方的服务节点,以达到服务间点对点通信的目的。
- 配置中心:用于服务的基础配置更新,达到代码和配置分离的目的,减少服务的发布次数,让配置变更更快更及时。
- API 网关:通过统一的网关层收敛鉴权、链路 ID 生成等基础服务,并聚合后端服务为客户端提供 RESTful 接口;同时负责南北向流量(外网入口流量)的流量治理。
- 服务治理:通过限流、熔断等基础组件,杜绝微服务架构出现雪崩的隐患。
- 链路追踪:通过 trace 把整个微服务链路清晰地绘制出来,实现精准的故障排查,极大降低故障排查难度。
- 监控告警:通过 Prometheus 和 Grafana 这类基础组件绘制服务状态监控大盘,针对资源、服务、业务各项指标做精准的监控报警。
可观测性
可观测性是通过系统向外部输出信息,来检测系统内部的运行状态,主要包括日志、监控指标和链路追踪三部分。在 Kubernetes 中,日志一般用 EFK(Elasticsearch、Fluentd、Kibana)收集并分析,监控指标一般用 Prometheus 采集、配合 Grafana 展示,这两项都可以做到对业务代码无侵入。
链路追踪则是三者中唯一无法完全做到无侵入的一环,Istio 也不例外。网格代理 Envoy 能够自动识别 trace 中的 header,在请求 upstream 时自动生成 span 并携带发送;但要把整个链路的追踪信息串联起来,仍需要在代码中额外透传一部分链路追踪信息。
Istio 规定需要携带以下 header。
1 | x-request-id |
拿到这些信息后,再通过 Jaeger 的类库等工具进行 trace 分析。
Kubernetes 架构与组件
Kubernetes 集群由 Master 与 Node 两类角色组成,Master 负责决策与状态管理,Node 负责真正运行容器。

Master 组件
- API Server:提供 HTTP/HTTPS RESTful API,即 Kubernetes API,是集群的前端接口。各种客户端以及 Kubernetes 其他组件都通过它管理集群的各种资源。
- Scheduler:负责决定将 Pod 放在哪个 Node 上运行。调度时会充分考虑集群的拓扑结构、当前各节点的负载,以及应用对高可用、性能、数据亲和性的需求。
- Controller Manager:负责管理集群各种资源,保证资源处于预期的状态。为满足不同业务场景,其中实现了多种 Controller。
- etcd:负责保存集群的配置信息和各种资源的状态信息。数据变化时 etcd 通过 watch 通知 API Server,其他组件再从 API Server 上 watch 这些变化——etcd 只与 API Server 交互,它并不认识其余组件。
Node 组件
- kubelet:运行在集群所有节点上,负责启动 Pod 和容器,是 Node 上的 agent。当 Scheduler 确定在某个 Node 上运行 Pod 后,会把 Pod 的具体配置信息(image、volume 等)发送给该节点的 kubelet,kubelet 依此创建并运行容器,并向 Master 报告运行状态。kubelet 会在 API Server 上注册当前工作节点,定期汇报节点资源使用情况,并通过 cAdvisor 监控容器和节点的资源占用状况;它还会定时向 API Server 汇报心跳,一段时间内心跳没有更新,controller manager 就会把该节点的
Readycondition 置为Unknown(kubectl get nodes显示NotReady),并把它上面的 Pod 标记为NodeLost,随后按驱逐策略处理。 - kube-proxy:每个节点上运行的网络代理,实现 Service 概念的一部分。它监听 API Server 中 Service 和 Endpoint 的变化情况,并通过 iptables 或 ipvs 为服务配置负载均衡(仅支持 TCP 和 UDP)。
- Container Runtime:负责运行容器的软件。Kubernetes 支持多种容器运行时,如 containerd、CRI-O 以及任何实现了 CRI 的运行时;Docker 自 1.20 起被标记弃用,内置的 dockershim 在 1.24 中已正式移除。
- Pod 网络:以 CNI 插件形式提供,实现 Pod 间的相互通信,常见实现有 flannel、calico。
- CoreDNS(早期为 kube-dns):为集群提供 DNS 服务,是 Pod 内使用的 DNS 服务器,执行
kubeadm init时作为附加组件安装。
查看 kube-proxy 当前的工作模式。
1 | curl 127.0.0.1:10249/proxyMode |
集群运行模式
Kubernetes 的各组件可以有三种部署形态。
独立组件模式:系统各组件直接以守护进程的方式运行于节点之上,各组件相互协作构成集群。

静态 Pod 模式:除 kubelet 和容器运行时之外的其他组件(etcd、kube-apiserver、kube-controller-manager、kube-scheduler 等)都以静态 Pod 对象的形式运行于 Master 主机之上。

自托管模式(self-hosted):类似第二种方式,同样把除 kubelet 和容器运行时之外的组件运行为 Pod,区别在于这些 Pod 托管运行在集群自身之上、受控于 DaemonSet 类型的控制器,而不是静态 Pod 对象。
kubeadm 部署的集群运行为第 2 种或第 3 种模式,默认是静态 Pod 模式;需要自托管模式时,kubeadm init 加上 --features-gates=selfHosting 选项即可。第 1 种模式需要把各组件跑在系统之上的独立守护进程中,其间用到的证书及 Token 等认证信息也都需要手动生成,过程烦琐且极易出错,一般不推荐使用。
kubeadm 与 kubectl
kubeadm:用于初始化集群。kubectl:客户端命令行工具,用来部署和管理应用,查看、创建、删除和更新各种资源。
1 | kubectl get nodes # 查看节点状态 |
下面这段会话演示了给工作节点补打角色标签,以及静态 Pod 模式下控制面组件全部落在 Master 节点的样子。
1 | [root@k8s01 ~]# kubectl get nodes |
以 kubectl create deployment httpd-app --image=httpd --replicas=2 为例,一次部署请求会这样流转。
kubectl发送部署请求到 API Server,API Server 校验后把 Deployment 对象写进 etcd。- Deployment controller 通过自己的 Informer 从 API Server watch 到这个新对象,创建出对应的 ReplicaSet;ReplicaSet controller 同理 watch 到 ReplicaSet,创建出两个 Pod。
- Scheduler watch 到
spec.nodeName还是空的 Pod,执行调度并把两个副本分别绑定到 k8s02 和 k8s03。 - 两个节点上的 kubelet 各自 watch 到绑到自己身上的 Pod,创建并运行容器。
这里没有”API Server 主动通知某个组件”这回事:控制器、调度器、kubelet 都是自己持有 Informer 去 list-watch API Server。正因为是拉模型,控制器重启后重新 list 一遍就能续上,也才谈得上水平扩展和自愈。
之后执行 kubectl get pod 时,API Server 会从 etcd 中读取这些数据返回。

核心资源对象
Kubernetes 的 API 对象大体可分为五个类别:工作负载(Workload)、发现和负载均衡(Discovery & LB)、配置和存储(Config & Storage)、集群(Cluster)、元数据(Metadata)。它们基本上都围绕同一个核心目的设计,即如何更好地运行和丰富 Pod 资源,从而为容器化应用提供更灵活、更完善的操作与管理组件。
Kubernetes 的调度器是统一按照 Pod 而非容器的资源需求进行计算的,Pod 是 Kubernetes 里的原子调度单位。可以这样类比二者的关系:Pod 扮演的是传统基础设施里虚拟机的角色,而容器则是这个虚拟机里运行的用户程序。容器本质是被 Namespace 和 Cgroups 约束起来的一组进程,PID 1 底下可以有任意子进程(这也正是需要 --init、信号转发、僵尸进程回收这些东西的原因)。”一个容器只跑一个主进程”是最佳实践而不是机制约束——这样做生命周期才和容器一致、信号语义才清晰。
工作负载
Pod 是工作负载型资源中的基础资源,它负责运行容器,并为其解决环境性的依赖,例如向容器注入共享的或持久化的存储卷、配置信息或密钥数据等。其上的控制器按应用形态来选择。
- 无状态应用:
ReplicaSet用于确保每个 Pod 副本在任一时刻均能满足目标数量;Deployment用于管理无状态的持久化应用(例如 HTTP 服务器),它为 Pod 和 ReplicaSet 提供声明式更新,是构建在 ReplicaSet 之上的更高级控制器。 - 有状态应用:
StatefulSet用于管理有状态的持久化应用(如数据库服务程序),与 Deployment 的不同之处在于它会为每个 Pod 创建一个独有的持久性标识符,并确保各 Pod 之间的顺序性。 - 每节点一份:
DaemonSet用于确保每个节点都运行某个 Pod 的一个副本,新增的节点会被自动添加此类 Pod,节点移除时此类 Pod 会被回收。常用于运行集群存储守护进程(如 glusterd、ceph)、日志收集进程(如 fluentd、logstash),以及监控进程(如 Prometheus 的 NodeExporter、collectd、Datadog agent、Ganglia 的 gmond 等)。 - 一次性任务:
Job用于管理运行完成后即可终止的应用,例如批处理作业。Job 创建一个或多个 Pod 并确保其符合目标数量,直到 Pod 正常结束而终止。
发现和负载均衡
这一类包含为工作负载提供发现机制与负载均衡的 Service、Endpoint 资源,以及通过七层代理实现请求流量负载均衡的 Ingress 资源。
Service 是建立在一组 Pod 对象之上的资源抽象,它通过标签选择器选定一组 Pod,为这组 Pod 定义统一固定的访问入口。Service 有自己的 IP 和端口,并为后端 Pod 提供负载均衡。Service 对象创建完成后即可作为服务被各客户端访问,但要真正响应这些请求,还是要依赖各后端的资源对象。
需要注意的是,Service 的地址并不配置于任何主机或容器的网络接口之上,而是通过 Node 之上的 kube-proxy 配置成 iptables 或 ipvs 规则,从而将发往此地址的所有流量调度至其后端的各 Pod 对象。Service 网络在集群创建时予以指定,而各 Service 的地址则在用户创建 Service 时动态配置。

Service 主要有三种常用类型,每一种都以其前一种为基础才能实现。
ClusterIP:仅用于集群内部通信。NodePort:接入集群外部请求,工作于每个节点的主机 IP 之上。LoadBalancer:把外部请求负载均衡至多个 Node 的主机 IP 的 NodePort 之上。它需要协同集群外部的组件才能实现,而该外部组件并不接受 Kubernetes 的管理。
端口概念辨析

port:<cluster ip>:port,提供给集群内部访问 Service 的入口。nodePort:<node ip>:nodePort,提供给集群外部访问 Service 的入口。targetPort:容器真正监听的那个端口。可以直接写端口号,也可以写containerPort的name来引用。containerPort:声明性的元数据,只是把容器监听的端口写出来(便于起名字和查看),本身不参与任何转发。
这两者不是”映射”关系——写数字时 targetPort 必须等于容器实际监听的端口,否则流量送不到。
可以类比 docker run -p 16379:6379 --name k8s-redis redis redis-server:16379 是宿主机侧的端口,对应的是 nodePort;6379 才同时是 targetPort 和 containerPort,容器侧这两个值始终是同一个端口。
请求是如何到达 Pod 的
当通过 Service 的域名访问时,会先由 CoreDNS 解析出 Service 对应的 Cluster IP(虚拟 IP)。请求到达宿主机网络后,就会被 kube-proxy 所配置的 iptables 或 ipvs 规则拦截,之后被转发到实际的某个后端 Pod 上面去。
以 ipvs 模式、后端 3 个 Pod 为例。
- 生成一个 Service 时,kube-proxy 先在宿主机创建一个虚拟网卡(如
kube-ipvs0),并以 Service IP 作为它的 IP 地址。 - kube-proxy 通过 Linux 的 IPVS 模块为这个 IP 地址设置 3 个虚拟主机(负载均衡策略为轮询),虚拟主机的 IP 和端口正是对应被代理的那三个 Pod。
这样就不需要为每个 Pod 单独维护 iptables 规则,而是把规则放到内核态处理,降低了维护规则的代价;但包过滤、SNAT 等能力仍需要 iptables 来实现。
自己跟一遍这条链
上面是结论,想真正搞懂就得把规则翻出来看。iptables 模式下是一条三级跳转(下面是链的结构示意,实际输出里 XXX 是根据 Service 名字算出的哈希后缀):
1 | iptables -t nat -L KUBE-SERVICES -n # 第一级:按 目的IP:端口 匹配到 Service |
第二级那三行概率值最值得看:为什么是 0.33333、0.50000、然后没有概率?
因为这些规则是顺序求值的,每一条只在前面都没命中时才轮到它。三个后端要各占 1/3:
- 第一条
1/3命中 → 第一个 Pod; - 没命中的 2/3 里,第二条给
1/2→ 整体2/3 × 1/2 = 1/3; - 都没命中的剩下 1/3 无条件走第三条 →
1/3。
所以第 k 条的概率是 1/(n-k+1),而不是每条都写 1/n。理解了这一点,两个推论也就自然了:
一、iptables 模式没有会话保持,也配不了调度算法。 它用的是 statistic random,每个新连接独立掷一次骰子——同一个客户端的两次请求可能落到不同 Pod。想要会话保持只能靠 Service 的 sessionAffinity: ClientIP(那会额外用 -m recent 记住来源 IP),而 lc/wlc/sh 这类算法在 iptables 模式下根本无从表达。IPVS 模式才有 -s rr|lc|wlc|sh 可选:
1 | ipvsadm -Ln # 直接看到 ClusterIP 下挂着哪几个 RealServer、用什么算法 |
二、删 Pod 的瞬间为什么会有连接被打到已经死掉的后端。 规则更新不是原子的:Pod 被删 → endpoint controller 摘 endpoint → kube-proxy watch 到变化 → 重写这一串规则。这几步之间有毫秒到秒级的窗口,窗口内旧规则还在,流量照旧被 DNAT 到那个正在退出的 Pod 上。这也正是 Pod 优雅退出要在 preStop 里先 sleep 几秒的原因——等规则传播完再真正关闭监听。
规则条数上两种模式差别很大:iptables 模式下规则数随 Service 数 × 后端数 线性增长,而且是线性遍历匹配,几千个 Service 时 kube-proxy 每次全量刷新要花几百毫秒甚至更久;IPVS 用的是内核里的哈希表,查找接近 O(1),这才是大规模集群要换 IPVS 的真正原因。
配置与存储
Kubernetes 支持通过标准的 CSI(Container Storage Interface)统一存储接口扩展支持更多类型的存储系统。这一类中最常用的两个对象如下。
ConfigMap:以环境变量或存储卷的方式接入到 Pod 资源的容器中,可被多个同类的 Pod 共享引用,从而实现一次修改、多处生效。Secret:存储敏感数据,如私钥、密码等。
集群级资源
Pod、Deployment、Service 和 ConfigMap 等资源属于名称空间级别,可由相应的项目管理员管理。除此之外还有一些集群级别的资源,用于定义集群自身的配置信息,它们仅应该由集群管理员进行操作。
Namespace:资源对象名称的作用范围,绝大多数对象都隶属于某个名称空间,默认时隶属于default。Node:Kubernetes 集群的工作节点,其标识符在当前集群中必须是唯一的。Role:名称空间级别的、由规则组成的权限集合,可被 RoleBinding 引用。ClusterRole:集群级别的、由规则组成的权限集合,可被 RoleBinding 和 ClusterRoleBinding 引用。RoleBinding:将 Role 中的许可权限绑定在一个或一组用户之上,它隶属于且仅能作用于一个名称空间;绑定时既可以引用同一名称空间中的 Role,也可以引用全局名称空间中的 ClusterRole。ClusterRoleBinding:将 ClusterRole 中定义的许可权限绑定在一个或一组用户之上,它能够引用全局名称空间中的 ClusterRole,并能通过 Subject 添加相关信息。
Namespace 的作用边界
Namespace 可以把一个物理的 cluster 在逻辑上划分为多个虚拟 cluster,每个虚拟 cluster 就是一个 Namespace,不同 Namespace 里的资源对象是完全隔离的。但要注意这种隔离仅用于限制资源对象名称的作用域,并不能实现 Pod 间的网络通信隔离,网络层面的隔离要靠 NetworkPolicy。
两个内置的常用 Namespace:default 是创建资源时默认放入的名称空间,kube-system 存放 Kubernetes 自己创建的系统资源。

元数据型资源
此类资源对象用于为集群内部的其他资源配置其行为或特性。例如 HorizontalPodAutoscaler 可用于自动伸缩工作负载类型资源对象的规模,Pod 模板资源可为 Pod 资源的创建预制模板,而 LimitRange 则可为名称空间的资源设置 CPU 和内存等系统级资源的数量限制。
容器运行时与 CRI
CRI(Container Runtime Interface,容器运行时接口)是 kubelet 与底层容器运行时之间的标准接口。kubelet 调用下层容器运行时(如 containerd、Docker)的执行过程,都是通过 CRI 的 gRPC 接口间接完成的。
引入 CRI 带来两个好处。
- 将 kubelet 与容器运行时解耦,运行时可以自由替换而不必改动 kubelet。
- 解放 kubelet 的负担,运行时相关的实现细节不再堆积在 kubelet 内部。
CRI 接口本身可以分为两部分。
- 容器运行时服务 RuntimeService:主要负责管理 Pod 和容器的生命周期,例如创建、删除、查询容器。
- 镜像服务 ImageService:主要负责容器镜像的生命周期管理,例如拉取、删除、查询镜像。
顺带记住 Kubernetes 里这三个容易混淆的接口缩写。
CNI:容器网络接口,负责网络。CSI:容器存储接口,负责存储。CRI:容器运行时接口,负责容器运行。
图解汇总
📌 素材来源:以下图解为 尚硅谷 Kubernetes 课程 的配套截图,图片版权归尚硅谷所有,仅作个人学习笔记与复习整理之用。











































