基于k3s+wireguard+kilo构建跨网的k3s集群
之前活动期间购买过多台服务器,但是通过不同账号享受的首单优惠,不在一个网络内,无法通过内网进行连接,之前通过tailscale进行跨网部署,但是后期问题较多,所以重新更换了方案。了解到kilo是基于WireGuard构建的多云网络覆盖,并且专为Kubernetes设计,所以切换到了kilo。 由于服务器的性能,所以采用了k3s作为k8s的实现,kilo作为跨网的网络覆盖。
前提
多台服务器
腾讯云: tx1-master, tx2-agent1, tx3-agent2(不在同一网络)
这是之前购买的三台服务器,但是都是通过不同账号购买,无法通过内网连接,只能通过公网ip进行连接
kilo可以创建多个location,但是每个location必须确保拥有一个公网ip,所以我们需要在每台服务器上安装wireguard,然后将每台服务器的公网ip添加到kilo的location中。
系统
tx1和tx2使用的centos,tx3使用的是debian11,正常来说可以安装wireguard和k3s即可
网络端口
由于跨网络,我们需要提前开放一些端口,需要在相关云主机的控制台里进行配置。
| 协议 | 端口 | 来源 | 说明 |
|---|---|---|---|
| TCP | 6443 | k3s-agent | Kubernetes API Server,master节点需要对agent节点开放6443端口,否则节点无法注册到集群中 |
| UDP | 51820 | k3s-server和agent节点 | kilo网络通信端口,集群内部跨主机网络传输会通过kilo |
| TCP | 10250 | k3s-server和k3s-agent | Kubelet metrics |
| TCP | 2379-2380 | k3s-server和k3s-agent | 仅对于具有嵌入式 etcd 的 HA 需要 |
启用ipv4转发
在/etc/sysctl.conf中变更net.ipv4.ip_forward的值为1,然后执行sysctl -p使其生效
安装
安装wireguard
具体可以参考wireguard官方网站的安装手册。安装完成之后,输入wg命令,如果没有报错,说明安装成功。
master节点
安装k3s
curl -sfL https://rancher-mirror.oss-cn-beijing.aliyuncs.com/k3s/k3s-install.sh | \
INSTALL_K3S_VERSION=v1.26.5+k3s1 \
INSTALL_K3S_MIRROR=cn \
K3S_CLUSTER_INIT=true \
INSTALL_K3S_EXEC="--tls-san $server_public_ip --node-external-ip $server_public_ip --flannel-backend none --kube-proxy-arg metrics-bind-address=0.0.0.0 --kube-apiserver-arg feature-gates=EphemeralContainers=true" \
sh -s -
将$server_public_ip替换为master节点的公网ip,执行上述命令,即可完成master节点的安装。
简要说明:
K3S_CLUSTER_INIT=true: 集群模式,会安装内置的 etcd,而不是 sqlite3;--tls-san $server_public_ip:$server_public_ip改为你自己指定的 k3s server 公网 IP,–tls-san会在TLS 证书上添加其他主机名或 IPv4/IPv6 地址作为使用者备用名称--node-external-ip server_public_ip:指定node的公网IP--flannel-backend none: 不使用flannel作为网络插件,因为我们使用kilo作为网络插件
具体参数的说明可以参考k3s官方文档
查看k3s.service的程序状态
➜ ~ systemctl status k3s.service
● k3s.service - Lightweight Kubernetes
Loaded: loaded (/etc/systemd/system/k3s.service; enabled; vendor preset: disabled)
Active: active (running) since Wed 2023-07-19 18:20:03 CST; 5 days ago
Docs: https://k3s.io
Process: 11836 ExecStartPre=/sbin/modprobe overlay (code=exited, status=0/SUCCESS)
Process: 11834 ExecStartPre=/sbin/modprobe br_netfilter (code=exited, status=0/SUCCESS)
Process: 11831 ExecStartPre=/bin/sh -xc ! /usr/bin/systemctl is-enabled --quiet nm-cloud-setup.service (code=exited, status=0/SUCCESS)
Main PID: 11838 (k3s-server)
Tasks: 211
Memory: 3.4G
CGroup: /system.slice/k3s.service
......
安装kilo
-
指定server节点所在云的kilo拓扑
k3s kubectl annotate node tx-master-1 kilo.squat.ai/location="txy-1" k3s kubectl annotate node tx-master-1 kilo.squat.ai/force-endpoint={{ public_ip }}:51820 k3s kubectl annotate node tx-master-1 kilo.squat.ai/persistent-keepalive=20配置可参考kilo官方文档
-
修改启动参数
下载yaml文件
wget https://raw.githubusercontent.com/squat/kilo/main/manifests/kilo-k3s.yaml调整kilo的启动参数为全互联模式
... apiVersion: apps/v1 kind: DaemonSet metadata: name: kilo namespace: kube-system labels: app.kubernetes.io/name: kilo spec: selector: matchLabels: app.kubernetes.io/name: kilo template: metadata: labels: app.kubernetes.io/name: kilo spec: serviceAccountName: kilo hostNetwork: true containers: - name: kilo image: squat/kilo args: - --kubeconfig=/etc/kubernetes/kubeconfig - --hostname=$(NODE_NAME) + - --encapsulate=never + - --mesh-granularity=full ... ...--encapsulate=never表示不使用 ipip 协议对同一个逻辑区域内的容器网络流量进行加密。--mesh-granularity=full表示启用全互联模式。
-
部署kilo
安装crds和kilokubectl apply -f https://raw.githubusercontent.com/squat/kilo/main/manifests/crds.yaml kubectl apply -f kilo-k3s.yaml
部署完成后通过ifconfig会发现多了一个kilo0和kube-bridge的网络接口,可以通过wg show kilo0查看网卡的详细信息
agent节点
token=******
server_public_ip=*.*.*.*
node_public_ip=*.*.*.*
curl -sfL https://rancher-mirror.oss-cn-beijing.aliyuncs.com/k3s/k3s-install.sh | INSTALL_K3S_MIRROR=cn K3S_TOKEN=$token K3S_URL=https://$server_public_ip:6443 sh -s - --node-external-ip $node_public_ip --kube-proxy-arg "metrics-bind-address=0.0.0.0"
token:通过在主机执行cat /var/lib/rancher/k3s/server/node-token获取
server_public_ip:即为master节点的公网ip
node_public_ip:即为agent节点的公网ip
安装完成后,通过kubectl get nodes查看节点状态,如果状态为Ready,则表示安装成功。
指定agent的拓扑
# tx2-agent1
k3s kubectl annotate node tx2-agent1 kilo.squat.ai/location="txy-2"
k3s kubectl annotate node tx2-agent1 kilo.squat.ai/force-endpoint={{ server_public_ip }}
k3s kubectl annotate node tx2-agent1 kilo.squat.ai/persistent-keepalive=20
# tx2-agent2
k3s kubectl annotate node tx2-agent2 kilo.squat.ai/location="txy-3"
k3s kubectl annotate node tx2-agent2 kilo.squat.ai/force-endpoint={{ server_public_ip }}
k3s kubectl annotate node tx2-agent2 kilo.squat.ai/persistent-keepalive=20
验证
部署1个busybox的DaemonSet,使其落在每一个Node 上。验证网络流向
# busybox.yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: busybox
labels:
app: busybox
spec:
selector:
matchLabels:
name: busybox
template:
metadata:
labels:
name: busybox
spec:
containers:
- name: busybox
image: busybox
args:
- sleep
- "3600"
kubectl apply -f busybox.yaml
部署完成通过kubectl get pods -o wide查看pod的状态,如果状态为Running,则表示部署成功。
通过kubectl exec -it busybox-xxxxx -- sh进入容器,尝试ping其他节点的pod,如果ping通,则表示网络通信正常。

到这里已经完成了k3s+kilo的部署。
参考文档: