kubernetes(k8s)容器内无法连接同所绑定的Service ClusterIP问题记录

kubernetes(k8s)容器内无法连接同所绑定的Service ClusterIP问题记录

1. k8s环境

k8s使用kubernetes-server-linux-amd64_1.19.10.tar.gz 二进制bin 的方式手动部署

k8s 版本:

bash 复制代码
[root@master ~]# kubectl version
Client Version: version.Info{Major:"1", Minor:"19", GitVersion:"v1.19.10", GitCommit:"98d5dc5d36d34a7ee13368a7893dcb400ec4e566", GitTreeState:"clean", BuildDate:"2021-04-15T03:28:42Z", GoVersion:"go1.15.10", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"19", GitVersion:"v1.19.10", GitCommit:"98d5dc5d36d34a7ee13368a7893dcb400ec4e566", GitTreeState:"clean", BuildDate:"2021-04-15T03:20:25Z", GoVersion:"go1.15.10", Compiler:"gc", Platform:"linux/amd64"}
2. 测试nginx-busybox应用

2.1 构建nginx测试镜像Dockerfile

bash 复制代码
# 基于官方 Nginx 镜像
FROM nginx

# 安装 Busybox
RUN apt-get update && apt-get install -y busybox

# 复制 Nginx 配置文件
# COPY nginx.conf /etc/nginx/nginx.conf

# 复制自定义 HTML 文件(可选)
COPY index.html /usr/share/nginx/html/

# 在容器启动时执行的命令
CMD ["nginx", "-g", "daemon off;"]
bash 复制代码
echo "hello world" > index.html
docker build . -t nginx-busybox:v1.0

2.2 创建k8s 测试资源nbusybox_deployment.yaml

bash 复制代码
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nbusybox-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nbusybox
  template:
    metadata:
      labels:
        app: nbusybox
    spec:
      containers:
        - name: nbusybox
          image: nginx-busybox:v1.0
          ports:
            - containerPort: 80


---
apiVersion: v1
kind: Service
metadata:
  annotations: {}
  labels:
    k8s.kuboard.cn/name: nbusybox-service-v1
  name: nbusybox-service
spec:
  clusterIP: 10.233.0.45
  ports:
    - name: mrmsqs
      nodePort: 30233
      port: 80
      protocol: TCP
      targetPort: 80
  selector:
    app: nbusybox
  sessionAffinity: None
  type: NodePort

kubectl create -f nbusybox_deployment.yaml

2.3 ping service 测试

bash 复制代码
[root@master ~]# docker ps | grep nbusybox
975b550531df   3740b49d5078           "/docker-entrypoint...."   31 minutes ago   Up 31 minutes             k8s_nbusybox_nbusybox-deployment-6b48bb8f65-mpnhg_default_1a60a955-c5fa-4e08-b8f3-7461edd9ea48_0
6d4a77f60cee   k8s.gcr.io/pause:3.2   "/pause"                 31 minutes ago   Up 31 minutes             k8s_POD_nbusybox-deployment-6b48bb8f65-mpnhg_default_1a60a955-c5fa-4e08-b8f3-7461edd9ea48_0

进入容器:

bash 复制代码
 docker exec -it 975b550531df  /bin/bash

http get 所在的service clusterIP 发现不通:

bash 复制代码
root@nbusybox-deployment-6b48bb8f65-mpnhg:/# busybox wget nbusybox-service.default.svc.cluster.local
Connecting to nbusybox-service.default.svc.cluster.local (10.233.0.45:80)

而在http get 其他的service clusterIP 发现可通:

bash 复制代码
root@nbusybox-deployment-6b48bb8f65-mpnhg:/# busybox wget nginxbusybox-service.default.svc.cluster.local
Connecting to nginxbusybox-service.default.svc.cluster.local (10.233.0.62:80)
saving to 'index.html'
index.html           100% |*******************************************************************************************************************************|    11  0:00:00 ETA
'index.html' saved

以为是kube-proxy 在iptables 的转发模式所致, 尝试更改 kube-proxy 的代理模式为ipvs

bash 复制代码
./kube-proxy --logtostderr=true --v=4 --hostname-override=192.168.0.251 --master=http://192.168.0.250:8080 --proxy-mode=ipvs

发现问题仍然存在。

kube-proxy 在iptables 和 ipvs 模式下,不会处理ip 包的转发,而是交由linux 网络协议栈处理。猜测是linux 网络协议栈的处理问题。尝试在宿主机对docker0 网卡抓包:

