Kubernetes Service 与 kube‑proxy 深度详解|五种 Service 类型、服务发现、会话保持、金丝雀发布、kube‑proxy 三种模式完整实验教程
摘要:Pod 生命周期是短暂的,重建、调度后 Pod‑IP 会发生变化,业务不能硬编码 PodIP 访问。Service 是 Kubernetes 集群核心网络抽象,提供固定虚拟 IP、负载均衡、服务发现。本文从实际痛点出发,完整讲解 VS‑Code 编写 K8s 资源、Service 五大类型、3 种服务发现方式、会话保持、基于副本的金丝雀灰度发布;深度拆解 kube‑proxy 的 iptables / IPVS / Userspace 三种工作模式,附带全套可复制 YAML、实验命令、原理图、排坑经验,适合云原生运维入门学习。
目录
- 前置:VS Code 编写 Kubernetes 资源清单
- 为什么需要 Service?真实业务痛点
- Service 核心概念与基础实操(ClusterIP)
- Kubernetes 三种服务发现机制
- Service 五大类型完整实验:ClusterIP / NodePort / LoadBalancer (MetalLB) / ExternalName / Headless 无头服务
- Service 会话保持 sessionAffinity
- 基于 Service+Deployment 实现金丝雀(灰度)发布
- kube‑proxy 底层深度剖析:iptables / IPVS / Userspace 模式
- 常见问题排坑总结
- 实验环境清理
1、前置:VS Code 编写 Kubernetes 资源清单
日常写 YAML 资源清单,推荐使用 VS Code,搭配两个官方扩展,实现语法校验、自动补全、集群资源可视化管理。
1.1 VS Code 两个核心扩展
- YAML by Red Hat(红帽 YAML 支持)
专门处理 YAML 语法,不是 K8s 专属,是底层依赖。
- YAML 语法错误检测、Schema 校验(字段错误、缺少必填项标红)
- 自动补全字段、枚举值,悬浮鼠标查看字段说明
- 文件格式化、代码大纲、锚点
& *支持 - Helm 的
!Ref !Sub自定义标签需要手动配置参数,否则报语法错误
- Kubernetes by Microsoft(微软 K8s 扩展)
K8s 运维工作台,会自动安装上面 YAML 扩展。
- 侧边树视图:查看命名空间、Pod、Deployment、Service、Node,实时刷新
- 右键直接操作资源:
apply / delete / describe / 日志 / 进入pod终端 / 端口转发 - Helm chart 脚手架、仓库管理
- 自动拉取集群 CRD 的 OpenAPI Schema,实现自定义资源补全
⚠️注意:Kubernetes 扩展本身不做语法校验,只是提供 schema,真正校验、补全逻辑全部交给 YAML 扩展;CRD 补全需要 VS Code 能连通 K8s 集群。
1.2 VS Code 连接 K8s 集群完整步骤
- 下载 Windows 版
kubectl.exe,放到$HOME\.kube\目录,把这个目录加入系统环境变量PATH。 - 将 K8s master 节点
~/.kube/config集群认证配置文件拷贝到 Windows 本地路径:$HOME\.kube\config。 - 重启 VS Code,打开 Kubernetes 侧边栏,刷新,即可看到集群全部资源。
1.3 使用 VS Code 编写资源
- 新建本地文件夹存放 yaml 清单,用 VS Code 打开该文件夹。
- 新建
.yaml文件,输入首字母例如p,编辑器弹出 Kubernetes 资源模板,选择Kubernetes Pod自动生成基础模板。 - 补全小技巧:输入字段后加上冒号
:,触发自动提示。 - 写完 yaml,右键文件,选择
Apply直接部署资源,不需要来回切换命令行终端。
示例自动生成 Pod 模板:
yaml
apiVersion: v1
kind: Pod
metadata:
name: myapp
labels:
app.kubernetes.io/name: myapp
spec:
containers:
- name: myapp
image: <Image>
resources:
limits:
memory: "128Mi"
cpu: "500m"
ports:
- containerPort: <Port>
2、为什么需要 Service?真实业务痛点
Pod 是短暂生命周期资源 ,Deployment 扩缩容、滚动更新、节点故障都会删除重建 Pod,Pod 的 IP 地址会随之改变。
示例 1:直接访问 PodIP 的问题
Pod 重建 IP 就变,客户端无法写死 PodIP 访问业务。集群外部网络默认也不能直接访问 PodIP。
yaml
kubectl run web --image=hub.laoma.cloud/library/httpd --image-pull-policy=IfNotPresent -o yaml --dry-run=client > pod-web.yml
kubectl apply -f pod-web.yml
kubectl get pod -o wide
# 拿到PodIP,集群外部无法直接curl访问,pod删除重建IP发生变化
示例 2:hostPort 端口绑定坑
hostPort 会把容器端口直接绑定宿主机端口,同一个宿主机同一个端口只能被一个进程占用。
yaml
ports:
- containerPort: 80
hostPort: 8080
当 Deployment 副本数大于 1,多个 Pod 调度到同一节点,会出现 Pod Pending,事件提示:didn't have free ports for the requested pod ports,节点没有空闲端口。
✨痛点总结
- Pod IP 动态变化,客户端不能硬编码 PodIP;
- hostPort 端口冲突,无法单机多副本;
- 多副本业务缺少内置负载均衡;
- Pod 故障重建,前端访问地址需要不断修改。
👉 Service 就是用来解决上面全部问题的核心资源。
Service 核心定义
Service 将一组 Pod 封装成一个网络服务。Service 拥有固定不变 Cluster‑IP,实现负载均衡、服务发现。
- Service 通过
selector标签选择器筛选后端 Pod,自动维护 Endpoints(端点列表,保存所有后端 PodIP + 端口); - Pod 新建、删除、重建,Endpoints 会自动更新,Service IP 永远不会改变;
- 底层由每个节点上的
kube‑proxy组件实现流量转发; - 业务客户端只访问 Service,完全不需要感知后端 Pod 变化。
实验准备命名空间
yaml
kubectl create ns services
kubectl config set-context --current --namespace services
3、Service 基础实操:ClusterIP(默认类型)
先创建 3 副本 httpd Deployment 作为后端业务
yaml
kubectl create deployment web --image=hub.laoma.cloud/library/httpd:2.4.58 --replicas=3
kubectl get pods --show-labels
创建 ClusterIP Service,--tcp=Service端口:Pod容器端口
yaml
kubectl create service clusterip web --tcp=8080:80
kubectl get svc
输出示例
yaml
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
web ClusterIP 10.103.19.150 <none> 8080/TCP 6m
查看 Service 详情,重点看Selector、Endpoints
yaml
kubectl describe service web
Selector: app=web:标签选择器,匹配哪些 Pod 作为后端;Endpoints:所有匹配标签 Pod 的PodIP:容器端口集合,真实后端地址。
访问测试
yaml
curl 10.103.19.150:8080
验证 Service 四大核心能力
1)负载均衡能力
修改每个 Pod 主页为 Pod 名称,循环访问 Service 观察流量分发
yaml
for pod in $(kubectl get pods -o name | awk -F/ '{print $2}')
do
kubectl exec -it $pod -- bash -c "echo \$pod > htdocs/index.html"
done
# 循环60次访问service
for i in {1..60};do curl -s 10.103.19.150:8080;done|sort |uniq -c
现象:请求均衡分发到各个后端 Pod。
2)自动发现新增 Pod
新建一个拥有相同标签app=web的 Pod,会自动加入 Service 后端列表
yaml
kubectl run web --image=hub.laoma.cloud/library/httpd --labels=app=web
for i in {1..60};do curl -s 10.103.19.150:8080;done|sort |uniq -c
3)Pod 重建,Service 自动更新 Endpoints
重启 Deployment,所有 Pod 全部重建,Service 自动同步后端端点,访问不受影响
yaml
kubectl rollout restart deployment web
for i in {1..60};do curl -s 10.103.19.150:8080;done|sort |uniq -c
4)Deployment selector 和 Service selector 互相独立
Deployment 的 selector 用于管理 Pod;Service selector 只用来挑选后端 Pod,两者标签可以完全不一样,互不绑定。
示例:deployment 匹配
app1:web1,service 匹配app2:web2,只要 Pod 同时具备这两个标签就可以作为后端。
⚠️重要知识点:ClusterIP ping 不通是正常现象!
ClusterIP 是内核 iptables/ipvs 虚拟出来的 IP,只处理 Service 定义的 TCP/UDP 业务端口,不处理 ICMP 协议(ping)。
现象:ping ClusterIP 没有回应,但是 curl 访问业务端口正常,属于预期行为,不是故障。
yaml 方式创建 Service
从命令行导出 yaml 模板
yaml
kubectl delete svc web
kubectl create service clusterip web --tcp=8080:80 -o yaml --dry-run=client > svc-web.yml
svc‑web.yml
yaml
apiVersion: v1
kind: Service
metadata:
labels:
app: web
name: web
spec:
ports:
- name: 8080-80
port: 8080 # Service(ClusterIP)监听端口
protocol: TCP
targetPort: 80 # 后端Pod容器端口
selector:
app: web # 标签选择器,筛选后端Pod
type: ClusterIP
字段说明
port:Service 自身端口(ClusterIP 端口)targetPort:Pod 容器里面业务监听端口selector:标签筛选后端 Podtype:服务类型,默认ClusterIP
4、K8s 三种服务发现方式
服务发现:集群内部 Pod 如何找到 Service 访问后端业务。一共 3 种方式。
方式 1:直接写 ClusterIP 访问
直接写死 Service 的 ClusterIP 地址访问。 ✅优点:简单;❌缺点:ClusterIP 是集群动态分配,IP 发生变化业务就要改配置,生产环境不推荐。
实验示例:mysql + wordpress
yaml
# 创建mysql pod
kubectl run mysql --image=hub.laoma.cloud/library/mysql \
--image-pull-policy=IfNotPresent \
--env=MYSQL_ROOT_PASSWORD=redhat \
--env=MYSQL_USER=tom \
--env=MYSQL_PASSWORD=redhat \
--env=MYSQL_DATABASE=blog \
--dry-run=client -o yaml > pod-mysql.yaml
kubectl apply -f pod-mysql.yaml
kubectl expose pod mysql --port=3306 --target-port=3306
# 使用service ip访问数据库
mysql -u tom -predhat -h 10.111.69.45 --ssl-mode=DISABLED -e 'show databases;'
方式 2:环境变量方式发现 Service
⚠️硬性前提:必须先创建 Service,再启动 Pod! Pod 启动的时候,会把当前命名空间已经存在的 Service 注入环境变量;如果 Pod 先启动,后续新建 Service,不会自动注入到已经运行的 Pod。
yaml
kubectl run test --rm -it --image=hub.laoma.cloud/library/busybox sh
env|grep MYSQL
输出示例
yaml
MYSQL_SERVICE_HOST=10.111.69.45
MYSQL_SERVICE_PORT=3306
业务程序读取MYSQL_SERVICE_HOST拿到服务地址。 ❌缺点:依赖启动顺序;跨命名空间 Pod 拿不到对方 Service 环境变量,生产很少使用。
方式 3:DNS 域名访问(生产首选)
K8s 集群默认部署 CoreDNS,提供集群内部 DNS 解析。 完整 DNS 域名格式: 服务名.命名空间.svc.cluster.local
- 同一个命名空间可以简写,直接写 Service 名字即可。
查看 coredns 组件
yaml
kubectl get deployments.apps -n kube-system |grep coredns
# kube‑dns serviceIP固定:10.96.0.10
kubectl get svc kube-dns -n kube-system
测试 DNS 解析
yaml
kubectl run busybox --rm -it --image=hub.laoma.cloud/library/busybox /bin/sh
# 完整域名访问
wget mysql.services.svc.cluster.local:3306
# 同命名空间简写,直接写service名字
wget mysql:3306
Pod 内部/etc/resolv.conf的 nameserver 指向10.96.0.10,也就是 coredns 的 serviceIP。
✅生产最佳实践:业务配置全部写 Service 域名,不写 IP,不需要关心 ClusterIP 变化。 wordpress 连接数据库直接配置环境变量:
WORDPRESS_DB_HOST=mysql。
5、Service 五大类型详解
| Service 类型 | 核心作用 | 访问范围 |
|---|---|---|
| ClusterIP(默认) | 分配集群内部虚拟 IP | 仅集群内部 Pod 访问 |
| NodePort | 每个节点打开统一宿主机端口 | 集群内外都可访问 |
| LoadBalancer | 分配独立外部 VIP,需要 MetalLB | 外部客户端访问 |
| ExternalName | DNS CNAME 代理外部域名 | 集群内访问外部域名 |
| Headless 无头服务 | 不分配 ClusterIP,DNS 直接返回 PodIP | 多用于 StatefulSet 有状态应用 |
5.1 ClusterIP
默认类型,分配集群内部网段虚拟 IP;NodePort、LoadBalancer 底层都依赖 ClusterIP。 设置clusterIP: None就是无头 Headless Service。
5.2 NodePort
- 集群每个节点都会监听同一个 NodePort 端口 ,端口默认范围:
30000‑32767; - 外部客户端访问
任意节点IP:NodePort端口; - 创建 NodePort Service 会自动生成对应的 ClusterIP。
yaml
apiVersion: v1
kind: Service
metadata:
labels:
app: web
name: web
spec:
ports:
- port: 8080
nodePort: 30080 # 手动指定,不指定自动随机分配
protocol: TCP
targetPort: 80
selector:
app: web
type: NodePort
端口区分:
nodePort:宿主机节点监听端口;port:ClusterIP 服务端口;targetPort:Pod 容器业务端口。
访问示例:curl http://节点IP:30080
5.3 LoadBalancer
原生 K8s 本身没有实现外部负载均衡;裸金属物理机集群需要部署 MetalLB 组件,分配外部局域网 VIP。
MetalLB 完整部署
yaml
wget https://laoma.cloud/class/course-materials/softwares/stage03/metallb-0.14.8.tar.gz
tar -xf metallb-0.14.8.tar.gz
sed -i 's/quay.io/hub.laoma.cloud/g' metallb-0.14.8/config/manifests/metallb-native.yaml
kubectl apply -f metallb-0.14.8/config/manifests/metallb-native.yaml
# 等待所有pod就绪
kubectl get all -n metallb-system
配置 IP 地址池(给 LoadBalancer 分配的外部 IP 段) ippool.yaml
yaml
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: first-pool
namespace: metallb-system
spec:
addresses:
- 10.1.8.40-10.1.8.80
L2.yaml 二层宣告配置
yaml
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
name: example
namespace: metallb-system
kubectl apply -f ippool.yaml
kubectl apply -f L2.yaml
创建 LoadBalancer Service
yaml
apiVersion: v1
kind: Service
metadata:
labels:
app: web
name: web
spec:
ports:
- port: 80
targetPort: 80
selector:
app: web
type: LoadBalancer
创建后EXTERNAL‑IP字段会分配来自 IPAddressPool 的外部 IP,客户端直接访问这个 VIP。
📝流量路径:客户端 → MetalLB ARP 宣告 VIP → 节点 kube‑proxy → Service → 后端 Pod MetalLB 只负责 ARP 宣告占用 IP,流量转发全部依靠 kube‑proxy。
5.4 ExternalName
不做流量代理,只做 DNS CNAME 记录。集群内部解析 Service 域名,直接 CNAME 跳转到外部域名。
yaml
apiVersion: v1
kind: Service
metadata:
name: www
spec:
type: ExternalName
externalName: www.laoma.cloud
集群内访问www.services.svc.cluster.local,DNS 直接返回 CNAME 记录指向www.laoma.cloud。
5.5 Headless 无头服务
设置clusterIP: None,不分配 ClusterIP 虚拟 IP,kube‑proxy 不会处理这个 Service。 DNS 解析 Service 名称,直接返回全部后端 Pod 的 IP 地址列表。
典型用途:StatefulSet 有状态应用(Redis 集群、Mysql 主从),给每个 Pod 提供稳定 DNS 域名。
yaml
apiVersion: v1
kind: Service
metadata:
name: web-headless
spec:
clusterIP: None
selector:
app: web
ports:
- port: 80
targetPort: 80
两种模式
- 带 selector:DNS 直接返回后端 PodIP;
- 不带 selector:手动自定义 Endpoints。
6、Service 会话保持 sessionAffinity(会话亲和)
默认 Service 是轮询随机分发请求;开启会话保持,同一个客户端 IP 的请求,始终转发到同一个后端 Pod。
适用场景:web 登录会话、WebSocket 长连接、游戏服务。
关键字段
sessionAffinity: ClientIP:开启基于客户端 IP 会话保持;sessionAffinityConfig.clientIP.timeoutSeconds:会话超时时间,默认 10800 秒(3 小时)。
实操演示
yaml
kubectl create deployment web --image=hub.laoma.cloud/library/httpd --replicas=2
kubectl expose deployment web --port 80
# 修改pod主页内容为pod名称
for pod in $(kubectl get pods -o name | awk -F/ '{print $2}'); do
kubectl exec -it $pod -- bash -c "echo \$pod > htdocs/index.html"
done
# 未开启会话保持,流量随机分散
for i in {1..20};do curl -s $(kubectl get svc web -o jsonpath='{.spec.clusterIP}');done|sort |uniq -c
开启会话保持
yaml
kubectl patch svc web -p '{"spec":{"sessionAffinity":"ClientIP"}}'
# 再次访问,全部请求落到同一个Pod
for i in {1..20};do curl -s $(kubectl get svc web -o jsonpath='{.spec.clusterIP}');done|sort |uniq -c
底层原理
- iptables 模式:依靠 iptables 概率标记实现;
- IPVS 模式:kube‑proxy 自动切换
sh源地址哈希调度算法,实现会话粘性。
7、基于 Service 实现金丝雀发布(灰度发布)
金丝雀发布:少量流量导入新版本应用,验证新版本稳定性,没问题再逐步把全部流量切到新版本。
实现原理:
- 一套 Service,selector 匹配新旧两套 Deployment 的公共标签;
- 通过调整新旧 Deployment 副本数量,控制流量权重比例;
- 少量副本运行新版本接收一小部分流量,观察业务是否异常。
⚠️局限:这种方式只能按副本比例切流量;不能按照请求头、用户 ID 精准切流量,精细化灰度需要 Ingress 网关。
完整实验步骤
- 创建 ConfigMap 保存两个版本网页
yaml
mkdir web
echo hello nginx 1.28 > web/index28.html
echo hello nginx 1.29 > web/index29.html
kubectl create configmap web --from-file=./web
- 稳定版本 Deployment(1.28,track: stable) webapp‑1.28.yaml
yaml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: web
name: web-28
spec:
replicas: 10
selector:
matchLabels:
app: web
tier: frontend
track: stable
template:
metadata:
labels:
app: web
tier: frontend
track: stable
spec:
containers:
- image: hub.laoma.cloud/library/nginx:1.28
name: nginx
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
volumeMounts:
- name: webcontent
mountPath: "/usr/share/nginx/html"
volumes:
- name: webcontent
configMap:
name: web
items:
- key: index28.html
path: index.html
kubectl apply -f webapp-1.28.yaml
- Service,selector 匹配公共标签
app: web,tier: frontend,同时匹配 stable 与 canary 的 Pod webapp‑svc.yaml
yaml
apiVersion: v1
kind: Service
metadata:
labels:
app: web
name: web
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
app: web
tier: frontend
kubectl apply -f webapp-svc.yaml
- 金丝雀新版本 Deployment(1.29,track:canary) webapp‑1.29.yaml
yaml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: web
name: web-29
spec:
replicas: 1
selector:
matchLabels:
app: web
tier: frontend
track: canary
template:
metadata:
labels:
app: web
tier: frontend
track: canary
spec:
containers:
- image: hub.laoma.cloud/library/nginx:1.29
name: nginx
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
volumeMounts:
- name: webcontent
mountPath: "/usr/share/nginx/html"
volumes:
- name: webcontent
configMap:
name: web
items:
- key: index29.html
path: index.html
kubectl apply -f webapp-1.29.yaml
- 调整副本数量,改变流量占比
yaml
# 8个旧版本,2个新版本
kubectl scale deployment web-28 --replicas 8
kubectl scale deployment web-29 --replicas 2
# 压测观察流量分配
for i in {1..50}; do curl -s $(kubectl get svc web -o jsonpath='{.spec.clusterIP}'); done | sort -n|uniq -c
# 逐步迁移流量:6旧4新
kubectl scale deployment web-28 --replicas 6
kubectl scale deployment web-29 --replicas 4
8、kube‑proxy 深度剖析:Service 底层实现
kube‑proxy 运行在集群每一个节点上,以 DaemonSet 部署。 核心职责:监听 API‑Server 中 Service、Endpoint 资源变化,在宿主机内核生成转发规则,实现 Service 流量转发与负载均衡。
kube‑proxy 三种工作模式对比
| 模式 | 性能 | 适用场景 | 特点 |
|---|---|---|---|
| iptables | 中等,服务 > 1000 性能明显下降 | 小规模测试集群 | 依赖 netfilter iptables 规则;规则数量膨胀 CPU 飙升 |
| IPVS | 极高,支持上万服务规模 | 生产环境首选 | 内核哈希表 O (1) 查找;支持多种高级调度算法 |
| Userspace | 性能很差 | 已废弃(K8s1.25 + 移除) | 用户态进程转发,不推荐使用 |
8.1 查看当前 kube‑proxy 运行模式
yaml
# 查看configmap配置
kubectl get cm -n kube-system kube-proxy -o yaml|grep mode
# 查看pod日志确认真实运行模式
kubectl get pods -n kube-system -l k8s-app=kube-proxy -o name
kubectl logs -n kube-system kube-proxy-xxx |grep Using
输出Using iptables proxy代表 iptables 模式。
8.2 切换到 IPVS 模式
- 修改 kube‑proxy configmap
yaml
kubectl edit configmap -n kube-system kube-proxy
修改配置
yaml
mode: "ipvs"
- 滚动重启 kube‑proxy daemonset
yaml
kubectl rollout restart daemonset -n kube-system kube-proxy
# 验证切换成功
kubectl logs -n kube-system kube-proxy-xxxx |grep Using
#输出 Using ipvs Proxier
IPVS 模式详解
IPVS 在内核维护哈希表,查找效率 O (1),不受服务数量影响。 支持调度算法:
rr:轮询(默认)wrr:加权轮询(生产推荐)lc:最少连接(长连接 WebSocket)sh:源地址哈希(对应 service 的 ClientIP 会话保持)sed:最短预期延迟nq:最少队列
IPVS 完整参考配置
yaml
apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
mode: ipvs
ipvs:
scheduler: "wrr"
tcpTimeout: 900
tcpFinTimeout: 120
udpTimeout: 300
excludeCIDRs:
- "127.0.0.1/32"
strictARP: true
IPVS 实操验证
yaml
# 创建3副本deployment
kubectl create deployment web --image=nginx --replicas=3
# 修改每个pod主页为pod名称
for pod in $( kubectl get pods -o custom-columns=NAME:.metadata.name --no-headers)
do
kubectl exec $pod -- bash -c "echo \$pod > /usr/share/nginx/html/index.html"
done
kubectl expose deployment web --port=80
# 在节点执行ipvsadm查看虚拟服务与real‑server
ipvsadm -Lnt $(kubectl get svc web -o jsonpath='{.spec.clusterIP}'):80
# 循环访问,观察负载均衡分发
for i in {1..60}; do curl -s $(kubectl get svc web -o jsonpath='{.spec.clusterIP}'); done| sort | uniq -c
当 Service 开启
sessionAffinity:ClientIP,IPVS 会自动切换sh源哈希算法实现会话粘性。
iptables 模式详解
kube‑proxy 动态生成大量 iptables nat 表规则链(KUBE‑SERVICES / KUBE‑SVC‑xxx / KUBE‑SEP‑xxx)。 缺点:每新增 Service/Endpoint 就新增多条 iptables 规则;上千服务时,逐条匹配规则 CPU 开销巨大。
查看 iptables 规则
yaml
iptables-save > iptables.list
cat iptables.list | grep <你的service‑cluster‑ip>
完整链路:访问 ClusterIP → KUBE‑SERVICES 总链 → KUBE‑SVC‑xxx 服务专属链概率负载均衡 → KUBE‑SEP‑xxx 端点链 DNAT 转发到 PodIP。
Userspace 模式(废弃)
kube‑proxy 进程在用户态监听 Service 端口,接收流量再转发 Pod;性能很差,K8s1.25 版本彻底移除。
9、常见排坑总结
- Service 访问不通
- 检查
Endpoints是否存在;selector标签是否匹配 Pod;Pod 容器containerPort端口配置是否正确。
- ping ClusterIP 不通
正常现象,ClusterIP 虚拟 IP 不响应 ICMP ping,只处理 Service 定义 TCP/UDP 端口。
- 环境变量拿不到 Service 变量
必须先创建 Service,再启动 Pod!优先使用 DNS 域名访问。
- NodePort 访问失败
节点防火墙放行端口范围
30000‑32767。
- kube‑proxy 切换 IPVS 不生效
确认节点已经加载 ipvs 内核模块,安装
ipvsadm工具。
- 金丝雀发布流量不符合预期
Service selector 要同时匹配新旧 Deployment 的公共标签,只通过调整副本数改变流量权重。
10、实验环境清理
yaml
kubectl delete ns services