采用Wireguard连接k8s集群内网
1. 背景
Kubernetes虚拟集群的私有网络在开发客户端无法直接访问。
其它方案,如sshuttle方案,存在缺点:
效率较低。
windows下需要借助wsl才能使用,安装复杂且进一步拉低效率。
Wireguard是一个非常简洁的建立vpn隧道的软件
本文尝试采用wireguard连接开发终端与kubernetes虚拟集群私有网络。
参考文献:https://dev.to/ivanmoreno/how-to-connect-with-kubernetes-internal-network-using-wireguard-48bh
2. 服务器端部署
2.1. 预装软件
宿主机如果是Redhat或者CentOS操作系统,默认内核中没有把wireguard模块编译进去,需要预装下列软件:
# CentOS 8
sudo dnf install elrepo-release epel-release -y
sudo dnf install kmod-wireguard wireguard-tools -y
# CentOS 7
sudo yum install epel-release https://www.elrepo.org/elrepo-release-7.el7.elrepo.noarch.rpm
sudo yum install yum-plugin-elrepo
sudo yum install kmod-wireguard wireguard-tools -y
2.2. 查看集群中的DNS地址
[root@master ~]# kubectl -n kube-system get svc | grep kube-dns | awk '{print $3}'
10.43.0.10
当然也可以在rancher中查看,即在namepsace:kube-system下的ClusterIP:kube-dns中查看IP地址。
2.3. 创建命名空间
apiVersion: v1
kind: Namespace
metadata:
name: dev-wireguard # 自定义
labels:
name: dev-wireguard
2.4. 创建配置文件
apiVersion: v1
kind: ConfigMap
metadata:
name: wireguard-config
namespace: dev-wireguard # 前面创建的namespace
data:
PUID: "1000"
PGID: "1000"
TZ: "Asia/Shanghai"
SERVERURL: "172.31.171.124" # 设置为宿主机IP地址
SERVERPORT: "31820" # 这是后面nodeport准备暴露到宿主机的端口,生成客户端配置文件使用
PEERS: "2" # 这里是开发客户端的数量,按开发人数和开发设备数量设置,可以适当富余一些
PEERDNS: "10.43.0.10" # 这里替换成2.1中查到的DNS地址
ALLOWEDIPS: "10.42.0.0/16, 10.43.0.0/16" # 设置为K3s集群中的网段
INTERNAL_SUBNET: "10.13.13.0" # wireguard vpn网络子网,与正在使用的局域网、其他vpn等不冲突即可
2.5. 创建用于保存wireguard生成的配置文件的存储
可以用NFS,也可以用本地存储。如果用本地存储注意指定pod运行的节点。
这里假设使用本地存储:/var/opt/wireguard-conf
2.6. 部署wireguard
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
workload.user.cattle.io/workloadselector: apps.deployment-dev-wireguard-wireguard-server
name: wireguard-server
namespace: dev-wireguard
spec:
progressDeadlineSeconds: 600
replicas: 1
revisionHistoryLimit: 10
selector:
matchLabels:
workload.user.cattle.io/workloadselector: apps.deployment-dev-wireguard-wireguard-server
strategy:
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
type: RollingUpdate
template:
metadata:
labels:
workload.user.cattle.io/workloadselector: apps.deployment-dev-wireguard-wireguard-server
spec:
affinity: {}
containers:
- envFrom:
- configMapRef:
name: wireguard-config
optional: false
image: linuxserver/wireguard
imagePullPolicy: Always
name: wireguard
ports:
- containerPort: 51820
name: udp51820
protocol: UDP
resources: {}
securityContext:
allowPrivilegeEscalation: true
capabilities:
add:
- SYS_MODULE
- NET_ADMIN
privileged: true
readOnlyRootFilesystem: false
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
volumeMounts:
- mountPath: /lib/modules
name: host-volumes
- mountPath: /config
name: wireguard-conf
dnsPolicy: ClusterFirst
nodeName: prod-master
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
terminationGracePeriodSeconds: 30
volumes:
- hostPath:
path: /lib/modules
type: Directory
name: host-volumes
- hostPath:
path: /var/opt/wireguard-conf
type: DirectoryOrCreate
name: wireguard-conf
补充说明:
如果镜像linuxserver/wireguard:latest无法拉取,可以换成lscr.io/linuxserver/wireguard:latest试试
2.7. 创建service暴露端口到宿主机
kind: Service
apiVersion: v1
metadata:
name: wireguard-service
namespace: dev-wireguard
spec:
type: NodePort
ports:
- port: 51820 # wireguard监听端口
nodePort: 31820 # 端口30000-32767之间,不要与其他nodeport端口冲突
protocol: UDP # UDP协议
targetPort: 51820 # wireguard监听端口
selector:
workload.user.cattle.io/workloadselector: apps.deployment-dev-wireguard-wireguard-server # 与pod的label一致
2.8. 获取客户端配置文件
Wireguard服务端部署成功后,会在wireguard容器中自动为客户端生成配置文件,目录在:/config下面
root@wireguard-server-6cd4cf69df-8pkrs:/# cd /config
root@wireguard-server-6cd4cf69df-8pkrs:/config# ls -lah
total 36K
drwxr-xr-x 7 abc users 4.0K Jun 5 13:39 .
drwxr-xr-x 1 root root 4.0K Jun 5 13:39 ..
-rw------- 1 abc users 190 Jun 5 13:39 .donoteditthisfile
drwxr-xr-x 2 abc users 4.0K Jun 5 13:39 coredns
drwx------ 2 abc users 4.0K Jun 5 13:39 peer1
drwx------ 2 abc users 4.0K Jun 5 13:39 peer2
drwxr-xr-x 2 abc users 4.0K Jun 5 13:39 server
drwxr-xr-x 2 abc users 4.0K Jun 5 13:39 templates
-rw------- 1 abc users 705 Jun 5 13:39 wg0.conf
说明:
因为前面configmap中的参数PEERS我们设置为2,所以这里生成了两个客户端配置文件目录peer1和peer2
客户端配置文件是peerX目录下面的peerX.conf
为确保客户端IP不冲突,必须确保这里的配置文件不重复使用,所以开发负责人应对配置文件的分配使用进行记录和管理
自动生成的配置文件中部分内容可能需要修改
以上面/config/peer1/peer1.conf为例:
自动生成的文件内容为:
[Interface]
Address = 10.13.13.2
PrivateKey = GFXJCJOhDhc8lm/uu91epjR1iXJU6emnGnnsN7vs9XA=
ListenPort = 51820
DNS = 10.43.0.10
[Peer]
PublicKey = i/38CcmMkRI3AXVbIhPEXMkoqdUVxQokMV4fOYwI0XY=
PresharedKey = fLbEsshT2UEr6lqC/T+lvtD6gMwDBzRIRXb2WRhVxbo=
Endpoint = 172.31.171.124:31820 # 检查这里,必须是客户端能够访问的宿主机IP和nodeport端口
AllowedIPs = 10.42.0.0/16,10.43.0.0/16 # 检查这里,为了不影响其他地址的访问,这里限制在kubernetes集群内部网段
3. 客户端部署
3.1. Windows
3.1.1. 安装软件
下载并安装 Wireguard
3.1.2. 导入配置文件
Wireguard服务器端程序自动生成了客户端配置文件,请通过服务器管理人员获得配置文件,类似:peer1.conf
运行Wireguard,并加载配置文件,实现vpn连接。
至此,Wireguard建立的VPN网络已经连接完成。
3.1.3. 设置搜索域
因为在kubernetes集群中,POD的IP常常是动态变化的,因此通常都使用域名访问,而集群中为了访问方便,又会使用搜索域(DNS后缀)。为了符合kubernetes集群中的习惯,需要在开发客户端进行搜索域设置。如下图所示:
至少需要添加两个搜索域,一个是后端服务的搜索域:<namespace>.svc.cluster.local,另一个是所有服务公共的搜索域:svc.cluster.local。
3.1.4. 修改组策略
在Windows下,默认只会给不带点号(.)分隔符的域名自动附加搜索域(DNS后缀),但是对于类似mysql.dev-mw这样的域名,我们也希望它自动附加搜索域,这需要通过修改Windows的本地组策略实现。
# cmd
C:\> gpedit
参考下图设置:
3.2. Linux
3.2.1. 安装软件
Debian/Ubuntu
$ sudo apt install wireguard
CentOS8
$ sudo yum install elrepo-release epel-release $ sudo yum install kmod-wireguard wireguard-tools
CentOS7
$ sudo yum install epel-release elrepo-release $ sudo yum install yum-plugin-elrepo $ sudo yum install kmod-wireguard wireguard-tools
Arch/Manjaro
$ sudo pacman -S wireguard-tools
3.2.2. 获取配置文件
Wireguard服务器端程序自动生成了客户端配置文件,请通过服务器管理人员获得配置文件,类似:peer1.conf。保存位置随意。比如:~/.wireguard/peer1.conf
3.2.3. 建立Wireguard网络
通过导入配置文件建立网络
$ nmcli connection import type wireguard file ~/.wireguard/peer1.conf
执行成功后即完成vpn连接,通过下面命令查看:
$ ip addr ... 3: peer1: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1420 qdisc noqueue state UNKNOWN group default qlen 1000 link/none inet 10.13.13.2/32 scope global noprefixroute peer1 valid_lft forever preferred_lft forever ...
启动
$ nmcli connection up peer1
关停
$ nmcli connection down peer1
删除
$ nmcli connection delete peer1
3.2.4. 设置DNS和搜索域
$ sudo vim /etc/resolv.conf
nameserver 10.43.0.10
search dev-server.svc.cluster.local svc.cluster.local
其中:
1)10.43.0.10 替换成虚拟集群中实际的DNS服务地址(通常就是10.43.0.10)
2)dev-server替换成你自己环境的后端服务namespace。