← 返回 Kubernetes图解 目录

🌐 K8s网络与服务图解

Service类型/服务发现/Ingress/NetworkPolicy · SVG可视化

① Service类型对比

Service就像公司的电话接入系统
ClusterIP = 内线电话——只有公司内部员工(Pod)能互相拨打,外部打不进来
NodePort = 大门公告栏——在大门上贴一张公告,告诉外部访客"你要找XX部门,走30000号门"
LoadBalancer = 总机转接——外部拨打一个统一号码(公网IP),总机自动帮你转接到空闲的分机
ExternalName = 分机转外部——内线拨打分机号,实际转接到外部电话(如云数据库)
4种Service类型对比 ClusterIP 📞 内线电话 10.96.0.1:80 Pod1 Pod2 仅集群内部可访问 默认类型 ✅ 最常用 NodePort 📋 大门公告栏 NodeIP:30080 Pod1 Pod2 每个Node开放一个端口 范围:30000-32767 ⚠️ 端口范围受限 LoadBalancer 📠 总机转接 EXTERNAL-IP:80 LB Node1 Node2 云厂商提供外部LB 自动分配公网IP 💰 每个LB都收费 ExternalName 📞 分机转外部 my-db.internal.cloud 外部服务(RDS) → CNAME记录 不代理流量 🔗 DNS CNAME Service类型对比总结 ClusterIP NodePort LoadBalancer ExternalName 仅集群内部 集群+Node端口 公网LB 外部CNAME 微服务间调用 测试/临时暴露 生产对外服务 引用外部服务 type: ClusterIP type: NodePort type: LoadBalancer type: ExternalName ✅ 安全/默认 ⚠️ 端口有限 💰 费用高 🔗 仅DNS 关系:ClusterIP ⊂ NodePort ⊂ LoadBalancer(后者包含前者的所有能力)
4种Service类型:ClusterIP内部通信、NodePort开放端口、LoadBalancer公网LB、ExternalName引用外部
service.yaml — Service定义
📁 k8s/
pod.yaml
service.yaml
ingress.yaml
networkpolicy.yaml
apiVersion: v1 kind: Service metadata: name: my-app-svc labels: app: my-app spec: type: LoadBalancer # ← ClusterIP/NodePort/LoadBalancer/ExternalName selector: # ← 通过Label找到目标Pod app: my-app ports: - name: http port: 80 # ← Service暴露的端口 targetPort: 8080 # ← Pod容器端口 nodePort: 30080 # ← NodePort专用(30000-32767) - name: https port: 443 targetPort: 8443

② Service发现机制

Service发现 = 公司通讯录——新员工(Pod)入职后,不需要记住每个人的电话号码(IP),只要查通讯录(DNS)就能找到对应部门(Service)。
DNS方式:查通讯录 → my-svc.my-ns.svc.cluster.local → 得到ClusterIP
环境变量方式:入职时HR直接在工位上贴一张纸条 → MY_SVC_SERVICE_HOST=10.96.0.1
Service发现:DNS vs 环境变量 DNS方式(推荐)📞 公司通讯录 Pod (调用方) curl http://my-svc CoreDNS 解析服务名→IP 查询 DNS解析规则 同NS: my-svc → 跨NS: my-svc.prod.svc.cluster.local ✅ 推荐:Pod启动顺序无关,自动解析 ✅ 支持跨Namespace访问 环境变量方式 📝 工位纸条 Pod启动时注入 MY_SVC_SERVICE_HOST=10.96.0.1 MY_SVC_SERVICE_PORT=80 MY_SVC_PORT=tcp://10.96.0.1:80 ⚠️ 只能获取已存在的Service ⚠️ 先启动的Pod看不到后创建的Service 变量名规则:{SVC_NAME}_SERVICE_HOST/PORT 不推荐作为主要发现方式
DNS是推荐的Service发现方式,环境变量作为历史兼容仍存在
K8s DNS格式:<service-name>.<namespace>.svc.cluster.local。同Namespace下可简写为 <service-name>。CoreDNS是K8s默认DNS服务器,以Pod形式运行在kube-system命名空间中。

③ Ingress网关

