news 2026/10/27 10:24:39

6、Kubernetes的Servicekube‑proxy

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
6、Kubernetes的Servicekube‑proxy

一、VS Code 编写 K8s 资源文件

1.1 安装与扩展

  • VS Code 分 User Installer / System Installer,功能无差别,仅安装位置、自动更新权限不同。
  • 两个必备扩展:
    • YAML by Red Hat:通用 YAML 支持,负责语法校验、Schema 校验、字段补全、悬浮文档、格式化、锚点跳转。
    • Kubernetes by Microsoft:k8s 开发运维工作台,依赖 Red Hat YAML 扩展;提供 Cluster Explorer(上下文 / 命名空间 / 工作负载 / Service/Pod/Node 实时树视图)、apply/delete/describe/ 日志跟随 / 进 Pod shell / 端口转发、Helm 操作、CRD Schema 智能感知。

1.2 连接集群

  1. 下载kubectl.exe放到$HOME\.kube\并加入 PATH。
  2. 将集群凭据config放到$HOME\.kube\config,左侧 Cluster Explorer 即可看到集群。
  3. 编写资源时输入p选择Kubernetes Pod自动生成模板;补全小技巧:关键字后加冒号:。

二、Service 是什么

2.1 背景问题(两个前置实验结论)

  1. Pod IP 仅集群内部可达,集群外部无法通过 PodIP 访问 Pod。
  2. 控制器动态创建 / 销毁 Pod,Pod IP 不断变化;hostPort占用节点端口,同一节点无法跑多个同端口 Pod。
  3. 前端应用无法跟踪后端 Pod 的 IP 变化,也无法做负载均衡。

2.2 Service 概念

  • Service 把一组 Pod 的网络应用统一暴露成网络服务;拥有固定不变的 ClusterIP 和端口,为后端 Pod 提供负载均衡。
  • Service 通过selector标签选择后端 Pod,自动维护 Service ↔ Pod(Endpoints)映射关系;后端 Pod 增删变化对客户端透明。
  • 关键目标:无需改造老应用即可接入服务发现。

三、Service 基本管理

3.1 命令创建

# 创建 Deployment(3 副本 httpd) kubectl create deployment web --image=hub.laoma.cloud/library/httpd:2.4.58 --replicas=3 # 创建 ClusterIP 类型 Service:访问 ClusterIP 的 8080 转发到 Pod 的 80 kubectl create service clusterip web --tcp=8080:80 kubectl get svc kubectl describe service web # 查看 Selector、Endpoints、Session Affinity kubectl describe svc web | grep -e Endpoints -e IP: curl 查看到的IP地址:8080 # 访问测试
  • --tcp=8080:80:Service 端口 8080 → 后端 Pod 端口 80。
  • Service 默认标签app=<svc-name>;Endpoints字段列出当前后端 PodIP:Port 列表。

3.2 负载均衡验证

# 把每个 Pod 主页改成自己的 Pod 名 for pod in $(kubectl get pods -o name | awk -F/ '{print $2}'); do kubectl exec -it $pod -- bash -c "echo $pod > htdocs/index.html" done # 连续访问 100 次,统计各 Pod 命中次数(轮询负载均衡) for i in {1..100}; do curl -s 自己的IP地址:8080; done | sort | uniq -c
  • 新创建标签匹配app=web的 Pod 会自动被 Service 纳入后端;rollout restart重建 Pod 后 Service 仍能动态发现新 Pod。
  • Deployment 的 selector 与 Service 的 selector 可以是不同标签(如 deploy 匹配app1=web1,svc 匹配app2=web2)。

3.3 expose 与 yaml 创建

# expose 方式:--port=Service端口 --target-port=Pod端口 --selector=标签 kubectl expose deployment web --port=8080 --target-port=80 --selector=app2=web2 # 导出 yaml 模板 kubectl create service clusterip web --tcp=8080:80 -o yaml --dry-run=client > svc-web.yml kubectl apply -f svc-web.yml

