当前位置: 首页 > news >正文

K8S - 深入解析 Service 与 Ingress - 服务暴露与流量管理

一、引言

在 Kubernetes 的弹性架构中,Pod 是应用的最小部署单元,但其动态特性导致直接访问面临两大挑战:

• IP 不固定:Pod 重启或扩缩容时 IP 地址会变化

• 生命周期短暂:故障恢复或滚动更新时旧 Pod 会被替换

为解决这些问题,Kubernetes 提供两大核心抽象:

Service:

• 服务发现:为动态 Pod 提供稳定访问入口(DNS 名称 + 虚拟 IP)

• 四层负载均衡:自动分发流量至健康 Pod

Ingress:

• 七层路由控制:基于 HTTP/HTTPS 协议实现域名、路径等高级路由规则

• 流量治理:支持 TLS 终止、重定向、金丝雀发布等场景

二、核心原理

2.1 Pod IP 的局限性

Pod IP 的动态性会导致以下问题:

• 服务中断风险:客户端直接依赖 Pod IP 时,Pod 重建后需手动更新配置

• 扩展性瓶颈:手动维护 IP 列表难以应对动态扩缩容场景

2.2 Service 的工作原理

Service 通过 三层抽象模型 解决 Pod 动态性问题,实现稳定服务暴露:

              ┌──────────────────┐│     Service<─── 稳定入口 (DNS/ClusterIP)ClusterIP: VIP  │└───────┬──────────┘│通过标签选择器 (Label Selector) 关联│┌───────▼──────────┐│    Endpoints<─── 动态维护健康 Pod 列表│  Pod IP:Port 列表 │└───────┬──────────┘│┌─────────────┼───────────────┐│             │               │┌─────▼─────┐ ┌─────▼─────┐ ┌───────▼─────┐│   Pod 1   │ │   Pod 2   │ │    Pod 3<─── 实际服务实例│app=backend│ │app=backend  │ app=backend │└───────────┘ └───────────┘ └─────────────┘

核心机制解析:

1.ClusterIP(虚拟 IP)
• Kubernetes 为每个 Service 分配一个集群内唯一的虚拟 IP(ClusterIP)。

• 客户端通过该 IP 或 DNS 名称访问服务,如 backend-service.default.svc.cluster.local。

• ClusterIP 作为逻辑抽象层,完全屏蔽后端 Pod IP 的动态变化。

2.标签选择器(Label Selector)

• Service 通过声明式标签(如 app=backend)筛选目标 Pod,未匹配标签的 Pod 不会加入 Endpoints。

• 松耦合设计:允许 Pod 滚动更新(如 app=backend-v2)时无缝切换,无需修改 Service 配置。

3.Endpoints 动态更新

Endpoints Controller 实时监控 Pod 状态,自动维护 IP:Port 列表:

• Pod 扩缩容:新 Pod 启动时自动加入列表,旧 Pod 终止时移除。

• 健康检查:若 Pod 处于 NotReady 状态,自动从列表剔除。

4.流量分发与负载均衡

kube-proxy 组件:

• iptables/IPVS 模式:基于内核级规则实现高性能四层负载均衡(默认轮询算法)。

• 会话保持(Session Affinity):通过 service.spec.sessionAffinity 配置粘性会话。

客户端无感知:所有流量通过 ClusterIP 或 DNS 入口,屏蔽后端 Pod 变化。

2.3 Service 类型及适用场景

Service通过 服务发现与 负载均衡保障 Pod 的可靠访问,其三种类型在实现方式与适用场景上存在显著差异:
在这里插入图片描述

对比解析

1.负载均衡层级

• ClusterIP/NodePort:四层(TCP/UDP),依赖 kube-proxy的 iptables/IPVS规则。

• LoadBalancer:四层(云厂商 LB)或七层(如 AWS ALB 结合 Ingress)。

2.实现组件差异

