第 6 章 · 02 调度网络与服务暴露 上一节认识了对象,本节回答两个"怎么":Pod 怎么被放到正确的节点(调度),外部流量怎么进来并到达容器(网络)。前半节走一遍 Pod 创建完整链路,掌握 nodeName、亲和性、污点容忍三套调度手段;后半节拆解 Service 四种类型、Ingress 与 DNS,以及它们背后的控制器与 kube-proxy 协作流程。 学习目标 完整复述 Pod 创建链路的七步流程 掌握 nodeName、nodeAffinity、taint/toleration 三类调度手段 说清 Service 四种类型与 NodePort 的语义 理解 Service 创建背后的 Endpoint、iptables、DNS 协作链路 掌握 Ingress
上一节认识了对象,本节回答两个"怎么":Pod 怎么被放到正确的节点(调度),外部流量怎么进来并到达容器(网络)。前半节走一遍 Pod 创建完整链路,掌握 nodeName、亲和性、污点容忍三套调度手段;后半节拆解 Service 四种类型、Ingress 与 DNS,以及它们背后的控制器与 kube-proxy 协作流程。
这是 K8s 面试第一高频流程题,七步链路:
核心认知:Scheduler 只负责"决定跑在哪",真正运行 Pod 的是 kubelet。整个链路的关键词是"监视"——组件之间不直接调用,而是通过 API server 观察状态变化,这正是控制器循环在流程层面的体现。
直接指定(nodeName):在 Pod spec 写 nodeName 指定节点——最粗暴,节点不存在则 Pod 卡 Pending。
节点亲和性(nodeAffinity):两类规则。requiredDuringSchedulingIgnoredDuringExecution 是硬性规则,不满足就不调度;preferredDuringSchedulingIgnoredDuringExecution 是软性偏好,找不到匹配节点也照常调度。
spec: affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: region operator: In # NotIn = 永不调度到这类节点 values: - asia - emea
污点与容忍(Taint/Toleration):与亲和性方向相反——节点打污点"拒绝",Pod 加容忍"我愿意接受"。三种 effect:
| effect | 行为 |
|---|---|
| NoSchedule | 阻止新资源调度到该节点 |
| PreferNoSchedule | 尽量调度到其他节点 |
| NoExecute | 阻止调度,且驱逐节点上已运行的 Pod |
典型场景:唯一节点打了 app=web:NoSchedule 后创建 Pod 会卡 Pending;修复方法是在 Pod 加匹配的容忍(key/value/effect 全部一致)。注意污点对"所有资源"生效,想按标签精细控制应用 nodeAffinity。
Pod 的 IP 是临时的(重建就变),Service 提供稳定的访问入口:把运行在一组 Pod 上的应用抽象为网络服务。两个关键认知:
Service 与 Deployment 没有直接连接——Service 通过 selector 直接指向 Pod(这是最常见的误解)。Service 生命周期与 Pod 无关:Pod 死了 Service 还在。
四种类型:
| 类型 | 说明 |
|---|---|
| ClusterIP(默认) | 仅集群内部可访问 |
| NodePort | 每个节点上暴露端口,内外皆可访问;自动附带创建 ClusterIP |
| LoadBalancer | 对接云厂商负载均衡器 |
| ExternalName | 把 Service 映射到外部地址 |
创建 Service 的两个必查点:targetPort 必须匹配 Pod 的 containerPort;selector 必须匹配至少一个 Pod 的标签——否则 Endpoints 为空、流量不通。NodePort 的端口范围 30000-32767,一般让集群自动分配;它暴露在每个节点上,并被路由到其中一个 Pod。
创建 Service 时,背后是一场三方接力:
容器侧还有两件事:kubelet 调度 Pod 时写入 /etc/resolv.conf 的 nameserver 指向 kube-dns;发往 Service IP 的请求经 iptables 规则(kube-proxy 添加)转发。排障时对照验证:kubectl describe svc 的 Endpoints 段应能与 kubectl get pod -o wide 的 Pod IP 对上。
Service 是集群内的稳定入口,Ingress 是集群外的 HTTP/HTTPS 路由:把外部流量按规则路由到集群内 Service。两个概念:Ingress(规则资源)与 Ingress Controller(规则的实现,本质是一组 Pod,如 Nginx Ingress Controller)——只有规则没有 Controller 等于白写。
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: someapp-ingress spec: rules: - host: my.host http: paths: - path: / backend: serviceName: someapp-internal-service servicePort: 8080
使用场景:多子域各自对应 Service;单域名多路径映射不同 Service。三个注意点:host 用通配符 * 等于把所有流量转发到对应后端,可能导致整个集群被打垮;建议配置 Default Backend 处理未匹配规则的请求;TLS 的 Secret 必须与 Ingress 在同一个命名空间。
集群 DNS:kube-dns 负责添加 Service 的 DNS 记录。跨命名空间引用格式 <service>.<namespace>——如 ConfigMap 中写 some_url: samurai.jack,指的是 jack 命名空间中的 samurai 服务。
NetworkPolicy:应用中心的网络规则,指定 Pod 如何被允许与其他网络实体通信。两个关键认知:默认行为是非隔离——没有任何策略时 Pod 进出流量全放行;流量是否放行是双向判断——源端 egress 放行且目的端 ingress 放行,两者都必须允许。注意 NetworkPolicy 需要支持它的 CNI 插件(Calico、Cilium 等)才生效。
本节打通了"调度 + 网络"两条链路:Pod 创建七步链路揭示了组件间的监视协作模式;nodeName、亲和性、污点容忍构成从强制到偏好的调度光谱;Service 四兄弟提供稳定入口,幕后是 Controller 建 Endpoint、kube-proxy 建 iptables、kube-dns 建记录的接力;Ingress 把 HTTP 路由带到集群门口。应用跑起来了、流量进来了,剩下的问题是运维:配置怎么管理、故障怎么发现、发布怎么滚动——下一节进入生产运维。
第 6 章第 3 节《配置存储与生产运维》将讲解 ConfigMap/Secret、探针三兄弟、资源限制与 QoS、滚动更新与蓝绿/金丝雀策略,以及标准排障路径。