2. Kubernetes基础回顾
在深入跨云多集群架构之前,我们必须先夯实单集群内的核心对象模型与通信原理。Kubernetes 之所以能够成为分布式系统的“操作系统”,其根本在于它用一套声明式 API 将基础设施的复杂性抽象为若干可组合、可观测、可移植的对象。本章将聚焦于 Pod、Service、Deployment、Ingress 与 Namespace 这五个最核心的对象,剖析它们各自的职责边界、协作关系以及在实际生产环境中的设计要点。理解这些基础对象在单集群内的行为模式,是后续理解多集群服务网格、联邦调度和跨云故障域隔离的基石。
上图展示了单集群内核心对象的静态拓扑与动态协作关系。控制平面通过 API Server 暴露声明式接口,Deployment 作为工作负载的“期望状态”声明者,通过 ReplicaSet 间接管理 Pod 的生命周期。Service 作为一层稳定的虚拟 IP 抽象,屏蔽了后端 Pod IP 的易变性,而 Ingress 则在 L7 层将外部域名流量路由至对应的 Service。Namespace 则从逻辑上划分了资源边界,使得同一集群可以服务于多个团队或环境。下面我们将逐一拆解这些对象的设计哲学与实战要点。
2.1 Pod:最小调度单元与容器共享模型
核心原理:为什么 Pod 是原子单位?
Pod 是 Kubernetes 中可创建和部署的最小单元,它代表集群中运行的单个进程实例。但 Pod 并非简单的容器封装,其核心价值在于调度原子性与资源共享模型。一个 Pod 内的多个容器共享同一个网络命名空间(Network Namespace)、IPC 命名空间以及可选的共享存储卷(Volume)。这意味着 Pod 内的容器可以通过 localhost 直接通信,且它们对外的 IP 地址是唯一的。这种设计使得“紧密耦合的辅助进程”(如日志收集 sidecar、流量代理 sidecar)可以与主应用容器打包部署,共享生命周期。
操作流程:Pod 的创建与调度过程
- 提交:用户通过
kubectl apply -f pod.yaml向 API Server 提交 Pod 定义。 - 存储:API Server 将 Pod 对象写入 etcd,并返回确认信息。
- 调度:kube-scheduler 通过 watch 机制发现未绑定的 Pod,根据资源请求(requests/limits)、节点亲和性、污点容忍度等策略,选出最优节点并更新 Pod 的
nodeName字段。 - 运行:目标节点上的 kubelet 监听到 Pod 绑定信息,调用容器运行时(如 containerd)拉取镜像并启动容器。
- 探针:kubelet 根据
livenessProbe和readinessProbe定期检查容器健康状态,并将状态上报至 API Server。
案例拆解:多容器 Pod 的适用场景
假设我们有一个 Web 应用需要实时收集访问日志并推送至 Kafka。若将日志收集逻辑写入主应用代码,会耦合业务与基础设施逻辑。更优的方案是采用 Sidecar 模式:主容器运行 Nginx 服务,Sidecar 容器运行 Filebeat。两者共享一个名为 log-volume 的 emptyDir 卷,Nginx 将日志写入该卷,Filebeat 读取并转发。这种模式下,Pod 的 IP 是唯一的,Service 只需负载均衡到该 Pod 即可,无需关心内部有几个容器。
apiVersion: v1
kind: Pod
metadata:
name: web-with-sidecar
spec:
containers:
- name: nginx
image: nginx:1.25
ports:
- containerPort: 80
volumeMounts:
- name: log-volume
mountPath: /var/log/nginx
- name: filebeat
image: elastic/filebeat:8.11.0
volumeMounts:
- name: log-volume
mountPath: /var/log/nginx
readOnly: true
volumes:
- name: log-volume
emptyDir: {}
2.2 Deployment:声明式应用管理引擎
核心原理:调谐循环与期望状态
Deployment 是 Kubernetes 中最常用的工作负载控制器,它通过 控制器模式(Controller Pattern) 不断将当前状态(Actual State)调谐至期望状态(Desired State)。Deployment 本身不直接管理 Pod,而是通过管理 ReplicaSet 来实现 Pod 的副本数控制与版本更新。这种间接层级提供了回滚和版本追溯的能力:每次变更都会生成一个新的 ReplicaSet,旧版本 ReplicaSet 被保留但缩容至 0,以便快速回滚。
操作流程:滚动更新与回滚
| 步骤 | 操作 | kubectl 命令 | 效果 |
|---|---|---|---|
| 1 | 创建 Deployment | kubectl create deployment web --image=nginx:1.25 | 生成 ReplicaSet 与 1 个 Pod |
| 2 | 更新镜像版本 | kubectl set image deployment/web web=nginx:1.26 | 触发滚动更新,新 RS 创建,旧 RS 缩容 |
| 3 | 查看更新状态 | kubectl rollout status deployment/web | 显示更新进度直至完成 |
| 4 | 回滚到上一版本 | kubectl rollout undo deployment/web | 旧 RS 重新扩容,新 RS 缩容至 0 |
实战场景:多集群环境下的版本策略
在跨云多集群场景中,Deployment 的清单文件(YAML)通常作为应用发布单元被 GitOps 工具(如 ArgoCD)同步至多个集群。此时需注意 replicas 字段的差异化处理:例如生产集群 A 需要 10 个副本,灾备集群 B 仅需 2 个副本。建议将副本数通过 Kustomize 的 patches 或 Helm 的 values.yaml 进行覆盖,而非直接修改基础 YAML,以保证基础配置的一致性。
spec.minReadySeconds 可以避免新 Pod 刚启动尚未就绪就被计入可用状态,从而减少滚动更新期间的流量损失。同时,务必配置 resources.requests,否则调度器无法准确计算节点资源余量,可能导致 Pod 调度失败或节点过载。
2.3 Service:稳定的服务发现与负载均衡抽象
核心原理:虚拟 IP 与 Endpoint 管理
由于 Pod 是易失的,其 IP 不可依赖,Service 提供了一种稳定的访问入口。Service 通过标签选择器(Selector)动态关联一组 Pod,并维护一个 Endpoint 列表(或 EndpointSlice)。当 Pod 变化时,Service 的 Endpoint 自动更新。Service 的 ClusterIP 是虚拟 IP,仅在集群内部可达。kube-proxy 组件负责将发往 ClusterIP 的流量转发至后端 Pod,实现四层负载均衡。
类型对比与选择
| Service 类型 | 访问范围 | 典型场景 | 实现方式 |
|---|---|---|---|
| ClusterIP | 集群内部 | 内部微服务调用 | kube-proxy iptables/IPVS |
| NodePort | 集群外部(节点 IP+端口) | 临时调试、无 LB 环境 | 节点端口映射 |
| LoadBalancer | 集群外部(云 LB) | 云环境对外暴露服务 | 云控制器调用云 API |
| ExternalName | 集群外部(DNS CNAME) | 访问集群外数据库 | DNS 解析 |
案例拆解:跨云场景下的服务发现痛点
假设我们在 AWS 与 GCP 各有一个集群,且需要互相调用服务。若直接使用各自的 ClusterIP,则无法跨集群通信。此时有两种常见方案:其一,使用 LoadBalancer 类型将服务暴露至公网,但需自行处理 TLS 与鉴权;其二,使用 多集群 Service(MCS) 或服务网格(如 Istio)的跨集群负载均衡能力。在基础回顾阶段,我们需明确:单集群的 Service 无法解决跨集群发现问题,这将在后续章节详细展开。
clusterIP 设置为固定值(除非使用 headless service 或无头服务)。ClusterIP 的分配范围由 API Server 的 --service-cluster-ip-range 决定,手动指定容易冲突。对于不需要负载均衡的客户端直连场景,应使用 clusterIP: None 的 Headless Service,配合 StatefulSet 使用。
2.4 Ingress:七层路由与统一入口
核心原理:从四层到七层的跃迁
Service 工作在 L4(传输层),只能基于 IP 和端口转发。而 Ingress 工作在 L7(应用层),能够基于 HTTP 路径、域名、请求头等属性进行路由。Ingress 本身只是一个规则集合,真正执行转发的是 Ingress Controller(如 Nginx Ingress、Traefik、AWS ALB Ingress Controller)。Ingress 资源定义了“外部流量如何到达集群内 Service”的规则,而 Controller 负责将这些规则转化为实际的反向代理配置。
配置示例与路径匹配规则
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: web-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
rules:
- host: api.example.com
http:
paths:
- path: /v1(/|$)(.*)
pathType: ImplementationSpecific
backend:
service:
name: api-v1-service
port:
number: 80
- path: /v2(/|$)(.*)
pathType: ImplementationSpecific
backend:
service:
name: api-v2-service
port:
number: 80
实战场景:多集群入口的统一管理
在多集群架构中,Ingress 的挑战在于 DNS 解析与流量分发。通常我们会部署一个全局负载均衡器(如 AWS Route53、GCP Cloud DNS 或外部 DNS + 负载均衡器),将域名解析到多个集群的 Ingress Controller 入口 IP。此时,Ingress 的配置需要保持同步,且需考虑会话保持(Session Affinity)策略。建议将 Ingress 资源放入独立的 Namespace,并通过 GitOps 统一管理,避免各集群配置漂移。
service.beta.kubernetes.io/aws-load-balancer-type: nlb 与 GCP 的 networking.gke.io/load-balancer-type: Internal。建议使用 ingressClassName 字段指定 Controller,而非依赖默认类。
2.5 Namespace:多租户隔离与资源配额
核心原理:逻辑隔离而非安全隔离
Namespace 是 Kubernetes 用于实现多租户资源划分的逻辑边界。它不提供网络隔离(默认情况下),也不提供安全隔离(需配合 NetworkPolicy 与 RBAC)。Namespace 的主要作用是:资源对象的归属管理、资源配额(ResourceQuota) 的分配以及 策略(LimitRange) 的设定。例如,我们可以为 production 和 development 两个团队分别创建 Namespace,并设置不同的 CPU/内存配额。
操作流程:创建与切换
- 创建 Namespace:
kubectl create namespace dev - 在指定 Namespace 下创建资源:
kubectl apply -f app.yaml -n dev - 切换默认上下文:
kubectl config set-context --current --namespace=dev - 查看配额:
kubectl describe resourcequota -n dev
案例拆解:多集群中的命名空间策略
在跨云多集群管理中,我们通常会在每个集群中创建相同的 Namespace 集合(如 prod、staging、shared),以保证应用部署的一致性。但需注意,Namespace 的删除是级联的,会删除其下所有资源。在多集群场景下,误删 Namespace 可能导致多个集群的配置丢失。建议为关键 Namespace 开启 kubectl apply --prune 的防护,或使用 Velero 等备份工具定期备份 Namespace 下的资源清单。
service.namespace.svc.cluster.local)。若需隔离,必须配合 NetworkPolicy 定义允许的入站/出站规则。此外,系统创建的 kube-system、kube-public、kube-node-lease 不应被删除或修改。
2.6 集群架构总结与多集群扩展思考
回顾本章,单集群的架构可以概括为:控制平面(大脑) + 工作节点(四肢) + 声明式对象模型(语言)。Pod 是运行载体,Deployment 是管理载体,Service 是通信载体,Ingress 是入口载体,Namespace 是组织载体。这五个对象构成了绝大多数无状态应用部署的最小闭环。
当我们迈向跨云多集群时,上述对象的概念依然适用,但引入了新的维度:集群间服务发现、全局负载均衡、配置同步以及故障域隔离。例如,在多集群中,Deployment 的副本数可能需要根据集群的实时容量进行动态调整;Service 的 ClusterIP 无法跨集群访问,需要借助 MCS 或服务网格;Ingress 的 DNS 解析需要指向多个集群的入口。理解单集群的协作机制,是理解这些扩展方案的前提。
| 对象 | 层级 | 核心职责 | 常见故障点 |
|---|---|---|---|
| Pod | 计算 | 运行容器,共享网络/存储 | 镜像拉取失败、探针配置不当 |
| Deployment | 工作负载 | 声明式更新、回滚、扩缩容 | 资源请求未设置、更新策略过激 |
| Service | 网络 | 稳定虚拟 IP,负载均衡 | 选择器不匹配、端口命名错误 |
| Ingress | 入口 | L7 路由,域名分发 | Controller 未部署、注解拼写错误 |
| Namespace | 组织 | 资源隔离与配额 | 误删级联、配额耗尽 |