• ClusterIP:纯 Kubernetes 原生组件(kube-proxy),无外部依赖。

• LoadBalancer:依赖云厂商基础设施(如 AWS ELB、GCP Cloud Load Balancing)。

3.故障域与可用性

• NodePort:单节点故障导致服务不可用(需手动多节点暴露)。

• LoadBalancer:云厂商 LB 自动处理节点故障,支持跨可用区容灾。

4.选型策略

• 内部服务:ClusterIP + DNS 服务发现。

• 生产公网暴露:LoadBalancer(四层入口) + Ingress(七层路由)。

• 临时访问:NodePort + kubectl port-forward(避免直接暴露节点端口)。

2.4 Service 与 DNS 解析

DNS 命名规则

<service-name>.<namespace>.svc.cluster.local

1.访问方式

• 集群内直连:同一命名空间下可通过 http://backend-service:5000访问

• 跨命名空间访问:需使用完整域名

例:http://backend-service.prod.svc.cluster.local:5000

2.解析流程

客户端请求 → CoreDNS 解析 Service 名称 → 返回 ClusterIP → 流量经 kube-proxy 负载均衡至 Pod

3.最佳实践
• 禁用 IP 硬编码:ClusterIP 可能因 Service 重建而变化,依赖 DNS 名称确保稳定性。

• 跨命名空间显式调用:避免因命名空间默认值导致路由错误。

注意:Service 的 IP 地址在服务部署后由 Kubernetes 自动分配。

2.5 Ingress 的七层流量治理

Ingress 不是具体的流量代理,而是路由规则的声明式抽象,需配合 Ingress Controller(如 Nginx、Traefik)实现功能:

核心能力:

• 基于域名(example.com)或 路径(/api)路由到不同 Service

• 支持 TLS 证书管理、请求限速、跨域配置等高级策略

与 Service 的关系:

• Service:负责四层(TCP/UDP)负载均衡

• Ingress:补充七层(HTTP/HTTPS)逻辑

典型架构路径:

客户端 → Ingress ControllerServicePod

三、Service 与 Ingress 实战

3.1 实战环境准备
1.安装必要工具

Mac/Linux 用户# 安装 Docker 并启动服务
brew install --cask docker
open /Applications/Docker.app
# 安装 kubectl 命令行工具
brew install kubectl
# 安装 Kind(本地K8S集群工具)
brew install kind
# 验证安装
docker --version          # 预期输出: Docker version 24.x+
kubectl version --client  # 预期输出: Client Version: v1.28.x
kind version              # 预期输出: kind v0.20.x
Windows 用户
下载Docker Desktop安装 Chocolatey(包管理器):Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))
通过 Chocolatey 安装工具:
choco install kind kubernetes-cli

2.创建本地 Kubernetes 集群

# 创建单节点集群(命名为 k8s-lab)
kind create cluster --name k8s-lab# 验证集群状态
kubectl cluster-info
# 预期输出:Kubernetes control plane is running at https://127.0.0.1:xxxxx

3.2 完整实例
1.目的

• 展示 Service如何通过标签关联 Pod,并通过 Endpoints动态更新实现服务发现。

• 通过 Ingress 统一管理前后端外部流量。

2.实例部署链路架构图

                    ┌──────────┐│  用户请求  │└────┬─────┘│▼┌──────────┐│  Ingress │└────┬─────┘│┌─────────────────┴─────────────────┐│                                  │▼                                  ▼

┌───────────────┐ ┌───────────────┐
│ 前端 Service │ │ 后端 Service │
│ (ClusterIP) │ │ (ClusterIP) │
└───────┬───────┘ └───────┬───────┘
│ │
▼ ▼
┌───────────────┐ ┌───────────────┐
│ 前端 Pod │ │ 后端 Pod │
└───────────────┘ └───────────────┘

3.完整步骤

步骤 1:创建命名空间

# 创建命名空间
kubectl create namespace example

步骤2:部署后端服务

