1. 简介

Kubernetes 将容器组织为称为 Pod 的单元,每个 Pod 负责其中容器的存储分配、资源调度和网络配置。因此,要获取某个容器的 IP 地址等信息,通常我们会查看其所在 Pod 的定义。

然而,有时我们希望从 Pod 内部获取这些网络配置信息。本文将探讨几种方式,帮助你从容器内部或通过 Kubernetes 工具获取 Pod 或容器的 IP 地址。

我们假设使用的是 Docker 作为容器运行时,测试环境为 Debian 12(Bookworm)+ GNU Bash 5.2.15。


2. 创建 Pod

Kubernetes 中,Pod 通常通过配置文件定义并创建。

以下是一个简单的 Pod 定义文件:

$ cat compod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: compod
spec:
  containers:
  - name: deb1
    image: debian:latest
    command: ["sh"]
    tty: true
  - name: deb2
    image: debian:latest
    command: ["sh"]
    tty: true

使用 kubectl 创建该 Pod:

$ kubectl apply --filename=compod.yaml

或者直接通过命令行输入定义内容:

$ kubectl apply --filename=- <<< '
apiVersion: v1
kind: Pod
metadata:
  name: compod
spec:
  containers:
  - name: deb1
    image: debian:latest
    command: ["sh"]
    tty: true
  - name: deb2
    image: debian:latest
    command: ["sh"]
    tty: true
'
pod/compod created

接下来,我们来看看 Kubernetes 是如何为 Pod 分配网络地址的。


3. Pod 网络基础

Kubernetes 的网络模型通常由底层容器运行时(如 Docker)支持,也可以通过插件(如 Flannel、Calico)进行扩展。

关键组件包括:

  • 网络插件:为 Pod 分配 IP
  • kube-apiserver:为 Service 分配 IP
  • kubelet / cloud-controller-manager:为节点分配 IP

每个 Pod 内的容器通过一个 veth 接口连接到主机上的一个 bridge 网络接口。例如:

+------------+ +------------+
| container1 | | container2 |
|(10.244.0.#)| |(10.244.0.#)|
|   veth0    | |    veth1   |
+------------+ +------------+
             ^ ^
             v v            
+-----------------------------+
|            host             |
|        (10.244.0.1)         |
|           bridge            |
+-----------------------------+

这种结构使得 Pod 内容器拥有独立 IP,并可通过 bridge 与外部通信。


4. Pod IP 地址分配机制

4.1. 获取节点 CIDR 地址

Kubernetes 每个节点会被分配一个 CIDR 子网。查看当前节点的子网:

$ kubectl get node minikube --output=jsonpath={..podCIDR}
10.244.0.0/24

这个子网用于为该节点上的 Pod 分配 IP。

4.2. 查看 Kubernetes 网桥

查看主机上的网络接口:

$ ip address show
3: bridge: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether ce:e9:1c:47:3f:16 brd ff:ff:ff:ff:ff:ff
    inet 10.244.0.1/16 brd 10.244.255.255 scope global bridge

可以看到 Kubernetes 使用的网桥 bridge,IP 为 10.244.0.1

4.3. 容器虚拟以太网接口

每个容器都有一个对应的 veth* 接口连接到这个网桥:

$ ip address show
4: veth24d8dc94@if2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master bridge state UP group default
35: veth28f88740@if2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master bridge state UP group default

这些接口与容器内的 eth0 对应,实现网络通信。


5. 在容器内部获取 IP 地址

5.1. 列出容器

使用 docker ps 查看容器信息:

$ docker ps
CONTAINER ID   IMAGE                       NAMES
ff9f22b59b1d   debian                      k8s_deb2_compod_default_855cfd1d-5aec-4240-b750-1283af2c1a26_0
6cc96be009e3   debian                      k8s_deb1_compod_default_855cfd1d-5aec-4240-b750-1283af2c1a26_0

5.2. 进入容器

使用 kubectl execdocker exec 进入容器:

$ kubectl exec --stdin --tty pod/compod --container deb1 -- bash

5.3. 使用 ip/proc 获取 IP

在容器中运行:

root@compod:/# ip address show
2: eth0@if35: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    link/ether c2:98:17:b5:04:e2 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 10.244.0.33/16 brd 10.244.255.255 scope global eth0

如果容器没有 ip 命令,可以查看 /proc/net/fib_trie

$ cat /proc/net/fib_trie
Main:
  +-- 10.244.0.0/16 2 0 2
     +-- 10.244.0.0/26 2 0 2
        |-- 10.244.0.33
           /32 host LOCAL

5.4. 无 Shell 容器的处理

如果容器没有 shell,可以使用 kubectl exec 直接读取文件:

$ kubectl exec --stdin --tty pod/compod --container deb1 -- cat /proc/net/fib_trie

5.5. 极简容器的调试方式

使用 kubectl debug 创建调试容器:

$ kubectl debug --tty --stdin pod/compod --image=debian:latest --target=deb1 -- bash

该调试容器与目标容器共享命名空间,可使用完整工具链。

⚠️ 注意:同一个 Pod 中的所有容器共享 IP。


6. 从 Pod 定义中获取 IP 地址

使用 kubectl get 查看 Pod 的 IP:

$ kubectl get pod/compod --output wide
NAME     READY   STATUS    RESTARTS   AGE   IP            NODE       NOMINATED NODE   READINESS GATES
compod   2/2     Running   0          25h   10.244.0.33   minikube   <none>           <none>

使用 kubectl describe 也能看到:

$ kubectl describe pod/compod
Name:             compod
IP:               10.244.0.33

使用 jsonpath 提取 IP:

$ kubectl get pod/compod --output=jsonpath='{..podIP}'
10.244.0.33

若存在多个 IP:

$ kubectl get pod/compod --output=jsonpath='{..podIPs}'
[{"ip":"10.244.0.33"}]

⚠️ 注意:使用 docker inspect 不会显示 Kubernetes 的 IP,因为 Docker 网络不参与 Kubernetes 的 IP 分配。


7. 总结

✅ 本文总结了从容器内部及外部获取 Kubernetes Pod 和容器 IP 的多种方式:

方法 说明
ip address 最直接,但容器可能无此命令
/proc/net/fib_trie 无需安装工具,适用于极简容器
kubectl exec 可直接执行命令或读取文件
kubectl debug 创建调试容器,适合无工具容器
kubectl get / describe 从外部快速获取 Pod IP

⚠️ 踩坑提示:

  • Docker 网络接口不参与 Kubernetes IP 分配,docker inspect 无法获取有效信息。
  • 极简容器可能连 /proc 都不挂载,需提前规划好调试方式。

熟练掌握这些方法,有助于在实际部署中快速定位网络问题,提升调试效率。


原始标题:Get Kubernetes Pod and Container IP Address From Within a Container