← 返回 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定义
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定义
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 级防火墙,默认全通,按需收紧