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;
  • 核心依赖两种代理模式:iptablesipvs

二、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 会随机分配端口。

相关推荐
小鸡脚来咯2 小时前
Linux 服务器问题排查指南(面试标准回答)
linux·服务器·面试
末日汐2 小时前
磁盘与文件系统
linux·运维·数据库
水天需0102 小时前
Linux PS4 环境变量详解
linux
小新ya2 小时前
vscode增删改查文件,一直等待中...
linux·vscode
济6173 小时前
linux(第十四期)--官方 SDK 移植实验-- Ubuntu20.04
linux·运维·服务器
云qq3 小时前
x86操作系统23——进程相关系统调用
linux·c语言·汇编·ubuntu
小猪佩奇TONY3 小时前
Linux 内核学习(16) --- linux x86-64 虚拟地址空间和区域
linux·运维·学习
L1624763 小时前
Docker 安装部署全流程使用指南(Linux 通用版)
linux·docker·容器
杰克崔3 小时前
kprobe及kretprobe的基于例子来调试分析其原理
linux·运维·服务器·车载系统