docker ping 域名报错: Name or service not known;ping IP地址报错:connect: Network is unreacha

基础环境

jenkins + jenkins agnet(agnet 在eks中)

jenkins 是脱离 eks 单独安装的,执行任务时调用 api 在eks中创建 jenkins agent 来执行构建任务;

问题描述

最近做 jenkins 项目的构建测试时;
Dockerfile 中 使用 centos 镜像,拉取 redis 构建测试环境
Dockerfile 如下:

FROM centos:7
RUN curl -o redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz" \
    && tar -xvf redis.tar.gz

jenkins 构建时报错如下:
image

排查及解决

eks 做了 公网、私网的划分;

启动 此次 docker 容器的机器,恰巧都在私网环境内(私网做了 vpc nat 地址的转发,机器可以连接到公网);

问题详细排查一

进入到 eks 私有子网的主机。查看主机网络环境配置

[root@ip-10-20-149-250 ec2-user]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc mq state UP group default qlen 1000
    link/ether 02:e9:4a:3b:09:87 brd ff:ff:ff:ff:ff:ff
    inet 10.20.149.250/19 brd 10.20.159.255 scope global dynamic eth0
       valid_lft 2548sec preferred_lft 2548sec
    inet6 fe80::e9:4aff:fe3b:987/64 scope link
       valid_lft forever preferred_lft forever
3: eni9968a90ce79@if3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc noqueue state UP group default
    link/ether 6a:fa:13:f5:71:c7 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet6 fe80::68fa:13ff:fef5:71c7/64 scope link
       valid_lft forever preferred_lft forever
30: eni78614c52579@if3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc noqueue state UP group default
    link/ether ae:25:89:17:66:ed brd ff:ff:ff:ff:ff:ff link-netnsid 2
    inet6 fe80::ac25:89ff:fe17:66ed/64 scope link
       valid_lft forever preferred_lft forever
37: enic0ff5a8c056@if3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc noqueue state UP group default
    link/ether d2:43:df:28:0a:34 brd ff:ff:ff:ff:ff:ff link-netnsid 3
    inet6 fe80::d043:dfff:fe28:a34/64 scope link
       valid_lft forever preferred_lft forever
38: eniff206d3e1a9@if3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc noqueue state UP group default
    link/ether b2:18:ec:36:90:5f brd ff:ff:ff:ff:ff:ff link-netnsid 1
    inet6 fe80::b018:ecff:fe36:905f/64 scope link
       valid_lft forever preferred_lft forever
84: enidccd1a02d40@if3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc noqueue state UP group default
    link/ether aa:33:6a:95:43:75 brd ff:ff:ff:ff:ff:ff link-netnsid 4
    inet6 fe80::a833:6aff:fe95:4375/64 scope link
       valid_lft forever preferred_lft forever
85: eni8851af7fcac@if3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc noqueue state UP group default
    link/ether a2:12:01:54:ed:17 brd ff:ff:ff:ff:ff:ff link-netnsid 5
    inet6 fe80::a012:1ff:fe54:ed17/64 scope link
       valid_lft forever preferred_lft forever
[root@ip-10-20-149-250 ec2-user]#

发现没有 docker0 网络接口,再次查看 /etc/docker/daemon.json 配置文件

[root@ip-10-20-149-250 ec2-user]# cat /etc/docker/daemon.json
{
  "bridge": "none",
  .....

发现没有 bridge 的网络绑定;这下渐渐明白了;

以前只是对 eks 的网络构建有一点点的连接,通过 aws 自己的 eni 插件实现的;看来就这个机会,可以再深入的了解一下了;

问题详细排查 二

众所周知,公有云 k8s 服务中,网络部分 各大厂商的解决方案是不同的;

aws 中,eks 中的网络解决方案中,使用了 Amazon VPC CNI 网络插件,进行 pod之间 网络的打通;

amazon-vpc-cni-k8s 网络插件,有2个组件构成
	1. CNI Plugin,它会在调用时连接主机和 pod 的网络堆栈。
	2. ipamd,一个长期运行的节点-本地IP地址管理(IPAM)守护进程,负责:
		维护一个可用 IP 地址的热池,以及
		为 Pod 分配 IP 地址。

该插件实现的基本要求是:
	1. 所有容器都可以在没有 NAT 的情况下与所有其他容器通信
	2. 所有节点都可以在没有 NAT 的情况下与所有容器通信(反之亦然)
	......

到这里,其实大家已经知道。eks中pod用的是和ec2相同的 vpc IP 地址段;并且每个IP地址都依赖于一个eni,eni可以有多个IP地址;
每个eni都有自己的路由规则用于pod的传出流量;.....

eks 中docker容器并没有像 单机版本 docker 容器一样使用docker0 网络做 桥接;而是使用了真实的 vpc IP地址;

结果

到这里真想就大白了;

普通 docker 中,使用docker0 做网络的桥接;eks 中 pod 的启动是分配了 真实的IP地址的;

这里直接使用 docker build 启动的容器,是没有 docker0 做为桥接,然后又没人给他分配 eni IP地址(eks中,cni 插件来管),所以我docker build 的容器,启动时是没有网络环境的;

解决

  1. jenkins 在 eks 中启动 agent 节点,在docker build 环节中,尽量不使用 网络资源;如果真要使用 自己构建完基础镜像,依托于基础镜像再进行 jenkins 构建操作;

  2. 索性,不使用eks中的jenkins agent 来构建docker镜像;直接在jenkins机器上直接构建;

  3. 构建时 指定网络

# 这里直接指定 build 时使用 主机网络;完美解决;
docker build --network=host . -t ${IMAGE_REPO}:${GIT_COMMIT}
posted @ 2022-07-28 00:17  Star-Hitian  阅读(1560)  评论(0编辑  收藏  举报