K8s+Nginx-ingress+Websocket基础知识理解

K8s+Nginx-ingress+Websocket基础知识理解

Kubernetes基础核心概念

  • 必须掌握:Pod/Service/Ingress的关系
  • 关键理解:Ingress Controller实际是Nginx的集群化实现
  • 重点掌握:Service的ClusterIP和NodePort类型区别
Pod/Service/Ingress的关系

用一个 "快递配送系统" 来比喻 Kubernetes 中的这三个概念:

🚛 Pod = 送货的快递员
  • 实际作用:
    • 就是真正干活的"工人",里面运行着应用程序代码(比如Java/Python服务)
    • 每个快递员(Pod)可以携带多个包裹(容器),但通常一个快递员只带一个主要包裹(你的服务)
  • 特点:
    • 随时可能消失(比如快递员辞职了)
    • 住址(IP)经常变化(每次重启都会变)

举例:开发了一个网站后台,运行在Pod里,但用户没法直接联系这个"快递员"。

🏪 Service = 快递网点
  • 实际作用:
    • 给不稳定的快递员(Pod)提供一个固定联系电话(虚拟IP)
    • 自动管理背后的快递员团队(多个Pod负载均衡)
  • 关键能力:
    • 记住所有快递员的住址,即使他们换了住处
    • 对外提供永久热线电话(ClusterIP)或门店地址(NodePort)

举例:用户拨打400-12345(Service)就能联系到你的网站后台,不用管背后是哪个Pod在服务。

🌉 Ingress = 快递总调度中心
  • 实际作用:
    • 根据用户要寄送的地址(域名+路径),决定转接到哪个网点(Service)
    • 统一管理所有对外入口(一个公网IP应对多个服务)
  • 特殊技能:
    • 处理特殊快递需求(比如WebSocket需要保持长连接)
    • 可以给快递加安全锁(HTTPS证书)

举例:

  • 用户访问 www.yoursite.com/api → 调度到后台Service
  • 访问 www.yoursite.com/ws → 转到WebSocket Service
🔍 三者的协作流程
💡 需要记住的要点
  1. Pod是干活的:但朝不保夕,不能直接依赖
  2. Service是稳定联络点:给你的服务一个固定"电话号码"
  3. Ingress是智能前台:把不同网址请求分发给对应的Service

当前遇到的WebSocket问题,主要就是 Ingress这个"调度中心"没有正确配置特殊快递通道(WebSocket协议) ,需要调整它的路由规则。

Ingress Controller实际是Nginx的集群化实现
🎪 Ingress Controller = 马戏团的售票处 + 节目调度员

假设经营一个大型马戏团,有多个表演帐篷(Service),每个帐篷里有不同的表演(Pod)。观众(用户)从正门进来时:

🎟️ 传统Nginx = 单个售票亭
  • 只有一个工作人员(Nginx进程)
  • 需要手动修改节目单(nginx.conf)
  • 如果观众暴增,售票员会忙不过来(单点性能瓶颈)
  • 某个帐篷着火(Pod崩溃)时,要人工更新节目单
🏟️ Ingress Controller = 智能售票系统
  1. 自动售票机集群(多个Nginx实例)

    • 每个入口都有一模一样的智能售票机(Pod副本)
    • 一台机器坏了,其他机器立刻顶上(高可用)
  2. 实时电子节目牌(Kubernetes API监听)

    • 当新帐篷搭建好(Pod创建),系统自动更新节目单
    • 帐篷位置变更(Pod迁移)时,电子牌自动刷新路线
  3. 智能分流规则

    markdown 复制代码
    # 比如这个配置告诉系统:
    - 拿"/magic"门票的观众 → 魔术帐篷(Service)
    - 带小孩的观众 → 马戏帐篷(Service)
    - 要互动的观众 → WebSocket特别通道
🔧 关键工作原理
  1. 后台监控:时刻盯着马戏团经理(Kubernetes API)的指令
  2. 自动生成配置 :把Ingress规则变成Nginx能懂的nginx.conf
  3. 热更新:不用重启就生效新规则(就像电子牌瞬间刷新)
