警告
本文最后更新于 2023-05-05,文中内容可能已过时。
微服务的流行推动着容器技术的发展,伴随着新技术的应用产生了新的问题。比如开发人员本机无法运行诸多的微服务,如何保障开发正常进行。本文将介绍如何打通开发环境网与docker环境之间的网络。
由于Kubernetes集群会使用CNI插件创建Pod/Service内部子网,外面一般无法访问内部IP和域名,给开发、测试、 联调带来了很大的麻烦,因此打通开发测试环境Kubernetes集群内部子网和办公室的局域网、实现互联互通是经常遇到的问题。
选一台docker节点做路由转发,连接办公室网络和 docker 集群服务
- 节点 IP 地址 192.168.1.90
- 容器网段 10.42.0.0/16
- 办公网段 192.168.0.0/24

我的网络整体结构本身不复杂,所以相对来说配置简单。
节点,做snat:
开启转发
1
2
3
| vim /etc/sysctl.d/k8s.conf
net.ipv4.ip_forward = 1
sysctl -p
|
来自办公室访问docker service snat
iptables命令是Linux上常用的防火墙软件,是netfilter项目的一部分。可以直接配置,也可以通过许多前端和图形界面配置。
语法
选项
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| -t<表>:指定要操纵的表;
-A:向规则链中添加条目;
-D:从规则链中删除条目;
-i:向规则链中插入条目;
-R:替换规则链中的条目;
-L:显示规则链中已有的条目;
-F:清楚规则链中已有的条目;
-Z:清空规则链中的数据包计算器和字节计数器;
-N:创建新的用户自定义规则链;
-P:定义规则链中的默认目标;
-h:显示帮助信息;
-p:指定要匹配的数据包协议类型;
-s:指定要匹配的数据包源ip地址;
-d:指定要匹配的数据包目的ip地址;
-j<目标>:指定要跳转的目标;
-i<网络接口>:指定数据包进入本机的网络接口;
-o<网络接口>:指定数据包要离开本机所使用的网络接口。
|
iptables命令选项输入顺序:
1
| iptables -t 表名 <-A/I/D/R> 规则链名 [规则号] <-i/o 网卡名> -p 协议名 <-s 源IP/源子网> --sport 源端口 <-d 目标IP/目标子网> --dport 目标端口 -j 动作
|
表名包括:
- raw:高级功能,如:网址过滤。
- mangle:数据包修改(QOS),用于实现服务质量。
- net:地址转换,用于网关路由器。
- filter:包过滤,用于防火墙规则。
规则链名包括:
- INPUT链:处理输入数据包。
- OUTPUT链:处理输出数据包。
- PORWARD链:处理转发数据包。
- PREROUTING链:用于目标地址转换(DNAT)。
- POSTOUTING链:用于源地址转换(SNAT)。
动作包括:
- [accept]:接收数据包。
- DROP:丢弃数据包。
- REDIRECT:重定向、映射、透明代理。
- SNAT:源地址转换。
- DNAT:目标地址转换。
- MASQUERADE:IP伪装(NAT),用于ADSL。
- LOG:日志记录。
1
| iptables -t nat -A POSTROUTING -s 192.168.11.0/24 -d 10.42.0.0/16 -j MASQUERADE
|
POSTROUTING是源地址转换(SNAT),要把你内部网络上受防火墙保护的ip地址转换成你本地的公网地址才能让它们上网。
PREROUTING是目的地址转换(DNAT),要把别人的公网IP换成你们内部的IP,才让访问到你们内部受防火墙保护的服务器。
MASQUERADE,地址伪装,算是snat中的一种特例,可以实现自动化的snat
借用阿里云的一张图

多个内网段SNAT,就是多条SNAT语句即可
1
2
3
| iptables -t nat -A POSTROUTING -s 192.168.0.0/24 -d 10.42.0.0/16 -j MASQUERADE
iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -d 10.42.0.0/16 -j MASQUERADE
iptables -t nat -A POSTROUTING -s 192.168.11.0/24 -d 10.42.0.0/16 -j MASQUERADE
|
在办公室的出口路由器上,设置静态路由,将docker的网段,路由到节点上
1
| ip route 10.42.0.0 255.255.255.0 192.168.1.90
|
以上步骤操作后,我们就可以在本地电脑通过访问docker ip去访问服务。