Ingress = 前台门卫——外部访客来到公司大楼(集群),不认识你的员工(Pod),也不知道他们在哪个楼层。前台门卫(Ingress)根据访客要找的部门(域名/路径)指引到正确的办公室(Service)。
• 按部门指引 = 域名路由api.example.com → api-svc / web.example.com → web-svc
• 按楼层指引 = 路径路由/api → api-svc / /app → web-svc
• 检查证件 = TLS终结:门卫帮你拆快递(TLS解密),里面的信件(明文)再转给内部
Ingress:7层路由网关 外部用户 HTTPS请求 🚪 Ingress Controller (Nginx/Traefik) TLS终结 路由规则 7层(HTTP/HTTPS)路由 📋 Ingress规则 api.example.com → api-svc:80 web.example.com → web-svc:80 example.com/api → api-svc:80 *.example.com → wildcard-svc:80 TLS: tls.crt + tls.key api-svc ClusterIP: 10.96.1.1:80 Pod1 Pod2 web-svc ClusterIP: 10.96.1.2:80 Pod3 Pod4 api.example.com web.example.com TLS终结流程 客户端 ──HTTPS──→ Ingress Controller(解密TLS, 取出HTTP) ──HTTP──→ Service ──→ Pod
Ingress是7层(HTTP)路由网关,根据域名/路径将流量转发到不同Service,支持TLS终结
ingress.yaml — Ingress定义
📁 k8s/
service.yaml
ingress.yaml
networkpolicy.yaml
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: my-app-ingress annotations: nginx.ingress.kubernetes.io/ssl-redirect: "true" spec: tls: # ← TLS终结配置 - hosts: - api.example.com secretName: api-tls-secret # ← 存证书的Secret rules: # ← 路由规则 - host: api.example.com # ← 域名匹配 http: paths: - pathType: Prefix path: "/" backend: service: name: api-svc port: number: 80 - host: web.example.com http: paths: - pathType: Prefix path: "/" backend: service: name: web-svc port: number: 80

④ NetworkPolicy

NetworkPolicy = 门禁卡——公司里不是谁都能随便进任何部门的。门禁卡规定了谁能进(入站/Ingress)和谁能出(出站/Egress)。
• 没有门禁卡 = 默认所有人都可以进出(默认允许所有流量)
• 有门禁卡 = 只有卡上写的部门才能进出(白名单模式)
• 入站规则(Ingress) = 谁能来我这里   出站规则(Egress) = 我能去哪里
NetworkPolicy:网络隔离(门禁卡) ❌ 无NetworkPolicy(默认全通) Pod A Pod B Pod C 所有Pod可以互访 ⚠️ 前后端/数据库都在同一网络平面 ✅ 有NetworkPolicy(白名单) frontend backend database ✗ 禁止直接访问 frontend→backend→database 三层隔离 frontend不能直接访问database NetworkPolicy规则示例 backend的Ingress规则 允许来源:frontend Pod (podSelector) 允许端口:TCP 8080 拒绝:其他所有来源 database的Ingress规则 允许来源:backend Pod (podSelector) 允许端口:TCP 3306 拒绝:其他所有来源(含frontend)
NetworkPolicy以白名单模式工作:定义了规则后,只有匹配的流量被允许,其余全部拒绝
NetworkPolicy由网络插件(CNI)实现。如果CNI不支持(如flannel默认不支持),写NetworkPolicy也不会生效。支持NetworkPolicy的CNI:Calico、Cilium、Weave等。

⑤ 面试速答

4种Service类型的区别和使用场景?

ClusterIP:默认类型,分配集群内部IP,仅集群内可访问。用于微服务间内部调用。
NodePort:在ClusterIP基础上,在每个Node上开放一个端口(30000-32767)。适合测试环境或临时暴露服务。
LoadBalancer:在NodePort基础上,向云厂商申请一个外部负载均衡器(公网IP)。适合生产环境对外提供服务,但每个LB都有费用。
ExternalName:不代理流量,只返回CNAME记录,将集群内服务名映射到外部DNS名。适合引用集群外服务(如云RDS)。

Service是如何把流量转发到Pod的?kube-proxy的三种模式?

kube-proxy负责实现Service到Pod的转发,有三种模式:
userspace(旧模式):kube-proxy在用户空间监听,收到请求后转发到Pod。性能差。
iptables(默认):通过iptables规则做DNAT,将Service IP直接转到Pod IP。性能好但不能做健康检查。
IPVS(推荐):通过IPVS(LVS)做负载均衡,支持多种算法(rr/lc/wlc等),性能最好,适合大规模集群。

Service的Endpoint是什么?和Pod什么关系?