注意:Service IP 只做 TCP/UDP 端口转发,ping 不通 ClusterIP,但可以 ping 通 PodIP。

Service 核心 yaml 字段

apiVersion: v1 kind: Service metadata: name: web labels: app: web spec: type: ClusterIP selector: app: web ports: - name: 8080-80 port: 8080 # ClusterIP 监听端口 protocol: TCP targetPort: 80 # 后端 Pod 端口

四、Service 发现(集群内三种访问方式)

4.1 通过 IP 访问

实验:mysql Pod + ClusterIP Service,WordPress 通过 ServiceIP 连接数据库。

# mysql Pod + Service kubectl run mysql --image=hub.laoma.cloud/library/mysql --image-pull-policy=IfNotPresent \ --env=MYSQL_ROOT_PASSWORD=redhat --env=MYSQL_USER=tom \ --env=MYSQL_PASSWORD=redhat --env=MYSQL_DATABASE=blog \ --dry-run=client -o yaml > pod-mysql.yaml kubectl apply -f pod-mysql.yaml kubectl expose pod mysql --port=3306 --target-port=3306 # WordPress 直接用 ServiceIP 作为数据库地址 kubectl run wordpress --image=hub.laoma.cloud/library/wordpress --image-pull-policy=IfNotPresent \ --env=WORDPRESS_DB_USER=tom --env=WORDPRESS_DB_PASSWORD=redhat \ --env=WORDPRESS_DB_NAME=blog --env=WORDPRESS_DB_HOST=10.111.69.45 kubectl expose pod wordpress --port=80 --target-port=80 --type NodePort

4.2 通过环境变量访问

  • Pod 启动时,kubelet 把已存在的 Service 注入环境变量:
    • <SVC>_SERVICE_HOST、<SVC>_SERVICE_PORT
    • <SVC>_PORT_<PORT>_TCP_ADDR、<SVC>_PORT_<PORT>_TCP_PORT、<SVC>_PORT等。
  • 限制:Service 必须先于 Pod 创建,后创建的 Service 不会回填到已有 Pod;Pod 只能访问同一命名空间的 Service。
# 进入临时 Pod 查看注入变量 kubectl run test --rm -it --image=busybox sh env | grep MYSQL # MYSQL_SERVICE_HOST=10.111.69.45 MYSQL_SERVICE_PORT=3306 # WordPress 用环境变量引用 --env=WORDPRESS_DB_HOST='$(MYSQL_SERVICE_HOST)'

4.3 通过 DNS 名称访问(推荐)

  • kubeadm 默认安装CoreDNS(Service 名kube-dns,ClusterIP10.96.0.10,端口 53);新 Service 创建后 CoreDNS 自动添加 DNS 记录。
  • Pod 的/etc/resolv.conf:nameserver 10.96.0.10,搜索域svc.cluster.local等。
  • 访问格式:
    • 同命名空间:<service>或<service>.<namespace>
    • 跨命名空间:<service>.<namespace>.svc.cluster.local
kubectl run busybox --rm -it --image=busybox /bin/sh wget wordpress:80 # 同 ns,省略命名空间 wget wordpress.services:80 # 显式指定 ns wget wordpress.services.svc.cluster.local:80 # WordPress 直接用 Service 名连库 --env=WORDPRESS_DB_HOST=mysql

五、Service 类型(4 种 + Headless)

表格

类型作用范围说明
ClusterIP(默认)仅集群内部从预留 IP 池分配内部 ClusterIP;其他类型都基于它构建;可在spec.clusterIP指定合法 IP,置"None"即无头服务
NodePort集群所有节点在每个节点上开放同一端口(默认 30000‑32767),外部通过节点IP:NodePort访问;内部仍先经过 ClusterIP
LoadBalancer集群外部需要云厂商 LB 或第三方 MetalLB 提供独立外部 IP;K8s 本身不实现 LB
ExternalName集群内部把 Service 映射成外部域名的 CNAME 记录,不创建代理、不分配 IP、不做负载均衡
Headless集群内部clusterIP: None,不分配 ClusterIP,kube‑proxy 不处理;DNS 直接返回后端 Pod 的 A/AAAA 记录

