如何使用不同云厂商的服务器搭建 K3S 集群
简介
由于买的国内厂商打折服务器,大部分情况下都无法在同一家厂商买到多台优惠服务器,此时想搭建 K3S 集群就需要走公网,直接通过K3S 的安装方式节点之间无法通信,因此需要使用 WireGuard
来组网。
在阅读本篇之前建议你先阅读 WireGuard
的Quickstart
来了解它的概念,这将对接下来配置WireGuard
十分重要:
本篇以两台服务器为例信息如下:
集群节点类型 | 厂商 | 公网 IP 地址 | 内网 IP 地址 | 操作系统 |
---|---|---|---|---|
master | 腾讯云 | 42.xxx.xxx.60 | 172.17.16.4 | CentOS Linux 7.9 |
node-1 | qingcloud | 139.xx.xx.46 | 10.190.19.38 | CentOS Linux 7.9 |
首先会通过 WireGuard
为两台机器创建一块虚拟网卡并指定虚拟 ip 形如:
[root@k3s-master ~]# ifconfig wg0
wg0: flags=209<UP,POINTOPOINT,RUNNING,NOARP> mtu 1420
inet 192.168.2.1 netmask 255.255.255.255 destination 192.168.2.1
unspec 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 txqueuelen 1000 (UNSPEC)
RX packets 1764 bytes 441372 (431.0 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 1341 bytes 165156 (161.2 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
最终信息如下:
+---------------------------------------+ +--------------------------------------------+
| | | |
| Master 腾讯云 公:42.xxx.xxx.60 | | Node-1 QingCloud 公:139.xx.xx.46 |
| | | |
| 内:172.17.16.4 虚拟Ip: 192.168.2.1 | | 内:10.190.19.38 虚拟IP: 192.168.2.2 |
| | | |
+---------------------------------------+ +--------------------------------------------+
安装WireGuard
在搭建跨云的 k3s
集群前,需要先把 WireGuard
安装好,WireGuard
对内核有要求,要升级到 5.15.2-1.el7.elrepo.x86_64
以上
分别在Master
(表示腾讯云的服务器在集群中作为master节点使用)和Node-1
(表示QingCloud的服务器在集群中作为工作节点使用)执行如下命令以开启 IP 地址转发:
echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf
echo "net.ipv4.conf.all.proxy_arp = 1" >> /etc/sysctl.conf
sysctl -p /etc/sysctl.conf
对两台服务器修改主机名称
# 腾讯云执行
hostnamectl set-hostname k3s-master
# QingCloud执行
hostnamectl set-hostname k3s-node-1
修改 iptables 以允许NAT
对两台服务器都进行如下设置,添加 iptables 规则,允许本机的 NAT 转换,执行前需要将如下的192.168.1.1/24
修改为在简介中决定设定的虚拟ip:
iptables -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
iptables -A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
iptables -A FORWARD -i wg0 -o wg0 -m conntrack --ctstate NEW -j ACCEPT
iptables -t nat -A POSTROUTING -s 192.168.1.1/24 -o eth0 -j MASQUERADE
释意:
wg0
: 为虚拟网卡名称,两台服务器可以都叫wg0
192.168.1.1
: 为虚拟 IP 地址段, Master
设置为192.168.2.1
, Node-1
改为192.168.2.2
eth0
: 为服务器的物理网卡
升级内核
配置好 iptables 只有升级内核以安装WireGuard
,否则安装WireGuard
时会出现如下错误:
[#] ip link add wg0 type wireguard
RTNETLINK answers: Operation not supported
Unable to access interface: Protocol not supported
[#] ip link delete dev wg0
Cannot find device "wg0"
在所有节点都执行如下操作:
- 载入公钥
rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org
- 升级安装
elrepo
rpm -Uvh http://www.elrepo.org/elrepo-release-7.0-5.el7.elrepo.noarch.rpm
- 载入
elrepo-kernel
元数据
yum --disablerepo=\* --enablerepo=elrepo-kernel repolist
- 安装最新版本的内核
yum --disablerepo=\* --enablerepo=elrepo-kernel install kernel-ml.x86_64 -y
- 删除旧版本工具包
yum remove kernel-tools-libs.x86_64 kernel-tools.x86_64 -y
- 然后修改默认内核版本,首先查看当前实际启动顺序
grub2-editenv list
- 查看内核插入顺序
grep "^menuentry" /boot/grub2/grub.cfg | cut -d "'" -f2
- 设置默认启动, 将
CentOS Linux (5.15.2-1.el7.elrepo.x86_64) 7 (Core)
改为步骤6中列出的最新内核信息
grub2-set-default 'CentOS Linux (5.15.2-1.el7.elrepo.x86_64) 7 (Core)'
- 重新创建内核配置
grub2-mkconfig -o /boot/grub2/grub.cfg
- 重启服务器
reboot
- 验证当前内核版本
uname -r
安装WireGuard
在两台服务器都需要执行如下操作,安装流程非常简单,CentOS 内核更新到 5.15.2以上版本后,其中就已经包含了 WireGuard
的内核模块,只需要安装 wireguard-tools
包即可
yum install epel-release https://www.elrepo.org/elrepo-release-7.el7.elrepo.noarch.rpm
yum install yum-plugin-elrepo kmod-wireguard wireguard-tools -y
配置 WireGuard
wireguard-tools
包提供了我们所需的工具 wg
和 wg-quick
,可以使用它们来分别完成手动部署和自动部署。
先按照官方文档描述的形式,生成Master
节点和Node-1
节点服务器 用于加密解密的密钥
在Master节点操作
wg genkey | tee privatekey | wg pubkey > publickey
然后在当前目录下就生成了 privatekey
和 publickey
两个文件
注意:
密钥是配置到本机的,而公钥是配置到其它机器里的,结果示例如下:
cat privatekey publickey
EMWcI01iqM4zkb7xfbaaxxxxxxxxDo2GJUA=
0ay8WfGOIHndWklSIVBqrsp5LDWxxxxxxxxxxxxxxQ=
然后编写配置文件,以供 wg-quick
使用
vim /etc/wireguard/wg0.conf
然后写入如下内容
[Interface]
PrivateKey = EMWcI01iqM4zkb7xfbaaxxxxxxxxDo2GJUA=
Address = 192.168.2.1
ListenPort = 5418
[Peer]
PublicKey = Node-1服务器的 publickey后续Node-1生成后再改
EndPoint = 139.xx.xx.46:5418
AllowedIPs = 192.168.2.2/32
在Node-1节点操作
wg genkey | tee privatekey | wg pubkey > publickey
查看结果
[root@k3s-node-1 ~] cat privatekey publickey
QGl72V7FyFokmF15cPGLcLWkOOBV+CHw6KWL+MtUj2o=
b/yQJHLEo1NisJcE3eBewjX+wFBDROQ3njGRQhZpADQ=
然后编写配置文件,以供 wg-quick
使用
vim /etc/wireguard/wg0.conf
然后写入如下内容
[Interface]
PrivateKey = QGl72V7FyFokmF15cPGLcLWkOOBV+CHw6KWL+MtUj2o=
Address = 192.168.2.2
ListenPort = 5418
[Peer]
# PublicKey为Master机器的
PublicKey = 0ay8WfGOIHndWklSIVBqrsp5LDWxxxxxxxxxxxxxxQ=
EndPoint = 42.xxx.xxx.60:5418
AllowedIPs = 192.168.2.1/32
然后到Master机器使用vim /etc/wireguard/wg0.conf
编辑Peer
下的PublicKey
为Node-1
的PublicKey
开放端口
到云厂商的防火墙(安全组)规则配置处开放 5418
端口,下行规则,协议为UDP
配置说明
Interface: 小节是属于本机的配置.
Address: 是分配给本机在简介部分约定的虚拟 IP,
ListenPort: 是主机之间通讯使用的端口,是 UDP 协议的。
Peer: 是属于需要通信的服务器的信息,有多少需要通信的主机,就添加多少个 Peer 小节,更多内容参阅WireGuard官网配置。
EndPoint: 由于这里是跨厂商所以这里的EndPoint为服务器的公网 IP 与 WireGuard 监听的 UDP 端口,如果你的机器通过内网也能通信,直接用内网 IP 也可以,当然要注意这个 IP 需要所有加入该局域网的主机都能通信才行。
AllowedIPs: 是指本机发起连接的哪些 IP 应该将流量转发到这个节点,比如给主机 B 分配了内网 IP 192.168.1.2,那么在主机 A 上发送到 192.168.1.2 的数据包,都应该转发到这个 EndPoint 上,它其实起的是一个过滤作用。而且多个 Peer 时,这里配置的 IP 地址不能有冲突。
各个节点生产的 privatekey 和 publickey 分别如下
各个节点配置文件如下:
在Master 节点cat /etc/wireguard/wg0.conf
:
[Interface]
PrivateKey = EMWcI01iqM4zkb7xfbaaxxxxxxxxDo2GJUA=
Address = 192.168.2.1
ListenPort = 5418
[Peer]
PublicKey = b/yQJHLEo1NisJcE3eBewjX+wFBDROQ3njGRQhZpADQ=
EndPoint = 139.xx.xx.46:5418
AllowedIPs = 192.168.2.2/32
在Node-1节点cat /etc/wireguard/wg0.conf
:
[Interface]
PrivateKey = QGl72V7FyFokmF15cPGLcLWkOOBV+CHw6KWL+MtUj2o=
Address = 192.168.2.2
ListenPort = 5418
[Peer]
PublicKey = 0ay8WfGOIHndWklSIVBqrsp5LDWxxxxxxxxxxxxxxQ=
EndPoint = 42.xxx.xxx.60:5418
AllowedIPs = 192.168.2.1/32
启动 WireGuard
边写好配置文件后,对所有节点执行 wg-quick
工具来创建虚拟网卡
wg-quick up wg0
上面命令中的 wg0
对应的是 /etc/wireguard/wg0.conf
这个配置文件,其自动创建的网卡设备,名字就是 wg0
。
创建好虚拟网卡后测试是否连通
例如在 Master 节点ping Node-1的虚拟ip要能 ping 通否则请检查配置是否正确
[root@k3s-master ~]# ping 139.xx.xx.46
PING 139.xx.xx.46 (139.xx.xx.46) 56(84) bytes of data.
64 bytes from 139.xx.xx.46: icmp_seq=1 ttl=50 time=48.8 ms
64 bytes from 139.xx.xx.46: icmp_seq=2 ttl=50 time=45.1 ms
^C
--- 139.xx.xx.46 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1000ms
rtt min/avg/max/mdev = 45.119/47.008/48.897/1.889 ms
在Node-1上ping Master亦如是
然后就可以使用 wg
命令来查看通信情况
[root@k3s-master ~]# wg
interface: wg0
public key: 0ay8WfGOIHndWklSIVBqrsp5LDWxxxxxxxxxxxxxxQ=
private key: (hidden)
listening port: 5418
peer: 0f0dn60+tBUfYgzw7rIihKbqxxxxxxxxa6Wo=
endpoint: 122.xx.xx.155:5418
allowed ips: 192.168.1.3/32
latest handshake: 3 minutes, 3 seconds ago
transfer: 35.40 KiB received, 47.46 KiB sent
自动化配置
系统重启后,WireGuard
创建的网卡设备就会丢失,WireGuard
提供了自动化的脚本来解决这件事,在两台服务器都执行如下操作
systemctl enable wg-quick@wg0
使用上述命令生成 systemd 守护脚本,开机会自动运行 up 指令。
配置热重载
wg-quick 并未提供重载相关的指令,但是提供了 strip
指令,可以将 conf 文件转换为 wg 指令可以识别的格式。
wg syncconf wg0 <(wg-quick strip wg0)
即可实现热重载。
完成 WireGuard
的安装配置以后,接下来就可以安装 k3s 的集群了。
安装 K3S 集群
Master 节点安装
export MASTER_EXTERNAL_IP=42.xx.xx.60
export MASTER_VIRTUAL_IP=192.168.2.1
安装 K3S
curl -sfL http://rancher-mirror.cnrancher.com/k3s/k3s-install.sh | INSTALL_K3S_MIRROR=cn sh -s - --node-external-ip $MASTER_EXTERNAL_IP --advertise-address $MASTER_EXTERNAL_IP --node-ip $MASTER_VIRTUAL_IP --flannel-iface wg0
参数说明:
- --node-external-ip: 42.xx.xx.60 设置为当前节点的外部 IP
- --advertise-address: 42.xx.xx.12 用于设置 kubectl 工具以及子节点进行通讯使用的地址,可以是 IP,也可以是域名,在创建 apiserver 证书时会将此设置到有效域中。
- --node-ip: 10.20.30.1 上文中约定的的虚拟ip
- --flannel-iface wg0 wg0 是 WireGuard 创建的网卡设备,我需要使用虚拟局域网来进行节点间的通信,所以这里需要指定为 wg0。
由于 WireGuard 的所有流量都是加密传输的,通过它来进行节点间的通信,就已经能够保证通信安全,也就没有必要改用其它的 CNI 驱动,使用默认的就可以了。
在主节点执行上述命令后,一分钟不到就可以看到脚本提示安装完成。通过命令查看下主控端的运行情况
systemctl status k3s
如果运行正常,那么就看看容器的运行状态是否正常
kubectl get pods -A
-A
参数用于查看所有命名空间,如果容器都处于 running 状态,那么安装就成功了,接下来要可以添加被控节点。
Agent 安装
有了上述安装主控的经验,安装 work 节点更加简单,参数需要一定的调整
在Node-1节点 执行
export MASTER_VIRTUAL_IP=192.168.2.1
export NODE_EXTERNAL_IP=139.xx.xx.46
export NODE_VIRTUAL_IP=192.168.2.2
export K3S_TOKEN=K1031c4c705056a0752a09801e99b56cf0f89571b4d678a138a44deb49a0e1d9722::server:5d89600a5330100489c4c3dbcce1dec0
将 K3S_TOKEN
的值改为在Master节点执行/var/lib/rancher/k3s/server/node-token
后得到的值
将NODE_EXTERNAL_IP
设置为Node-1的公网ip
安装
curl -sfL http://rancher-mirror.cnrancher.com/k3s/k3s-install.sh | INSTALL_K3S_MIRROR=cn K3S_URL=https://$MASTER_VIRTUAL_IP:6443 K3S_TOKEN=$K3S_TOKEN sh -s - --node-external-ip $NODE_EXTERNAL_IP --node-ip $NODE_VIRTUAL_IP --flannel-iface wg0
执行后稍等一会,安装成功后,照例查看服务运行状态
systemctl status k3s-agent
都安装好以后 在 Master 节点检查,可以看到两个节点
kubectl get nodes -o wide
至此 多云 K3S 集群已经搭建完毕。
参考文档:
[2] WireGuard官方文档
[3] Network Address Translation
[4] K3S