镜像: python:3.9(官方镜像,内置简易 HTTP 服务器)backend-deployment.yamlapiVersion: apps/v1
kind: Deployment
metadata:name: backendnamespace: example
spec:replicas: 2selector:matchLabels:app: backend  # 选择器标签template:metadata:labels:app: backend  # 必须与 selector.matchLabels 一致spec:containers:- name: serverimage: python:3.9command: ["python", "-m", "http.server", "5000"]ports:- containerPort: 5000  # 容器实际监听端口

部署与验证

kubectl apply -f backend-deployment.yaml
# 查看 Pod 详细信息(包含 IP 和标签)
kubectl get pods -n example -l app=backend -o wide --show-labels输出示例:
NAME                        READY   STATUS    IP            NODE    LABELS
backend-7766cc5668-abcde    1/1     Running   10.244.0.10   node1   app=backend
backend-7766cc5668-fghij    1/1     Running   10.244.0.11   node2   app=backend

观察点:

• 两个 Pod 的 IP分别为 10.244.0.10和 10.244.0.11。

• 标签app=backend与 Deployment 中定义的标签一致。

步骤3:创建 Service 并验证 Endpoints

Service 为后端 Pod 提供稳定访问入口。

backend-service.yaml

# backend-service.yaml
apiVersion: v1
kind: Service
metadata:name: backend-servicenamespace: example
spec:selector:app: backendports:- protocol: TCPport: 5000      # Service 监听端口targetPort: 5000  # Pod 端口type: ClusterIP     # 默认类型,集群内可访问

注:Service 的 selector.app=backend与 Pod 的 labels.app=backend匹配。

部署与验证

kubectl apply -f backend-service.yaml
# 查看 ServiceClusterIPEndpoints 信息
kubectl get svc,ep -n example -l app=backend输出示例:
NAME                    TYPE        CLUSTER-IP     PORT(S)   AGE
backend-service         ClusterIP   10.96.56.77   5000/TCP  5s
NAME                    ENDPOINTS                        AGE
backend-service         10.244.0.10:5000,10.244.0.11:5000  5s

验证点:

• Endpoints 由 Kubernetes 自动维护,始终记录当前匹配 Pod 的 IP 和端口。

• Endpoints 实时关联的 Pod IP,与 步骤 2中的 Pod IP 完全一致(10.244.0.10和 10.244.0.11)。

• 端口对应关系:Endpoints 端口 5000与 Pod 的 containerPort一致。

步骤 4:部署前端应用并创建 Service

镜像:nginx:1.25

frontend-deployment.yamlapiVersion: apps/v1
kind: Deployment
metadata:name: frontendnamespace: example
spec:replicas: 1selector:matchLabels:app: frontendtemplate:metadata:labels:app: frontend     spec:containers:- name: nginximage: nginx:1.25ports:- containerPort: 80
frontend-service.yamlapiVersion: v1
kind: Service
metadata:name: frontend-servicenamespace: example
spec:selector:app: frontendports:- protocol: TCPport: 80targetPort: 80type: ClusterIP

部署与验证:

kubectl apply -f frontend-deployment.yaml
kubectl apply -f frontend-service.yaml# 查看前端 PodService
kubectl get pods,svc -n example -l app=frontend -o wide
# 输出示例:
# NAME                            READY   STATUS    IP            NODE
# frontend-5d8f6c6c7d-xyzab       1/1     Running   10.244.0.12   node1# NAME                    TYPE        CLUSTER-IP     PORT(S)
# frontend-service        ClusterIP   10.96.58.89   80/TCP

步骤5:配置 Ingress 路由前后端流量

example-ingress.yaml

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:name: example-ingressnamespace: exampleannotations:nginx.ingress.kubernetes.io/rewrite-target: /
spec:rules:- host: demo.example.comhttp:paths:- path: /pathType: Prefixbackend:service:name: frontend-service  # 前端流量port:number: 80- path: /apipathType: Prefixbackend:service:name: backend-service   # 后端流量port:number: 5000

