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

Kubernetes Service 详解:服务暴露与流量管理全指南

Kubernetes Service 详解:服务暴露与流量管理

一、Service 核心概述

1.1 什么是 Service?

在 Kubernetes 中,Pod 是应用的载体,但 Pod IP 具有动态性(重建后会变更),直接通过 Pod IP 访问服务不稳定。Service 作为 Pod 的“统一访问入口”,通过 Label 关联一组提供相同服务的 Pod,实现负载均衡固定访问地址,屏蔽 Pod 动态变化的细节。

1.2 核心原理

Service 的功能依赖 kube-proxy(每个 Node 节点上运行的代理进程):

  1. 创建 Service 时,API Server 将配置写入 Etcd;
  2. kube-proxy 监听 Etcd 中 Service 和 Pod 的变化,生成对应的访问规则(如 iptables/ipvs 规则);
  3. 外部请求访问 Service 地址时,kube-proxy 按规则将请求转发到后端 Pod。

1.3 kube-proxy 工作模式

kube-proxy 支持三种工作模式,决定请求转发的效率和策略:

模式核心原理优缺点
userspacekube-proxy 监听端口,请求先转发到 proxy 再转发到 Pod(用户空间转发)稳定但效率低(内核/用户空间数据拷贝),已逐步淘汰
iptableskube-proxy 生成 iptables 规则,请求直接通过内核转发到 Pod效率高,无中间转发;但不支持灵活负载均衡策略(如会话保持),Pod 故障无重试
ipvs基于 Linux IPVS 模块,生成虚拟服务规则,直接转发请求效率最高,支持更多负载均衡算法(轮询、加权轮询等),推荐生产环境使用
开启 ipvs 模式(推荐)
# 1. 编辑 kube-proxy 配置(修改模式为 ipvs)
kubectl edit cm kube-proxy -n kube-system
# 将 mode: "" 改为 mode: "ipvs"# 2. 重启 kube-proxy Pod(使配置生效)
kubectl delete pod -l k8s-app=kube-proxy -n kube-system# 3. 验证 ipvs 规则(需安装 ipvsadm 工具)
ipvsadm -Ln
# 输出示例(可见 Service 对应的后端 Pod 地址):
# TCP  10.97.97.97:80 rr
#   -> 10.244.1.39:80               Masq    1      0          0
#   -> 10.244.1.40:80               Masq    1      0          0

二、Service 资源清单与类型

2.1 通用资源清单格式

apiVersion: v1  # 固定版本
kind: Service   # 资源类型
metadata:name: <service-name>  # Service 名称namespace: <namespace>  # 所属命名空间
spec:selector:  # 关联 Pod 的 Label(核心)app: nginx-podtype: <service-type>  # Service 类型(如 ClusterIP/NodePort)clusterIP: <virtual-ip>  # 虚拟 IP(ClusterIP 模式下可选,默认自动分配)sessionAffinity: <affinity-type>  # 会话亲和性(ClientIP/None)ports:  # 端口映射规则- protocol: TCP  # 协议(默认 TCP)port: 80  # Service 暴露的端口(集群内访问端口)targetPort: 80  # Pod 内部的端口(需与容器端口一致)nodePort: 30002  # NodePort 模式下的节点端口(30000-32767 范围内)

2.2 四种 Service 类型

Service 支持四种类型,适配不同访问场景(从集群内到集群外):

类型核心作用适用场景
ClusterIP集群内访问,自动分配虚拟 IP(仅集群内可见)集群内部服务间通信(如后端 API 服务)
NodePort暴露 Service 到节点端口(NodeIP:NodePort),集群外可访问开发/测试环境,快速暴露服务
LoadBalancer结合外部负载均衡器(如阿里云 SLB、AWS ELB),对外提供固定访问地址生产环境,需要高可用外部访问
ExternalName将集群外部服务映射为集群内 Service(通过域名关联)访问集群外服务(如数据库、第三方 API)

三、Service 实战使用

3.0 实验环境准备

先通过 Deployment 创建 3 个 Nginx Pod(带 app=nginx-pod 标签),作为 Service 的后端:

# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:name: pc-deploymentnamespace: dev
spec:replicas: 3selector:matchLabels:app: nginx-podtemplate:metadata:labels:app: nginx-podspec:containers:- name: nginximage: nginx:1.17.1ports:- containerPort: 80
# 创建 Deployment
kubectl create -f deployment.yaml# 验证 Pod(确认 Label 为 app=nginx-pod)
kubectl get pods -n dev -o wide --show-labels