Endpoint是Service实际指向的Pod IP列表。当你创建Service并指定selector时,K8s自动创建同名的Endpoint对象,里面包含所有匹配selector的Pod的IP:Port。
如果Service不指定selector(如ExternalName或手动管理),则不会自动创建Endpoint,你需要手动创建Endpoint对象来指定外部IP。可以用 kubectl get endpoints 查看。

Ingress和Service的区别?为什么不直接用LoadBalancer?

Service是4层(TCP/UDP)负载均衡,每个对外服务需要一个LoadBalancer,费用高。
Ingress是7层(HTTP/HTTPS)路由网关,一个Ingress Controller可以处理多个域名/路径的路由规则,共用一个公网入口。
举例:你有10个HTTP服务,用LoadBalancer需要10个公网IP(贵);用Ingress只需1个公网IP,通过域名/路径区分(便宜)。Ingress还支持TLS终结、URL重写、限流等高级功能。

Ingress Controller是什么?常用的有哪些?

Ingress Controller是Ingress规则的执行者,以Pod形式运行在集群中。它监听Ingress资源变化,动态更新自己的配置。
常见选择:
Nginx Ingress:最成熟/使用最广,基于Nginx反向代理
Traefik:云原生设计,配置热更新,UI友好
Kong:API网关功能丰富,插件生态好
Envoy/Istio Gateway:Service Mesh方案

K8s中Pod之间如何通信?跨Node的Pod通信原理?

同Node同Pod:通过localhost通信(共享网络命名空间)。
同Node不同Pod:通过Pod CIDR网段通信,走veth pair + cbr0网桥。
跨Node不同Pod:通过CNI网络插件实现。以Calico为例:Pod发出包→veth pair→路由表→宿主机网卡→对端宿主机→对端veth pair→目标Pod。Calico用BGP协议在各Node间传播路由信息。

NetworkPolicy的Ingress和Egress规则怎么理解?

Ingress规则(入站):规定哪些流量可以进入目标Pod。类似"谁能来我办公室"。
Egress规则(出站):规定目标Pod可以访问哪些外部地址。类似"我能去哪些办公室"。
注意:K8s的NetworkPolicy是白名单模式——一旦对某个Pod应用了NetworkPolicy,所有未明确允许的流量都会被拒绝。默认不应用任何策略时,所有流量都允许。

Service发现中DNS和环境变量方式的优缺点?

DNS方式(推荐):
✅ 不受Pod启动顺序影响,随时可解析
✅ 支持跨Namespace:svc-name.ns.svc.cluster.local
✅ CoreDNS自动维护,Service创建/删除实时生效
环境变量方式
❌ 只能看到Pod启动前已存在的Service(启动后创建的看不到)
❌ 变量名有格式限制,不支持跨Namespace
❌ 端口多了变量名会非常冗长
✅ 不依赖DNS,简单直接(但仅作为兼容方式)

Headless Service是什么?使用场景?

Headless Service是将 clusterIP 设置为 None 的Service。它不分配ClusterIP,也不做负载均衡,DNS查询直接返回所有匹配Pod的IP列表。
使用场景:
1. StatefulSet:每个Pod有固定身份,客户端需要直连特定Pod(如MySQL主从)
2. 服务发现:需要知道所有Pod的IP,而非随机分配一个
DNS返回格式:pod-name.headless-svc.ns.svc.cluster.local → 直接解析到Pod IP

SessionAffinity和Headless Service分别解决什么问题?

SessionAffinity:让同一个客户端IP的请求始终转发到同一个Pod。设置 sessionAffinity: ClientIP。适合有状态会话(如WebSocket、登录状态),但Pod挂了会丢失。
Headless Service:不分配ClusterIP,DNS直接返回Pod IP列表。客户端可以自己选择连接哪个Pod。适合StatefulSet场景(如数据库主从,客户端需要明确连接主或从)。
区别:SessionAffinity是"透明"的粘性(客户端不知道),Headless是"显式"的选择(客户端知道并选择具体Pod)。

← 上一篇:核心概念 下一篇:部署与调度 →
核心三原则速记

K8s网络三原则:① Service 是 Pod 的稳定门面,ClusterIP 内部访问、NodePort/LoadBalancer 外部暴露 → ② Ingress 是 L7 流量入口,一个 IP 路由多个 Service → ③ NetworkPolicy 是 Pod 级防火墙,默认全通,按需收紧