已发表的技术专栏(订阅即可观看所有专栏)
0 grpc-go、protobuf、multus-cni 技术专栏 总入口
1 grpc-go 源码剖析与实战 文章目录
2 Protobuf介绍与实战 图文专栏 文章目录
3 multus-cni 文章目录(k8s多网络实现方案)
4 grpc、oauth2、openssl、双向认证、单向认证等专栏文章目录
本篇文章继续提供测试案例:
基于veth pair、namespace以及路由技术,实现跨主机命名空间之间的通信
1、网络拓扑如下 |
2、网络拓扑构建 |
2.1、第1步:在master上执行下面的命令 |
ip netns add ns1
ip link add veth1a type veth peer name veth1b
ip link set veth1a netns ns1
ip netns exec ns1 ip addr add 10.244.1.2/24 dev veth1a
ip netns exec ns1 ip link set veth1a up
ip addr add 10.244.1.3/24 dev veth1b
ip link set veth1b up
ip netns exec ns1 route add default gw 10.244.1.3
ip route add 10.244.2.0/24 via 10.211.55.123
echo 1 > /proc/sys/net/ipv4/ip_forward
route -n
ip netns exec ns2 route -n
2.2、第2步:在slave上执行下面的命令 |
ip netns add ns2
ip link add veth2a type veth peer name veth2b
ip link set veth2a netns ns2
ip netns exec ns2 ip addr add 10.244.2.2/24 dev veth2a
ip netns exec ns2 ip link set veth2a up
ip addr add 10.244.2.3/24 dev veth2b
ip link set veth2b up
ip netns exec ns2 route add default gw 10.244.2.3
ip route add 10.244.1.0/24 via 10.211.55.122
echo 1 > /proc/sys/net/ipv4/ip_forward
route -n
ip netns exec ns2 route -n
3、跨主机通信测试 |
登录到master节点上,进行跨主机通信测试
测试两种协议,ICMP协议和HTTP协议。
3.1、测试案例1:在master节点上跨主机ping slave节点上ns2里的veth2a网卡 |
针对ICMP协议,进行测试。
ip netns exec ns1 ping 10.244.2.2
3.2、测试案例2:在master节点上跨主机远程访问slave节点上ns2里的http-web服务 |
针对HTTP协议,进行测试。
3.2.1、http-web服务代码 |
提供一个http-web服务,代码如下
package main
import (
"encoding/json"
"fmt"
"net/http"
)
type Stu struct {
Age int
Msg string
}
const ip = "10.244.2.2"
func sayHello(w http.ResponseWriter, r *http.Request) {
stu := Stu{Age: 12, Msg: "hello world! this is Veth pair Test!"}
stuJson, e := json.Marshal(&stu)
if e != nil {
panic(e)
}
w.Write(stuJson)
fmt.Printf("Reply MSG:%v\tlen(Msg):%d\n", string(stuJson), len(stuJson))
}
func main() {
http.HandleFunc("/", sayHello)
fmt.Printf(fmt.Sprintf("App URL: http://%s:%d\n", ip, 9090))
err := http.ListenAndServe(fmt.Sprintf("%s:%d", ip, 9090), nil)
if err != nil {
fmt.Printf("http server failed, err:%v\n", err)
return
}
}
本地编译,上传到slave服务器上
build:
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o http-web main.go
scp:
scp http-web root@10.211.55.123:/root
all:
make build && make scp
在本地执行
make all
即可。
3.2.2、namespace 隔离说明(为什么在ns2命名空间里可以访问本地宿主机的文件) |
说明一点:
namespace仅仅是对网络资源的隔离,
namespace隔离的网络跟宿主机的网络是互不影响的。
但是,在namespace里是可以访问本地的宿主机的。
如下:
3.2.3、在slave节点上,ns2命名空间里启动http-web服务 |
ip netns exec ns2 ./http-web
3.2.4、在master节点上,ns1去测试ns2里的http-web服务 |
ip netns exec ns1 ip a s
ip netns exec ns1 curl 10.244.2.2:9090
4、原理介绍 |
4.1、测试用例中可以实现跨主机通信的原理? |
观察网络拓扑创建命令,似乎跟以前差不多。
只是新增了一条路由而已,如下:
ip route add 10.244.2.0/24 via 10.211.55.123
就可以实现跨主机通信了。
主要原因是:
- 将每个节点作为路由器来使用了。
- 如,将master节点,slave节点分别作为路由器来使用。
- 既然是将节点作为路由器来使用,那么,当节点如master节点收到数据包后,对数据包进行一层一层的解析,依次获取目的MAC地址,发现MAC地址是自己的MAC地址,继续获取目的IP地址,
- 查询本地的路由表,判断是否有去往目的地址的路由
- 如果有,就将此数据包转发到此路由上
- 如果没有,就采取其他策略,如丢弃。
- 当然,存在目标路由的话,还不行,还要查看iptables规则,查看FORWARD是否允许转发。
4.2、如何将一个linxu服务器作为路由器使用呢? |
配置如下命令即可
echo 1 > /proc/sys/net/ipv4/ip_forward
准确的说:
配置完成后,服务器就具备了路由器的路由转发功能了。
4.3、具体如何使用呢? |
4.3.1、将Linux服务器作为路由器的注意点 |
为了更好的理解,将Linux服务器作为路由器来使用,
可以先将原来的网络拓扑图转换为下面的形式,
假设master节点上的10.244.1.0/24网段的数据包的目的地址是10.244.2.0/24
slave节点上的10.244.2.0/24网段的数据包的目的地址是10.244.1.0/24
那么,
对于10.244.1.0/24网段的下一跳的地址,并不是本主机的对外的地址,
而是目的IP所在宿主机的对外物理地址,即10.211.55.123
同理,10.244.2.0/24的下一跳的地址是10.211.55.122
因此,将Linux服务器作为路由器有一个暗含要求:
节点必须在同一个网段呢。
4.3.2、具体设置路由 |
在master节点上,假设10.244.1.0/24网段的数据包的目的地址是10.244.2.0/24
那么,需要在master节点上,添加的路由是
ip route add 10.244.2.0/24 via 10.211.55.123
在slave节点上,假设10.244.2.0/24网段的数据包的目的地址是10.244.1.0/24
那么,需要在slavae节点上,添加的路由是
ip route add 10.244.1.0/24 via 10.211.55.122
5、传输过程,数据包的报文内容变化 |
5.1、在master节点上,抓取veth1b网卡的数据包 |
tcpdump -nn -i veth1b -w icmp-veth1b.pcap
5.2、在master节点上,抓取eth0网卡的数据包 |
tcpdump -nn icmp -i eth0 -w icmp-eth0.pcap
5.3、根据抓包情况,分析一下报文 |
直接路由转发数据包的方式,性能比较高。
不像vxlan模式没有经过额外的封包,解封包过程。
6、整个传输过程,经历过哪些iptables规则链 |
为了验证测试,分别在master节点、slave上添加日志埋点;
此过程,需要使用到rsyslog服务
6.1、在master节点上安装rsyslog服务 |
yum -y install rsyslog
6.1.1、更新配置文件 |
echo "kern.* /var/log/iptables.log" >> /etc/rsyslog.conf
.*,表示所有等级的消息都添加到iptables.log文件里
信息等级的指定方式
- .XXX,表示 大于XXX级别的信息
- .=XXX,表示等于XXX级别的信息
- 如,kern.=notice /var/log/iptables.log, 将notice以上的信息添加到iptables.log里
- .!XXX, 表示在XXX之外的等级信息
6.1.2、重启rsyslog服务 |
systemctl restart rsyslog
systemctl status rsyslog
6.2、在slave节点上安装rsyslog服务 |
可完全参考master节点安装过程
6.3、添加针对icmp协议的DNAT规则 |
如果测试的是tcp服务的协议的话,添加日志埋点时,可能存在测试不足的情况。
因为tcp协议,除了我们自己测试在用外,其他服务也可能在用tcp服务等等吧。
因此,这里使用icmp协议来测试。
(因为测试环境只有我们在用icmp协议,可以唯一确定,然后将规则链的匹配条件设置到最大)
6.4、添加日志埋点 |
6.4.1、在master节点上,添加日志埋点 |
将当前的日志统计清零
iptables -t nat -Z
iptables -t filter -Z
插入日志埋点前,先查看一下,当前的现状
iptables -t nat -nvL PREROUTING --line-number
iptables -t filter -nvL FORWARD --line-number
iptables -t nat -nvL POSTROUTING --line-number
插入日志埋点
iptables -t nat -I PREROUTING -p icmp -j LOG --log-prefix "Nat-PREROUTING-1-"
iptables -t filter -A FORWARD -p icmp -j LOG --log-prefix "Filter-FORWARD-1-"
iptables -t nat -I POSTROUTING -p icmp -j LOG --log-prefix "Nat-POSTROUTING-1-"
实时查看日志
tail -f /var/log/iptables.log
6.4.2、在slave节点上,添加日志埋点 |
将当前的日志统计清零
iptables -t nat -Z
iptables -t filter -Z
插入日志埋点前,先查看一下,当前的现状
iptables -t nat -nvL PREROUTING --line-number
iptables -t filter -nvL FORWARD --line-number
iptables -t nat -nvL POSTROUTING --line-number
插入日志埋点
iptables -t nat -I PREROUTING -p icmp -j LOG --log-prefix "Nat-PREROUTING-1-"
iptables -t filter -A FORWARD -p icmp -j LOG --log-prefix "Filter-FORWARD-1-"
iptables -t nat -I POSTROUTING -p icmp -j LOG --log-prefix "Nat-POSTROUTING-1-"
slave节点上的日志埋点跟master节点是一样的
6.5、第1次请求时,经过的iptables规则链 |
6.6、第1次反馈时,经过的iptables规则链 |
反馈时,只经过了FORWARD链。
6.7、第2次以及以后的请求、反馈时,经过的iptables规则链 |
请求、反馈时,只经过了FORWARD链。
7、总结 |
本机主要是利用了Linux服务器可以作为路由器转发功能,这一特点
实现了不同宿主机上不同命名空间的跨主机通信
这种方式,性能比较高。
当然,要求是必须是宿主机在同一个网段。
如果,你已经理解了本文的测试方案,那么,
恭喜你了!
flannel中的Host-gw模式的核心,你已经掌握了。