🌰 实际例子对比
场景 传统Nginx Ingress Controller
新增表演帐篷 手动修改配置 + 重启Nginx 自动发现新Service,立即生效
观众暴增 售票员累瘫(502错误) 自动扩容更多售票机(HPA)
WebSocket长连接 要手动写proxy_set_header 加个注解nginx.ingress.kubernetes.io/websocket-services就行
💡 记住这个本质

Ingress Controller = 会自我管理的Nginx集群

  • 它把原本需要手动操作的Nginx,变成了能自动:
    • 发现服务
    • 生成配置
    • 扩容缩容
    • 故障自愈的智能系统

当前遇到的WebSocket问题,就像是要给互动表演开特殊通道,只需要告诉这个"智能售票系统"正确的分流规则(加特定注解)即可。

Service的ClusterIP和NodePort类型区别
🏠 Service的两种类型:ClusterIP vs NodePort 对比
🏢 ClusterIP(公司内线电话)
  • 作用范围:仅限公司内部(Kubernetes集群内部)使用

  • 访问方式:

    • 每个部门(Pod)分配一个固定分机号(虚拟IP)
    • 只能通过公司内网拨打(其他Pod/内部组件访问)
  • 特点:

    • 完全隔离外部,像财务部核心系统
    • 默认的Service类型,最安全
  • 适用场景

    ini 复制代码
    # 数据库服务,只允许集群内其他Pod访问
    kubectl expose deploy mysql --port=3306
🌐 NodePort(公司前台总机+外线)
  • 作用范围:向全世界公开服务(通过服务器IP)

  • 访问方式:

    • 会在所有服务器上开启一个固定外线号码(30000-32767端口)
    • 访问方式:http://<任意服务器IP>:<固定端口>
  • 特点:

    • 像公司前台,任何人都能拨打
    • 自动包含ClusterIP功能(内网也能用)
  • 适用场景

    ini 复制代码
    # 临时测试网站,快速让外网访问
    kubectl expose deploy webapp --type=NodePort --port=80
🎨 直观对比表
特性 ClusterIP NodePort
IP类型 虚拟IP(仅集群内有效) 服务器真实IP
端口范围 任意指定(如80, 3306) 固定30000-32767范围
安全性 高(仅内网) 低(暴露公网)
适用阶段 生产环境内部通信 开发测试/临时公开
访问示例 curl http://10.96.1.2:80 curl http://<公网IP>:31234
🌟 关键记忆点
  1. ClusterIP
    • 像公司内网OA系统
    • 只有员工(Pod)能访问
    • 适合数据库/内部API
  2. NodePort
    • 像公司门口招牌上的电话
    • 路人(公网用户)也能打进来
    • 需要额外配置防火墙规则
💡 进阶理解

当使用kubectl get svc时:

bash 复制代码
BashNAME       TYPE        CLUSTER-IP     PORT(S)        
webapp     ClusterIP   10.96.1.2      80/TCP          # 只能内部访问
test-svc   NodePort    10.96.33.15    80:31234/TCP    # 外部通过31234端口访问

➡️ NodePort的80:31234表示:内部用80端口,外部用31234端口

🚨 注意NodePort的隐患

如果直接在生产环境使用NodePort:

  1. 需要手动管理安全组(比如只允许特定IP访问31234端口)
  2. 更适合用Ingress + ClusterIP组合(更安全可控)

Nginx-ingress核心配置

  • 必须掌握的注解(annotations):

    lua 复制代码
    nginx.ingress.kubernetes.io/proxy-read-timeout: "3600"
    nginx.ingress.kubernetes.io/proxy-send-timeout: "3600"
    nginx.ingress.kubernetes.io/websocket-services: "your-service-name"
  • 必须理解的配置段:

    bash 复制代码
    bash 体验AI代码助手 代码解读复制代码proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
🌐 Nginx-Ingress 核心配置
🎮 把Ingress想象成游戏服务器路由器

假设开了一个网游公司,玩家(客户端)要通过路由器(Ingress)连接不同的游戏服务器(Pod)。WebSocket就像实时对战通道,需要特殊设置:

🔑 必须掌握的三个"魔法开关"(注解)
bash 复制代码
annotations:
  # 1. 设置通话超时(防止掉线)
  nginx.ingress.kubernetes.io/proxy-read-timeout: "3600"  # 最长发呆1小时不断线
  nginx.ingress.kubernetes.io/proxy-send-timeout: "3600"  # 发送消息超时时间
  
  # 2. 开通VIP对战通道(WebSocket)
  nginx.ingress.kubernetes.io/websocket-services: "game-ws-server"  # 指定哪个服务需要WS

