大白话搞懂k8s网络,轻松应对web服务的开发调试

AI 总结

文章讲解k8s网络调试,核心是分清Pod、Node、Cluster三者身份。集群内节点(Master/Worker)可直接访问PodIP、ClusterIP和Service域名;集群外机器不能直连,需使用kubectl port-forward、NodePort等方式。开发自测推荐port-forward,但不能用于生产。集群内微服务调用应统一使用SVC域名,禁止硬编码IP,跨命名空间需写完整域名。容器服务需监听0.0.0.0,否则无法被外部调用。

web服务开发好了,部署到k8s上了,前端调用不符合预期,仅仅看日志经常会很棘手,知道怎样做接口测试,debug直连环境能解决所有问题。开发调k8s服务,永远卡在网络问题,本质原因就一个:没分清 PodNodeCluster 三者的身份,搞不懂谁能访问谁。

核心概念

  • Node: 节点,可以是一台物理机,可以是一台虚拟机
  • Cluster:集群,可以认为是一套完整的系统,如果在一个节点上搭建k8s叫单节点环境,如果在多个节点上搭建k8s叫多节点环境(常说的高可用环境)
  • Pod:部署在 Node 内部,K8s 最小运行单元,跑业务容器(如我们的 Golang 服务)
┌─────────────────────────────────────────────────────────────┐
│                      Cluster(K8s集群)                       │
│  ┌──────────────────────┐        ┌──────────────────────┐   │
│  │     Node 节点 B      │        │     Node 节点 C      │   │
│  │ (物理/虚拟机服务器) │        │ (物理/虚拟机服务器) │   │
│  │                      │        │                      │   │
│  │  ┌──────┐  ┌──────┐  │        │  ┌──────┐  ┌──────┐  │   │
│  │  │ Pod1 │  │ Pod2 │  │        │  │ Pod3 │  │ Pod4 │  │   │
│  │  │user服务│ │order │  │        │  │ 其他 │ │ 其他 │  │   │
│  │  └──────┘  └──────┘  │        │  └──────┘  └──────┘  │   │
│  └──────────────────────┘        └──────────────────────┘   │
│                                                             │
│  ┌──────────────────────┐                                   │
│  │     Master Node A    │                                   │
│  │  控制平面:调度、管理 │                                   │
│  └──────────────────────┘                                   │
└─────────────────────────────────────────────────────────────┘
▲        │ 集群外(D机器 / 开发本地电脑,不能直连PodIP)

先理清环境,机器清单:

  • A:Master 控制节点(属于 K8s 集群节点)
  • B、C:Worker Node 工作节点(属于 K8s 集群节点)
  • D:独立机器,不在集群内(集群外)

集群:A+B+C 组成一套 K8s,Pod 运行在 B / C 上,存在 PodIP、Service (ClusterIP)。
核心结论前置
✅ A、B、C 都属于集群内节点:可以直接访问 PodIP、ClusterIP、Service 域名 ❌ D 属于集群外机器:不能直连 PodIP / ClusterIP,必须走端口转发、NodePort、Ingress、LoadBalancer

访问场景

场景 1:在 A 机器(Master 节点)访问 B/C 上的 Pod、SVC

A 是集群一员,属于集群内访问

方式一:直接访问PodIP

# 在A机器执行
curl http://<B上PodIP>:8080
curl http://<C上PodIP>:8080

方式二:访问Service

curl http://<svc-clusterip>:8080
# 同命名空间还可以用svc名称访问(需要节点配置集群DNS解析,或者手动配置)
curl http://demo-svc:8080
# 完整域名
curl http://demo-svc.dev.svc.cluster.local:8080

场景 2:在 B 机器(Worker 节点)访问 B/C 上的 Pod、SVC

B 也是集群一员,访问同上

场景 3:在 D 机器(集群外独立机器)访问 B/C 的 Pod、SVC

D 不在集群网络平面,无法直接连通 PodIP、ClusterIP

方案一:kubectl port-forward(开发自测首选,临时用)

kubectl port-forward svc/demo-svc 8888:8080 -n dev --address 0.0.0.0

方案二:SVC 配置 NodePort 后,会在所有集群节点(A/B/C)开放同一个端口

spec:
  type: NodePort
  ports:
  - port: 8080
    targetPort: 8080
    nodePort: 30080
D 机器访问:
curl http://B机器物理IP:30080
curl http://C机器物理IP:30080

port-forward 端口转发实战

port-forward 是开发自测神器,底层是打通「本地电脑 ↔ 集群」的临时隧道,不用改集群配置、不用暴露公网,用完即走,专门解决外网机器调试集群服务的问题。

  • 转发Service(推荐!日常自测首选)
  • 转发单个Pod (仅排错使用)
  • 后台常驻转发 (解决终端关闭即断开问题)
# 格式:kubectl port-forward svc/服务名 本地端口:集群SVC端口 -n 命名空间
kubectl port-forward svc/order-svc 8888:8080 -n dev
# 格式:kubectl port-forward pod/POD名称 本地端口:容器端口 -n 命名空间
kubectl port-forward pod/order-7f9685796c-2xgq7 8888:8080 -n dev

nohup kubectl port-forward svc/order-svc 8888:8080 -n dev > /dev/null 2>&1

集群内服务互调

集群内微服务调用,**禁止硬编码任何 IP!**统一使用 SVC 域名,依靠 K8s CoreDNS 自动解析,适配所有环境。
域名规则:

  • 同命名空间:服务名:端口
  • 跨命名空间:服务名.命名空间.svc.cluster.local:端口
// 优先读取环境变量,本地调试用本地地址,集群自动用SVC域名
func getOrderURL() string {
	envURL := os.Getenv("ORDER_SERVICE_URL")
	if envURL != "" {
		return envURL
	}
	// 集群内跨命名空间调用标准域名
	return "http://order-svc.test.svc.cluster.local:8080"
}

func callOrderAPI() error {
	resp, err := http.Get(getOrderURL() + "/health")
	if err != nil {
		return fmt.Errorf("调用订单服务失败: %w", err)
	}
	defer resp.Body.Close()

	res, _ := io.ReadAll(resp.Body)
	fmt.Println("调用成功,响应:", string(res))
	return nil
}

结尾总结:

  • PodIP/ClusterIP 是集群内网地址,外网无法直接访问,不是故障是机制
  • port-forward 仅用于开发自测,绝对不用于生产对外服务
  • 集群内调用只认 SVC 域名,拒绝硬编码 IP,避免扩容重建后失效
  • 跨命名空间调用必须写完整域名,简写无法 DNS 解析
  • 容器服务需监听 0.0.0.0,监听 127.0.0.1 会导致无法被外部调用

评论 (0)