3.1 ClusterIP 类型(集群内访问)

默认类型,自动分配集群内唯一虚拟 IP,仅集群内 Pod/节点可访问。

配置文件(service-clusterip.yaml)
apiVersion: v1
kind: Service
metadata:name: service-clusteripnamespace: dev
spec:selector:app: nginx-pod  # 关联 Label 为 app=nginx-pod 的 Podtype: ClusterIPclusterIP: 10.97.97.97  # 可选,固定虚拟 IP(不指定则自动分配)ports:- port: 80  # Service 端口targetPort: 80  # Pod 端口
操作命令
# 1. 创建 Service
kubectl create -f service-clusterip.yaml# 2. 查看 Service(CLUSTER-IP 为 10.97.97.97)
kubectl get svc -n dev -o wide
# 输出示例:
# NAME                TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)   AGE
# service-clusterip   ClusterIP   10.97.97.97   <none>        80/TCP    13s# 3. 查看后端 Pod(Endpoints 列表为关联的 Pod 地址)
kubectl describe svc service-clusterip -n dev
# 输出关键信息:
# Endpoints:         10.244.1.39:80,10.244.1.40:80,10.244.2.33:80# 4. 集群内访问测试(轮询转发到后端 Pod)
curl 10.97.97.97
负载均衡策略
  • 默认策略:轮询(rr),通过 ipvs/iptables 实现;
  • 会话保持:设置 sessionAffinity: ClientIP,同一客户端请求固定转发到同一 Pod:
    spec:sessionAffinity: ClientIP  # 新增会话亲和性配置
    

3.2 Headless Service(无 ClusterIP)

不分配虚拟 IP,通过 Service 域名直接解析到后端 Pod IP,适用于自定义负载均衡场景(如客户端自行控制转发)。

配置文件(service-headliness.yaml)
apiVersion: v1
kind: Service
metadata:name: service-headlinessnamespace: dev
spec:selector:app: nginx-podclusterIP: None  # 关键:不分配 ClusterIPtype: ClusterIPports:- port: 80targetPort: 80
操作命令
# 1. 创建 Service
kubectl create -f service-headliness.yaml# 2. 查看 Service(CLUSTER-IP 为 None)
kubectl get svc service-headliness -n dev -o wide# 3. 域名解析测试(集群内 Pod 中执行)
# 先创建测试 Pod
kubectl run busybox11 --image=busybox -n dev --sleep 6000
# 进入 Pod 解析 Service 域名
kubectl exec -it busybox11 -n dev -- /bin/sh
/ # nslookup service-headliness.dev.svc.cluster.local
# 输出示例(直接返回后端 Pod IP):
# Address 1: 10.244.1.39
# Address 2: 10.244.1.40
# Address 3: 10.244.2.33

3.3 NodePort 类型(集群外访问)

在每个 Node 节点上暴露一个固定端口(30000-32767),外部通过 NodeIP:NodePort 访问 Service,适用于开发/测试环境。

配置文件(service-nodeport.yaml)
apiVersion: v1
kind: Service
metadata:name: service-nodeportnamespace: dev
spec:selector:app: nginx-podtype: NodePort  # 类型为 NodePortports:- port: 80  # Service 端口targetPort: 80  # Pod 端口nodePort: 30002  # 自定义节点端口(可选,默认自动分配)
操作命令
# 1. 创建 Service
kubectl create -f service-nodeport.yaml# 2. 查看 Service(PORT(S) 显示 80:30002/TCP)
kubectl get svc -n dev -o wide
# 输出示例:
# NAME               TYPE       CLUSTER-IP      PORT(S)       AGE
# service-nodeport   NodePort   10.105.64.191   80:30002/TCP  10s# 3. 外部访问测试(浏览器/ curl 访问任意 Node IP:30002)
curl http://192.168.100.100:30002  # 192.168.100.100 为 Node IP

3.4 ExternalName 类型(映射外部服务)

将集群外部服务(如百度、自建数据库)映射为集群内 Service,通过 Service 域名即可访问外部服务,无需暴露外部地址。

