一次业务投诉引发的思考:如何优雅地将K8s服务暴露给外部?

前言

不知道你们有没有同样的感受,不管是测试还是开发,最怕公司产品问题反馈群中的投诉,尤其是 有领导在群里的时候。这不怕啥来啥,早上上班刚坐到工位,还没来的及泡杯茶,群里就有投诉信息了, 大概问题就是"有用户需要退款,但是因为有冻结费用,导致退款失败,重点是这个用户已经没有排课了"。这里简单说一下我们的业务场景: 用户在平台上排课后,会将钱包中的钱冻结,课程取消或者结算后,会将冻结的钱解冻。

收到投诉不要慌,先在群里回复一句"正在处理",表明技术在积极响应,然后再去看看问题具体是什么。

问题定位

经过排查用户的上课信息等等,发现2023年11月份有一节课结束后,没有进行结算,导致冻结的钱没有解冻。这个课程时间有点长了,日志也没有, 很难定位到为啥没有进行结算。

解决诉求

排查代码,并没有发现哪里会造成结算失败,用户迫切要退款,现在的方案有两种:

  • 方案一:修复数据
  • 方案二:调接口重新走一遍结算逻辑 显然方案二是比较好的,修数据太麻烦了,然后去看了看对应的服务,发现这个服务的TYPE是LoadBalancer,简单一查,原来可以通过此IP 来访问接口,这样就将用户的诉求解决了。

我的疑问

但是我有个疑问,为什么这个服务的TYPE是LoadBalancer,而不是NodePort呢?,他们之间有啥区别呢?如何将Service暴露到集群外部呢?

进入正题

K8s为Service创建的ClusterIP是对后端Pod列表的一层抽象,对于集群外部没有任何意义,但是现实是许多Service需要对集群外部 提供服务,所以K8s提供了多种方式来暴露Service,供集群外部访问。

设置方式

通过Service资源对象的类型字段"type"进行设置。

  • ClusterIP:默认值,仅在集群内部可访问。
  • NodePort:将Service的端口号映射到每个Node的端口号上,使得集群外部可以通过Node的IP和NodePort访问Service。
  • LoadBalancer:将Service映射到一个已存在的负载均衡器的IP地址上,使得集群外部可以通过该IP地址访问Service。
  • ExternalName:将Service映射到一个外部的域名上,使得集群外部可以通过该域名访问Service。
  • 还可以通过Ingress将服务暴露到集群外部

NodePort:快速测试,慎用生产

原理 :通过节点IP+静态端口(30000-32767)暴露服务。

yaml 复制代码
apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  type: NodePort
  ports:
    - port: 80
      targetPort: 8080
      nodePort: 31000  # 手动指定(可选)
  selector:
    app: my-app

适用场景 :开发测试、临时演示。

致命缺陷:

  • 端口管理混乱(需人工避免冲突)
  • 单点故障(节点宕机服务不可用)
  • 无负载均衡能力

LoadBalancer:云厂商的"一键解决方案"

原理 :自动创建云负载均衡器(如阿里云SLB),分配独立IP。

yaml 复制代码
spec:
  type: LoadBalancer
  ports:
    - protocol: TCP
      port: 443
      targetPort: 8443

优势:

  • 自动健康检查
  • 支持HTTPS终结
  • 云厂商提供高可用保障

坑点:

  • 成本高 :每个Service一个LB实例($$$)
  • 速度慢 :LB创建可能需要1-2分钟

Ingress:HTTP/HTTPS流量的统一网关

原理 :通过Ingress Controller(如Nginx)实现域名路由和反向代理。

yaml 复制代码
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-ingress
spec:
  rules:
    - host: foo.example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: my-service
                port:
                  number: 80

核心能力:

  • 基于域名的路由
  • 支持TLS证书自动化

方案选型决策

根据业务需求快速匹配方案:

graph TD A[需要暴露服务?] --> B{流量类型} B -->|HTTP/HTTPS| C[Ingress/Gateway API] B -->|TCP/UDP| D[LoadBalancer] A --> E[临时测试?] E -->|是| F[NodePort] E -->|否| G[生产环境?] G -->|是| H[云厂商?] H -->|有预算| I[LoadBalancer] H -->|控制成本| J[Ingress+LB]

最后

在K8s中暴露服务时, 没有绝对的最佳方案 ,只有最适合当前业务场景的选择。理解每种技术的优势和成本,才能在设计架构时游刃有余。

附录:

相关推荐
亿牛云爬虫专家19 分钟前
Kubernetes下的分布式采集系统设计与实战:趋势监测失效引发的架构进化
分布式·python·架构·kubernetes·爬虫代理·监测·采集
ai小鬼头3 小时前
Ollama+OpenWeb最新版0.42+0.3.35一键安装教程,轻松搞定AI模型部署
后端·架构·github
萧曵 丶4 小时前
Rust 所有权系统:深入浅出指南
开发语言·后端·rust
老任与码4 小时前
Spring AI Alibaba(1)——基本使用
java·人工智能·后端·springaialibaba
华子w9089258595 小时前
基于 SpringBoot+VueJS 的农产品研究报告管理系统设计与实现
vue.js·spring boot·后端
星辰离彬5 小时前
Java 与 MySQL 性能优化:Java应用中MySQL慢SQL诊断与优化实战
java·后端·sql·mysql·性能优化
GetcharZp6 小时前
彻底告别数据焦虑!这款开源神器 RustDesk,让你自建一个比向日葵、ToDesk 更安全的远程桌面
后端·rust
jack_yin7 小时前
Telegram DeepSeek Bot 管理平台 发布啦!
后端
小码编匠7 小时前
C# 上位机开发怎么学?给自动化工程师的建议
后端·c#·.net
库森学长7 小时前
面试官:发生OOM后,JVM还能运行吗?
jvm·后端·面试