恒美微站 Logo 恒美微站
  • 首页
  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心
  • 联系我们

K8s多节点集群服务暴露实践:从Service负载均衡到nginx反向代理

  • 首页
  • 资讯中心
  • /
  • K8s多节点集群服务暴露实践:从Service负载均衡到nginx反向代理

相关资讯

AI系统入侵的法律归责:主观故意如何认定与刑事责任分析 2026/10/15 7:35:45
Selenium Web自动化从入门到实战:定位、等待与工程化指南 2026/10/15 7:35:45
AnyPS5:让任意设备接入PS5的完整方案 2026/10/15 7:35:45

最新资讯

AnyPS5通用化中间件:跨设备输入转发与协议逆向实践
数字取证:从 Steganos Data Safe 加密演进到 Passware Kit 实战支持
AI工业控制系统搭建实战:从数据采集到模型上线的完整指南
具身智能为何不能照搬自动驾驶时间表:技术卡点与落地实践
Unity uGUI 3D旋转卡片特效实战:从RectTransform原理到拖拽交互
从零搭建数据分析智能体:自然语言查数、自动分析并给出结论

今日推荐

AI视频生成的时间一致性难题与时空建模演进
基于bbox的PDF文档解析:多栏重排与水印过滤实战
探矿数据进RAG前的清洗全攻略:TXT、Word、PDF、网页四类文档处理实践

本周热门

UE动画修改实战:从资产编辑到重定向与蒙太奇驱动
统计随机数生成器攻击下的KLJN安全密钥交换协议Matlab仿真
政务API安全治理:资产测绘、低代码编排与行标对标实践

本月精选

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证
2026 大模型集体涨价:用 Python 做企业 Token 成本测算与选型避坑(附配置)

K8s多节点集群服务暴露实践:从Service负载均衡到nginx反向代理