配置文件(service-externalname.yaml)
apiVersion: v1
kind: Service
metadata:name: service-externalnamenamespace: dev
spec:type: ExternalName  # 类型为 ExternalNameexternalName: www.baidu.com  # 外部服务域名(或 IP)
操作命令
# 1. 创建 Service
kubectl create -f service-externalname.yaml# 2. 域名解析测试(集群内 Pod 中执行)
kubectl exec -it busybox11 -n dev -- /bin/sh
/ # nslookup service-externalname.dev.svc.cluster.local
# 输出示例(解析到百度 IP):
# Address 1: 39.156.66.18
# Address 2: 39.156.66.14

四、Ingress:统一入口管理(7层负载均衡)

4.1 为什么需要 Ingress?

NodePort 和 LoadBalancer 存在明显缺点:

  • NodePort:占用大量节点端口,服务增多时难以管理;
  • LoadBalancer:每个 Service 需一个外部 LB,成本高、配置繁琐。

Ingress 作为 7层负载均衡器,通过一个入口(NodePort/LB)暴露多个 Service,支持域名路由、HTTPS 终止、路径匹配等高级功能,本质是对 Nginx/HAProxy 等反向代理的抽象。

4.2 核心组件

  • Ingress 资源:定义路由规则(如“nginx.chenyu.com → nginx-service”);
  • Ingress Controller:实现反向代理的程序(如 Nginx-Ingress),监听 Ingress 规则变化,生成对应的代理配置。

4.3 Ingress 实战

4.3.1 部署 Ingress Controller(Nginx 版本)
# 1. 创建目录并下载部署文件
mkdir ingress-controller && cd ingress-controller
wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/baremetal/deploy.yaml# 2. 部署 Ingress Controller(默认命名空间 ingress-nginx)
kubectl apply -f deploy.yaml# 3. 验证部署(Pod 状态为 Running)
kubectl get pod -n ingress-nginx
# 输出示例:
# NAME                                       READY   STATUS    AGE
# nginx-ingress-controller-fbf967dd5-4qpbp   1/1     Running   12h# 4. 查看 Ingress 暴露的 NodePort(80 对应 HTTP,443 对应 HTTPS)
kubectl get svc -n ingress-nginx
# 输出示例:
# NAME            TYPE       PORT(S)                      AGE
# ingress-nginx   NodePort   80:32240/TCP,443:31335/TCP   11h
4.3.2 准备后端 Service(Nginx + Tomcat)

创建两个 Service 作为 Ingress 路由目标:

# tomcat-nginx.yaml
apiVersion: apps/v1
kind: Deployment
metadata:name: nginx-deploymentnamespace: dev
spec:replicas: 3selector:matchLabels:app: nginx-podtemplate:metadata:labels:app: nginx-podspec:containers:- name: nginximage: nginx:1.17.1ports:- containerPort: 80
---
apiVersion: apps/v1
kind: Deployment
metadata:name: tomcat-deploymentnamespace: dev
spec:replicas: 3selector:matchLabels:app: tomcat-podtemplate:metadata:labels:app: tomcat-podspec:containers:- name: tomcatimage: tomcat:8.5-jre10-slimports:- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:name: nginx-servicenamespace: dev
spec:selector:app: nginx-podtype: ClusterIPports:- port: 80targetPort: 80
---
apiVersion: v1
kind: Service
metadata:name: tomcat-servicenamespace: dev
spec:selector:app: tomcat-podtype: ClusterIPports:- port: 8080targetPort: 8080
# 创建资源
kubectl create -f tomcat-nginx.yaml
4.3.3 HTTP 路由配置

通过域名路由到不同 Service(如 nginx.chenyu.com → nginx-service):

# ingress-http.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:name: ingress-httpnamespace: dev
spec:ingressClassName: nginx  # 指定 Ingress Controller 类型rules:- host: nginx.chenyu.com  # 自定义域名(需配置本地 Hosts 解析)http:paths:- path: /pathType: Prefixbackend:service:name: nginx-serviceport:number: 80- host: tomcat.chenyu.com  # 另一个域名http:paths:- path: /pathType: Prefixbackend:service:name: tomcat-serviceport:number: 8080
# 1. 创建 Ingress 规则
kubectl create -f ingress-http.yaml# 2. 验证规则(可见 Hosts 与 Service 的映射)
kubectl describe ingress ingress-http -n dev# 3. 本地配置 Hosts(将域名解析到任意 Node IP)
echo "192.168.100.100 nginx.chenyu.com tomcat.chenyu.com" >> /etc/hosts# 4. 访问测试(通过 NodePort 32240 访问)
curl http://nginx.chenyu.com:32240  # 访问 Nginx
curl http://tomcat.chenyu.com:32240  # 访问 Tomcat
4.3.4 HTTPS 路由配置(带证书)