部署与验证:

# 安装 Ingress 控制器(如未安装)
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/cloud/deploy.yaml# 部署 Ingress
kubectl apply -f example-ingress.yaml# 获取 Ingress 外部 IP
kubectl get ingress -n example
# 输出示例:
# NAME              CLASS   HOSTS             ADDRESS       PORTS
# example-ingress   nginx   demo.example.com  203.0.113.10  80

步骤6:全链路验证与动态服务发现测试

验证流量全链路(用户 → Ingress → 前端 Service → 前端 Pod → 后端 Service → 后端 Pod)及动态服务发现能力。# 测试1:通过 Ingress 访问前端
curl -H "Host: demo.example.com" http://203.0.113.10
# 预期输出:Nginx 默认欢迎页(说明前端 ServiceIngress 路由正常)# 测试2:通过 Ingress 访问后端 API
curl -H "Host: demo.example.com" http://203.0.113.10/api
# 预期输出:Python HTTP 服务器目录列表(说明后端 ServiceIngress 路由正常)# 测试3:进入前端 Pod 验证服务发现
kubectl exec -it $(kubectl get pod -n example -l app=frontend -o jsonpath="{.items[0].metadata.name}") -n example -- sh
while true; do wget -q -O- http://backend-service:5000 && sleep 1; done
输出:交替显示不同pod IP 
10.244.0.10 - - [时间戳] "GET / HTTP/1.1" 200 -
10.244.0.11 - - [时间戳] "GET / HTTP/1.1" 200 -Ctrl+C退出。

结论:

• Ingress 成功将外部流量路由到前端和后端 Service。

• Service 实现了负载均衡,请求均匀分发到后端 Pod。

步骤7:动态扩缩容与 Endpoints 验证

验证 Pod 扩缩容场景下 Service 的自动服务发现能力。

# 操作1:扩展后端 Pod 数量
kubectl scale deployment backend -n example --replicas=3
# 观察 Endpoints 变化(关键验证点)
watch kubectl get pods,ep -n example -l app=backend -o wide
输出:
# Pod 列表(约 30 秒后)
NAME                        READY   STATUS    IP            NODE
backend-7766cc5668-abcde    1/1     Running   10.244.0.10   node1
backend-7766cc5668-fghij    1/1     Running   10.244.0.11   node2
backend-7766cc5668-klmno    1/1     Running   10.244.0.13   node1  # 新增 Pod# Endpoints
NAME               ENDPOINTS
backend-service    10.244.0.10:5000,10.244.0.11:5000,10.244.0.13:5000
结论:•Service会自动将新 Pod IP(例如:10.244.0.13)加入 Endpoints。•无需人工干预,服务发现机制会即时生效。

步骤8:模拟 Pod 故障与服务自愈

验证 Pod 异常退出后,Service 如何保障业务连续性。# 操作1:手动删除一个后端 Pod
kubectl delete pod backend-7766cc5668-abcde -n example# 观察故障恢复过程(关键验证点)
watch kubectl get pods,ep -n example -l app=backend -o wide
输出:
# Pod 列表(删除后)
NAME                        READY   STATUS        IP            NODE
backend-7766cc5668-abcde    0/1     Terminating   10.244.0.10   node1  # 正在终止
backend-7766cc5668-fghij    1/1     Running       10.244.0.11   node2
backend-7766cc5668-klmno    1/1     Running       10.244.0.13   node1# 约 30 秒后,新 Pod 启动完成
NAME                        READY   STATUS    IP            NODE
backend-7766cc5668-fghij    1/1     Running   10.244.0.11   node2
backend-7766cc5668-klmno    1/1     Running   10.244.0.13   node1
backend-7766cc5668-pqrst    1/1     Running   10.244.0.14   node3  # 新 Pod# Endpoints 自动更新
NAME               ENDPOINTS
backend-service    10.244.0.11:5000,10.244.0.13:5000,10.244.0.14:5000

