下载openvpn的helm安装包:

http://mirror.azure.cn/kubernetes/charts/  # 里面有很多开源的软件包找打openvpn随便下一个即可

下载解压:

wget http://mirror.azure.cn/kubernetes/charts/openvpn-4.2.5.tgz
tar -zxvf openvpn-4.2.5.tgz
cd openvpn

编辑values.yaml文件:

replicaCount: 1
updateStrategy: {}
imagePullSecretName:
image:
  repository: jfelten/openvpn-docker
  tag: 1.1.0
  pullPolicy: IfNotPresent
service:
  type: LoadBalancer
  externalPort: 443
  internalPort: 443
  externalIPs: []
  nodePort: 32085 # 想改就改一下不想改也行,后面客户端用这个端口来连接openvpn
  annotations: {}
podAnnotations: {}
ipForwardInitContainer: false
resources:
  limits:
    cpu: 300m
    memory: 128Mi
  requests:
    cpu: 300m
    memory: 128Mi
readinessProbe:
  initialDelaySeconds: 5
  periodSeconds: 5
  successThreshold: 2
persistence:
  enabled: true
  storageClass: "managed-nfs-storage" # 存储
  accessMode: ReadWriteOnce
  size: 2M
openvpn:
  OVPN_NETWORK: 10.240.0.0
  OVPN_SUBNET: 255.255.0.0
  OVPN_PROTO: tcp
  OVPN_K8S_POD_NETWORK: "10.42.0.0" # Pod网络
  OVPN_K8S_POD_SUBNET: "255.255.0.0" # Pod掩码
  OVPN_K8S_SVC_NETWORK: "10.43.0.0" # svc网络
  OVPN_K8S_SVC_SUBNET: "255.255.0.0" # svc掩码
  DEFAULT_ROUTE_ENABLED: true
  dhcpOptionDomain: true
  redirectGateway: true
  useCrl: false
  taKey: false
  cipher: AES-256-CBC # 打开注释,客户端需要此加密,其他不用改默认就行
  istio:
    enabled: false
    proxy:
      port: 15001
  iptablesExtra: []
  ccd:
    enabled: false
    config: {}
nodeSelector: {}
tolerations: []

打包:

helm package .

安装:

helm install openvpn -n openvpn openvpn-4.2.4.tgz

查看:

helm ls -n openvpn
NAME   	NAMESPACE	REVISION	UPDATED                                	STATUS  	CHART        	APP VERSION
openvpn	openvpn  	1       	2022-06-21 14:13:14.736488456 +0800 CST	deployed	openvpn-4.2.4	1.1.0

查看日志:出现下面这些行日志其实是k8s控制器的程序的存活性检测。

Tue Jun 21 07:51:46 2022 TCP connection established with [AF_INET]127.0.0.1:33320
Tue Jun 21 07:51:46 2022 127.0.0.1:33320 Connection reset, restarting [0]
Tue Jun 21 07:51:46 2022 127.0.0.1:33320 SIGUSR1[soft,connection-reset] received, client-instance restarting

去掉就绪性探测:去掉下面这段配置即可,再查看日志就不会一直输出上面的信息了。

kubectl edit deployments.apps -n openvpn openvpn
...
        readinessProbe:
          exec:
            command:
            - nc
            - -z
            - 127.0.0.1
            - "443"
          failureThreshold: 3
          initialDelaySeconds: 5
          periodSeconds: 5
          successThreshold: 2
          timeoutSeconds: 1
...

暴露服务:

方法一:使用NodePort方式,连接地址和端口为 NodeIP:32200。

kubectl get svc -n openvpn
NAME      TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)         AGE
openvpn   NodePort   10.43.227.213   <none>        443:32200/TCP   115m

第二种:使用ingress-controller的4层代理代理这个tcp服务

kubectl get configmap -n ingress-nginx tcp-services -o yaml
...
data:
  "1194": openvpn/openvpn:443


客户端配置文件:

生成配置:使用helm安装好后会提示如下这几行命令,其实就是执行pod里面的/etc/openvpn/setup/newClientCert.sh 脚本,第一个参数为名称(随便写),第二个参数为暴露的服务IP,就是客户端连接到openvpn的IP。

POD_NAME=$(kubectl get pods --namespace "openvpn" -l "app=openvpn,release=openvpn" -o jsonpath='{ .items[0].metadata.name }')
SERVICE_NAME=$(kubectl get svc --namespace "openvpn" -l "app=openvpn,release=openvpn" -o jsonpath='{ .items[0].metadata.name }')
SERVICE_IP=$(kubectl get svc --namespace "openvpn" "$SERVICE_NAME" -o go-template='{{ range $k, $v := (index .status.loadBalancer.ingress 0)}}{{ $v }}{{end}}')
KEY_NAME=kubeVPN
kubectl --namespace "openvpn" exec -it "$POD_NAME" /etc/openvpn/setup/newClientCert.sh "$KEY_NAME" "$SERVICE_IP"
kubectl --namespace "openvpn" exec -it "$POD_NAME" cat "/etc/openvpn/certs/pki/$KEY_NAME.ovpn" > "$KEY_NAME.ovpn"

配置文件:

client
nobind
dev tun
remote 192.168.199.45 32200 tcp # 这个32200端口就是nodeport映射出来的端口或ingress代理的端口
redirect-gateway def1

<key>
...
</key>
<cert>
...
</cert>
<ca>
...
</ca>

吊销证书脚本:

KEY_NAME=<name>
POD_NAME=$(kubectl get pods -n "openvpn" -l "app=openvpn,release=openvpn" -o jsonpath='{.items[0].metadata.name}')
kubectl -n "openvpn" exec -it "$POD_NAME" /etc/openvpn/setup/revokeClientCert.sh $KEY_NAME


linux端连接:

安装客户端:

yum install -y openssl lzo pam openssl-devel lzo-devel pam-devel easy-rsa openvpn

配置文件:注意后缀为conf

ls /etc/openvpn/client/xxx.conf

启动服务:

systemctl status openvpn-client@xxx.service

查看路由表:多了如下几条路由,这样客户端的就可以访问PodIP和ServiceIP了。

]# ip route list 
...
10.42.0.0/16 via 10.240.0.5 dev tun0 
10.42.1.0/24 via 10.240.0.5 dev tun0 
10.43.0.0/16 via 10.240.0.5 dev tun0 
...


将linux客户端作为路由:

打开转发:

cat >> /etc/sysctl.conf <<EOF
net.ipv4.ip_forward = 1
EOF
sysctl -p

做SNAT:

iptables -t nat -A POSTROUTING -d 10.42.0.0/16 -o tun0 -j MASQUERADE
iptables -t nat -A POSTROUTING -d 10.43.0.0/16 -o tun0 -j MASQUERADE

在路由器上添加静态路由,将10.42.0.0/16 和 10.43.0.0/16 两个网段的下一跳设置为这台linux客户端的IP即可。

参考:

blog.frognew.com/2019/03/kubernetes-and-openvpn.html
www.1nth.com/post/k8s-openvpn/

openvpn服务端各配置解释:

https://www.ilanni.com/?p=9847


windows客户端连接:

        导入配置点击连接即可。