通过网络命名空间实现网络分流的思想及方法

场景描述

以k8s环境为例,在kubernetes集群中是通过CoreDNS来控制集群DNS流量走向。

在业务环境中,存在eth0、eth1、eth2等多个网络设备,其对应不同的网络出口。那如何将指定DNS流量进行分流呢?

大家可能想到的是:根据三元组信息(源IP、协议、出口IP)+ 代理转发的方式实现分流。

没错,下面按照这种思路实现~

简述下kubernetes集群中DNS请求流程:

  1. 进入pod centos 容器中,执行nslookup www.baidu.com命令
  2. 进行域名解析时,会首先找到容器中的/etc/resolv.conf文件,根据此文件会将dns服务器指向CoreDNS容器地址
  3. DNS请求到达CoreDNS后,会针对 www.baidu.com 域名解析,如果不是kubernetes集群域名,则DNS请求到CoreDNS forward插件
  4. forward插件会根据配置,读取kubernets宿主机中/etc/resolv.conf文件,将www.baidu.com域名通过公网DNS解析
  5. 此时CoreDNS容器网络环境与kubernets宿主机网络没连通,是利用hostPort将宿主机53端口映射到CoreDNS容器中,将DNS报文传输并通过互联网络解析完成。

我们了解CoreDNS解析流程后,会发现在第5步骤中:CoreDNS容器与Kubernetes宿主机网络没有连通,导致从CoreDNS没办法获取到宿主机的网络设备,无法按照我们预期进行DNS流量分流。

这里说明一下CoreDNS容器默认没有配置hostNetwork网络模式(hostNetwork代表继承宿主机的网络栈),所以对于CoreDNS容器来说是网络隔离的。

下面进入到咱们今天的话题《通过设置net命名空间进行网络分流》。

大致思路为:CoreDNS收到集群中dns请求后,forward插件在向公共DNS服务器发起 net.Dial() 网络请求前,将该线程上下文设置成kubernetes宿主机的net命名空间,那么此时 net.Dial() 网络请求就可以获取到宿主机所有的网络设备,达到网络分流。

第一步,将宿主机里命名空间文件挂在到CoreDNS容器中

执行kubectl edit deployment.apps -n kube-system coredns 命令,修改CoreDNS Deployment。增加内容如下:

yaml 复制代码
volumes:
  - name: host-namespace
    hostPath:
      path: /proc/1/ns

这里是将Linux系统中1号进程的命名空间目录挂进了CoreDNS容器中。 相应的将该目录映射到容器任意一个位置,比如创建/host-netns目录。

第二步,修改CoreDNS项目源码实现DNS网络请求分流

在封装dns.Client{}结构体时,这里 netcardIP 变量可以理解为 eth0 网卡IP,代表从该网口作为出口。

重新封装dns.Client{}后,调用dialInNamespace()函数将本线程设置为宿主机的网络命名空间。

通过系统调用,将网络命名空间文件描述设置当前线程。

第三步,修改CoreDNS权限模式

这里需要将容器权限更改为特权模式,修改方式也是更改 CoreDNS Deployment配置。

技术文章持续更新,请大家多多关注呀~~

搜索微信公众号,关注我【 帽儿山的枪手 】

相关推荐
fetasty14 小时前
rustfs加picgo图床搭建
docker
YuMiao14 小时前
gstatic连接问题导致Google Gemini / Studio页面乱码或图标缺失问题
服务器·网络协议
蝎子莱莱爱打怪1 天前
GitLab CI/CD + Docker Registry + K8s 部署完整实战指南
后端·docker·kubernetes
小p2 天前
docker学习7:docker 容器的通信方式
docker
小p2 天前
docker学习5:提升Dockerfile水平的5个技巧
docker
小p2 天前
docker学习3:docker是怎么实现的?
docker
Jony_3 天前
高可用移动网络连接
网络协议
chilix4 天前
Linux 跨网段路由转发配置
网络协议
小p4 天前
docker学习: 2. 构建镜像Dockerfile
docker
小p4 天前
docker学习: 1. docker基本使用
docker