为域名配置 HTTPS,需先生成证书并创建 Secret:

# 1. 生成自签名证书(有效期 365 天)
openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 \-keyout tls.key -out tls.crt \-subj "/C=CN/ST=BJ/L=BJ/O=nginx/CN=chenyu.com"# 2. 创建 Kubernetes Secret(存储证书)
kubectl create secret tls tls-secret --key tls.key --cert tls.crt
# ingress-https.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:name: ingress-httpsnamespace: dev
spec:tls:  # HTTPS 配置- hosts:- nginx.chenyu.com- tomcat.chenyu.comsecretName: tls-secret  # 关联证书 SecretingressClassName: nginxrules:- host: nginx.chenyu.comhttp:paths:- path: /pathType: Prefixbackend:service:name: nginx-serviceport:number: 80- host: tomcat.chenyu.comhttp:paths:- path: /pathType: Prefixbackend:service:name: tomcat-serviceport:number: 8080
# 1. 创建 HTTPS Ingress 规则(先删除 HTTP 规则)
kubectl delete ingress ingress-http -n dev
kubectl create -f ingress-https.yaml# 2. 访问测试(通过 HTTPS 端口 31335)
curl -k https://nginx.chenyu.com:31335  # -k 忽略证书校验

五、总结

Service 是 Kubernetes 服务暴露的核心组件,通过 Label 关联 Pod 实现负载均衡和固定访问;Ingress 则解决了多 Service 统一入口的问题,支持 7 层路由和 HTTPS 等高级功能。

组件核心场景推荐用法
Service集群内服务通信、简单外部访问(NodePort)内部服务用 ClusterIP,测试环境用 NodePort
Ingress生产环境多服务统一入口、HTTPS 终止、域名路由搭配 Nginx-Ingress,配置域名和路径路由

通过合理组合 Service 和 Ingress,可实现从集群内到集群外的灵活、安全、高效的服务访问架构。

http://www.dtcms.com/a/577288.html

相关文章:

  • HTML onclick用法
  • 如何理解HTML语义化
  • 【JVM】Java为啥能跨平台?JDK/JRE/JVM的关系?
  • 数据存储新势力:Doris如何挑战ClickHouse的霸主地位?
  • Vmware中主机ip a没有ip地址
  • 在 VSCode 中:如何主动生成c_cpp_properties.json文件
  • 南京网站设计外包做图片视频的网站有哪些问题
  • 雄县哪里有建设网站的常州企业建站系统
  • Spring事件监听的核心机制是什么?
  • 制造企业的数据目录编写
  • 产品迭代快,如何避免战略失焦?
  • 监听某个端口是什么意思
  • ArkTS跨语言交互
  • 破局AI舆情分析的“最后一公里“:BettaFish多智能体系统深度剖析
  • 基于机载相控阵天线的卫星通信链路预算示例(二):上行链路预算
  • web安全开发,oa系统poc方式检测,基于Python,flask,前端回馈,常见的OApoc。
  • 我的容器管理革命:从命令行地狱到可视化操控的蜕变
  • 网站怎么设置qq网站招商页面怎么做
  • cuda10 cudnn7.5--旧版本
  • 「个人 Gitee 仓库」与「企业 Gitee 仓库」同步的几种常见方式
  • 基于扩展卡尔曼滤波的电池荷电状态估算的MATLAB实现
  • 身份安全纵深防御:内网隐身、动态授权与全链路审计的协同技术方案
  • 怎么找到网站站长ifanr wordpress
  • UE5 C++ 反射 运行时获取类和字符串的信息
  • Vue 3 中 ref 和 reactive 的区别与使用场景
  • 和规划网站如何产品推广会议流程
  • LVS/IPVS与Keepalived在云原生环境中的深度学习与实践(一)
  • 汽车信息安全--关于安全强度的误区
  • .NET Framework 4.8 + Microsoft.Data.Sqlite 报 Library e_sqlite3 not found
  • 力扣1539. 第 k 个缺失的正整数