1
2
3
4
5
6
7
8
9
10
| OVPN_DATA=/data/openvpn
SERVER_PUBLIC_URL=172.30.4.195
DNS_SERVER=180.168.255.118
SERVER_SUBNET=10.4.0.0/24
docker run \
-v ${OVPN_DATA}:/etc/openvpn \
--rm \
kylemanna/openvpn:2.4 \
ovpn_genconfig -u udp://${SERVER_PUBLIC_URL} -n ${DNS_SERVER} -p "route 10.42.0.0 255.255.0.0" -s ${SERVER_SUBNET}
|
参数说明
-u SERVER_PUBLIC_URL # vpn所在服务器的公网ip
-n DNS_SERVER # dns服务器地址
-p PUSH # 推送路由
-s SERVER_SUBNET # vpn内网范围,一定要注意,不要和已有物理网络、Kubernetes网络冲突。

修改配置
注释push "block-outside-dns"
一行,我这里不注释 dns 解析异常
1
2
3
4
5
6
7
| OVPN_DATA=/data/openvpn
docker run \
-v ${OVPN_DATA}:/etc/openvpn \
--rm -it \
kylemanna/openvpn:2.4 \
ovpn_initpki
|
在此要输入ca的密码,需要输入两次。
1
2
| Enter New CA Key Passphrase:
Re-Enter New CA Key Passphrase:
|

此处要输入组织,可直接回车跳过。
1
| Common Name (eg: your user, host, or server name) [Easy-RSA CA]:
|
输入之前设置的私钥密码,需要输入两次
1
| Enter pass phrase for /etc/openvpn/pki/private/ca.key:
|

1
2
3
4
5
6
7
8
| OVPN_DATA=/data/openvpn
docker run -d \
--name openvpn \
-v ${OVPN_DATA}:/etc/openvpn \
-p 1194:1194/udp \
--cap-add=NET_ADMIN \
kylemanna/openvpn:2.4
|
CLIENTNAME可以是你想要的名字
1
2
3
4
5
6
7
8
| OVPN_DATA=/data/openvpn
CLIENTNAME=docker
docker run \
-v ${OVPN_DATA}:/etc/openvpn \
--rm -it \
kylemanna/openvpn:2.4 \
easyrsa build-client-full ${CLIENTNAME} nopass
|
输入之前设置的密码
1
| Enter pass phrase for /etc/openvpn/pki/private/ca.key:
|

1
2
3
4
5
6
7
8
9
| OVPN_DATA=/data/openvpn
CLIENTNAME=docker
mkdir -p /data/openvpn/conf
docker run \
-v ${OVPN_DATA}:/etc/openvpn \
--rm \
kylemanna/openvpn:2.4 \
ovpn_getclient ${CLIENTNAME} > /data/openvpn/conf/${CLIENTNAME}.ovpn
|
参考之前的Cenos7搭建OpenVPN
服务端配置文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
| server 10.4.0.0 255.255.255.0
verb 3
key /etc/openvpn/pki/private/192.168.1.91.key
ca /etc/openvpn/pki/ca.crt
cert /etc/openvpn/pki/issued/192.168.1.91.crt
dh /etc/openvpn/pki/dh.pem
#tls-auth /etc/openvpn/pki/ta.key
key-direction 0
keepalive 10 60
persist-key
persist-tun
proto udp
# Rely on Docker to do port mapping, internally always 1194
port 1194
dev tun0
status /tmp/openvpn-status.log
user nobody
group nogroup
comp-lzo no
### Route Configurations Below
route 192.168.254.0 255.255.255.0
### Push Configurations Below
#push "block-outside-dns"
push "dhcp-option DNS 180.168.255.118"
push "comp-lzo no"
push "route 10.42.0.0 255.255.0.0"
client-cert-not-required
auth-user-pass-verify /etc/openvpn/checkpsw.sh via-env
username-as-common-name
script-security 3
|
客户端配置文件
1
2
3
4
5
6
7
8
9
10
11
12
| client
nobind
dev tun
auth-user-pass
remote-cert-tls server
remote 192.168.1.91 1194 udp
<ca>
-----BEGIN CERTIFICATE-----
-----END CERTIFICATE-----
</ca>
|
参考链接:
打通Kubernetes内网与局域网的N种方法
办公环境下 Kubernetes 网络互通方案
OpenVPN访问Kubernetes集群内网