💡 为什么重要? 普通HTTP像发邮件,WebSocket像打电话,需要保持长连接不中断

🛠️ 必须理解的两个"接线指令"(配置段)
bash 复制代码
# 这两行相当于告诉路由器:
# "遇到带Upgrade头的请求,就切换成实时对战模式(WS协议)"
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";

⚠️ 云环境特别注意: 华为云/阿里云的负载均衡器可能默认拦截Upgrade头,需要额外配置!

🧩 完整解决方案(WebSocket场景)
yaml 复制代码
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: game-ingress
  annotations:
    # 基础保活设置
    nginx.ingress.kubernetes.io/proxy-read-timeout: "3600"
    nginx.ingress.kubernetes.io/proxy-send-timeout: "3600"
    
    # WebSocket专属配置
    nginx.ingress.kubernetes.io/websocket-services: "game-ws-server"
    nginx.ingress.kubernetes.io/configuration-snippet: |
      proxy_set_header Upgrade $http_upgrade;
      proxy_set_header Connection "upgrade";
      
    # 华为云特殊配置(如果需要)
    kubernetes.io/elb.id: "your-elb-id"
spec:
  rules:
  - host: game.yourdomain.com
    http:
      paths:
      - path: /ws
        pathType: Prefix
        backend:
          service:
            name: game-ws-server
            port: 
              number: 8080
🌩️ 云环境三大检查清单
  1. 安全组规则

    • 放行WebSocket端口(通常是80/443)
    • 允许TCP长连接(不是仅HTTP)
  2. 负载均衡器配置

    • 查看是否支持WebSocket协议
    • 检查健康检查设置(建议调大超时时间)
  3. K8s服务暴露方式

    bash 复制代码
    # 确认Service类型是否正确
    kubectl get svc game-ws-server -o yaml | grep type
    • 推荐:ClusterIP + Ingress(不要直接用NodePort)
🐞 故障排查四板斧
  1. 检查握手过程

    bash 复制代码
    # 查看WebSocket连接是否成功升级协议
    kubectl logs -n ingress-nginx deploy/ingress-nginx-controller | grep "upgrade"
  2. 模拟连接测试

    bash 复制代码
    # 使用websocat工具测试(比curl更准确)
    websocat -v ws://game.yourdomain.com/ws
  3. 抓包分析

    bash 复制代码
    # 进入Ingress Pod抓包
    kubectl exec -it ingress-pod -- tcpdump -i any -w /tmp/ws.pcap
  4. 云平台诊断

    • 华为云查看ELB监控指标: 连续连接数 ≠ 0表示长连接建立成功
💼 不同云厂商秘笈
云平台 关键配置项 控制台位置
华为云 配置ELB监听器的"高级特性" 弹性负载均衡 → 监听器 → 高级配置
阿里云 开启"WebSocket增强型" SLB实例 → 监听配置 → 协议支持
AWS 设置ALB的idle_timeout EC2 → 负载均衡 → 超时设置
🚀 终极调试技巧

遇到问题时分步验证:

  1. 先用NodePort临时暴露WebSocket服务,测试基础功能
  2. 再通过Ingress访问,对比差异
  3. 最后添加云平台特殊配置

📌 记住:WebSocket问题90%出在三个地方:

  1. 超时时间太短
  2. 协议头未正确传递
  3. 云平台中间件拦截

WebSocket协议特性

🌐 WebSocket协议:就像对讲机 vs 传统HTTP的信鸽
🕊️ 传统HTTP(信鸽送信)
  1. 每次请求都要重新建立连接
    • 你问一句(请求),鸽子飞出去
    • 对方回一句(响应),鸽子飞回来
    • 缺点:每次都要等鸽子往返,延迟高
  2. 只能你主动发起
    • 服务器不能主动给你发消息
    • 像不断刷新网页看新消息