5.1 ClusterIP

默认类型;可手动指定spec.clusterIP,必须落在service-cluster-ip-rangeCIDR 内,非法值 API 返回 422。

5.2 NodePort

kubectl expose deployment web --type NodePort --port=8080 --target-port=80 \ -o yaml --dry-run=client > service-NodePort.yaml kubectl apply -f service-NodePort.yaml kubectl get service # 8080:31917/TCP # 访问任一节点 curl http://10.1.8.30:31917 curl http://10.1.8.31:31917 curl http://10.1.8.32:31917

三个端口概念:

  • nodePort:节点上监听的端口(30000‑32767,可手动指定固定端口如30080);
  • port:ClusterIP 上监听端口;
  • targetPort:Pod 监听端口。

iptables 规则验证(每个节点额外增加 KUBE‑NODEPORTS 链规则):

iptables-save | grep 31917 # -A KUBE-NODEPORTS --dport 31917 -j KUBE-SVC-WE5D4GWSX3MMPCHH iptables-save | grep KUBE-SVC-WE5D4GWSX3MMPCHH # 规则链按概率分流到各 KUBE-SEP-xxx 后端端点链

5.3 LoadBalancer(MetalLB 实现,裸金属集群)

K8s 自身不实现 LoadBalancer,裸金属环境用MetalLB提供外部 IP。

部署步骤

# 下载并修改镜像仓库地址 wget https://laoma.cloud/.../metallb-0.14.8.tar.gz tar -xf metallb-0.14.8.tar.gz sed -i 's/quay.io/hub.laoma.cloud/g' metallb-0.14.8/config/manifests/metallb-native.yaml kubectl apply -f metallb-0.14.8/config/manifests/metallb-native.yaml kubectl get all -n metallb-system # controller 1 副本 + speaker DaemonSet 每节点一个

配置地址池 + L2 宣告

# ippool.yaml apiVersion: metallb.io/v1beta1 kind: IPAddressPool metadata: name: first-pool namespace: metallb-system spec: addresses: - 10.1.8.40-10.1.8.80 --- # L2.yaml apiVersion: metallb.io/v1beta1 kind: L2Advertisement metadata: name: example namespace: metallb-system
kubectl apply -f ippool.yaml kubectl apply -f L2.yaml

创建 LoadBalancer Service 并测试

kubectl expose deployment web --type LoadBalancer --port=80 --target-port=80 \ -o yaml --dry-run=client > service-LoadBalancer.yaml kubectl apply -f service-LoadBalancer.yaml kubectl get service # web LoadBalancer 10.109.101.67 10.1.8.40 80:32101/TCP curl http://10.1.8.40:80 # 注意:用 Service 端口 80,不是 NodePort 32101

流量路径客户端 → MetalLB VIP(L2 模式 ARP 宣告,流量进入集群任意节点)→ 节点内核拦截 Service IP → kube‑proxy 匹配 iptables/IPVS 规则 → Service 选择健康 Pod → CNI 跨节点转发 → Pod 网络命名空间 → Pod 响应原路返回。

MetalLB 只负责 ARP 宣告 + 占用 IP,转发仍由 kube‑proxy + Service 完成。

5.4 ExternalName

apiVersion: v1 kind: Service metadata: name: www spec: type: ExternalName externalName: www.laoma.cloud

查询www.<ns>.svc.cluster.local时 DNS 返回 CNAME 记录www.laoma.cloud;重定向发生在 DNS 层,不经过代理转发。

5.5 Headless Service(clusterIP: None)

  • 不分配 ClusterIP,kube‑proxy 不处理,平台不提供负载均衡。
  • 带 selector:控制平面创建 EndpointSlice,DNS 直接返回后端 Pod 的 A/AAAA 记录(用于 StatefulSet、自定义负载均衡、直连 Pod)。
  • 不带 selector:不创建 EndpointSlice;ExternalName 走 CNAME,其他类型对就绪端点配置 A/AAAA 记录;此时port必须与targetPort匹配。

