从零开始的云原生之旅(十二):从 Service 到 Ingress——K8s 服务暴露完全指南

从零开始的云原生之旅(十二):从 Service 到 Ingress------K8s 服务暴露完全指南

这一篇承上启下:梳理 Kubernetes Service 全家桶的暴露方式,帮你判断何时需要引入 Ingress,以及在架构演进中如何逐步升级流量入口。

📖 文章目录

  • 前言:为什么要在动手前先厘清入口方案?
  • 一、服务暴露的四块拼图
    • [1.1 ClusterIP:集群内的基础流量交换机](#1.1 ClusterIP:集群内的基础流量交换机)
    • [1.2 NodePort:最直接的外部访问方式](#1.2 NodePort:最直接的外部访问方式)
    • [1.3 LoadBalancer:云环境的标准入口](#1.3 LoadBalancer:云环境的标准入口)
    • [1.4 ExternalName:为老系统提供过渡桥梁](#1.4 ExternalName:为老系统提供过渡桥梁)
  • [二、从四种 Service 到 Ingress:关键问题解析](#二、从四种 Service 到 Ingress:关键问题解析)
  • [三、典型架构演进:单体 → 多服务 → 统一入口](#三、典型架构演进:单体 → 多服务 → 统一入口)
  • [四、实战示例:一步步接入 Ingress](#四、实战示例:一步步接入 Ingress)
    • [4.1 编写 Service 与 Deployment](#4.1 编写 Service 与 Deployment)
    • [4.2 暴露 NodePort 进行基础联调](#4.2 暴露 NodePort 进行基础联调)
    • [4.3 引入 Ingress 统一域名与路径](#4.3 引入 Ingress 统一域名与路径)
  • [五、决策清单:什么时候从 Service 升级到 Ingress?](#五、决策清单:什么时候从 Service 升级到 Ingress?)
  • 六、常见误区与排查建议
  • [七、知识延伸:为 Ingress 深度剖析做准备](#七、知识延伸:为 Ingress 深度剖析做准备)
  • 结语:保持架构的弹性与节奏

前言:为什么要在动手前先厘清入口方案?

很多团队在部署第一个 Kubernetes 集群时,往往一头扎进 Ingress 或 Istio,却忽视了 Service 本身已经提供了多种暴露方式。结果就是:

  • 明明只是内部系统,却提前上了 Ingress,增加复杂度;
  • 对外暴露服务时没有规划 IP、端口,导致测试和生产配置割裂;
  • 旧系统需要访问集群内部服务,却被迫走 NodePort,性能与安全双输。

因此,本篇目标非常明确:厘清 Kubernetes 服务暴露的基石,给出一条渐进式演进路径,让后续的 Ingress、服务网格决策都有据可依。


一、服务暴露的四块拼图

1.1 ClusterIP:集群内的基础流量交换机

yaml 复制代码
apiVersion: v1
kind: Service
metadata:
  name: api-svc
spec:
  type: ClusterIP
  selector:
    app: api
  ports:
  - port: 8080
    targetPort: 8080
  • 定位:默认创建的 Service 类型,只在集群内部可达。
  • 能力:提供稳定虚拟 IP(ClusterIP),屏蔽 Pod 变动。
  • 适用:微服务之间的东西向流量;前端 Pod 调用后端 API。
  • 限制:无法被集群外直接访问,需要配合其他方式暴露。

📌 记住:Kubernetes 中真正的"Service 发现"是由 ClusterIP 提供的。

1.2 NodePort:最直接的外部访问方式

yaml 复制代码
apiVersion: v1
kind: Service
metadata:
  name: api-service
  labels:
    app: api
spec:
  # 类型:NodePort(通过节点端口暴露,便于本地访问)
  type: NodePort
  
  # 选择器:选择app=api的Pod
  selector:
    app: api
  
  ports:
  - name: http
    protocol: TCP
    port: 8080        # Service端口
    targetPort: 8080  # Pod端口
    nodePort: 30080   # 节点端口(可选,范围30000-32767)
  • 定位:在每个 Node 上打开同一个端口对外提供访问。
  • 优点:部署简单、无需额外负载均衡。
  • 缺点:端口暴露在所有节点上,存在安全风险;端口区间受限(30000-32767),常见的使用是对某个具体的服务直接暴露到官网。
  • 常见用途
    • 本地/测试环境快速验证;
    • 与外部硬件负载均衡器对接时的后端目标。

1.3 LoadBalancer:云环境的标准入口

在云平台(如 AWS、GCP、阿里云)上,Service 设置为 LoadBalancer 会自动申请云负载均衡。

维度 说明
优点 一键获得公网入口、健康检查、弹性扩缩支撑
成本 需要付费(按时或按流量),并受限于云厂商能力
场景 面向公网的 API、落地到云平台的正式环境

本质上,LoadBalancer 仍然是对 NodePort 的进一步封装:云 LB 会将请求转发到 Node 上暴露的端口。集群内部依旧通过 ClusterIP 做服务发现。

1.4 ExternalName:为老系统提供过渡桥梁

yaml 复制代码
apiVersion: v1
kind: Service
metadata:
  name: legacy-db
spec:
  type: ExternalName
  externalName: db.prod.example.com
  • 定位:将 DNS 查询直接 CNAME 到外部域名。
  • 作用:统一服务发现入口,让集群内应用以 Service 名称连接旧系统。
  • 限制:不是真正的代理,没有负载均衡与健康检查,只是 DNS 层映射。

当你在迁移遗留系统时,ExternalName 可以作为"过渡层",帮助新旧系统解耦命名方式。


二、从四种 Service 到 Ingress:关键问题解析

当系统逐渐复杂,我们会遇到以下痛点:

  1. 域名管理困难:NodePort 只提供端口,没有域名;LoadBalancer 需要为每个服务申请一个公网入口。
  2. 路径路由缺失 :想让 /api/web 指向不同服务,NodePort / LoadBalancer 无法在 L4 层完成。(L4是网络层,而路径是在L7引用层)
  3. HTTPS 统一管理:为每个 Service 单独配置证书既费时又难维护。
  4. 灰度与策略:基础 Service 无法识别 Header、Cookie,更谈不上金丝雀发布。

这时,Ingress 登场:它在 L7(应用层) 提供路由、证书、重写等能力,复用现有 Service 作为后端目标。可以把它理解为"为 Service 加了一层反向代理和策略引擎"。
/api /web /static Client LoadBalancer/NodePort Ingress Controller api-svc web-svc static-svc


三、典型架构演进:单体 → 多服务 → 统一入口

text 复制代码
阶段A:单体应用
浏览器 → NodePort → Pod

阶段B:多服务拆分
外部 → LoadBalancer → 多个 Service

阶段C:统一入口
外部 → LoadBalancer → Ingress Controller → Service → Pod

⭐️ 建议采用"先 Service、再 Ingress"的节奏。只有当多个服务需要统一入口或策略治理时,再引入 Ingress,避免过早增加复杂度。


四、实战示例:一步步接入 Ingress

4.1 编写 Service 与 Deployment

yaml 复制代码
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: api
spec:
  replicas: 3
  selector:
    matchLabels:
      app: api
  template:
    metadata:
      labels:
        app: api
    spec:
      containers:
      - name: api
        image: ghcr.io/example/api:v1
        ports:
        - containerPort: 8080

配套 Service:

yaml 复制代码
# service.yaml
apiVersion: v1
kind: Service
metadata:
  name: api-svc
spec:
  selector:
    app: api
  ports:
  - port: 8080
    targetPort: 8080

4.2 暴露 NodePort 进行基础联调

bash 复制代码
# 临时将 Service 改为 NodePort
kubectl patch svc api-svc -p '{"spec": {"type": "NodePort"}}'

# 查看端口
kubectl get svc api-svc
# NAME      TYPE       CLUSTER-IP    PORT(S)           NODE-PORT
# api-svc   NodePort   10.0.0.12     8080/TCP          30321/TCP

# 在开发机验证
curl http://<NodeIP>:30321/healthz

这一阶段主要用于联调与确认路由逻辑,确保后端容器正常工作。

4.3 引入 Ingress 统一域名与路径

需要注意的是,第一次使用ingress的同学,应该是没有配置具体的ingress controller。我们需要kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.10.0/deploy/static/provider/cloud/deploy.yaml

yaml 复制代码
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: app-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
  ingressClassName: nginx
  rules:
  - host: app.local
    http:
      paths:
      - path: /api(/|$)(.*)
        pathType: Prefix
        backend:
          service:
            name: api-svc
            port:
              number: 8080
      - path: /(.*)
        pathType: Prefix
        backend:
          service:
            name: web-svc
            port:
              number: 80
  • ingressClassName 指定控制器(如 Nginx)。
  • rewrite-target 注解规整后端路径。
  • 通过单一域名 app.local 暴露多个服务。

到此,我们完成了 Service → Ingress 的演进:底层依然是 ClusterIP/NodePort,Ingress 只是附加的 L7 策略层。


五、决策清单:什么时候从 Service 升级到 Ingress?

场景 是否需要 Ingress 说明
内部系统,只需集群内互访 ClusterIP 足够,借助 Service DNS 即可
临时演示/联调,需要快速暴露 ⚠️ 可选 NodePort 最直接,但记得回收端口
云上生产环境,每个服务都需要公网入口 LoadBalancer + Ingress 组合,节省 IP 和证书成本
希望按照路径/域名划分流量 Ingress 提供 L7 路由能力
需要统一 TLS、鉴权、WAF 策略 Ingress 注解 + 控制器可扩展
计划实施金丝雀/熔断/限流 🚨 Ingress 能力有限,应评估服务网格(Istio 等)

牢记"从简到繁"的原则:Ingress 是对 Service 的增强,不是替代。先把 Service 配置扎实,再考虑引入更高层的治理能力。


六、常见误区与排查建议

  1. 误区:以为创建 Ingress 就能访问

    • ✅ 实际上需要运行 Ingress Controller(如 Nginx、Traefik)。
    • 检查:kubectl get pods -n ingress-nginx
  2. 误区:忘记更新本地 hosts 或 DNS

    • ✅ L7 路由依赖 Host Header,务必在测试机上配置 app.local
  3. 误区:PathType 设置不当

    • PrefixExact 匹配方式不同;对于 REST API,推荐使用 Prefix
  4. 误区:忽视 Service 选择器

    • ✅ 如果 Service 的 selector 与 Pod 标签不匹配,会导致 Ingress 返回 503。
  5. 排查流程建议

text 复制代码
1. kubectl get svc -n ingress-nginx         # 控制器 Service 是否就绪?
2. kubectl describe ingress app-ingress     # 规则是否生效?有无事件报错?
3. kubectl get endpoints api-svc            # Service 是否指向 Pod?
4. curl -H "Host: app.local" http://<LB>/  # 指定 Host 进行访问

七、知识延伸:为 Ingress 深度剖析做准备

接下来你会在《Ingress 深度剖析:从 Service 到统一入口》中看到:

  • 更细致的 Ingress 规范字段解释(IngressClass、默认后端、PathType)。
  • 控制面、数据面的多种实现选择。
  • TLS、注解、请求生命周期的高级玩法。

提前把 Service 的基础打牢,会让你在理解 Ingress 架构时更游刃有余。


结语:保持架构的弹性与节奏

Kubernetes 提供的 Service 类型就像拼图:按需组合即可构建出适合团队规模的流量路径。不要一开始就追求"大而全"的方案,而是遵循以下节奏:

  1. ClusterIP 夯实服务发现:保证内部调用稳定。
  2. NodePort/LoadBalancer 快速暴露:在不同环境满足访问需求。
  3. Ingress 统一入口:当服务数量、策略需求增加时再引入。
  4. 服务网格:在需要东西向治理与高级流量控制时再升级。

下一篇,我们将顺势深入 Ingress 世界,解锁更多 L7 路由与策略细节。

🌟 架构没有银弹,适度演进才能保持系统的可维护性与韧性。

相关推荐
中电金信2 小时前
云原生时代,应用运维模式如何破局?
运维·云原生
ringking1232 小时前
docker源文件配置以及密钥文件
运维·docker·容器
编织幻境的妖2 小时前
Docker和Kubernetes 常用命令
docker·容器·kubernetes
周杰伦_Jay4 小时前
【基于 Spring Cloud Alibaba 的微服务电商项目】完整实现思路
微服务·云原生·架构
❀͜͡傀儡师5 小时前
docker-compose一键部署Hadoop集群
hadoop·docker·容器
java_logo6 小时前
BUSYBOX Docker 容器化部署指南
java·运维·python·nginx·docker·容器·运维开发
Z***25807 小时前
后端服务网格实践,Istio与Linkerd对比
云原生·istio
m***D2867 小时前
后端服务网格配置,Istio虚拟服务
云原生·istio