📻 WebSocket(对讲机通话)

  1. 一次握手,长久通话
    • 第一次HTTP握手后,就升级成双向通道
    • 之后随时可以互相喊话,不用重复连接
  2. 关键特点
    • 低延迟:像打电话一样实时(游戏/聊天室)
    • 省资源:不用每次建立TCP连接
    • 双工通信:双方可以同时说话
🔧 WebSocket的三大生命特征
  1. 握手阶段(HTTP升级请求)

    bash 复制代码
    GET /chat HTTP/1.1
    Host: example.com
    Upgrade: websocket       ← 关键头
    Connection: Upgrade      ← 关键头
    Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
  2. 协议升级(服务器响应)

    makefile 复制代码
    HTTP/1.1 101 Switching Protocols
    Upgrade: websocket
    Connection: Upgrade
    Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
  3. 数据帧传输

    • 之后所有通信都走二进制帧(不再是HTTP协议)
    • 每个帧带类型标识:文本/二进制/ping/pong/关闭
⚠️ 容易出问题的地方
  1. 中间设备拦截

    • 防火墙/Nginx/云负载均衡可能阻断长连接
    • 需要特殊配置(就是之前说的proxy_set_header
  2. 心跳保活

    • 长时间不说话会被断开

    • 解决方案:

      javascript 复制代码
      // 前端定时发心跳包
      setInterval(() => ws.send('ping'), 30000)
  3. 协议升级失败

    • 检查请求头是否完整包含:

      makefile 复制代码
      Upgrade: websocket
      Connection: Upgrade
🎮 实际场景例子
  1. 网页聊天室
  • HTTP:每次发送消息都要刷新页面
  • WebSocket:像微信一样实时收到消息
  1. 多人游戏同步
javascript 复制代码
// 玩家移动时实时广播给其他玩家
ws.on('player_move', (data) => {
  broadcastToAllPlayers(data)
})
  1. 股票价格实时推送
  • 传统方案:每5秒轮询请求最新价格
  • WebSocket:价格变动时服务器主动推送
🌩️ 云环境特别注意事项
  1. ALB/NLB配置

    • 需要开启"WebSocket支持"(华为云叫"WebSocket增强型")
    • 调整空闲超时时间(建议≥3600秒)
  2. K8s Ingress注解

    lua 复制代码
    annotations:
      nginx.ingress.kubernetes.io/proxy-read-timeout: "3600"
      nginx.ingress.kubernetes.io/websocket-services: "你的服务名"
  3. 安全组规则

    • 放行WS端口(通常是80/443)
    • 允许TCP长连接(不只是HTTP)
🔍 快速检测WS是否正常工作
  1. 浏览器开发者工具

    • 查看Network → WS → 确认状态码是101
  2. 命令行测试

    bash 复制代码
    # 使用websocat工具测试
    websocat ws://your-server.com/chat
  3. 抓包看关键帧

    css 复制代码
    # 在服务器上抓包
    tcpdump -i any -A 'tcp port 80 and (tcp[((tcp[12:1] & 0xf0) >> 2):4] = 0x47455420)'

记住:WebSocket = 把HTTP短连接改造成双向高速公路

当前遇到的问题大多是因为:

  1. 收费站(Ingress)没开特殊通道
  2. 交管系统(云平台)设置了不合理限流
  3. 车辆(客户端)没按时交养路费(心跳包)
相关推荐
hzsnone2 小时前
公网服务器上Nginx或者Openresty如何屏蔽IP直接扫描
服务器·nginx·openresty
东风微鸣3 小时前
GitOps:云原生时代的革命性基础设施管理范式
docker·云原生·kubernetes·可观察性
GolangSpace4 小时前
YAML:Kubernetes世界里的标准工作语言
kubernetes
David爱编程4 小时前
Kubernetes NetworkPolicy 实践与策略误区
云原生·容器·kubernetes
Gold Steps.8 小时前
K8S周期性备份etcd数据实战案例
云原生·kubernetes·数据安全·etcd
❀͜͡傀儡师8 小时前
Kubernetes (K8s) 部署Doris
云原生·容器·kubernetes
PanYu——BJ14 小时前
CentOS Nginx 1.13.9 部署文档
linux·nginx·centos
小西↬15 小时前
vite+vue3+websocket处理音频流发送到后端
javascript·websocket·音视频
陈陈CHENCHEN19 小时前
【Kubernetes】集群环境下的应用部署案例
kubernetes