六、Service 会话保持(Session Affinity)

6.1 原理

  • spec.sessionAffinity:None(默认)/ClientIP(基于客户端 IP 亲和)。
  • sessionAffinityConfig.clientIP.timeoutSeconds:粘性时长,默认10800 秒(3 小时)。
  • 首次访问记录「客户端 IP ↔ Pod」映射,后续请求转发同一 Pod;适合有状态服务:Java Web 登录态、购物车、WebSocket、游戏长连接。

6.2 实验

kubectl create deployment web --image=hub.laoma.cloud/library/httpd --replicas=2 kubectl expose deployment web --port 80 # 改各 Pod 主页为 Pod 名 for pod in $(kubectl get pods -o name | awk -F/ '{print $2}'); do kubectl exec -it $pod -- bash -c "echo $pod > htdocs/index.html" done # 默认无亲和:20 次请求两个 Pod 各 10 次 for i in {1..20}; do curl -s 10.111.90.183; done | sort | uniq -c # 开启 ClientIP 亲和 kubectl patch svc web -p '{"spec":{"sessionAffinity":"ClientIP"}}' # 同一客户端 20 次请求全部落到同一个 Pod for i in {1..20}; do curl -s 10.111.90.183; done | sort | uniq -c

七、金丝雀发布(Canary)

7.1 思路

同时保留旧版本(stable)与新版本(canary)两套 Deployment,共用同一个 Service,用track标签区分;通过调整两套副本比例控制新版本流量占比,验证无误后逐步全量。

7.2 实验步骤

# 1. 准备两个版本页面 ConfigMap mkdir web echo hello nginx 1.28 > web/index28.html echo hello nginx 1.29 > web/index29.html kubectl create configmap web --from-file=./web

旧版本 Deployment(track: stable,10 副本)

apiVersion: apps/v1 kind: Deployment metadata: labels: {app: web} name: web-28 spec: replicas: 10 selector: matchLabels: {app: web, tier: frontend, track: stable} template: metadata: labels: {app: web, tier: frontend, track: stable} spec: containers: - image: hub.laoma.cloud/library/nginx:1.28 name: nginx imagePullPolicy: IfNotPresent ports: - containerPort: 80 volumeMounts: - name: webcontent mountPath: "/usr/share/nginx/html" volumes: - name: webcontent configMap: name: web items: - key: index28.html path: index.html

Service(selector 只匹配 app + tier,不区分 track)

apiVersion: v1 kind: Service metadata: labels: {app: web} name: web spec: ports: - port: 80 protocol: TCP targetPort: 80 selector: app: web tier: frontend

新版本 Deployment(track: canary,1 副本):镜像nginx:1.29,ConfigMap 取index29.html,标签track: canary。

7.3 流量比例验证

kubectl apply -f webapp-1.28.yaml kubectl apply -f webapp-svc.yaml kubectl apply -f webapp-1.29.yaml # 8 旧 + 2 新 → 约 80% / 20% 流量 kubectl scale deployment web-28 --replicas 8 kubectl scale deployment web-29 --replicas 2 for i in {1..50}; do curl -s 10.98.235.36; done | sort -n | uniq -c # 39 hello nginx 1.28 / 11 hello nginx 1.29 # 逐步扩大新版本:6 旧 + 4 新 kubectl scale deployment web-28 --replicas 6 kubectl scale deployment web-29 --replicas 4

八、kube‑proxy

8.1 作用

kube‑proxy 是节点上运行的核心网络组件(DaemonSet),监听 Service 与 Endpoint 变化,负责Service → 后端 Pod 的流量转发与负载均衡。

8.2 三种工作模式对比

表格

模式地位性能适用场景特点
iptables默认模式中(服务数 < 1000)小规模、环境稳定依赖内核 netfilter,规则链随服务 / 端点增多膨胀,匹配逐条遍历,规则多时 CPU 高、延迟大
IPVS生产推荐极高(十万级服务)中大规模生产环境基于内核 IPVS + 哈希表,O (1) 查找,绕过复杂规则链,支持多种调度算法
Userspace已废弃低仅旧版兼容全用户态转发,性能最差;K8s 1.25+ 已移除

