Service 详解

K8s Service 核心实战:从访问方式到代理模式全解析

​

一、Service 核心概念

在 K8s 集群中,Pod 具有"用后即焚"的特性,重建后 IP 地址会动态变化,直接访问 Pod 会导致服务不可用。 ​ Service 正是为解决这一问题而生:它作为 Pod 的固定代理入口,通过 Label 关联 Pod,无论 Pod 如何重建、IP 如何变化,都能通过 Service 稳定访问 Pod 提供的服务。 ​

Service 工作原理

Service 的本质是一条代理规则 ,真正实现流量转发的是集群中的 kube-proxy 组件:

  • 创建 Service 时,会向 kube-proxy 下发代理规则;
  • kube-proxy 根据规则将请求转发到后端 Pod;
  • 核心依赖两种代理模式:iptables 和 ipvs。

二、Service 代理模式

1. iptables 模式

  • 实现方式 :基于内核模块 netfilter 实现流量转发,内核层转发效率较高;
  • 缺点:负载均衡策略单一(仅随机转发),无 Pod 健康检查能力,后端 Pod 不可用时无法自动剔除。

2. ipvs 模式

ipvs(Virtual Server)同样基于 netfilter,但功能更强大:

  • 优势:支持丰富的负载均衡算法(轮询、加权轮询、最小连接数、最少负载等),自带 Pod 健康检查、连接重试;
  • 前提:集群节点需安装 ipvs 内核模块,否则会自动降级为 iptables 模式。
实操:验证并开启 ipvs 模式
bash 复制代码
# 1. 检查 ipvs 内核模块是否加载
lsmod | grep -e ip_vs -e nf_conntrack_ipv4
# 正常输出示例:
# ip_vs_sh
# ip_vs_wrr
# ip_vs_rr 
# ip_vs
# nf_conntrack
​
# 2. 验证 ipvs 功能(需安装 ipvsadm)
ipvsadm -Ln
​
# 3. 修改 kube-proxy 配置,开启 ipvs 模式(kubeadm 部署需手动配置)
kubectl edit cm kube-proxy -n kube-system
# 找到 mode 字段,修改为:
mode: "ipvs"
​
# 4. 删除现有 kube-proxy Pod(会自动重建并加载新配置)
kubectl get pod --show-labels -n kube-system | grep kube-proxy
kubectl delete pod -l k8s-app=kube-proxy -n kube-system
​
# 5. 验证 Pod 重建完成
kubectl get po -n kube-system | grep kube-proxy

三、Service 常用访问方式

K8s 提供 3 种核心 Service 类型,适配不同访问场景:

类型 特点 适用场景
ClusterIP 仅分配集群内部虚拟 IP,外部无法访问 集群内 Pod 间通信
NodePort 节点暴露 30000-32767 端口,外部可访问 测试/小流量外部访问
LoadBalancer 对接公有云负载均衡(阿里云/AWS 等) 生产环境外部大规模访问

四、实战案例

案例 1:ClusterIP 类型(集群内访问)

创建 3 个 Nginx Pod,通过 ClusterIP 类型 Service 代理,实现集群内访问。

资源清单(hpa-nginx.yml)
yaml 复制代码
apiVersion: v1          
kind: Service
metadata:
  name: svc-nginx
  namespace: test
spec:
  type: ClusterIP           # 默认类型,可省略
  ports:                    # 端口映射
  - port: 80                # Service 暴露的内部端口
    targetPort: 80          # Pod 内容器的端口
  selector:                 # 关联 Label 为 app=deploy-nginx 的 Pod
    app: deploy-nginx
---
apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
  name: hpa-nginx
  namespace: test
spec:
  minReplicas: 3
  maxReplicas: 10
  targetCPUUtilizationPercentage: 6
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: deploy-nginx
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: deploy-nginx
  namespace: test
spec:
  replicas: 3
  selector:
    matchLabels:
      app: deploy-nginx       
  template:
    metadata:
      labels:
        app: deploy-nginx     # 与 Service selector 标签一致
    spec:
      containers:
      - name: nginx
        image: nginx:1.17.0
        ports:
        - containerPort: 80
          protocol: TCP