结论:

• 旧 Pod (10.244.0.10) 从 Endpoints 移除。

• 新 Pod (10.244.0.14) 自动加入,服务流量无缝切换。

动态更新原理:

• Deployment 控制器确保 Pod 数量符合 replicas: 3。

• Service 持续监听 Pod 变化,实时更新 Endpoints。

步骤9:验证服务连续性

# 再次进入前端 Pod 发起连续请求,观察负载均衡效果
kubectl exec -it $(kubectl get pod -n example -l app=frontend -o jsonpath="{.items[0].metadata.name}") -n example -- sh
while true; do wget -q -O- http://backend-service:5000 && sleep 1; done
输出: 交替显示不同pod IP 
10.244.0.11 - - [时间戳] "GET / HTTP/1.1" 200 -
10.244.0.13 - - [时间戳] "GET / HTTP/1.1" 200 -
10.244.0.14 - - [时间戳] "GET / HTTP/1.1" 200 -

结论:
• 业务流量自动迁移至健康 Pod,实现零感知故障恢复。

• 证明 Service 的负载均衡和健康检查机制有效。

3.3 配置注意事项
在这里插入图片描述

3.4 总结与生产建议
在这里插入图片描述

生产建议:

• 为 Service 添加 readinessProbe,避免将流量路由到未就绪的 Pod。

• 使用 PodDisruptionBudget保障关键业务的最小可用实例数。

• Ingress 配置 TLS 加密(可通过 Cert-Manager 自动管理证书)。

通过本实例,您已掌握 Kubernetes 服务暴露与流量管理的核心机制。

四、总结

4.1 总结

架构回顾:

外部用户 --> Ingress --> 前端 Service --> 前端 Pod--> 后端 Service --> 后端 Pod

组件总结:

在这里插入图片描述

1.Pod 动态性验证:直接依赖 Pod IP 不可靠。

2.Service 核心能力:

• 通过稳定的 ClusterIP和 DNS 名称实现服务发现。

• 通过 Endpoints动态更新支持 Pod 扩缩容。

• 通过 负载均衡提升可用性。

3.Ingress 扩展性:实现七层路由与外部流量管理。

相关文章:

  • 在多socket多核计算机上配置MPI和OpenMP
  • Protubuf入门 --- 01基本语法与编译使用
  • C语言数据类型与内存布局
  • 算法竞赛进阶指南.巡逻
  • 13分区排烟 无法远程启动 12-1-4,排烟管道出口未连接室外
  • Linux-07-Shell
  • python常用科学计算库及使用示例
  • 数字智慧方案6185丨智慧银行解决方案(51页PPT)(文末有下载方式)
  • 【免费】2010-2019年上市公司排污费数据
  • 迪米特法则(LoD)
  • Baklib内容中台落地实战指南
  • 传奇各职业/战士/法师/道士/手套/手镯/护腕/神秘腰带爆率及出处产出地/圣战/法神/天尊/祈祷/虹魔/魔血
  • 用c 编写的笔记搜索程序
  • 如何用Python绘制两个圆之间的8条公切线
  • 第J6周:ResNeXt-50实战
  • C++ 动态内存管理详讲
  • 数字智慧方案5877丨智慧交通项目方案(122页PPT)(文末有下载方式)
  • SX24C01.UG-PXI程控电阻桥板卡
  • 英一真题阅读单词笔记 20-21年
  • 藏文词云生成器学习实践
  • 熬夜又不想伤肝?方法只有一个
  • 5月1日,多位省级党委书记调研旅游市场、假期安全等情况
  • 解放日报:让算力像“水电煤”赋能千行百业
  • 证监会副主席王建军被查
  • 全文丨中华人民共和国民营经济促进法
  • 辽宁省全力开展辽阳一饭店火灾事故救援处置工作