使用OpenVPN将Kubernetes集群网络暴露给本地开发网络

使用Helm在K8S上部署OpenVPN 下载openvpn的helm包

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

修改配置文件,详情参考stable/openvpn-github

cp  values.yaml openvpn-values.yaml
vi openvpn-values.yaml
replicaCount: 1
image:
  repository: jfelten/openvpn-docker
  tag: 1.1.0
  pullPolicy: IfNotPresent
service:
  type: ClusterIP
ipForwardInitContainer: true	#必须开启路由转发  
persistence:
  enabled: true
  storageClass: "nfs-client"	#使用的是nfs动态存储卷
  accessMode: ReadWriteOnce
  size: 2M
openvpn:
  OVPN_NETWORK: 10.244.0.0		#openvpn互联地址
  OVPN_SUBNET: 255.255.0.0
  OVPN_PROTO: tcp
  OVPN_K8S_POD_NETWORK: "10.68.0.0"	#k8s pod地址
  OVPN_K8S_POD_SUBNET: "255.255.0.0"
  OVPN_K8S_SVC_NETWORK: "172.20.0.0"	#k8s svc地址
  OVPN_K8S_SVC_SUBNET: "255.255.0.0"
  DEFAULT_ROUTE_ENABLED: true
  dhcpOptionDomain: true
  redirectGateway: true
  useCrl: false
  taKey: true
  cipher: AES-256-CBC					#高版本openvpn建议使用此加密

部署

helm install openvpn -n openvpn ./ -f openvpn-values.yaml

暴露1194端口

kubectl get cm -n ingress-nginx tcp-services -oyaml
#dota下面添加"对外port:namesapce:容器端口"
......
data:
  "1194": openvpn/openvpn:443

部署完成之后有个坑,不能解析k8s内部svc

nslookup kubernetes.default.svc.cluster.local
服务器:  UnKnown
Address:  192.168.1.1

DNS request timed out.
    timeout was 2 seconds.
DNS request timed out.

查看openvpn服务端配置

kubectl get cm -n openvpn openvpn -oyaml
......
push "dhcp-option DNS OVPN_K8S_DNS"

因为我用的是node-local-dns,pod的DNS地址会变成__PILLAR__LOCAL__DNS__的默认地址169.254.20.10所以导致不能解析

修改服务端配置

kubectl get svc -n kube-system -l k8s-app=kube-dns -o jsonpath='{$.items[*].spec.clusterIP}'
10.68.0.2
kubectl get cm -n openvpn openvpn -oyaml
push "dhcp-option DNS 10.68.0.2"

客户端配置生成

生使用下面的脚本生成一个客户端key

#!/usr/bin/env bash
KEY_NAME=$1
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"
./gen-client-key.sh kubeVPN

上面的命令会生成client.ovpn配置文件,因为前面用Helm部署openvpn时,创建的Servie是ClusterIP类型的,生成的配置文件 中的VPN服务地址会有错误,需要修改这个配置文件,将remote配置修改如下地址为k8s边缘节点的ip,端口为前面暴露的1194端口,同时删除redirect-gateway def1这行内容

remote 192.168.1.11 1194 tcp

如果收回并取消生成的客户端key,可以执行下面的脚本:

#!/usr/bin/env bash
KEY_NAME=$1
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

后记

下次把openldap集成到一起