执行命令
bash 复制代码
# 1. 创建资源
kubectl create -f hpa-nginx.yml
​
# 2. 查看 Pod 信息
kubectl get pod -n test -o wide
​
# 3. 查看 Service 信息(获取 ClusterIP)
kubectl get svc -n test
# 输出示例:
# NAME        TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
# svc-nginx   ClusterIP   10.110.174.205  <none>        80/TCP    10s
​
# 4. 验证集群内访问(修改 Pod 页面区分不同实例)
kubectl exec -it <pod-name> -n test -- /bin/bash
# 在容器内修改 index.html,写入 Pod IP
echo $(hostname -i) > /usr/share/nginx/html/index.html
​
# 5. 循环访问 Service,验证负载均衡
while :
do
    curl <ClusterIP>  # 替换为实际的 Service ClusterIP
    sleep 2
done

总结:ClusterIP 仅能在集群内部节点/Pod 访问,外部主机无法访问。

案例 2:NodePort 类型(外部访问)

修改上述清单,将 Service 改为 NodePort 类型,实现外部主机访问集群内 Pod。

资源清单(hpa-nginx.yml)
yaml 复制代码
apiVersion: v1
kind: Service
metadata:
  name: svc-nginx
  namespace: test
spec:
  type: NodePort         # 改为 NodePort 类型
  ports:
  - port: 80             # Service 内部端口
    targetPort: 80       # Pod 容器端口
    nodePort: 30007      # 自定义节点暴露端口(可选,范围 30000-32767)
  selector:              # 关联 Pod 标签
    app: deploy-nginx
---
# 以下 HPA、Deployment 部分与案例 1 一致,省略(直接复用即可)
apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
    name: hpa-nginx
    namespace: test
spec:
  minReplicas: 3
  maxReplicas: 10
  targetCPUUtilizationPercentage: 6
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: deploy-nginx
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: deploy-nginx
  namespace: test
spec:
  replicas: 3
  selector:
    matchLabels:
      app: deploy-nginx
  template:
    metadata:
      labels:
        app: deploy-nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.17.0
        ports:
        - containerPort: 80
          protocol: TCP
执行命令
bash 复制代码
# 1. 创建/更新资源
kubectl create -f hpa-nginx.yml
# 若已创建,用更新命令:kubectl apply -f hpa-nginx.yml
​
# 2. 查看 Service 信息
kubectl get svc -n test
# 输出示例:
# NAME        TYPE       CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
# svc-nginx   NodePort   10.110.174.205   <none>        80:32388/TCP   13s
# 说明:80(内部端口)、32388(节点暴露的 NodePort 端口)
​
# 3. 外部主机访问测试
# 访问地址:http://<集群节点IP>:<NodePort端口>
# 示例:http://192.168.0.13:32388

提示 :若自定义 nodePort,需确保端口在 30000-32767 范围内,且未被节点占用;若不指定,K8s 会随机分配端口。

相关推荐
律宏阔5 小时前
WSL Docker 端口明明空闲,但就是绑不上端口
linux·windows
律宏阔5 小时前
WSL 突然断网,无法 ping 内网或外网
linux·windows
穷人小水滴5 小时前
用容器编译 VirtualBox 虚拟机软件 (ArchLinux, podman)
linux·容器·virtualbox
乱码三千5 小时前
如何优雅地直连无公网 IP 的远程 GPU 服务器
linux·人工智能·程序员
yunwei375 小时前
使用 eBPF 跟踪 Nginx 请求
linux·后端·性能优化
yunwei375 小时前
使用 eBPF 跟踪 MySQL 查询
linux·后端·性能优化
yunwei375 小时前
eBPF 示例教程:使用 XDP 捕获 TCP 信息
linux·后端·性能优化
GeW5 小时前
制造业高端化,为什么必须重估Linux和数据库?
linux
GeW5 小时前
工业场景中的Linux与数据库选型:高端化转型的技术底座
linux
yunwei375 小时前
eBPF 开发者教程: 简单的 XDP 负载均衡器
linux·后端·性能优化