发布时间:2026/10/15 7:40:45
K8s多节点集群服务暴露实践:从Service负载均衡到nginx反向代理 说实话看到这个标题我估计不少人是卡在了同一个地方用工具一键装好了K8s节点也起来了但一访问服务就懵了——Service的ClusterIP只能在集群内部访问NodePort端口要记一大串不说多节点下到底该访问哪个IP再加一台nginx在前面又不知道该怎么和后端联动。这篇文章就把这条链路彻底讲明白。从K8s多节点集群怎么规划、怎么部署到Service负载均衡怎么暴露再到nginx反向代理怎么接住流量每一层都给你拆解开配合可以直接照着抄的配置命令。适合刚开始搞K8s集群、想把多节点和服务暴露链路走通的开发者也适合部署完集群之后被Ingress和nginx绕晕的运维朋友。1. 整体架构设计与思路拆解先捋清楚我们要搭的是一条什么链路。一个典型的多节点K8s集群你最终要解决的是两件事集群内部怎么调度和网络互通集群外部怎么访问业务。内部的事K8s自己管。多个节点组成了调度池Pod散布在不同节点上通过CNI网络插件实现跨节点通信。外部的事就得靠层层“接引”Pod的IP是漂移的你得有Service做第一层稳定抽象Service默认对内你得有第二层手段把它暴露到集群外暴露出去之后还是裸IP加端口不够优雅也做不了域名和证书管理于是第三层就到了nginx反向代理。这三级抽象各管一段很多人之所以搞混就是没想清楚“谁在给谁转发”。1.1 多节点集群带来的核心变化单个节点的K8s说白了就是在玩单机容器编排Pod被调度到唯一的节点上一切都简单。一旦扩展到多节点几个很现实的问题立刻出现节点之间需要容器网络互通。Pod的IP是K8s内部虚拟网段物理机不认必须靠网络插件CNI在节点间建立隧道或者路由。负载均衡要跨节点生效。Service的转发规则不能再只绑本机无论Pod跑到哪个节点流量都得能转过去。单点故障的问题出现。Master节点挂了集群调度会停摆所以生产环境通常需要至少3个控制平面节点。多节点下的资源调度、污点容忍、亲和性这些机制会直接影响你的Pod落在哪台机器上。我们这次做的是“一主多从”的标准搭配。控制平面一颗工作节点两颗总共3台机器。这个规模最能体现K8s的分布式特性负载压力又控制在个人折腾或者小型项目完全能负担的范围内。1.2 负载均衡和nginx反向代理的分工这里必须掰开揉碎讲清楚K8s体系内的“负载均衡”和nginx这个“负载均衡”干的不是同一层活。K8s里的Service承担的是Pod层面的负载均衡。你有3个Pod副本在跑Service通过标签选择器把这3个Pod归为一组然后在这组Pod之间分发流量。K8s内置的kube-proxy组件负责实现分发规则有iptables和IPVS两种模式。而nginx反向代理承担的是集群入口层面的负载均衡。它转发目标不是Pod而是Service的入口通常是NodePort端口或者Ingress Controller。也就是说nginx站在用户和集群之间用户只和nginx对话nginx再决定把请求交给集群里的哪个节点、哪个入口。这样分工的好处非常明显底层Pod怎么扩缩容、IP怎么变都不用动nginx配置nginx只认Service的口子就行。顶层用户入口怎么变、域名证书怎么加也不用动K8s集群。两头解耦这是整套架构的精髓。1.3 这套方案的选型考量有人会问都上了K8s了为什么不直接用Ingress还要单独搞一个nginx一个是场景匹配。Ingress Controller本身是一个运行在集群里的Pod它确实负责把外部流量按域名或路径转发到Service。但从外部到Ingress Controller这一步仍然需要暴露NodePort或者LoadBalancer。也就是说Ingress解决的是“域名/路径 → Service”的映射问题它解决不了“公网用户 → 集群入口”的最后一跳。另一个是资源与复杂度的权衡。个人的云服务器或者内网环境普遍没有云厂商自带的LB组件。与其引入一堆云上插件不如前置一个轻量nginx既承担入口负载均衡又顺便把HTTP层缓存、防盗链、请求头处理这些事一并干了。所以最终架构很清晰nginx物理机 → 任意节点的NodePort → Ingress Controller可选 → Service → Pod。2. 部署前的环境准备与组件选型这个环节的重要性很多人低估了。K8s部署失败一半以上的原因出在环境准备阶段版本不匹配、内核参数没调、端口没开、swap没关。按照下面的清单过一遍后面能省出大把排错时间。2.1 硬件配置与系统要求先给出一套经过实测的最低配置低于这个配置的机器折腾起来会很痛苦。节点角色数量最低配置操作系统Master1台2核4G40G硬盘Ubuntu 22.04 / CentOS 7.9Worker2台2核4G40G硬盘Ubuntu 22.04 / CentOS 7.9入口负载节点1台可复用Master/任意Worker1核1G即可同集群节点系统入口负载节点就是放nginx的那个角色。如果机器紧张复用Master节点完全可行只是生产环境不建议把nginx和K8s控制平面混部毕竟nginx吃流量Master追求稳定。操作系统方面个人更推荐Ubuntu 22.04理由很实在内核版本新对网络命名空间、iptables、overlayfs的支持都很好和containerd的兼容性也更省心。2.2 核心组件版本选型组件版本是另一个坑。K8s的版本管理有自己的讲究kubeadm、kubelet、kubectl、containerd、CNI插件各自都有版本要求混搭极易出问题。选定一条经过实际验证的版本组合直接照抄Kubernetes1.28.xcontainerd1.7.xCalico3.27.xnginx1.24.x选择理由大概说一下。1.28这个版本还在维护期内比较稳定而且kubeadm的配置格式和命令行为已经趋于成熟网上资料也多。containerd是K8s从1.24版本开始唯一默认支持的容器运行时这一项没有悬念。Calico是使用范围最广的CNI插件支持网络策略性能也能接受。nginx不用追新稳定版足够。2.3 网络规划与关键参数设定这一步是部署前最容易忽视、后期最难改的环节。两个CIDR会影响整个集群的网络布局Pod网段比如 10.244.0.0/16负责给每个Pod分配IPService网段比如 10.96.0.0/12负责给每个Service分配ClusterIP这两个网段必须和你的物理局域网网段错开同时不能互相重叠。很多人图省事直接用默认值结果和公司内网网段冲突后面所有外部访问策略都得跟着重写。还有几个内核参数每台节点都要提前调好cat EOF | sudo tee /etc/sysctl.d/k8s.conf net.ipv4.ip_forward 1 net.bridge.bridge-nf-call-iptables 1 net.bridge.bridge-nf-call-ip6tables 1 EOFnet.ipv4.ip_forward 1是必须开的没有它节点上的iptables转发规则根本不会生效。后面两个参数保证容器网络流量能正确经过iptables规则处理。设置完执行sudo sysctl --system让其生效。所有节点统一执行# 关闭swapK8s强制要求 sudo swapoff -a sed -i /swap/s/^/#/ /etc/fstab # 加载overlay和br_netfilter模块 cat EOF | sudo tee /etc/modules-load.d/containerd.conf overlay br_netfilter EOF # 关闭防火墙或放行必要端口 sudo systemctl stop firewalld # CentOS系 sudo systemctl disable firewalld关闭防火墙这步有争议但个人建议在内网环境下直接关掉或者至少放行K8s需要的全部端口否则后面Calico的BGP通信、master节点的6443端口都会变成排错地狱。3. 多节点集群部署实操环境准备好之后真正的部署就开始进入三阶段模式初始化Master加入Worker装网络插件。每一步都有明确的验证标志对照着核验不用瞎猜。3.1 容器运行时安装与配置先装containerd。这里有一个非常容易踩的坑默认安装完的containerdconfig.toml里的SystemdCgroup是false。必须改成true否则kubelet会和containerd在cgroup的驱动方式上不一致Pod会被拉起后反复重启。# 安装containerd sudo apt-get update sudo apt-get install -y containerd # 生成默认配置 sudo mkdir -p /etc/containerd containerd config default | sudo tee /etc/containerd/config.toml # 修改关键参数 sudo sed -i s/SystemdCgroup false/SystemdCgroup true/g /etc/containerd/config.toml # 镜像加速国内服务器强烈建议 sudo sed -i s|registry.k8s.io|registry.aliyuncs.com/google-containers|g /etc/containerd/config.toml sudo systemctl restart containerd sudo systemctl enable containerd这里再说一下为什么SystemdCgroup true这么关键。kubelet启动容器时需要确认容器的cgroup驱动方式如果它认为自己是systemd驱动而containerd用的是cgroupfs两边对不上kubelet就会认为容器异常不断尝试重启。这是个非常典型的看起来Pod活着但又好像没活的问题。3.2 初始化控制平面节点Master节点的初始化命令建议把参数写全而不是用默认init之后再慢慢补sudo kubeadm init \ --apiserver-advertise-address192.168.1.10 \ --pod-network-cidr10.244.0.0/16 \ --service-cidr10.96.0.0/12 \ --kubernetes-version1.28.2 \ --image-repositoryregistry.aliyuncs.com/google-containers几个参数说明一下--apiserver-advertise-addressMaster节点的IP。这个地址是工作节点来注册和通信的入口不能写错也不要写成127.0.0.1。--pod-network-cidrPod网段要和后面Calico的配置完全一致否则网络插件一装就出问题。--image-repository镜像仓库地址。不指定这个参数kubeadm会去拉registry.k8s.io的镜像在国内环境往往超时。初始化成功之后输出信息里会给出两条重要的内容一条是配置kubectl的命令还有一条是加入集群的完整命令那个kubeadm join一定要保存好复制丢失的话可以用下面的命令重新生成tokenkubeadm token create --print-join-command然后按提示配置当前用户的kubectl访问权限mkdir -p $HOME/.kube sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config sudo chown $(id -u):$(id -g) $HOME/.kube/config kubectl get nodes此时执行kubectl get nodes会看到Master节点处于NotReady状态这是正常的因为网络插件还没装。3.3 工作节点加入集群Workder节点要做的就简单多了。装好kubelet和kubeadm之后直接执行Master初始化生成的join命令sudo kubeadm join 192.168.1.10:6443 --token xxxxx \ --discovery-token-ca-cert-hash sha256:xxxxxxxx这里的核心动作其实是三件事先通过6443端口向apiserver认证身份拿到集群的证书信息建立互信把节点信息上报给集群开始接收调度任务join成功后回到Master节点上执行kubectl get nodes两个Worker节点开始会显示NotReady等待网络插件配置完毕后转为Ready。如果join过程报错最常见的原因就是token过期了用开头提到的kubeadm token create --print-join-command重新生成就行。3.4 部署Calico网络插件网络插件是集群真正跑起来的关键一步。Calico的部署方式现在统一用operator方式kubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/calico.yaml这里需要确认Calico的Pod网段和kubeadm初始化时指定的--pod-network-cidr一致。Calico默认的IP池就是10.244.0.0/16如果初始化时用了别的网段需要修改一下Calico的ConfigMap。验证网络插件是否生效kubectl get pods -n kube-system | grep calico等几个calico-xxxx的Pod都变成Running再等一下再执行kubectl get nodes所有节点应该都是Ready了。有个小细节Calico初始化需要一些时间第一次部署刷两三次都是正常的不要刚apply完就急着报错。一个验证集群状态的好方法kubectl run test-pod --imagebusybox --command -- sleep 3600 # 等pod启动后 kubectl exec -it test-pod -- ping 10.244.1.2如果能ping通其他节点上的Pod IP说明跨节点容器网络已经走通了。这一条验证的价值相当于给整个集群的网络基础设施做了个冒烟测试。4. 负载均衡的服务暴露方案集群起来了接下来就是重点中的重点Service的负载均衡到底怎么搭怎么把一个服务优雅地暴露出去。4.1 Service类型与负载均衡的对应关系K8s的Service本质上是一个稳定的访问入口。底层有哪些Pod、IP是多少用户不关心用户只认Service这个固定的虚拟IP。Service的type类型对应着不同的暴露方式类型访问范围底层实现适用场景ClusterIP集群内部kube-proxyiptables/IPVS内部服务调用NodePort集群外部在每台节点开指定端口临时调试、小规模暴露LoadBalancer集群外部需依赖云厂商LB或MetalLB生产环境暴露ExternalNameDNS级别映射到集群外部的域名把外部服务纳入集群我们这次的方案链条是nginx → NodePort或再挂一层Ingress → Service → Pod。4.2 通过NodePort快速暴露服务假设已经有一个Deployment在跑比如一个简单的Web应用有3个副本。执行kubectl expose deployment web-app --typeNodePort --port80 --target-port8080 --nameweb-svc查看Service详情kubectl describe svc web-svc会看到类似这样的输出Name: web-svc Type: NodePort ClusterIP: 10.96.35.42 Port: unset 80/TCP TargetPort: 8080/TCP NodePort: unset 30080/TCP这时集群中任意一个节点上访问http://任意节点IP:30080都能访问到你的服务。kube-proxy的规则会把请求转发到对应的Pod上而且节点本身也做了负载均衡——它监听iptables规则把到30080端口的流量随机分发到后端的多个Pod。写一个简单的测试Deployment来验证kubectl create deployment web-app --imagenginx:1.24 kubectl scale deployment web-app --replicas3地址不同但容器内容相同这种情况下负载均衡的分发效果需要用特定工具才能直观看到。可以这样验证# 进入集群内任意节点 curl http://10.96.35.42 # 多次访问观察轮询到不同Pod如果要观察实际转发到哪个Pod可以在Deployment里加一个返回节点名的初始化脚本或者直接用kubectl get endpoints查看后端Pod列表变化。4.3 MetalLB让Service拥有外部IPNodePort够用但不够优雅。每次暴露一个服务就要记一个30000的端口。生产环境更希望给Service分配一个独立的IP就像云厂商的负载均衡器那样。这里引入MetalLB它能在裸金属或自建机房环境里充当负载均衡器。# 安装MetalLB kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.11/config/manifests/metallb-native.yaml # 配置地址池 cat EOF | kubectl apply -f - apiVersion: metallb.io/v1beta1 kind: IPAddressPool metadata: name: first-pool namespace: metallb-system spec: addresses: - 192.168.1.100-192.168.1.200 EOF # 配置自动宣告 cat EOF | kubectl apply -f - apiVersion: metallb.io/v1beta1 kind: L2Advertisement metadata: name: first-pool namespace: metallb-system spec: ipAddressPools: - first-pool EOFMetalLB有两套机制可以做地址宣告分别是二层模式L2和BGP模式。L2模式简单直接适合内网环境原理是节点通过ARP响应直接抢占IP的所有权配置量最小。BGP模式适合大型网络它跟网络设备配合需要交换机的支持。地址池的网段必须和集群节点所在物理局域网是同网段否则分配出来的IP没法被局域网内的其他机器访问到。装好MetalLB再建一个LoadBalancer类型的Servicekubectl expose deployment web-app --typeLoadBalancer --port80 --target-port8080 --nameweb-lb等一会儿执行kubectl get svc web-lbEXTERNAL-IP列会变成一个192.168.1.x的地址直接用这个地址访问就行。4.4 Ingress Controller的接入有了LoadBalancer类型的Service流量已经能进集群了。但这里是最后一个衔接点入口IP有了域名、路径映射还需要Ingress来处理。nginx-ingress-controller是社区使用最广的Ingress实现。安装方式kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.9.0/deploy/static/provider/baremetal/deploy.yaml然后创建Ingress资源把域名映射到ServiceapiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: web-ingress spec: rules: - host: app.example.com http: paths: - path: / pathType: Prefix backend: service: name: web-svc port: number: 80这个Ingress资源一创建nginx-ingress-controller就会立刻生效自动把app.example.com的请求按规则转发到web-svc这个Service。受限于篇幅我这里对Ingress的讲解尽量简洁。实际使用中域名解析到哪、证书怎么挂在Ingress上都是另一个比较深的话题后面有机会单独展开。5. nginx反向代理部署与配置前几层处理完K8s集群自身的工作已经齐活。最后这一层nginx是把K8s服务真正对接到外部流量的入口关。很多人在K8s集群内部跑得很顺一挂nginx就出各种问题多半是配置上没理解透nginx和K8s的协作模式。5.1 nginx在整体架构中的定位nginx放在集群入口节点上它的作用可以概括为三句话统一对外入口用户只认nginx的IP向后端转发时做负载均衡把请求分发到多个集群节点终止SSL、处理HTTP头、做基础缓存减轻K8s集群的压力注意到一个关键点这里nginx向后转发的目标地址需要对应前面Config的NodePort或者Ingress Controller暴露的端口。不要试图让nginx直接转发到Service的ClusterIP——那是集群内部的虚拟IPnginx这台机器默认没有到那个网段的路由除非你把nginx本身也做成K8s集群内的一个Pod。所以两个方案方案Anginx直接转发到任意节点的NodePort如http://192.168.1.10:30080和http://192.168.1.11:30080nginx承担节点间负载均衡。方案Bnginx转发到Ingress Controller的Service入口让Ingress Controller来做域名到Service的映射。方案A链路最短配置最直接。方案B多一层抽象但能获得域名路由能力。个人建议如果只是内网用方案A足够如果要做域名、证书、多云环境方案B更合理。下面配置按方案A展开因为这套配置最容易复现、排查最直观。5.2 nginx核心配置与负载均衡upstreamnginx配置文件的核心在upstream块。它定义了后端服务器组nginx会按照设定的策略在这些服务器之间分发请求。# /etc/nginx/conf.d/k8s-loadbalancer.conf upstream k8s_backend { # least_conn; # 按连接数分发适合长连接场景 # ip_hash; # 按客户端IP哈希解决会话保持 server 192.168.1.11:30080 max_fails3 fail_timeout10s; server 192.168.1.12:30080 max_fails3 fail_timeout10s; server 192.168.1.13:30080 max_fails3 fail_timeout10s; } server { listen 80; server_name app.example.com; location / { proxy_pass http://k8s_backend; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } } # 健康检查接口可单独配置一个server块 server { listen 8080; location /health { access_log off; return 200 ok\n; } }需要注意几个核心点proxy_pass http://k8s_backend;后面的uri部分决定了请求的转发方式。如果写proxy_pass http://k8s_backend;且不带uringinx会把原始请求的完整URI原样转发如果写成proxy_pass http://k8s_backend/;等于告诉nginx要重写URI前缀。这个细节能让不少人在配了路径前缀的服务时踩坑。max_fails3 fail_timeout10s是两个参数需要正确理解。它不是“10秒内连续失败3次就永久下线后端”而是“在10秒统计周期内连续失败3次则将节点标记为不可用再等10秒后再尝试”。实测下来这种参数组合适合多数场景。ip_hash这个策略值得留意。如果你的应用有Session会话粘连的要求而K8s集群里用的是ClusterIP类型的Service那ip_hash这种基于客户端来源IP的调度策略是实质性的。不过更好的方案是让应用做无状态化会话放Redis或数据库里而不是依赖负载均衡层的亲和性。5.3 健康检查与故障转移机制nginx的负载均衡之所以好用是因为它自带的被动健康检查。当nginx转发请求给某个节点时如果连接失败、超时或收到错误响应它会自动把该节点标记为失败在一定时间内不再往后端分发流量。这个机制有一个局限它只在请求发生时才探测节点状态不会主动发起额外请求。也就是说如果某节点挂了但还没有新请求进来nginx不会立刻发现。要让监控更实时可以搭配定期curl测试地址的脚本或者引入更专业的主动健康检查方案。给一个简单的主动探测脚本思路#!/bin/bash # check_k8s_nodes.sh nodes(192.168.1.11 192.168.1.12 192.168.1.13) port30080 for node in ${nodes[]}; do if curl -s --connect-timeout 3 http://$node:$port/health | grep -q ok; then echo $node OK else echo $node FAIL fi done配合cron定时执行节点状态一目了然。如果发现某台节点连不上优先排查的是kubelet服务状态、NodePort端口是否被防火墙拦截、Pod是否还在正常运行。5.4 SSL终止与域名接入配置实际部署中90%的nginx接入场景都需要处理HTTPS。在K8s前置nginx上做SSL终止是最干净的做法server { listen 443 ssl; server_name app.example.com; ssl_certificate /etc/nginx/ssl/app.example.com.crt; ssl_certificate_key /etc/nginx/ssl/app.example.com.key; ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers HIGH:!aNULL:!MD5; location / { proxy_pass http://k8s_backend; proxy_set_header Host $host; proxy_set_header X-Forwarded-Proto https; } } # HTTP自动跳转HTTPS server { listen 80; server_name app.example.com; return 301 https://$host$request_uri; }证书文件放置路径按个人习惯但强烈建议统一路径管理避免以后维护多个站点时找不到证书文件。密钥和证书的安全权限要留意nginx需要能读到证书才能起服务但如果给other用户也加了读权限等于给系统留了一个不必要的暴露面。稳妥的做法是证书目录设为750权限属主设为nginx用户。6. 常见问题与排查技巧实录整套链路越往后越像黑盒用户请求从nginx到K8s中间好几层转发任何一层出问题表现都是访问不通或者报错。这一节把个人实际踩过的坑和排查经验整理成速查表形式遇到问题可以直接对照。6.1 节点加入失败的典型原因kubeadm join报错的情况基本集中在以下几类症状可能原因解决办法提示token过期或无效join token有默认24小时有效期重新执行kubeadm token create --print-join-command提示ca-cert-hash不匹配证书哈希值错误或集群证书已变更用 openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt连接超时6443端口被防火墙屏蔽检查Master节点的防火墙和云安全组配置提示节点已经存在之前加入过残留状态在目标节点执行sudo kubeadm reset清理后再加入最隐蔽的一个问题apiserver-advertise-address配置错误。如果Master节点有多个网卡kubeadm默认选择的面不是预期的那块会导致Worker节点访问不到apiserver。稳妥的做法是初始化时明确指定IP。6.2 负载均衡不生效时怎么排查这里的“不生效”分两种一种是流量只在部分Pod间分发另一种是完全访问不通。流量只分发到部分Pod通常是标签选择器的问题。Service通过selector匹配Pod标签如果Deployment的Pod标签和Service的selector对不上endpoints列表就是空的。排查命令kubectl get endpoints web-svc kubectl describe svc web-svc看endpoints有没有列表没有的话去检查Deployment的spec.template.metadata.labels和Service的spec.selector是否一致。这个命令排查过无数人的问题十有八九是标签写错。完全访问不通优先检查kube-proxy是否正常工作kubectl logs -n kube-system kube-proxy-xxxxx # 检查在节点上 sudo iptables -t nat -L -n | grep service-nodeport如果iptables规则是空的kube-proxy可能没正常工作看一下它的日志。另外如果用IPVS模式可以检查sudo ipvsadm -L -n6.3 nginx 502/504的快速定位502是nginx能连到上游但上游直接回了错误504是nginx等不到上游响应。对比排查错误码常见原因排查方向502后端端口未监听 / 防火墙 / Pod崩溃curl 后端节点NodePort验证502后端返回无有效响应查看Pod日志确认服务是否正常504nginx连接后未收到响应检查Pod是否超时 / 后端业务是否有慢查询连接被拒绝后端端口不对 / 防火墙拦截ss -lntp查看节点端口监听状态一个典型的场景配置好了nginx转发到NodePort访问出现502。到后端节点上直接跑curl http://192.168.1.11:30080发现也挂说明问题在K8s链路。再执行kubectl get pods -o wide看Pod状态如果崩溃循环看Pod日志kubectl logs --tail50 pod-name -c container-name如果curl通了但nginx还是502重点检查nginx的proxy_pass是否带了路径重写导致被转发的URI在K8s侧匹配不到路由。这个问题在部署了路径类的Ingress规则时尤其隐蔽。6.4 实测心得配置虽多链路清晰整套配置下来个人最大的感受是K8s体系的组件多但每个组件的职责边界其实非常清楚。你不需要把几百个参数都背下来只需要理解流量在每个节点上经过了哪几层出问题时按层次排查就好了。几个实操层面的经验可以分享给所有节点固定IP和主机名不要用动态IP否则K8s节点间的证书互信和注册信息全部失效。每完成一个阶段的部署立刻做一次验证不要等全部搭完再排查。多验证几次每次的验证成本远低于一次大规模排查。nginx的日志格式建议加一条增加$upstream_addr和$upstream_status字段这样能直接看到转发到了哪个节点、后端返回了什么状态码。所有配置先备份再改动尤其nginx配置改完先nginx -t测试再reload。最后再分享一个小技巧排查K8s链路时随手用很有帮助# 一次性查看所有关键组件的状态 kubectl get nodes -o wide kubectl get pods -n kube-system -o wide kubectl get svc -A这三条命令的输出基本覆盖了从节点到系统组件到Service的完整链路。任何一层异常顺着这条输出就能找到症结点。这也是我在多次排查中沉淀下来的习惯——先看整体再抓细节。整套链路里每个转发点都是一个可以稳定验证的关卡把每一关的状态弄清楚K8s这辆车的方向盘才算是真正握在了自己手里。

关于恒美微站

恒美微站专注于为个体商户、工作室提供极简自助建站服务,让每个人都能轻松拥有专业网站。

快速链接

  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心

服务项目

  • 可视化建站
  • 拖拽编辑
  • 主题定制
  • SEO 优化
  • 网站托管

联系方式

  • 📍 地址:北京市朝阳区建国路 88 号
  • 📞 电话:400-888-8888
  • ✉️ 邮箱:info@hmyw.cn
  • 🕐 时间:周一至周日 9:00-18:00

© 2024 恒美微站 hmyw.cn 版权所有 | 京 ICP 备 12345678 号