生产建议:IPVS 模式 + Calico 网络插件。

8.3 查看与切换模式

# 查看 ConfigMap 中的 mode(空字符串即默认 iptables) kubectl get cm -n kube-system kube-proxy -o yaml | grep mode # 查看当前运行模式(日志中 "Using iptables proxy" / "Using ipvs Proxier") kubectl get pods -n kube-system -l k8s-app=kube-proxy -o name kubectl logs -n kube-system kube-proxy-9xfwh | grep Using # 切换为 IPVS:编辑 ConfigMap,mode: "ipvs" kubectl edit configmap -n kube-system kube-proxy # 重启 DaemonSet 生效 kubectl rollout restart daemonset -n kube-system kube-proxy # 再次验证日志 kubectl logs -n kube-system <new-pod> | grep Using

8.4 IPVS 模式

工作原理:kube‑proxy 在宿主机内核创建 IPVS 虚拟服务器,把后端 Pod 注册为 Real Server;规则存于哈希表(O (1)),流量到达后按调度算法直接转发到 Pod,绕过 iptables 规则链。

支持的调度算法

表格

算法含义适用场景
rr轮询节点配置一致的简单均衡
wrr加权轮询最推荐,通用 Web/API/ 网关;权重正比于 Podresources.requests.cpu/memory
lc最少连接长连接、WebSocket、游戏服务
dh目标地址哈希会话保持
sh源地址哈希配合sessionAffinity: ClientIP
sed最短预期延迟‑
nq最少队列‑

实验验证

# 1. 创建 3 副本 nginx Deployment,主页写 Pod 名,创建 Service kubectl create deployment web --image=nginx --replicas=3 for pod in $(kubectl get pods -o custom-columns=NAME:.metadata.name --no-headers); do kubectl exec $pod -- bash -c "echo $pod > /usr/share/nginx/html/index.html" done kubectl expose deployment web --port=80 # 2. 查看 IPVS 虚拟服务器与后端 Real Server ipvsadm -Lnt 10.103.143.120:80 # TCP 10.103.143.120:80 rr # -> 10.224.19.38:80 Masq 1 ... # -> 10.224.113.164:80 Masq 1 ... # -> 10.224.113.165:80 Masq 1 ... # 3. 验证轮询:60 次访问各 Pod 命中 20 次 for i in {1..60}; do curl -s 10.103.143.120; done | sort | uniq -c

切换调度算法

kubectl edit configmap kube-proxy -n kube-system # ipvs: # scheduler: "wrr" # mode: "ipvs" kubectl rollout restart ds kube-proxy -n kube-system

生产最佳配置(KubeProxyConfiguration 节选)

mode: ipvs ipvs: scheduler: "rr" # rr / wrr / lc 三选一 tcpTimeout: 900 tcpFinTimeout: 120 udpTimeout: 300 excludeCIDRs: - "127.0.0.1/32" strictARP: true oomScoreAdj: -999 iptables: minSyncPeriod: 5s syncPeriod: 30s logging: format: text verbosity: 2

会话保持优先级

  1. Service 配置sessionAffinity: ClientIP→ kube‑proxy 自动使用 IPVS 的SH(源地址哈希),保证同一 IP → 同一 Pod,优先级最高。
  2. Service 不配置亲和性 → 使用 IPVSscheduler中设置的算法(rr /lc/wrr)。

8.5 iptables 模式

工作原理:kube‑proxy 监听 Service/Endpoint 变化,在宿主机内核动态生成 iptables 规则链;流量经 netfilter 逐条匹配规则,完成 DNAT 与负载均衡。

规则链分层(全链路)

  1. KUBE-SERVICES:服务总入口,匹配目的 ClusterIP + 端口,跳转到该 Service 专属调度链。
  2. KUBE-SVC-XXX:Service 专属调度链;非 Pod 网段流量先做KUBE-MARK-MASQSNAT 标记;再用statistic --mode random按概率分流到各端点链。
  3. KUBE-SEP-XXX:后端端点链,执行DNAT --to-destination <PodIP:Port>。

