【容器化】Kubernetes借助OpenVPN打通本地和集群内网

一、前言

当把开发环境、测试环境的微服务都容器化之后,整个容器集群的微服务都是网络隔离的状态(Pod的IP网段为私有网段)。那么本地开发的时候,需要连接到SpringCloud的注册中心、配置中心甚至一些公共服务(比如业务无关的推送、支付等)的时候,除了对所有容器进行端口暴露(步骤比较繁琐麻烦),还可以通过在Kubernetes集群中搭建OpenVPN服务器,本地通过OpenVPN客户端连接到Kubernetes集群的OpenVPN服务器,进行网络的打通。

二、部署OpenVPN

Kubernetes的网络模型为calico可使用OpenVPN进行隧道打通,选择其它网络模型时需验证是否满足OpenVPN的转发规则。

1、安装脚本结构

安装脚本地址:https://github.com/ShemgXu/k8s-component-openvpn

psw-file文件内容为OpenVPN客户端账号密码,每行表示一个账号密码

2、初始化脚本

#!/bin/bash
protocol="udp"
server="172.168.50.89"
port="30909"
#openvpn服务器地址
serverPublicUrl="$protocol://$server:$port"
#openvpn dns
dnsParams="-n 218.85.157.99 -n 218.85.152.99"
#vpn隧道子网段
serverSubnetParams="-s 10.10.0.0/24"
#vpn服务器内网网段
pushParams='-p "route 192.168.0.0 255.255.0.0" -p "route 10.10.0.0 255.255.255.0"'
clientName="vpn_pub_test"
isUpdateK8s=1

rm -rf ovpn0 && mkdir ovpn0 && cd ovpn0
#推送DNS
#getConfigCommand="docker run --net=none --rm -it -v $PWD:/etc/openvpn kylemanna/openvpn ovpn_genconfig -u $serverPublicUrl -C 'AES-256-GCM' -a 'SHA384' -T 'TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384' -b $dnsParams $serverSubnetParams $pushParams";
#不推送DNS
getConfigCommand="docker run --net=none --rm -it -v $PWD:/etc/openvpn kylemanna/openvpn ovpn_genconfig -u $serverPublicUrl -C 'AES-256-GCM' -a 'SHA384' -T 'TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384' -b -D $serverSubnetParams $pushParams";
eval $getConfigCommand

#2.生成PKI(公钥基础设施)、CA(证书颁发机构)、生成服务端证书、服务端证书签约、创建Diffie-Hellman证书
docker run -e EASYRSA_ALGO=ec -e EASYRSA_CURVE=secp384r1 --net=none --rm -it -v $PWD:/etc/openvpn kylemanna/openvpn ovpn_initpki
#按提示设置密码,比如:shemg

#生成服务端证书
docker run --net=none --rm -it -v $PWD:/etc/openvpn kylemanna/openvpn ovpn_copy_server_files
docker run -e EASYRSA_ALGO=ec -e EASYRSA_CURVE=secp384r1 --net=none --rm -it -v $PWD:/etc/openvpn kylemanna/openvpn easyrsa build-client-full $clientName
#Enter PEM pass phrase: 输入客户端密码
#Verifying - Enter PEM pass phrase: 输入客户端密码
#Enter pass phrase for /etc/openvpn/pki/private/ca.key:输入CA密码

#导出客户端配置文件
docker run --net=none --rm -v $PWD:/etc/openvpn kylemanna/openvpn ovpn_getclient $clientName > $clientName.ovpn

#客户端配置账号密码登录
echo 'verify-client-cert none' >> server/openvpn.conf
echo 'username-as-common-name' >> server/openvpn.conf
echo 'script-security 3' >> server/openvpn.conf
echo 'auth-user-pass-verify /etc/openvpn/checkpsw.sh via-env' >> server/openvpn.conf

#生成的配置信息.ovpn删除证书和秘钥信息<key>...</key>和<cert>...</cert>,并添加如下信息:
keyTagBeginNum=$(grep -n "<key>" ./$clientName.ovpn | cut -d ":" -f 1)
keyTagEndNum=$(grep -n "</key>" ./$clientName.ovpn | cut -d ":" -f 1)
sed -i "$keyTagBeginNum","$keyTagEndNum"d $clientName.ovpn
certTagBeginNum=$(grep -n "<cert>" ./$clientName.ovpn | cut -d ":" -f 1)
certTagEndNum=$(grep -n "</cert>" ./$clientName.ovpn | cut -d ":" -f 1)
sed -i "$certTagBeginNum","$certTagEndNum"d $clientName.ovpn
echo 'auth-user-pass' >> $clientName.ovpn

cp ../psw-file ../checkpsw.sh server

if [ "$isUpdateK8s" = "1" ]; then
    echo "update k8s..."
    kubectl delete secret ovpn0-cert ovpn0-key ovpn0-pki
    kubectl delete configmap ovpn0-conf ccd0
    kubectl delete service ovpn0
    kubectl delete deployment ovpn0

    #服务端秘钥
    kubectl create secret generic ovpn0-key --from-file=server/pki/private/"$server".key
    #服务端证书
    kubectl create secret generic ovpn0-cert --from-file=server/pki/issued/"$server".crt
    #服务端pki
    kubectl create secret generic ovpn0-pki --from-file=server/pki/ca.crt --from-file=server/pki/dh.pem --from-file=server/pki/ta.key
    kubectl create configmap ovpn0-conf --from-file=server/
    kubectl create configmap ccd0 --from-file=server/ccd
    kubectl apply -f ../openvpn.yaml
fi

将server值改为Kubernetes Master的访问IP,port为OpenVPN的映射端口

执行init_openvpn.sh部署OpenVPN Pod

chmod +x init_openvpn.sh
bash init_openvpn.sh

3、安装客户端

下载OpenVPN GUI客户端,下载地址

4、客户端连接

安装客户端成功后,将步骤2运行脚本ovpn0目录中的vpn_pub_test.ovpn复制到OpenVPN GUI客户端配置文件中,然后启动客户端,选择vpn_pub_test配置,即可连接到OpenVPN服务器所在的Kubernetes容器私有网络。