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. 车辆(客户端)没按时交养路费(心跳包)
相关推荐
蝎子莱莱爱打怪8 小时前
GitLab CI/CD + Docker Registry + K8s 部署完整实战指南
后端·docker·kubernetes
闲云一鹤11 小时前
nginx 快速入门教程 - 写给前端的你
前端·nginx·前端工程化
蝎子莱莱爱打怪4 天前
Centos7中一键安装K8s集群以及Rancher安装记录
运维·后端·kubernetes
何中应4 天前
Nginx转发请求错误
前端·后端·nginx
芝士雪豹只抽瑞克五4 天前
Nginx 高性能Web服务器笔记
服务器·nginx
阿里云云原生4 天前
Kubernetes 官方再出公告,强调立即迁移 Ingress NGINX
kubernetes
失重外太空啦4 天前
nginx
运维·nginx
至此流年莫相忘4 天前
Kubernetes实战篇之配置与存储
云原生·容器·kubernetes
天蓝不会忘记024 天前
lvs,haproxy,keepalived,nginx,tomcat介绍和实验
nginx·tomcat·lvs