发现 nbusybox-service.default.svc.cluster.local 这个service 可以正常连接了。

当一但关掉 wireshark, nbusybox-service.default.svc.cluster.local 这个service 就连接不了。

在wireshark 的抓包记录中,发现一条 从 10.0.9.2(容器ip) 发往 10.0.9.2 的http 响应,似乎构成了回环。

询问chatgpt:

bash 复制代码
linux 网络协议栈,对于源IP, 源MAC 跟目标IP, 目标MAC一样的IP包,能正常发送吗?

在 Linux 网络协议栈中,对于源 IP 地址(Source IP)和源 MAC 地址(Source MAC)与目标 IP 地址(Destination IP)和目标 MAC 地址(Destination MAC)完全相同的 IP 包,通常是无法正常发送的。

这是因为在以太网(Ethernet)协议中,源 MAC 和目标 MAC 是用于网络中的数据链路层寻址和交换的重要字段。当一个主机发送一个 IP 包时,它会填充源 IP 和源 MAC 字段,同时指定目标 IP 和目标 MAC 字段。当数据包通过网络进行传输时,数据链路层设备(如交换机)会根据目标 MAC 地址将数据包转发到正确的目的地。

如果源 IP 和源 MAC 与目标 IP 和目标 MAC 完全相同,这意味着数据包将被送回到自身,形成了一个循环。为了避免这种无限循环的情况发生,Linux 网络协议栈通常会阻止发送这样的数据包。

当尝试发送源 IP 和源 MAC 与目标 IP 和目标 MAC 完全相同的数据包时,Linux 网络协议栈通常会丢弃这些数据包或者不进行发送。这是为了确保网络的正常运行和防止数据包的无限循环。

需要注意的是,这种行为可能会因操作系统和网络配置而有所不同,但在大多数常见的 Linux 发行版和网络环境中,源 IP 和源 MAC 与目标 IP 和目标 MAC 完全相同的 IP 包通常无法正常发送。

关掉 wireshark 的混杂模式

再次开启wireshark 对docker0 抓包, 容器内对 nbusybox-service.default.svc.cluster.local service 就连接不了。

问题已初步定位,当启用了 docker0 的混杂模式,容器内对 nbusybox-service.default.svc.cluster.local service 就可以连接。

再次验证, 手动对docker0 启用混杂模式

bash 复制代码
ifconfig docker0 promisc

测试:

发现 容器内对 nbusybox-service.default.svc.cluster.local service 就可以连接。

3. 结论

当在容器内(10.0.9.2)访问 service, 而这个service 经负载均衡后,找回这个容器自身(10.0.9.2),这时tcp 连接就无法建立,这时开启docker0网卡的混杂模式,tcp连接就可以建立。 但笔者在使用v1.23.17 的k8s 版本在某云厂商的云服务器上部署,是可以在容器内访问自身的Service 的,因此该结论可能还跟操作系统或k8s的版本配置有关系。

相关推荐
春天花会开1313 小时前
Supabase 自部署 Edge Functions 超时从 60s 延长到 360s 完整复盘
运维·云原生
程序猿小郑5 小时前
Docker Compose 构建完整服务实战指南:从入门到最佳实践
docker·容器
ysu_031412 小时前
【2026】K8s GPU调度空占怎么解?Kueue与Volcano Gang配置
云原生·kubernetes·gpu算力·volcano·ai基础设施·kueue·gang scheduling
哈__1 天前
KES-Operator重塑Kubernetes环境下的KES数据库集群管理
数据库·kubernetes·operator·kes
九皇叔叔1 天前
K8S 资源菜单
docker·容器·kubernetes·k8s
wdfk_prog1 天前
ROS教程08:从 TransportTCP::connect() 追到 TCPROS Connection Header、序列化与 Socket 数据传输
运维·缓存·docker·容器·ros
Zhu7581 天前
docker环境快速部署postgresql数据库18及以上版本
postgresql·容器
安易算力1 天前
PUE优化工程实践:从1.5到1.2的制冷架构与气流组织改造路径
网络·python·容器·架构·kubernetes
小马同学-1 天前
nerdctl实战:Docker风格的Containerd操作利器
docker·容器·containerd
九皇叔叔1 天前
Kubernetes 命令式对象配置详解:使用 YAML 管理 Kubernetes 资源
docker·容器·k8s