在 Kubernetes 集群中,Spring Boot 服務獲取 Pod 當前 IP 的方案主要有兩種:通過環境變量注入 或 通過 Java 代碼動態獲取網絡接口 IP。以下是兩種方案的詳細說明及示例:
方案一:通過 Kubernetes Downward API 注入環境變量
原理
Kubernetes 提供 Downward API,可將 Pod 的元數據(如 status.podIP
)注入為容器的環境變量。Spring Boot 服務可直接讀取該環境變量。
步驟
-
在 Deployment 中配置環境變量
在 Pod 的spec.containers.env
中添加配置,將status.podIP
注入為POD_IP
:apiVersion: apps/v1 kind: Deployment metadata:name: springboot-app spec:replicas: 1selector:matchLabels:app: springboot-apptemplate:metadata:labels:app: springboot-appspec:containers:- name: springboot-appimage: your-springboot-imageenv:- name: POD_IPvalueFrom:fieldRef:fieldPath: status.podIP
-
在 Spring Boot 中讀取環境變量
@Component public class PodInfo {private final String podIp;public PodInfo(@Value("${POD_IP}") String podIp) {this.podIp = podIp;}public String getPodIp() {return podIp;} }
優點
- 配置簡單,直接通過環境變量獲取。
- 無需額外代碼邏輯。
缺點
- 需要修改 Deployment 配置,依賴 Kubernetes 環境。
方案二:通過 Java 代碼動態獲取網絡接口 IP
原理
Pod 的 IP 通常綁定在主網絡接口上,可通過遍歷 Java 網絡接口獲取非回環地址。
步驟
-
編寫工具類獲取 IP
import java.net.InetAddress; import java.net.NetworkInterface; import java.util.Collections; import java.util.List; import java.util.stream.Collectors;public class PodIpUtils {public static String getPodIp() {try {// 獲取所有網絡接口List<NetworkInterface> interfaces = Collections.list(NetworkInterface.getNetworkInterfaces());for (NetworkInterface ni : interfaces) {if (ni.isLoopback() || !ni.isUp()) {continue; // 跳過回環接口和不可用接口}// 獲取接口下的 IP 地址List<InetAddress> addresses = Collections.list(ni.getInetAddresses());for (InetAddress addr : addresses) {if (addr instanceof java.net.Inet4Address) {return addr.getHostAddress(); // 優先返回 IPv4 地址}}}} catch (Exception e) {// 日志記錄異常(可集成日志框架)System.err.println("Failed to get Pod IP: " + e.getMessage());}return null; // 未找到則返回 null} }
-
在 Spring Boot 中使用
@RestController public class PodIpController {@GetMapping("/pod-ip")public String getPodIp() {return PodIpUtils.getPodIp();} }
優點
- 無需修改 Kubernetes 配置,純代碼實現。
- 適用于任何運行環境(不依賴 Kubernetes)。
缺點
- 需處理多網卡、IPv6 等復雜場景。
- 在極少數網絡環境下可能獲取失敗。
完整示例代碼
1. 工具類(動態獲取 IP)
package com.example.utils;import java.net.InetAddress;
import java.net.NetworkInterface;
import java.util.Collections;public class PodIpUtils {public static String getPodIp() {try {for (NetworkInterface ni : Collections.list(NetworkInterface.getNetworkInterfaces())) {if (ni.isLoopback() || !ni.isUp()) continue;for (InetAddress addr : Collections.list(ni.getInetAddresses())) {if (addr instanceof java.net.Inet4Address) {return addr.getHostAddress();}}}} catch (Exception e) {e.printStackTrace();}return null;}
}
2. Controller(暴露 IP 接口)
package com.example.controller;import com.example.utils.PodIpUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
public class PodIpController {@GetMapping("/pod-ip")public String getPodIp() {return PodIpUtils.getPodIp();}
}
驗證方法
- 部署 Spring Boot 應用到 Kubernetes。
- 訪問
http://<Pod-IP>:8080/pod-ip
,應返回當前 Pod 的 IP。 - 檢查環境變量
POD_IP
(若使用方案一)。
注意事項
- 確保 Pod 的網絡接口已正確配置(如使用
kube-dns
或 CNI 插件)。 - 如果使用 HostNetwork(宿主網絡),需調整獲取 IP 的邏輯。
- 在多容器 Pod 中,每個容器的 IP 可能不同,需針對目標容器配置。