Kubernetes集群网络代理,Service的实现者
kube-proxy命令 是运行在每个节点上的网络代理,负责把 Service 的虚拟 IP(ClusterIP)翻译成后端 Pod 的真实地址。它是 Service 这一抽象能够落地的实现者 —— 你创建的每一条 Service,最终都变成节点上的一组 iptables 规则或 IPVS 转发条目。
kube-proxy 只处理Service 转发,不负责给 Pod 分配 IP,也不负责跨节点 Pod 之间的直连,那些是 CNI 插件的职责。删掉 kube-proxy,Pod 之间依然能互通,但所有 Service 会立刻失效 —— 这条边界是排查网络问题时首先要分清的方向。
在 kubeadm 集群中,kube-proxy 以 DaemonSet 形式运行在 kube-system 命名空间,配置存放在同名的 ConfigMap 里。
kube-proxy 由 kubeadm 自动部署为 DaemonSet,通常无需手工安装:
# 确认每个节点都有实例
kubectl get daemonset -n kube-system kube-proxy
kubectl get pods -n kube-system -l k8s-app=kube-proxy -o wide
# 查看版本
kube-proxy --version
二进制安装(非 kubeadm)时它由 systemd 托管,配置默认放在 /var/lib/kube-proxy/。
kube-proxy [flags]
常用标志:
--config=/var/lib/kube-proxy/config.conf 配置文件路径
--kubeconfig=/var/lib/kube-proxy/kubeconfig.conf 访问 apiserver 的凭据
--hostname-override=<node-name> 覆盖节点名
--cluster-cidr=10.244.0.0/16 集群 Pod 网段,用于判断是否需要 MASQUERADE
--proxy-mode=iptables|ipvs|nftables 转发模式
--masquerade-all 对所有出集群流量做 SNAT
--healthz-bind-address=0.0.0.0 健康检查监听地址
--metrics-bind-address=127.0.0.1:10249 指标监听地址
--v=2 日志级别
iptables 默认模式。用 iptables 的 nat 表实现,兼容性最好,规则数随 Service 线性增长
ipvs 基于内核 IPVS,用哈希表查找,大规模集群性能明显更好,需要内核模块支持
nftables 1.29 引入、1.31 进入 Beta 的新模式,规则集更简洁,面向超大规模集群
userspace 已废弃并在 1.14 中移除,不要使用
# 查看当前模式
kubectl -n kube-system get configmap kube-proxy -o yaml | grep mode
# 切换模式:编辑 ConfigMap,把 mode: "" 改成 mode: "ipvs"
kubectl -n kube-system edit configmap kube-proxy
# 修改后必须重启 DaemonSet 才生效
kubectl -n kube-system rollout restart daemonset kube-proxy
kubectl -n kube-system rollout status daemonset kube-proxy
IPVS 模式需要先加载内核模块:
sudo modprobe ip_vs
sudo modprobe ip_vs_rr
sudo modprobe ip_vs_wrr
sudo modprobe ip_vs_sh
sudo modprobe nf_conntrack
# 持久化,避免重启后丢失
printf 'ip_vs\nip_vs_rr\nip_vs_wrr\nip_vs_sh\nnf_conntrack\n' | \
sudo tee /etc/modules-load.d/ipvs.conf
ConfigMap kube-system/kube-proxy 中的 config.conf 就是 KubeProxyConfiguration:
apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
bindAddress: 0.0.0.0
clientConnection:
kubeconfig: /var/lib/kube-proxy/kubeconfig.conf
clusterCIDR: 10.244.0.0/16
mode: ipvs
metricsBindAddress: 127.0.0.1:10249
ipvs:
scheduler: rr
strictARP: true
conntrack:
maxPerCore: 32768
tcpEstablishedTimeout: 24h0m0s
# 查看日志
kubectl logs -n kube-system -l k8s-app=kube-proxy --tail=100
kubectl logs -n kube-system <kube-proxy-pod> -f
# 健康检查与指标
curl http://127.0.0.1:10256/healthz
curl -s http://127.0.0.1:10249/metrics | grep kubeproxy
# 查看某条 Service 的后端地址,为空说明选择器没匹配到 Pod
kubectl get endpointslices -l kubernetes.io/service-name=<svc-name> -o wide
kubectl get endpoints <svc-name> -o yaml
# 在集群内验证 Service 连通性
kubectl run curl-test --rm -it --image=curlimages/curl --restart=Never -- \
curl -s -o /dev/null -w '%{http_code}\n' http://<cluster-ip>:<port>
# Service 的总入口链
sudo iptables -t nat -L KUBE-SERVICES -n --line-numbers
# 找到某个 ClusterIP 对应的规则
sudo iptables -t nat -L KUBE-SERVICES -n | grep <cluster-ip>
# 该 Service 的转发链(KUBE-SVC-xxx)与后端链(KUBE-SEP-xxx)
sudo iptables -t nat -L KUBE-SVC-XXXXXXXXXXXXXXXX -n
sudo iptables -t nat -L KUBE-SEP-XXXXXXXXXXXXXXXX -n
# NodePort 链
sudo iptables -t nat -L KUBE-NODEPORTS -n
# 规则数量,过大说明该换 IPVS 或 nftables 了
sudo iptables -t nat -L -n | wc -l
# 带计数器查看,确认流量确实命中了规则
sudo iptables -t nat -L KUBE-SVC-XXXXXXXXXXXXXXXX -n -v
# 虚拟服务与真实后端
sudo ipvsadm -Ln
# 转发统计与速率
sudo ipvsadm -Ln --stats
sudo ipvsadm -Ln --rate
# 当前连接数
sudo ipvsadm -Lnc | wc -l
# 确认内核模块已加载
lsmod | grep ip_vs
# 查看连接跟踪表用量(iptables 模式的 sessionAffinity 依赖它)
sudo conntrack -C
cat /proc/sys/net/netfilter/nf_conntrack_max
# 临时调大上限
sudo sysctl -w net.netfilter.nf_conntrack_max=1048576
# 排查丢包
sudo dmesg | grep -i conntrack
curl <cluster-ip>:<port> 验证,不要用 ping。kube-system/kube-proxy 这个 ConfigMap 不会自动生效,必须 kubectl -n kube-system rollout restart daemonset kube-proxy。忘了这一步是「改了配置没反应」的头号原因。iptables -F 或 iptables -t nat -F。这会同时清掉 kube-proxy 和 CNI 的规则,导致整个集群网络中断,恢复需要重启所有节点的相关组件。ipvs.strictARP: true,否则 VIP 无法被外部访问。externalTrafficPolicy: Local 只把流量转发到本节点的 Endpoint:能保留客户端源 IP,但节点上没有 Endpoint 时会直接拒绝连接,配合 NodePort 使用时需要额外的健康检查。sessionAffinity: ClientIP 在 iptables 模式下依赖 conntrack,长连接多时容易打满 nf_conntrack_max,日志里出现 nf_conntrack: table full, dropping packet。--service-node-port-range 决定,kube-proxy 只是执行者,改它没用。kubectl — Kubernetes集群管理工具kubelet — 节点代理,负责启动 Podkubeadm — Kubernetes集群安装工具crictl — 容器运行时调试工具