文章

采用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。

License:  CC BY 4.0