实验验证

# 保存规则并按 ServiceIP 追踪链路 iptables-save > iptables.list grep 10.103.143.120 iptables.list grep KUBE-SVC-7D76YWGERGEPC4GC iptables.list grep -e KUBE-SEP-HYZM2VM7RCC7M2HX -e KUBE-SEP-CHPZVFCOFL4YLCYM -e KUBE-SEP-HM7RLUR2RXSQ3D6F iptables.list | grep DNAT

3 个后端 Pod 时概率分配为 1/3、1/2(剩余)、无条件兜底,合计各 1/3。

缺点:每新增 Service/Endpoint 都要增改规则;服务超过 1000 后规则链膨胀,CPU 占用飙升、延迟显著增加。

8.6 Userspace 模式

kube‑proxy 在用户态监听 Service 端口,接收流量后本地代理转发到后端 Pod;全用户态处理,性能极低;K8s 1.25+ 已彻底移除。

九、环境清理

kubectl delete ns services

思维导图

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/27 10:23:57

大模型开发工程师薪资40K起步?揭秘入行真相,小白必收藏!

大模型开发工程师岗位薪资高、缺口大&#xff0c;主要负责将大模型接入企业业务。非科班、文科生均可通过补Python入门。该岗位是AI时代的核心红利&#xff0c;前景广阔&#xff0c;适合各专业背景人士入行。 为什么大模型开发工程师这个岗位&#xff0c;这么火爆&#xff1f; …

作者头像 李华
网站建设 2026/10/27 10:23:55

电动汽车车牌查询,别为车型库养一支团队

很多团队第一次算这笔账&#xff0c;都是从"我们自己也能做"开始的。自建的成本从来不只是开发工时。第一块是数据获取&#xff0c;车型公告、电池参数、续航数据分散在工信部公告、厂家官网、第三方数据库里&#xff0c;口径还不统一&#xff1b;第二块是持续更新&a…

作者头像 李华
网站建设 2026/10/27 10:23:28

包干制小区物业系统:面向成本管控的架构与落地实践

包干制模式下&#xff0c;物业企业按固定物业费总额承接服务&#xff0c;自负盈亏。收入上限锁定&#xff0c;成本管控直接决定项目利润。这类场景的系统核心定位&#xff0c;和酬金制、商管收费系统不同&#xff1a;不再优先追求收费功能&#xff0c;而是围绕预算约束、人力效…

作者头像 李华
网站建设 2026/10/27 10:23:23

uniapp BLE 开发踩坑:小米手机数据接收截断问题排查全记录

一、问题背景项目基于 uniapp&#xff08;APP 端&#xff09;​ 做跨平台蓝牙通信&#xff0c;设备端是串口透传 BLE 模块&#xff0c;业务层自定义十六进制协议。正常流程&#xff1a;手机连接设备 → 开启 notify → 设备主动推数据前端解析协议帧&#xff08;帧头 AA AA F3 …

作者头像 李华
网站建设 2026/10/27 10:21:43

Zig语言的区块链:从0到1构建无隐藏控制流的底层区块链系统

引言:共识节点的确定性,不应该依赖“编译器不会做某件事”的假设 区块链节点有一个与其他软件截然不同的硬约束:同一笔交易,在全网数万个异构节点上,必须产生逐字节完全相同的结果。这个约束的严峻之处不在于“通常情况”,而在于极端情况——内存耗尽时、网络中断时、恶…

作者头像 李华
网站建设 2026/10/27 10:16:37

ros2的学习

--------------------2026.10.151.1今天学了怎么用话题订阅接收小海龟的当前坐标位置并计算与目标位置之间的距离&#xff0c;通过发布者发布速度数据让小海龟走到目标位置。1.1.1遇到问题&#xff1a;编译过程遇到一个问题&#xff1a;cmake里节点文件的路径添加错误&#xff…

作者头像 李华